Python 圖像處理—使用 Scikit-Image 進(jìn)行斑點(diǎn)檢測(cè)
點(diǎn)擊下面卡片關(guān)注“AI算法與圖像處理”,選擇加"星標(biāo)"或“置頂”
重磅干貨,第一時(shí)間送達(dá)
引言
圖像處理時(shí),我們需要的最重要的技能之一就是能夠識(shí)別圖像中的特定部分。一張圖片只有在特定的感興趣點(diǎn)能夠被識(shí)別和分別列出的情況下才有用。在本文中,我們將了解如何做到這一點(diǎn)。
讓我們從導(dǎo)入本文所需的庫(kù)開(kāi)始!
import matplotlib.pyplot as pltimport numpy as npimport pandas as pdimport skimagefrom skimage.io import imread, imshowfrom skimage.color import rgb2gray, rgb2hsvfrom skimage.measure import label, regionprops, regionprops_tablefrom skimage.filters import threshold_otsufrom scipy.ndimage import median_filterfrom matplotlib.patches import Rectanglefrom tqdm import tqdm
現(xiàn)在讓我們加載圖像。
tree = imread('laughing_tree.png')imshow(tree);

我們的任務(wù)是識(shí)別和隔離圖像中包含樹(shù)木獨(dú)特果實(shí)的部分(看起來(lái)像張開(kāi)的嘴)。
首先讓我們嘗試看看是否有任何簡(jiǎn)單的方法來(lái)基于圖像的值進(jìn)行識(shí)別。讓我們將圖像轉(zhuǎn)換為灰度,并使用 Otsu 方法。
tree_gray = rgb2gray(tree)otsu_thresh = threshold_otsu(tree_gray)tree_binary = tree_gray < otsu_threshimshow(tree_binary, cmap = 'gray');

這顯然不能很好地解決這個(gè)問(wèn)題,讓我們嘗試在幾個(gè)不同閾值上進(jìn)行迭代。
def threshold_checker(image):thresholds = np.arange(0.1,1.1,0.1)tree_gray = rgb2gray(image)fig, ax = plt.subplots(2, 5, figsize=(17, 10))for n, ax in enumerate(ax.flatten()):ax.set_title(f'Threshold : {round(thresholds[n],2)}',fontsize = 16)threshold_tree = tree_gray < thresholds[n]ax.imshow(threshold_tree);ax.axis('off')fig.tight_layout()threshold_checker(tree)

我們可以看到,盡管閾值處理似乎有所幫助,但它仍然包含了我們不感興趣的圖像部分。讓我們嘗試另一種方法。
tree_hsv = rgb2hsv(tree[:,:,:-1])plt.figure(num=None, figsize=(8, 6), dpi=80)plt.imshow(tree_hsv[:,:,0], cmap='hsv')plt.colorbar();

如果將圖像放入HSV色彩空間中,我們可以看到水果明顯具有紅色色調(diào),該紅色色調(diào)在圖像的其他部分不存在。讓我們嘗試分離圖像的這些部分。
lower_mask = tree_hsv [:,:,0] > 0.80upper_mask = tree_hsv [:,:,0] <= 1.00mask = upper_mask*lower_maskred = tree[:,:,0]*maskgreen = tree[:,:,1]*maskblue = tree[:,:,2]*masktree_mask = np.dstack((red,green,blue))plt.figure(num=None, figsize=(8, 6), dpi=80)imshow(tree_mask);

可以看到,除了果實(shí),還保留了大部分的天空部分。參考上一個(gè)色相通道圖像,我們可以看到這些部分在水果中也存在相同種類的紅色。
為了解決這個(gè)問(wèn)題,讓我們檢查一下圖像的 Value 通道。
tree_hsv = rgb2hsv(tree[:,:,:-1])plt.figure(num=None, figsize=(8, 6), dpi=80)plt.imshow(tree_hsv[:,:,2], cmap='gray')plt.colorbar();

可以看到那些明亮區(qū)域的值非常的高,在創(chuàng)建mask的時(shí)候我們需要考慮這一點(diǎn)。
lower_mask = tree_hsv [:,:,0] > 0.80upper_mask = tree_hsv [:,:,0] <= 1.00value_mask = tree_hsv [:,:,2] < .90mask = upper_mask*lower_mask*value_maskred = tree[:,:,0] * maskgreen = tree[:,:,1] * maskblue = tree[:,:,2] * masktree_mask = np.dstack((red, green, blue))plt.figure(num=None, figsize=(8, 6), dpi=80)imshow(tree_mask);

