OpenCV---圖像二值化


一:什么是二值圖像

彩色圖像:三個通道0-2550-2550-255,所以可以有2^24位空間

灰度圖像:一個通道0-255,所以有256種顏色

二值圖像:只有兩種顏色,黑和白,1白色,0黑色

二:圖像二值化

(一)先獲取閾值

(二)根據閾值去二值化圖像

(三)OpenCV中的二值化方法

(四)補充閾值類型

原灰度圖像的像素值

1.THRESH_BINARY:過門限的值為最大值,其他值為0

2.THRESH_BINARY_INV:過門限的值為0,其他值為最大值

3.THRESH_TRUNC:過門限的值為門限值,其他值不變

 

4.THRESH_TOZERO:過門限的值不變,其他設置為0

5.THRESH_TOZERO_INV:過門限的值為0,其他不變

三:代碼實現全局閾值

(一)全局閾值使用THRESH_OTSU大津法

def threshold_demo(image):
    gray = cv.cvtColor(image,cv.COLOR_RGB2GRAY)   #要二值化圖像,要先進行灰度化處理
    ret, binary = cv.threshold(gray,0,255,cv.THRESH_BINARY | cv.THRESH_OTSU)
    print("threshold value: %s"%ret)  #打印閾值,前面先進行了灰度處理0-255,我們使用該閾值進行處理,低於該閾值的圖像部分全為黑,高於該閾值則為白色
    cv.imshow("binary",binary)  #顯示二值化圖像 

threshold value: 140.0  #獲取的閾值是140

(二)全局閾值使用THRESH_TRIANGLE(三角形算法)

ret, binary = cv.threshold(gray,0,255,cv.THRESH_BINARY | cv.THRESH_TRIANGLE)

threshold value: 67.0

(三)上面使用大津法和三角形算法都是自動去獲取閾值,下面我們自己直接指定閾值

(1)THRESH_BINARY_INV大於閾值的都為0

ret, binary = cv.threshold(gray,127,255,cv.THRESH_BINARY_INV)

threshold value: 127.0

 (2)THRESH_TRUNC截斷大於127的值都為127

ret, binary = cv.threshold(gray,127,255,cv.THRESH_TRUNC)

(3)THRESH_TOZERO小於閾值的都為0和(1)相反

ret, binary = cv.threshold(gray,127,255,cv.THRESH_TOZERO)

相關知識補充

(1)threshold方法

①OpenC的threshold函數進行全局閾值。其函數原型為:threshold(src, thresh, maxval, type[, dst]) -> retval, dst
src參數表示輸入圖像(多通道,8位或32位浮點)。
thresh參數表示閾值。
maxval參數表示與THRESH_BINARY和THRESH_BINARY_INV閾值類型一起使用設置的最大值。
type參數表示閾值類型。
retval參數表示返回的閾值。若是全局固定閾值算法,則返回thresh參數值。若是全局自適應閾值算法,則返回自適應計算得出的合適閾值。
dst參數表示輸出與src相同大小和類型以及相同通道數的圖像。
②type參數閾值類型這部分參考博客:https://blog.csdn.net/iracer/article/details/49232703  ,寫的很不錯。

 (2)cv.THRESH_OTSU類型

推文:OTSU算法

cv2.threshold函數是有兩個返回值的,

第一個返回值,得到圖像的閾值,
第二個返回值,也就是閾值處理后的圖像,
cv.threshold(gray,0,255,cv.THRESH_BINARY | cv.THRESH_OTSU)  #這是我們自己設置的
我們自己不一定能夠找到一個最好的閾值,去二分化圖像,所以我們需要算法自己去尋找一個閾值,而cv.THRESH_OTSU就可以滿足這個需求,去找到一個最好的閾值。 
注意:他非常適用於圖像灰度直方圖具有雙峰的情況,他會在雙峰之間找到一個值作為閾值,對於非雙峰圖像,可能並不是很好用。
因為cv.THRESH_OTSU方法會產生一個閾值,那么函數cv2.threshold的的第二個參數(設置閾值)就是0(None)了,並且在cv2.threshold的方法參數中還得加上語句cv2.THRESH_OTSU。
這里面第三個參數maxval參數表示與THRESH_BINARY和THRESH_BINARY_INV閾值類型一起使用設置的最大值。
而我們使用的灰度圖像最大則為255,所以設置為255即可

