關(guān)于圖像處理和Python深度學(xué)習(xí)的教程:第二部分
我們將以對(duì)比度增強(qiáng)開(kāi)始第二部分。
6、對(duì)比度增強(qiáng)
某些類型的圖像(如醫(yī)學(xué)分析結(jié)果)對(duì)比度較低,很難發(fā)現(xiàn)細(xì)節(jié),如下所示:
xray = imread("images/xray.jpg")
xray_gray = rgb2gray(xray)
compare(xray, xray_gray)
在這種情況下,我們可以使用對(duì)比度增強(qiáng)使細(xì)節(jié)更加清晰。有兩種對(duì)比度增強(qiáng)算法:
對(duì)比度拉伸
直方圖均衡化
我們將在這篇文章中討論直方圖均衡化,它又有三種類型:
標(biāo)準(zhǔn)直方圖均衡化
自適應(yīng)直方圖均衡化
對(duì)比度受限自適應(yīng)直方圖均衡化(CLAHE)
直方圖均衡化將圖像對(duì)比度最高的區(qū)域擴(kuò)展到亮度較低的區(qū)域,使其均衡。
你可以通過(guò)從最高的像素值中減去最低的像素值來(lái)計(jì)算圖像的對(duì)比度。
>>> xray.max() - xray.min()
255
現(xiàn)在,讓我們嘗試exposure模塊中的標(biāo)準(zhǔn)直方圖均衡化:
from skimage.exposure import equalize_h(yuǎn)ist
enhanced = equalize_h(yuǎn)ist(xray_gray)
>>> compare(xray, enhanced)
我們已經(jīng)可以更清楚地看到細(xì)節(jié)了。
from skimage.exposure import equalize_h(yuǎn)ist
enhanced = equalize_h(yuǎn)ist(xray_gray)
>>> compare(xray, enhanced)
接下來(lái),我們將使用CLAHE,它為圖像中的不同像素鄰域計(jì)算許多直方圖,即使在最暗的區(qū)域也會(huì)得到更詳細(xì)的信息:
from skimage.exposure import equalize_adapthist
# Adjust clip_limit
enhanced_adaptive = equalize_adapthist(xray_gray, clip_limit=0.4)
compare(xray, enhanced_adaptive, "Image with contrast enhancement")
這個(gè)看起來(lái)好多了,因?yàn)樗梢栽诒尘爸酗@示細(xì)節(jié),在左下角顯示更多缺失的肋骨。你可以調(diào)整clip_limit以獲得更多或更少的細(xì)節(jié)。
7、變換
數(shù)據(jù)集中的圖像可能有幾個(gè)相互沖突的特征,如不同的比例、未對(duì)齊的旋轉(zhuǎn)等。ML和DL算法希望你的圖片具有相同的形狀和尺寸。因此,你需要學(xué)習(xí)如何修復(fù)它們。
旋轉(zhuǎn)
要旋轉(zhuǎn)圖像,請(qǐng)使用“transform”模塊中的“rotate”函數(shù)。
from skimage.transform import rotate
clock = imread("images/clock.jpg")
clockwise = rotate(clock, angle=-60)
compare(clock, clockwise, "Clockwise rotated image, use negative angles")
anti_clockwise = rotate(clock, angle=33)
compare(clock, anti_clockwise, "Anticlockwise rotated image, use positive angles")
縮放
另一個(gè)標(biāo)準(zhǔn)操作是縮放圖像。
我們對(duì)此操作使用rescale函數(shù):
butterflies = imread("images/butterflies.jpg")
>>> butterflies.shape
(720, 1280, 3)
from skimage.transform import rescale
scaled_butterflies = rescale(butterflies, scale=3 / 4, multichannel=True)
compare(
butterflies,
scaled_butterflies,
"Butterflies scaled down by a factor of 3/4",
axis=True,
)
當(dāng)圖像分辨率較高時(shí),縮小可能會(huì)導(dǎo)致質(zhì)量損失或像素不協(xié)調(diào),從而產(chǎn)生意外的邊或角。要考慮這種影響,可以將anti_aliasing設(shè)置為T(mén)rue,它使用高斯平滑:
https://gist.github.com/f7ae272b6eb1bce408189d8de2b71656
與之前一樣,平滑效果并不明顯,但在更細(xì)粒度的級(jí)別上會(huì)更明顯。
調(diào)整大小
如果希望圖像具有特定的寬度和高度,而不是按系數(shù)縮放,可以通過(guò)提供output_shape來(lái)使用resize函數(shù):
from skimage.transform import resize
puppies = imread("images/puppies.jpg")
# Also possible to set anti_aliasing
puppies_600_800 = resize(puppies, output_shape=(600, 800))
compare(puppies, puppies_600_800,
"Puppies image resized 600x800 (height, width)")
圖像恢復(fù)和增強(qiáng)
在文件變換、錯(cuò)誤下載或許多其他情況下,某些圖像可能會(huì)失真、損壞或丟失。
在本節(jié)中,我們將討論一些圖像恢復(fù)技術(shù),從修復(fù)開(kāi)始。
1、修補(bǔ)
修復(fù)算法可以智能地填補(bǔ)圖像中的空白。我找不到損壞的圖片,因此我們將使用此鯨魚(yú)圖像并手動(dòng)在其上放置一些空白:
whale_image = imread("images/00206a224e68de.jpg")
>>> show(whale_image)
>>> whale_image.shape
(428, 1916, 3)
以下函數(shù)創(chuàng)建四個(gè)變黑區(qū)域,以模擬圖像上丟失的信息:
def make_mask(image):
"""Create a mask to artificially defect the image."""
mask = np.zeros(image.shape[:-1])
# Make 4 masks
mask[250:300, 1400:1600] = 1
mask[50:100, 300:433] = 1
mask[300:380, 1000:1200] = 1
mask[200:270, 750:950] = 1
return mask.a(chǎn)stype(bool)
# Create the mask
mask = make_mask(whale_image)
# Apply the defect mask on the whale_image
image_defect = whale_image * ~mask[..., np.newaxis]
compare(whale_image, image_defect, "Artifically damaged image of a whale")
我們將使用inpaint模塊中的inpaint_biharmonic函數(shù)來(lái)填充空白,并傳遞我們創(chuàng)建的掩碼:
from skimage.restoration import inpaint
restored_image = inpaint.inpaint_biharmonic(
image=image_defect, mask=mask, multichannel=True
)
compare(
image_defect,
restored_image,
"Restored image after defects",
title_original="Faulty Image",
)
正如你所看到的,在看到故障圖像之前,很難判斷缺陷區(qū)域在哪里。
現(xiàn)在,讓我們制造一些噪聲
2、噪聲
如前所述,噪聲在圖像增強(qiáng)和恢復(fù)中起著至關(guān)重要的作用。
有時(shí),你可能會(huì)有意將其添加到如下圖像中:
from skimage.util import random_noise
pup = imread("images/pup.jpg")
noisy_pup = random_noise(pup)
compare(pup, noisy_pup, "Noise puppy image")
我們使用random_noise函數(shù)向圖像噴灑隨機(jī)的顏色斑點(diǎn)。因此,這種方法被稱為“鹽和胡椒(salt和 pepper)”技術(shù)。
3、降噪-去噪
但是,大多數(shù)情況下,你希望從圖像中移除噪聲,而不是添加噪聲。有幾種類型的去噪算法:
TV濾波器
雙邊去噪
小波降噪
非局部均值去噪
在本文中,我們將只看前兩個(gè)。我們先試試TV濾波器
from skimage.restoration import denoise_tv_chambolle
denoised_pup_tv = denoise_tv_chambolle(noisy_pup, weight=0.2, multichannel=True)
compare(
noisy_pup,
denoised_pup_tv,
"Total Variation Filter denoising applied",
title_original="Noisy pup",
)
圖像的分辨率越高,去噪所需的時(shí)間就越長(zhǎng)?梢允褂脵(quán)重參數(shù)控制去噪效果。
現(xiàn)在,讓我們嘗試denoise_bilateral:
from skimage.restoration import denoise_bilateral
denoised_pup_bilateral = denoise_bilateral(noisy_pup, multichannel=True)
compare(noisy_pup, denoised_pup_bilateral, "Bilateral denoising applied image")
它不如TV濾波器有效,如下所示:
compare(
denoised_pup_tv,
denoised_pup_bilateral,
"Bilateral filtering",
title_original="TV filtering",
)
4、分割
圖像分割是圖像處理中最基本和最日常的主題之一,它廣泛應(yīng)用于運(yùn)動(dòng)和目標(biāo)檢測(cè)、圖像分類等許多領(lǐng)域。
我們已經(jīng)看到了分割的一個(gè)實(shí)例—對(duì)圖像進(jìn)行閾值化以從前景中提取背景。
本節(jié)將學(xué)習(xí)更多內(nèi)容,例如將圖像分割為類似區(qū)域。
要開(kāi)始分割,我們需要了解超級(jí)像素的概念。
一個(gè)像素本身只代表一小部分顏色,一旦與圖像分離,單個(gè)像素將毫無(wú)用處。因此,分割算法使用對(duì)比度、顏色或亮度相似的多組像素,它們被稱為超級(jí)像素。
一種試圖找到超像素的算法是簡(jiǎn)單線性迭代聚類(SLIC),它使用k均值聚類。讓我們看看如何在skimage庫(kù)中提供的咖啡圖像上使用它:
from skimage import data
coffee = data.coffee()
>>> show(coffee)
我們將使用segmentation模塊中的slic函數(shù):
from skimage.segmentation import slic
segments = slic(coffee)
>>> show(segments)
默認(rèn)情況下,slic會(huì)查找100個(gè)線段或標(biāo)簽。要將它們放回圖像中,我們使用label2rgb函數(shù):
from skimage.color import label2rgb
final_image = label2rgb(segments, coffee, kind="avg")
>>> show(final_image)
讓我們將此操作包裝在函數(shù)中,并嘗試使用更多段:
from skimage.color import label2rgb
from skimage.segmentation import slic
def segment(image, n_segments=100):
# Obtain superpixels / segments
superpixels = slic(coffee, n_segments=n_segments)
# Put the groups on top of the original image
segmented_image = label2rgb(superpixels, image, kind="avg")
return segmented_image
# Find 500 segments
coffee_segmented_2 = segment(coffee, n_segments=500)
compare(coffee, coffee_segmented_2, "With 500 segments")
分割將使計(jì)算機(jī)視覺(jué)算法更容易從圖像中提取有用的特征。
5、等高線
對(duì)象的大部分信息都存在于其形狀中。如果我們能夠檢測(cè)出物體的線條或輪廓形狀,我們就可以提取出有價(jià)值的數(shù)據(jù)。
讓我們看看如何在實(shí)踐中使用多米諾骨牌圖像來(lái)尋找輪廓。
dominoes = imread("images/dominoes.jpg")
>>> show(dominoes)
我們將看看是否可以使用skimage中的find_contours函數(shù)來(lái)隔離瓷磚和圓。此函數(shù)需要一個(gè)二進(jìn)制(黑白)圖像,因此我們必須先對(duì)圖像設(shè)置閾值。
from skimage.measure import find_contours
# Convert to grayscale
dominoes_gray = rgb2gray(dominoes)
# Find optimal threshold with treshold_otsu
thresh = threshold_otsu(dominoes_gray)
# Binarize
dominoes_binary = dominoes_gray > thresh
domino_contours = find_contours(dominoes_binary)
生成的數(shù)組是(n,2)個(gè)數(shù)組的列表,表示等高線的坐標(biāo):
for contour in domino_contours[:5]:
print(contour.shape)
[OUT]:
(371, 2)
(376, 2)
(4226, 2)
(177, 2)
(11, 2)
我們將把操作包裝在一個(gè)名為mark_contours的函數(shù)中:
from skimage.filters import threshold_otsu
from skimage.measure import find_contours
def mark_contours(image):
"""A function to find contours from an image"""
gray_image = rgb2gray(image)
# Find optimal threshold
thresh = threshold_otsu(gray_image)
# Mask
binary_image = gray_image > thresh
contours = find_contours(binary_image)
return contours
要在圖像上繪制等高線,我們將創(chuàng)建另一個(gè)名為plot_image_contours的函數(shù),該函數(shù)使用上述函數(shù):
def plot_image_contours(image):
fig, ax = plt.subplots()
ax.imshow(image, cmap=plt.cm.gray)
for contour in mark_contours(image):
ax.plot(contour[:, 1], contour[:, 0], linewidth=2, color="red")
ax.a(chǎn)xis("off")
>>> plot_image_contours(dominoes)
正如我們所看到的,我們成功地檢測(cè)到了大部分輪廓,但我們?nèi)匀豢梢钥吹街行牡囊恍╇S機(jī)波動(dòng)。
在將多米諾骨牌圖像傳遞到輪廓查找函數(shù)之前,先進(jìn)行去噪:
dominoes_denoised = denoise_tv_chambolle(dominoes, multichannel=True)
plot_image_contours(dominoes_denoised)
就是這樣!我們消除了大部分噪聲,這些噪聲導(dǎo)致輪廓線不正確!
高級(jí)操作1、邊緣檢測(cè)
之前,我們使用Sobel算法來(lái)檢測(cè)對(duì)象的邊緣。在這里,我們將使用Canny算法,因?yàn)樗臁⒏鼫?zhǔn)確,所以得到了更廣泛的應(yīng)用。一如既往,函數(shù)canny需要灰度圖像。
這一次,我們將使用具有更多硬幣的圖像,因此需要檢測(cè)更多邊緣:
coins_3 = imread("images/coins_3.jpg")
# Convert to gray
coins_3_gray = rgb2gray(coins_3)
compare(coins_3, coins_3_gray)
要找到邊緣,我們只需將圖像傳遞給canny函數(shù):
from skimage.feature import canny
# Find edges with canny
canny_edges = canny(coins_3_gray)
compare(coins_3, canny_edges, "Edges detected with Canny algorithm")
該算法發(fā)現(xiàn)了幾乎所有硬幣的邊緣,但由于硬幣上的雕刻也被檢測(cè)到,因此噪聲非常大。我們可以通過(guò)調(diào)整sigma參數(shù)來(lái)降低canny的靈敏度:
canny_edges_sigma_2 = canny(coins_3_gray, sigma=2.5)
compare(coins_3, canny_edges_sigma_2, "Edges detected with less intensity")
正如你所見(jiàn),Canny現(xiàn)在只找到了硬幣的大致輪廓。
2、角點(diǎn)檢測(cè)
另一種重要的圖像處理技術(shù)是角點(diǎn)檢測(cè)。角點(diǎn)可以是圖像分類中對(duì)象的關(guān)鍵特征。
為了找到角點(diǎn),我們將使用Harris角點(diǎn)檢測(cè)算法。讓我們加載一個(gè)示例圖像并將其轉(zhuǎn)換為灰度:
windows = imread("images/windows.jpg")
windows_gray = rgb2gray(windows)
compare(windows, windows_gray)
我們將使用corner_h(yuǎn)arris函數(shù)生成一個(gè)測(cè)量圖像,該圖像屏蔽了角點(diǎn)所在的區(qū)域。
from skimage.feature import corner_h(yuǎn)arris
measured_image = corner_h(yuǎn)arris(windows_gray)
>>> show(measured_image)
現(xiàn)在,我們將此蒙版度量圖像傳遞給corner_peaks函數(shù),該函數(shù)這次返回角點(diǎn)坐標(biāo):
from skimage.feature import corner_peaks
corner_coords = corner_peaks(measured_image, min_distance=50)
>>> len(corner_coords)
79
該函數(shù)找到79個(gè)角點(diǎn)。讓我們將操作包裝到函數(shù)中:
def find_corner_coords(image, min_distance=50):
# Convert to gray
gray_image = rgb2gray(image)
# Produce a measure image
measure_image = corner_h(yuǎn)arris(gray_image)
# Find coords
coords = corner_peaks(measure_image, min_distance=min_distance)
return coords
現(xiàn)在,我們將創(chuàng)建另一個(gè)函數(shù),該函數(shù)使用上述函數(shù)生成的坐標(biāo)繪制每個(gè)角點(diǎn):
def show_image_cornered(image):
# Find coords
coords = find_corner_coords(image)
# Plot them on top of the image
plt.imshow(image, cmap="gray")
plt.plot(coords[:, 1], coords[:, 0], "+b", markersize=15)
plt.a(chǎn)xis("off")
show_image_cornered(windows)
不幸的是,該算法沒(méi)有按預(yù)期工作。標(biāo)記放置在磚的交叉處,而不是找到窗角。
這些是噪音,使它們毫無(wú)用處。讓我們對(duì)圖像進(jìn)行去噪處理,并再次將其傳遞給函數(shù):
windows_denoised = denoise_tv_chambolle(windows, multichannel=True, weight=0.3)
show_image_cornered(windows_denoised)
現(xiàn)在,這好多了!它找到了大部分窗戶角。
結(jié)論
在真正的計(jì)算機(jī)視覺(jué)問(wèn)題中,你不會(huì)同時(shí)使用所有這些。正如你可能已經(jīng)注意到的,我們今天學(xué)到的東西并不復(fù)雜,最多需要幾行代碼。棘手的部分是將它們應(yīng)用于實(shí)際問(wèn)題,并實(shí)際提高模型的性能。
感謝閱讀!
原文標(biāo)題 : 關(guān)于圖像處理和Python深度學(xué)習(xí)的教程:第二部分
發(fā)表評(píng)論
請(qǐng)輸入評(píng)論內(nèi)容...
請(qǐng)輸入評(píng)論/評(píng)論長(zhǎng)度6~500個(gè)字
最新活動(dòng)更多
-
11月20日火熱報(bào)名中>> 2024 智能家居出海論壇
-
11月28日立即報(bào)名>>> 2024工程師系列—工業(yè)電子技術(shù)在線會(huì)議
-
12月19日立即報(bào)名>> 【線下會(huì)議】OFweek 2024(第九屆)物聯(lián)網(wǎng)產(chǎn)業(yè)大會(huì)
-
即日-12.26火熱報(bào)名中>> OFweek2024中國(guó)智造CIO在線峰會(huì)
-
即日-2025.8.1立即下載>> 《2024智能制造產(chǎn)業(yè)高端化、智能化、綠色化發(fā)展藍(lán)皮書(shū)》
-
精彩回顧立即查看>> 【在線會(huì)議】多物理場(chǎng)仿真助跑新能源汽車(chē)
推薦專題
- 1 腦機(jī)接口芯片,華為出了新專利!
- 2 地平線開(kāi)啟配售,阿里百度各砸5000萬(wàn)美金,市值最高超500億
- 3 小馬智行沖刺納斯達(dá)克:或成「全球Robotaxi第一股」,兩年半營(yíng)收約12億元
- 4 云從科技:營(yíng)收低迷與虧損加劇,2025年盈利目標(biāo)挑戰(zhàn)重重
- 5 AI奇跡:域名賣(mài)爆,無(wú)名小島意外賺2億
- 6 逆境求生,泄密風(fēng)波中的高精地圖
- 7 特斯拉無(wú)人駕駛來(lái)了,馬斯克的餅卻不香了
- 8 未來(lái)的大模型,或許都是A卡來(lái)算的?
- 9 2024量子計(jì)算發(fā)展態(tài)勢(shì)研究報(bào)告
- 10 科技巨頭加速破冰,京東物流將接入淘寶
- 高級(jí)軟件工程師 廣東省/深圳市
- 自動(dòng)化高級(jí)工程師 廣東省/深圳市
- 光器件研發(fā)工程師 福建省/福州市
- 銷售總監(jiān)(光器件) 北京市/海淀區(qū)
- 激光器高級(jí)銷售經(jīng)理 上海市/虹口區(qū)
- 光器件物理工程師 北京市/海淀區(qū)
- 激光研發(fā)工程師 北京市/昌平區(qū)
- 技術(shù)專家 廣東省/江門(mén)市
- 封裝工程師 北京市/海淀區(qū)
- 結(jié)構(gòu)工程師 廣東省/深圳市