很好!現(xiàn)在我們需要找到一種方法來(lái)清理圖像中的小白點(diǎn)。為此,我們可以簡(jiǎn)單地使用 Skimage 庫(kù)中的中值濾波函數(shù)。
lower_mask = tree_hsv [:,:,0] > 0.80upper_mask = tree_hsv [:,:,0] <= 1.00value_mask = tree_hsv [:,:,2] < .90mask = median_filter(upper_mask*lower_mask*value_mask, 10)red = tree[:,:,0] * maskgreen = tree[:,:,1] * maskblue = tree[:,:,2] * masktree_mask = np.dstack((red, green, blue))plt.figure(num=None, figsize=(8, 6), dpi=80)imshow(tree_mask);

可以看到,結(jié)合了中值過(guò)濾器可以使我們獲得非常清晰的圖像。現(xiàn)在我們需要標(biāo)識(shí)每個(gè),為此,我們需要使用 Skimage 中的 label 函數(shù)。
tree_blobs = label(rgb2gray(tree_mask) > 0)imshow(tree_blobs, cmap = 'tab10');

可以看到該函數(shù)標(biāo)識(shí)了圖像中的不同。現(xiàn)在的下一步是獲取每個(gè)斑點(diǎn)的屬性。為此,我們需要使用 Skimage 中的 regionprops_table 函數(shù)。
properties =['area','bbox','convex_area','bbox_area','major_axis_length', 'minor_axis_length','eccentricity']df = pd.DataFrame(regionprops_table(tree_blobs, properties = properties))

regionprops_table 函數(shù)在數(shù)據(jù)幀中為我們提供每個(gè)斑點(diǎn)的屬性,這使我們能夠輕松地操作數(shù)據(jù)。讓我們使用bbox特性在圖像上繪制邊界框。
blob_coordinates = [(row['bbox-0'],row['bbox-1'],row['bbox-2'],row['bbox-3'] )forindex, row in df.iterrows()]fig, ax = plt.subplots(1,1, figsize=(8, 6), dpi = 80)for blob in tqdm(blob_coordinates):width = blob[3] - blob[1]height = blob[2] - blob[0]patch = Rectangle((blob[1],blob[0]), width, height,edgecolor='r', facecolor='none')ax.add_patch(patch)ax.imshow(tree);ax.set_axis_off()

成功了!
最后,讓我們從圖像中切出邊界框,并將其顯示為自己的圖像。
fig, ax = plt.subplots(1, len(blob_coordinates), figsize=(15,5))for n, axis in enumerate(ax.flatten()):axis.imshow(tree[int(blob_coordinates[n][0]):int(blob_coordinates[n][2]),int(blob_coordinates[n][1]):int(blob_coordinates[n][3])]);fig.tight_layout()

總結(jié)
了解如何進(jìn)行斑點(diǎn)檢測(cè)對(duì)于圖像處理來(lái)說(shuō)都是非常重要的。它可以用來(lái)將圖像的不同部分分割成不同的興趣點(diǎn)。雖然這是一個(gè)相對(duì)簡(jiǎn)單和直接的介紹,但希望對(duì)你喲一個(gè)啟發(fā)性的認(rèn)識(shí),如何通過(guò)使用斑點(diǎn)檢測(cè)來(lái)解決基本的圖像問(wèn)題。
個(gè)人微信(如果沒(méi)有備注不拉群!) 請(qǐng)注明:地區(qū)+學(xué)校/企業(yè)+研究方向+昵稱
下載1:何愷明頂會(huì)分享
在「AI算法與圖像處理」公眾號(hào)后臺(tái)回復(fù):何愷明,即可下載。總共有6份PDF,涉及 ResNet、Mask RCNN等經(jīng)典工作的總結(jié)分析
下載2:終身受益的編程指南:Google編程風(fēng)格指南
在「AI算法與圖像處理」公眾號(hào)后臺(tái)回復(fù):c++,即可下載。歷經(jīng)十年考驗(yàn),最權(quán)威的編程規(guī)范!
下載3:Python視覺(jué)實(shí)戰(zhàn)項(xiàng)目52講 在「AI算法與圖像處理」公眾號(hào)后臺(tái)回復(fù):Python視覺(jué)實(shí)戰(zhàn)項(xiàng)目,即可下載包括圖像分割、口罩檢測(cè)、車(chē)道線檢測(cè)、車(chē)輛計(jì)數(shù)、添加眼線、車(chē)牌識(shí)別、字符識(shí)別、情緒檢測(cè)、文本內(nèi)容提取、面部識(shí)別等31個(gè)視覺(jué)實(shí)戰(zhàn)項(xiàng)目,助力快速學(xué)校計(jì)算機(jī)視覺(jué)。
覺(jué)得不錯(cuò)就點(diǎn)亮在看吧
![]()
