圖像二值化【圖像閾值】簡介:
如果灰度圖像的像素值大於閾值,則為其分配一個值(可以是白色255),否則為其分配另一個值(可以是黑色0)
圖像二值化就是將灰度圖像上的像素值設置為0或255,也就是將整個圖像呈現出明顯的黑白效果的過程。
python代碼層面知識點:
opencv中圖像二值化方法:
- OTSU
- Triangle
- 自動和手動
自適應閾值
1 import cv2 as cv 2 import numpy as np 3 4 #全局閾值 5 def threshold_demo(image): 6 gray = cv.cvtColor(image,cv.COLOR_BGR2GRAY) 7 ret , binary = cv.threshold(gray,127,255,cv.THRESH_BINARY|cv.THRESH_OTSU)
#自適應閾值算法 cv.THRESH_BINARY|CV.THRESH_OTSU 8 print('threshold_value is:',ret) 9 cv.imshow('threshold_demo',binary) 10 11 #局部閾值 12 def local_threshold(image): 13 gray = cv.cvtColor(image,cv.COLOR_BGR2GRAY) 14 # dst = cv.adaptiveThreshold(gray,255,cv.ADAPTIVE_THRESH_GAUSSIAN_C,cv.THRESH_BINARY,25,10) 15 dst = cv.adaptiveThreshold(gray,255,cv.ADAPTIVE_THRESH_MEAN_C,cv.THRESH_BINARY,25,10) 16 cv.imshow('local_threshold',dst) 17 18 #自定義閾值 19 def custom_threshold(image): 20 gray = cv.cvtColor(image,cv.COLOR_BGR2GRAY) #轉化為灰度圖像 [h,w] h行*w列的數組 21 # print('gray:',gray) 22 h , w = gray.shape[:2] 23 m = np.reshape(gray,[1,w*h]) #將gray的圖像(h*w)轉化為[1行,w*h列]的數組 24 # print('m:',m) 25 mean = m.sum() / (w*h) #求整個一維數組平均值 26 print('mean:',mean) 27 ret,binary = cv.threshold(gray,mean,255,cv.THRESH_BINARY_INV) 28 print('ret:',ret) 29 cv.imshow('custom_threshold',binary) 30 31 src = cv.imread('1.jpg') 32 cv.namedWindow('input_image',cv.WINDOW_AUTOSIZE) 33 cv.imshow('input_image',src) 34 35 # threshold_demo(src) 36 # local_threshold(src) 37 custom_threshold(src) 38 39 cv.waitKey(0) 40 cv.destroyAllWindows()
原圖:
threshold_demo(src):
local_threshold(src):
#cv.ADAPTIVE_THRESH_GAUSSIAN_C 局部高斯C方法
#cv.ADAPTIVE_THRESH_MEAN_C 局部平均C方法
custom_threshold(src):
知識點:圖像二值化方法
1、全局閾值
①OpenCV的threshold函數進行全局閾值。其函數原型為:threshold(src, thresh, maxval, type[, dst]) -> retval, dst
src參數 表示輸入灰度圖像(多通道,8位或32位浮點)。
thresh參數 表示對像素值進行分類的閾值 如自定義為127。
maxval參數 它表示閾值最大變量 一般設置為255。
type參數 表示閾值類型。
retval參數 表示返回的閾值。若是全局固定閾值算法,則返回thresh參數值。若是全局自適應閾值算法,則返回自適應計算得出的合適閾值。
dst參數 表示輸出與src相同大小和類型以及相同通道數的圖像。
②type參數 閾值類型這部分參考博客:https://blog.csdn.net/iracer/article/details/49232703 ,寫的很不錯。
閾值類型:
閾值類型圖示:
③type參數單獨選擇上述五種閾值類型時,是固定閾值算法,效果比較差。
此外還有自適應閾值算法:(自適應計算合適的閾值,而不是固定閾值)
比如結合cv.THRESH_OTSU,寫成cv.THRESH_BINARY | cv.THRESH_OTSU。
例子:ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU) #大律法,全局自適應閾值,第二個參數值0可改為任意數字但不起作用。
比如結合cv.THRESH_TRIANGLE,寫成cv.THRESH_BINARY | cv.THRESH_TRIANGLE。
例子:ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_TRIANGLE) #TRIANGLE法,全局自適應閾值,第二個參數值0可改為任意數字但不起作用, cv.THRESH_TRIANGLE適用於單個波峰(如顯微鏡細胞圖像)。
補充:
cv.THRESH_OTSU和cv.THRESH_TRIANGLE也可單獨使用,不一定要寫成和固定閾值算法結合的形式。單獨寫和結合起來寫,都是自適應閾值算法優先。
例子:ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_OTSU) #大律法 ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_TRIANGLE) #TRIANGLE法
局部閾值
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,5,7........ )。
C參數是常數,表示從平均值或加權平均值中減去的數。 通常情況下,這是正值,但也可能為零或負值。當(其他值-均值>C 返回1,否者返回0)
補:在使用平均和高斯兩種算法情況下,通過計算每個像素周圍blockSize x blockSize大小像素塊的加權均值並減去常量C即可得到自適應閾值。如果使用平均的方法,則所有像素周圍的權值相同;
如果使用高斯的方法,則每個像素周圍像素的權值則根據其到中心點的距離通過高斯方程得到。
參考:https://blog.csdn.net/guduruyu/article/details/68059450
3.numpy的reshape函數是給數組一個新的形狀而不改變其數據,
函數原型:reshape(a, newshape, order='C')
a參數 表示需要重新形成的數組(新數組與原數組的數據內容完全一樣)。
newshape參數 表示int或int類型元組(tuple),若為(1, 3),表示生成的新數組是1行3列。
order參數 表表示使用此索引順序讀取a的元素,並使用此索引順序將元素放置到重新形成的數組中。
函數返回值:如果可能的話,這將是一個新的視圖對象; 否則,它會成為副本。
補充:
在全局閾值處理中,我們使用任意值作為閾值。那么,我們如何知道我們選擇的價值是好還是不好?答案是,試錯法。
但考慮雙峰圖像(簡單來說,雙峰圖像是直方圖有兩個峰值的圖像)。對於該圖像,我們可以將這些峰值中間的值近似作為閾值,這就是Otsu二值化的作用。
因此,簡單來說,它會根據雙峰圖像的圖像直方圖自動計算閾值。(對於非雙峰圖像,二值化不准確。)