(3)cv.THRESH_TRIANGLE類型(有丟失)適用於單個波峰

推文:圖像處理之三角法圖像二值化

THRESH_OTSU    flag, use Otsu algorithm to choose the optimal threshold value
THRESH_TRIANGLE    flag, use Triangle algorithm to choose the optimal threshold value
    ret, binary = cv.threshold(gray,0,255,cv.THRESH_BINARY | cv.THRESH_TRIANGLE)

(4)cv.THRESH_OTSU類型和cv.THRESH_TRIANGLE類型

THRESH_OTSU和THRESH_TRIANGLE和前面的說到的二值化方法組合使用,好處是不用自己指定thresh值,系統會進行計算並且作為返回值返回。
區別是:
THRESH_OTSU最適用於雙波峰
THRESH_TRIANGLE最適用於單個波峰,最開始用於醫學分割細胞等

四:代碼實現局部閾值(更加清晰)

(一)ADAPTIVE_THRESH_MEAN_C

def local_threshold(image):
    gray = cv.cvtColor(image,cv.COLOR_RGB2GRAY)   #要二值化圖像,要先進行灰度化處理
    dst = cv.adaptiveThreshold(gray,255,cv.ADAPTIVE_THRESH_MEAN_C,cv.THRESH_BINARY,25,10)
    cv.imshow("local_threshold", dst)

 (二)ADAPTIVE_THRESH_GAUSSIAN_C輪廓更加清晰

dst = cv.adaptiveThreshold(gray,255,cv.ADAPTIVE_THRESH_GAUSSIAN_C,cv.THRESH_BINARY,25,10)

相關知識補充

(1)adaptiveThreshold方法

def adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C, dst=None): # real signature unknown; restored from __doc__
OpenCV的adaptiveThreshold函數進行局部閾值。函數原型為:adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C[, dst]) -> dst

src參數表示輸入圖像(8位單通道圖像)。

maxValue參數表示使用 THRESH_BINARY 和 THRESH_BINARY_INV 的最大值.

adaptiveMethod參數表示自適應閾值算法平均 (ADAPTIVE_THRESH_MEAN_C)或高斯(ADAPTIVE_THRESH_GAUSSIAN_C)。 
thresholdType參數表示閾值類型,必須為THRESH_BINARY或THRESH_BINARY_INV的閾值類型。

blockSize參數表示塊大小(奇數且大於1,比如3,57........ )。

C參數是常數,表示從平均值或加權平均值中減去的數。 通常情況下,這是正值,但也可能為零或負值。
在使用平均和高斯兩種算法情況下,通過計算每個像素周圍blockSize x blockSize大小像素塊的加權均值並減去常量C即可得到自適應閾值。
如果使用平均的方法,則所有像素周圍的權值相同;
如果使用高斯的方法,則每個像素周圍像素的權值則根據其到中心點的距離通過高斯方程得到。

五:全局和局部的比較

 六:自己計算閾值

def custom_threshold(image):
    gray = cv.cvtColor(image,cv.COLOR_RGB2GRAY)   #要二值化圖像,要先進行灰度化處理
    h,w=gray.shape[:2]  #求寬高
    m = np.reshape(gray,[1,w*h])  #將圖像轉一維數組,一行,w*h列,轉換維度要保證其size不變
    mean = m.sum() / (w*h)  #求平均值來當做閾值,來分割圖像
    print("mean :",mean)
    ret,binary = cv.threshold(gray,mean,255,cv.THRESH_BINARY)
    cv.imshow("binary",binary) 

 

相關知識補充:

(1)reshape方法

def reshape(a, newshape, order='C'):
numpy的reshape函數是給數組一個新的形狀而不改變其數據,函數原型:reshape(a, newshape, order='C')

a參數表示需要重新形成的原始數組。

newshape參數表示int或int類型元組(tuple),若為(1, 3),表示生成的新數組是1行3列。

order參數表表示使用此索引順序讀取a的元素,並使用此索引順序將元素放置到重新形成的數組中。

函數返回值:如果可能的話,這將是一個新的視圖對象; 否則,它會成為副本。
注意:將圖像轉一維數組,轉換維度要保證其size不變,newshape==》[行,列]一行n列,要保證其容量大小不變

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM