python數位影像處理之進階形態學處理

來源:互聯網
上載者:User
這篇文章主要介紹了python數位影像處理之進階形態學處理,現在分享給大家,也給大家做個參考。一起過來看看吧

形態學處理,除了最基本的膨脹、腐蝕、開/閉運算、黑/白帽處理外,還有一些更進階的運用,如凸包,連通地區標記,刪除小塊地區等。

1、凸包

凸包是指一個凸多邊形,這個凸多邊形將圖片中所有的白色像素點都包含在內。

函數為:

skimage.morphology.convex_hull_image(image)

輸入為二值映像,輸出一個邏輯二值映像。在凸包內的點為True, 否則為False

例:

import matplotlib.pyplot as pltfrom skimage import data,color,morphology#產生二值測試映像img=color.rgb2gray(data.horse())img=(img<0.5)*1chull = morphology.convex_hull_image(img)#繪製輪廓fig, axes = plt.subplots(1,2,figsize=(8,8))ax0, ax1= axes.ravel()ax0.imshow(img,plt.cm.gray)ax0.set_title('original image')ax1.imshow(chull,plt.cm.gray)ax1.set_title('convex_hull image')

convex_hull_image()是將圖片中的所有目標看作一個整體,因此計算出來只有一個最小凸多邊形。如果圖中有多個目標物體,每一個物體需要計算一個最小凸多邊形,則需要使用convex_hull_object()函數。

函數格式:skimage.morphology.convex_hull_object(image,neighbors=8)

輸入參數image是一個二值映像,neighbors表示是採用4連通還是8連通,預設為8連通。

例:

import matplotlib.pyplot as pltfrom skimage import data,color,morphology,feature#產生二值測試映像img=color.rgb2gray(data.coins())#檢測canny邊緣,得到二值圖片edgs=feature.canny(img, sigma=3, low_threshold=10, high_threshold=50) chull = morphology.convex_hull_object(edgs)#繪製輪廓fig, axes = plt.subplots(1,2,figsize=(8,8))ax0, ax1= axes.ravel()ax0.imshow(edgs,plt.cm.gray)ax0.set_title('many objects')ax1.imshow(chull,plt.cm.gray)ax1.set_title('convex_hull image')plt.show()

2、連通地區標記

在二值映像中,如果兩個像素點相鄰且值相同(同為0或同為1),那麼就認為這兩個像素點在一個相互連通的地區內。而同一個連通地區的所有像素點,都用同一個數值來進行標記,這個過程就叫連通地區標記。在判斷兩個像素是否相鄰時,我們通常採用4連通或8連通判斷。在映像中,最小的單位是像素,每個像素周圍有8個鄰接像素,常見的鄰接關係有2種:4鄰接與8鄰接。4鄰接一共4個點,即上下左右,如下左圖所示。8鄰接的點一共有8個,包括了對角線位置的點,如下右圖所示。

在skimage包中,我們採用measure子模組下的label()函數來實現連通地區標記。

函數格式:

skimage.measure.label(image,connectivity=None)

參數中的image表示需要處理的二值映像,connectivity表示串連的模式,1代表4鄰接,2代表8鄰接。

輸出一個標記數組(labels), 從0開始標記。

import numpy as npimport scipy.ndimage as ndifrom skimage import measure,colorimport matplotlib.pyplot as plt#編寫一個函數來產生原始二值映像def microstructure(l=256):  n = 5  x, y = np.ogrid[0:l, 0:l] #產生網路  mask = np.zeros((l, l))  generator = np.random.RandomState(1) #隨機數種子  points = l * generator.rand(2, n**2)  mask[(points[0]).astype(np.int), (points[1]).astype(np.int)] = 1  mask = ndi.gaussian_filter(mask, sigma=l/(4.*n)) #高斯濾波  return mask > mask.mean()data = microstructure(l=128)*1 #產生測試圖片labels=measure.label(data,connectivity=2) #8連通地區標記dst=color.label2rgb(labels) #根據不同的標記顯示不同的顏色print('regions number:',labels.max()+1) #顯示連通地區塊數(從0開始標記)fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(8, 4))ax1.imshow(data, plt.cm.gray, interpolation='nearest')ax1.axis('off')ax2.imshow(dst,interpolation='nearest')ax2.axis('off')fig.tight_layout()plt.show()

在代碼中,有些地方乘以1,則可以將bool數組快速地轉換為int數組。

結果有10個連通的地區,標記為0-9

如果想分別對每一個連通地區進行操作,比如計算面積、外接矩形、凸包面積等,則需要調用measure子模組的regionprops()函數。該函數格式為:

skimage.measure.regionprops(label_image)

返回所有連通區塊的屬性列表,常用的屬性列表如下表:


屬性名稱 類型 描述
area int 地區內像素點總數
bbox tuple 邊界外接框(min_row, min_col, max_row, max_col)
centroid array   質心座標
convex_area int 凸包內像素點總數
convex_image ndarray 和邊界外接框同大小的凸包  
coords ndarray 地區內像素點座標
Eccentricity float 離心率
equivalent_diameter float 和地區面積相同的圓的直徑
euler_number int   地區歐拉數
extent float 地區面積和邊界外接框面積的比率
filled_area int 地區和外接框之間填充的像素點總數
perimeter float 地區周長
label int 地區標記

3、刪除小塊地區

有些時候,我們只需要一些大塊地區,那些零散的、小塊的地區,我們就需要刪除掉,則可以使用morphology子模組的remove_small_objects()函數。

函數格式:skimage.morphology.remove_small_objects(ar,min_size=64,connectivity=1,in_place=False)

參數:

ar: 待操作的bool型數組。

min_size: 最小連通地區尺寸,小於該尺寸的都將被刪除。預設為64.

connectivity: 鄰接模式,1表示4鄰接,2表示8鄰接

in_place: bool型值,如果為True,表示直接在輸入映像中刪除小塊地區,否則進行複製後再刪除。預設為False.

返回刪除了小塊地區的二值映像。

import numpy as npimport scipy.ndimage as ndifrom skimage import morphologyimport matplotlib.pyplot as plt#編寫一個函數來產生原始二值映像def microstructure(l=256):  n = 5  x, y = np.ogrid[0:l, 0:l] #產生網路  mask = np.zeros((l, l))  generator = np.random.RandomState(1) #隨機數種子  points = l * generator.rand(2, n**2)  mask[(points[0]).astype(np.int), (points[1]).astype(np.int)] = 1  mask = ndi.gaussian_filter(mask, sigma=l/(4.*n)) #高斯濾波  return mask > mask.mean()data = microstructure(l=128) #產生測試圖片dst=morphology.remove_small_objects(data,min_size=300,connectivity=1)fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(8, 4))ax1.imshow(data, plt.cm.gray, interpolation='nearest')ax2.imshow(dst,plt.cm.gray,interpolation='nearest')fig.tight_layout()plt.show()

在此例中,我們將面積小於300的小塊地區刪除(由1變為0),結果如:

4、綜合樣本:閾值分割+閉運算+連通地區標記+刪除小區塊+分色顯示

import numpy as npimport matplotlib.pyplot as pltimport matplotlib.patches as mpatchesfrom skimage import data,filter,segmentation,measure,morphology,color#載入並裁剪硬幣圖片image = data.coins()[50:-50, 50:-50]thresh =filter.threshold_otsu(image) #閾值分割bw =morphology.closing(image > thresh, morphology.square(3)) #閉運算cleared = bw.copy() #複製segmentation.clear_border(cleared) #清除與邊界相連的目標物label_image =measure.label(cleared) #連通地區標記borders = np.logical_xor(bw, cleared) #異或label_image[borders] = -1image_label_overlay =color.label2rgb(label_image, image=image) #不同標記用不同顏色顯示fig,(ax0,ax1)= plt.subplots(1,2, figsize=(8, 6))ax0.imshow(cleared,plt.cm.gray)ax1.imshow(image_label_overlay)for region in measure.regionprops(label_image): #迴圈得到每一個連通地區屬性集    #忽略小地區  if region.area < 100:    continue  #繪製外包矩形  minr, minc, maxr, maxc = region.bbox  rect = mpatches.Rectangle((minc, minr), maxc - minc, maxr - minr,               fill=False, edgecolor='red', linewidth=2)  ax1.add_patch(rect)fig.tight_layout()plt.show()


相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.