【CV】基于阈值处理的图像分割算法!
圖像處理
Author:louwill
Machine Learning Lab
基于閾值的圖像分割因其處理直觀、實現簡單和計算速度快,是一種更為常用的傳統圖像分割算法。本文基于圖像灰度閾值處理的基本原理,對全局閾值處理方法和大津法進行介紹,并用一些圖像實例進行展示。
灰度閾值基礎
給定灰度圖像,假設該圖像有目標物體和背景像素所構成,現在要從圖像中提取目標物體,一個最為直接的方法就是使用一個固定閾值將目標物體像素與背景像素分開,以區域為目標物體區域,否則為背景區域。
那么什么樣的圖像容易用閾值法進行分割呢?簡單來說,就是目標區域與背景區域具有較大圖像灰度差異時,用閾值法分割效果可能會比較好。這種較大的圖像灰度差異體現到圖像直方圖上時,就呈現處圖像灰度直方圖雙峰的特征。如圖1所示。
圖1 雙峰圖像直方圖
圖像使用閾值分割方法取得好的分割效果取決于如下關鍵因素:
直方圖波峰之間的間隔;
圖像的噪聲情況;
目標物體和背景的相對尺寸;
圖像光源的均勻性;
圖像反射的均勻性。
全局閾值處理
當圖像中存在較大的灰度變化時,使用全局閾值處理的方法一般就能夠取得較好的效果。但我們仍希望對于一幅圖像,能夠找到一個相對合理的閾值來作為全局閾值。因而就有迭代的閾值圖像分割算法。算法流程如下:
初始化全局閾值
基于分割該圖像,產生兩組像素:由灰度值大于的像素組成,由灰度值小于等于的像素組成
對和像素分別計算平均灰度值和
計算一個新的閾值
重復第2到第4步,直到連續迭代中的值間的差小于一個預定的參數為止。
下面來看一個使用全局閾值的圖像分割例子。直接讀入圖像,先基于Numpy進行灰度化和二值化處理。
img?=?cv2.imread('./harden.png') #?灰度化 y?=?0.2126*img[:,:,2]?+?0.7152*img[:,:,1]?+?0.0722*img[:,:,0] img[:,:,0]?=?y img[:,:,1]?=?y img[:,:,2]?=?y #?以128為閾值進行二值化 y[y>=128]?=?255 y[y<128]?=?0 img[:,:,0]?=?y img[:,:,1]?=?y img[:,:,2]?=?y plt.imshow(img);原圖和分割效果分別如圖2和3所示。
圖2?原圖
圖3 全局閾值分割效果圖
opencv也提供了全局閾值的分割方法,處理代碼如下:
import?cv2 import?numpy?as?np from?matplotlib?import?pyplot?as?plt img?=?cv2.imread('harden.png',?0) img?=?cv2.cvtColor(img,?cv2.COLOR_BGR2RGB) ret,?thresh1?=?cv2.threshold(img,?128,?255,?cv2.THRESH_BINARY) plt.imshow(thresh1);分割效果如圖4所示。
圖4 opencv閾值法分割
大津法(OTSU)
基于閾值的圖像二值化方法的一個關鍵在于如何選定閾值,這可以視作為一個全局尋優問題。大津法也即OTSU法,是由日本學者大津展之于1979年提出的一種圖像閾值分割方法。該方法將閾值劃分視作是一個統計決策問題,其目的在于將像素分配給兩組或多組的過程中使得引入的平均誤差最小。大津法給出的方案是使得兩組之間的類間方差最大時的閾值為最優閾值。所以大津法也叫最大類間方差法。
先來看一下大津法的基本原理。假設劃分閾值為,小于閾值的像素區域為,大于閾值的像素區域為。和分別為被閾值分開的兩類像素占總像素的比值。和分別為這兩個類像素均值,和分別為這兩個類中像素值的方差。
圖像的類內方差和類間方差為:
圖像的整體方差為:
圖像的可分離度定義為:
最大化圖像分離度即可,所以使得:
最大化即可。
基于NumPy的大津法實現例子如下代碼所示。
img?=?cv2.imread('./harden.png') img?=?img.astype(np.float) H,?W,?C?=?img.shape #?灰度化 out?=?0.2126*img[:,:,2]?+?0.7152*img[:,:,1]?+?0.0722*img[:,:,0] out?=?out.astype(np.uint8) #?初始化類間方差和最佳閾值 max_sigma?=?0 max_t?=?0#?遍歷迭代 for?_t?in?range(1,?255):#?小于閾值t的類v0v0?=?out[np.where(out<_t)]#?計算v0均值M0?=?np.mean(v0)?if?len(v0)?>?0?else?0.#?v0類像素占比w0?=?len(v0)/(H*W)#?大于閾值t的類v1v1?=?out[np.where(out>=_t)]#?計算v1均值M1?=?np.mean(v1)?if?len(v1)?>?0?else?0.#?v1類像素占比w1?=?len(v1)/(H*W)#?類間方差Sb2?=?w0*w1*((M0-M1)**2)#?尋優if?Sb2?>?max_sigma:max_sigma?=?Sb2max_t?=?_t#?打印最佳閾值???????? print(max_t)通過大津法尋優可知示例圖片的最佳劃分閾值為。然后以為閾值進行二值化。效果如圖5所示。
圖5?大津法閾值分割
opencv中直接提供了大津法的實現方法,如下代碼所示。
img?=?cv2.imread('./harden.png') #?灰度化 img?=?cv2.cvtColor(img,?cv2.COLOR_BGR2GRAY) #?大津法閾值化處理 ret,?th?=?cv2.threshold(img,?0,?255,?cv2.THRESH_BINARY+cv2.THRESH_OTSU) plt.imshow(th);小結
本文對基于閾值的圖像分割方法進行了簡單的介紹,并給出了相應的圖像實例。基于閾值的圖像分割方法簡單直接,計算速度快,在圖像灰度差異較大的情況下,是首選的分割方法。但閾值分割方法本身也存在抗噪能力弱、使用條件嚴格等缺點,所以往往會配合圖像濾波去噪等方法一起使用。
? ?參考資料
? ? [1]?數字圖像處理第四版
? ? [2]?https://opencv24-python-tutorials.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_thresholding/py_thresholding.html
本站qq群851320808,加入微信群請掃碼:
總結
以上是生活随笔為你收集整理的【CV】基于阈值处理的图像分割算法!的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【推荐系统】基于图嵌入技术的推荐系统长文
- 下一篇: mac下终端命令行下添加mysql命令