基於Python的圖像閾值化分割(迭代法)
1.閾值化分割原理
經過對圖像的灰度直方圖進行數學統計,選擇一個或多個閾值將像素劃分爲若干類。通常狀況下,當圖像由灰度值相差較大的目標和背景組成時,若是目標區域內部像素灰度分佈均勻一致,背景區域像素在另外一個灰度級上也分佈均勻,這時圖像的灰度直方圖會呈現出雙峯特性。
在這種狀況下,選取位於這兩個峯值中間的谷底對應的灰度值T做爲灰度閾值,將圖像中各個像素的灰度值與這個閾值進行比較,根據比較的結果將圖像中的像素劃分到兩個類中。像素灰度值大於閾值T的像素點歸爲一類,其他像素點歸爲另外一類。經閾值化處理後的圖像g(x,y)定義爲:
python
其中f(x,y)爲原圖像,T爲灰度閾值,g(x,y)爲分割後產生的二值圖像。算法
2.算法流程圖
3.代碼實現
from PIL import Image import matplotlib.pyplot as plt import numpy as np #讀入圖片並轉化爲矩陣 img = plt.imread('2.jpg') im = np.array(img) # 矩陣大小 l = len(im) w = len(im[0]) #求初始閾值 zmin = np.min(im) zmax = np.max(im) t0 = int((zmin+zmax)/2) #初始化相關變量初始化 t1=0 res1=0 res2=0 s1=0 s2=0 #迭代法計算最佳閾值 while abs(t0-t1)>0: for i in range(0,l-1): for j in range(0,w-1): if im[i,j]<t0: res1=res1+im[i,j] s1=s1+1 elif im[i,j]>t0: res2=res2+im[i,j] s2=s2+1 avg1=res1/s1 avg2=res2/s2 res1 = 0 res2 = 0 s1 = 0 s2 = 0 t1 = t0 #舊閾值儲存在t1中 t0=int((avg1+avg2)/2) #計算新閾值 #閾值化分割 #像素點灰度值小於最佳閾值t0用0填充,其他用255填充 im = np.where(im[...,:] < t0, 0, 255) #繪製原圖窗口 plt.figure() plt.imshow(img , cmap='gray') plt.title('original') #繪製原圖直方圖並顯示最佳閾值 plt.figure() plt.hist(img.ravel(),256) plt.title('hist') plt.axvline(t0) #繪製最佳閾值分割線 plt.text(25, 6100, "Best Threshold:{}".format(t0), size = 15, alpha = 0.8) #繪製閾值化分割後圖像 plt.figure() plt.imshow(Image.fromarray(im) , cmap='gray') plt.title('new') #繪製閾值化分割後圖像的直方圖 plt.figure() plt.hist(im.ravel(),256) plt.title('hist') plt.show()
4.閾值化分割結果
原始圖像
原始圖像直方圖
閾值化分割後圖像
閾值化分割後圖像直方圖
spa