文章目錄
- 前言
- 一、圖像顏色轉換
- 1.HSV顏色空間
- 2.顏色轉換
- 二、灰度化
- 1.最大值法
- 2.平均值法
- 3.加權均值法
- 三、二值化
- 1.全局閾值法
- 1.閾值法(THRESH_BINARY)
- 2.反閾值法(THRESH_BINARY_INV)
- 3.截斷閾值法(THRESH_TRUNC)
- 4.低閾值零處理(THRESH_TOZERO)
- 5.超閾值零處理(THRESH_TOZERO_INV)
- 6.OTSU算法
- 7.代碼展示
- 2.局部閾值法
前言
- 通過今天的學習,我掌握了OpenCV中有關圖像顏色轉換,灰度化,二值化的基本原理和操作方式
一、圖像顏色轉換
- 我們常見的單張圖像,不僅可以用 RGB 顏色空間來描述其色彩信息 ,還可以用 HSV 顏色空間來表示
1.HSV顏色空間
- RGB顏色模型使用紅、綠、藍三原色的強度來表示顏色,是一種加色法模型,即顏色的混合是添加三原色的強度。而HSV顏色空間使用色調(Hue)、飽和度(Saturation)和亮度(Value)三個參數來表示顏色
- HSV顏色空間更加符合人類對顏色的感知方式
- 顏色調整更加直觀,只需要調整色調和飽和度即可完成對圖像顏色的調整
- 在圖像處理中分割某種顏色物體時,只需在HSV空間中限定H的范圍,而無需同時處理R、G、B三個通道的復雜組合,使用更加簡便
2.顏色轉換
- 我們可以將使用RGB顏色模型表示的圖像轉換為灰度圖或者使用HSV顏色空間表示
- cv.cvtColor(img,code)
img = cv.imread('img\cat1.png')
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY) #RBG轉換為灰度圖
hsv = cv.cvtColor(img,cv.COLOR_BGR2HSV) #RBG轉換為HSV
cv.imshow('img',img)
cv.imshow('gray',gray)
cv.imshow('hsv',hsv)
cv.waitKey(0)
cv.destroyAllWindows()
二、灰度化
- 灰度化是圖像處理以及計算機視覺的常用操作,就是將彩色圖像轉換為灰度圖像的過程
- 灰度圖只有一個通道,以下介紹三種方法進行灰度化
1.最大值法
- 顧名思義就是將RBG三通道中的最大值取出作為灰度圖的像素值
img = cv.imread('img\cat1.png')
h,w,_ = img.shape
img1 = np.zeros((h,w),dtype=np.uint8)
for i in range(h):for j in range(w):arr = img[i][j]max_val = max(arr[0],arr[1],arr[2])img1[i][j] = max_val
cv.imshow('img1',img1)
cv.imshow('img',img)
cv.waitKey(0)
cv.destroyAllWindows()
2.平均值法
- 將RBG三通道的像素值取平均值取出作為灰度圖的像素值
img = cv.imread('img\cat1.png')
h,w,_ = img.shape
img1 = np.zeros((h,w),dtype=np.uint8)
for i in range(h):for j in range(w):arr = img[i][j]mean_val = np.uint8(int(img[i][j][0])+int(img[i][j][1])+int(img[i][j][2])//3)img1[i][j] = max_val
cv.imshow('img1',img1)
cv.imshow('img',img)
cv.waitKey(0)
cv.destroyAllWindows()
tips:在之前的章節提到,圖像是uint8類型的數組,使用Numpy的加法是取模運算,使用int函數進行類型轉換可以避免數據溢出
3.加權均值法
- 與均值法類似,只不過為每個通道的像素值加入了權重
img = cv.imread('img\cat1.png')
h,w,_ = img.shape
wr,wg,wb = 0.3,0.5,0.2
img1 = np.zeros((h,w),dtype=np.uint8)
for i in range(h):for j in range(w):val = round(wb*img[i][j][0] + wg*img[i][j][1] + wr*img[i][j][2])img1[i][j] = val
cv.imshow('img1',img1)
cv.imshow('img',img)
cv.waitKey(0)
cv.destroyAllWindows()
三、二值化
- 在對圖像進行灰度化處理后,我們可以進一步對圖像進行二值化操作(也就是二值化的操作對象必須是灰度圖),使得圖像的所有像素值只有兩種值
- 通過二值化處理,能夠幫助我們更好地分析圖像中的形狀、邊緣和輪廓等特征
- 以下介紹幾種常用的二值化處理方法
1.全局閾值法
- 對于整個灰度圖像,只設定一個閾值
1.閾值法(THRESH_BINARY)
- 通過設定一個閾值,將灰度圖中每一個點的像素值與之比較,如果小于閾值則設置為0,否則設置為maxval(需要自定義,通常設定為255)
2.反閾值法(THRESH_BINARY_INV)
- 與閾值法操作相反,即將灰度圖中每一個點的像素值與之比較,如果小于閾值則設置為maxval,否則設置為0
3.截斷閾值法(THRESH_TRUNC)
- 該方法將灰度圖中每一個點的像素值與閾值比較,大于閾值的設置為閾值,否則不改變
4.低閾值零處理(THRESH_TOZERO)
- 該方法將灰度圖中每一個點的像素值與閾值比較,低于閾值設置為0,否則不變
5.超閾值零處理(THRESH_TOZERO_INV)
- 該方法將灰度圖中每一個點的像素值與閾值比較,低于閾值不變,高于閾值設置為0
6.OTSU算法
- 該算法較為特殊,不是單純的閾值方法,通常它會結合
THRESH_BINARY
或THRESH_BINARY_INV
- OTSU算法是通過一個值將這張圖分前景色和背景色(也就是灰度圖中小于這個值的是一類,大于這個值的是一類。例如,如果你設置閾值為128,則所有大于128的像素點可以被視作前景,而小于等于128的像素點則被視為背景。
- 該算法將自動計算閾值
- OTSU算法就是在灰度圖的像素值范圍內遍歷閾值T,使得g((類間方差))最大,基本上雙峰圖片的閾值T在兩峰之間的谷底
7.代碼展示
img = cv.imread('img\cat1.png')
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)_,binary = cv.threshold(gray,thresh=150,maxval=255,type=cv.THRESH_BINARY) #閾值法
_,binary_inv = cv.threshold(gray,thresh=150,maxval=255,type=cv.THRESH_BINARY_INV) #反閾值法
_,binary_tru = cv.threshold(gray,thresh=150,maxval=255,type=cv.THRESH_TRUNC) #截斷閾值法
_,binary_zero = cv.threshold(gray,thresh=150,maxval=255,type=cv.THRESH_TOZERO) #低閾值零處理
_,binary_zero_inv = cv.threshold(gray,thresh=150,maxval=255,type=cv.THRESH_TOZERO_INV) #超閾值零處理
_,otsu = cv.threshold(gray,thresh=150,maxval=255,type=cv.THRESH_OTSU) #OTSU閾值法,默認結合閾值法
adapt = cv.adaptiveThreshold(gray,255,cv.ADAPTIVE_THRESH_MEAN_C,cv.THRESH_BINARY,3,10)
adapt_guass = cv.adaptiveThreshold(gray,255,cv.ADAPTIVE_THRESH_GAUSSIAN_C,cv.THRESH_BINARY,3,10)
cv.imshow('gray',binary)
cv.imshow('gray1',binary_inv)
cv.imshow('gray2',binary_tru)
cv.imshow('gray3',binary_zero)
cv.imshow('gray4',binary_zero_inv)
cv.imshow('otsu',otsu)
cv.imshow('adapt',adapt)
cv.imshow('adapt',adapt_guass)
cv.imshow('img',img)
cv.waitKey(0)
cv.destroyAllWindows()
2.局部閾值法
-
當圖片呈現出明暗分布不均勻的時候,如果繼續使用全局閾值法可能導致結果不夠準確,這時候我們可以使用自適應二值化的方法,對每一個像素點計算一個閾值,在結合普通的閾值法或反閾值法即可得到更加準確的結果
-
cv2.adaptiveThreshold(image_np_gray, maxval, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 7, 10)
-
maxval
:最大閾值,一般為255 -
adaptiveMethod
:小區域閾值的計算方式: -
thresholdType
:二值化方法,只能使用THRESH_BINARY、THRESH_BINARY_INV,也就是閾值法和反閾值法 -
blockSize
:選取的小區域的面積,如7就是7*7的小塊。 -
c
:最終閾值等于小區域計算出的閾值再減去此值 -
ADAPTIVE_THRESH_MEAN_C
:小區域內取均值 -
- 該方法使用指定大小的區域,計算區域內像素點的均值
- 該方法使用指定大小的區域,計算區域內像素點的均值
adapt = cv.adaptiveThreshold(gray,255,cv.ADAPTIVE_THRESH_MEAN_C,cv.THRESH_BINARY,3,10)
ADAPTIVE_THRESH_GAUSSIAN_C
:小區域內加權求和,權重是個高斯核-
- 該方法對指定大小區域內像素求加權均值,權重來自高斯分布
-
- 在opencv里,當kernel(小區域)的尺寸為1、3、5、7并且用戶沒有設置sigma的時候(sigma <= 0),核值就會取固定的系數,這是一種默認的值是高斯函數的近似
- 在opencv里,當kernel(小區域)的尺寸為1、3、5、7并且用戶沒有設置sigma的時候(sigma <= 0),核值就會取固定的系數,這是一種默認的值是高斯函數的近似
-
- 比如kernel的尺寸為3*3時,使用
[ 0.25 0.5 0.25 ] × [ 0.25 0.5 0.25 ] \left[\begin{array}{c}{{0.25}}\\ {{0.5}}\\ {{0.25}}\end{array}\right]\times\left[0.25~~~~0.5~~~~0.25\right] ?0.250.50.25? ?×[0.25????0.5????0.25]
進行矩陣的乘法,就會得到如下的權重值,其他的類似。
k e r n e l = [ 0.0625 0.125 0.0625 0.125 0.25 0.125 0.0625 0.125 0.0625 ] kernel=\left[\begin{array}{c}{{0.0625~~~0.125~~~0.0625}}\\{{0.125~~~~0.25~~~~0.125}}\\ {{0.0625~~~0.125~~~0.0625}} \end{array}\right] kernel= ?0.0625???0.125???0.06250.125????0.25????0.1250.0625???0.125???0.0625? ?
通過這個高斯核,即可對圖片中的每個像素去計算其閾值,并將該閾值減去固定值得到最終值
- 比如kernel的尺寸為3*3時,使用
adapt_guass = cv.adaptiveThreshold(gray,255,cv.ADAPTIVE_THRESH_GAUSSIAN_C,cv.THRESH_BINARY,3,10)
tips:使用高斯核可以降低噪聲對二值化的干擾,因為通常噪聲原理所選定的區域,對應的權重較小,對最終結果的影響也就越小
THE END