文章目錄
QQ:3020889729 小蔡
講解目的展示
(以上展示代碼是後邊實例的整合——簡單的把彩色/灰度圖像放在不同的數組中,然後遍歷即可)
在圖像處理中,常常對圖像進行特徵處理,而閾值也是圖像的特徵屬性——每一個像素對應着一定的數據——灰度圖像爲8位的強度數據,彩色圖像爲32位的BGR數據。
生活中我們其實在處理問題時經常用到閾值處理——比如:多個裁判評分去掉最低分和最高分,再計算實際數據。比如,一個公司在起步階段,需要一部分技術人員——只有超過預期能力纔會被選擇,否則就是被排除掉——當然,我的比喻可能不太對,但是呢,就是想希望這樣能讓你明白——opencv他也是這樣工作的,至於一些特殊的閾值比較方式就是opencv爲了解決問題所應用設計的了。
閾值函數——cv.threshold應用圖像閾值操作
函數參數簡介
輸入參數如下:
def threshold(src, thresh, maxval, type, dst=None): # real signature unknown; restored from __doc__
- 輸入圖像——受後邊的type影響——灰度圖像總適用,彩色圖像就不一定了
- 閾值
- 滿足閾值的最大輸出值
- 閾值類型——或者說,選擇一種閾值判定方法
- 最後是輸出——默認返回接受即可,不用設置的
輸出參數:
- 第一個參數爲設置的閾值
- 第二個參數爲閾值處理後的圖像
下面提一下閾值類型,我覺得很有必要——
閾值類型基本介紹
這些類型都跟實際需要的情況相關——自由選擇(一般選擇前5種,末尾支持的兩種可以作爲添加條件,補充閾值操作)。
需要知道的是,前五種除了應用灰度圖像外,也滿足彩色圖像——而最後兩種僅僅是二值操作,所以就只適用8位的灰度圖像了——即對強度數據進行閾值操作。
以下類型解釋——以表達式爲準,文字僅僅作爲參考和促進理解。
-
這個閾值類型指的是——當輸入圖像大於我們設置的閾值時,就把對應像素數據設置爲最大值,否則爲0。 -
這個閾值類型與上一個相反——當輸入圖像大於我們設置的閾值時,就把對應像素數據設置爲0,否則爲最大值。 -
這個閾值類型指——當輸入圖像大於我們設置的閾值時,就把對應像素數據設置爲我們設置的值(maxvalue),否則爲圖像本身的值。 -
這個閾值類型指——當輸入圖像大於我們設置的閾值時,就把對應像素數據保留,否則爲0。 -
這個閾值類型指——當輸入圖像大於我們設置的閾值時,就把對應像素數據設置爲0,否則爲原始數據。 -
Python: cv.THRESH_MASK——不支持——這個不多說明,因爲我知道的也是不多,後邊有機會補正。
-
Python: cv.THRESH_OTSU——不支持32位的彩色圖像, 僅僅支持8位灰度圖像
-
Python: cv.THRESH_TRIANGLE——不支持32位的彩色圖像, 僅僅支持8位灰度圖像
代碼實例
灰度圖像實例
import cv2 as cv
img = cv.imread('../imag_in_save/images.png')
img_gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) # 這樣可以獲得灰度圖像
# 也可以用img = cv.imread('../imag_in_save/images.png', 0)直接獲得
# 我是爲了最後邊的樣例做灰度變化和彩色變化對比做的準備操作的——即程序保留有彩色圖像的數據
ret1, thresh1 = cv.threshold(img_gray, 127, 255, cv.THRESH_BINARY) # src(x,y) > 127 => dst(輸出)(x,y) = 255
cv.imshow('imag', img)
cv.imshow('imag3', thresh1) # 輸出閾值處理的圖像
cv.waitKey(0) # 等待按鍵輸入
cv.destroyAllWindows()
效果:
原圖
遍歷(灰度)所有情況——所有閾值類型效果展示(以及代碼)
import cv2 as cv
if __name__ == "__main__":
img = cv.imread('../imag_in_save/images.png')
img_gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
# 依次遍歷轉換——可以直接使用list,但是我爲了展示就獨立寫了
ret1, thresh1 = cv.threshold(img_gray, 127, 255, cv.THRESH_BINARY) # 滿足閾值設置255(我們設置的最大值)反之爲0
ret2, thresh2 = cv.threshold(img_gray, 127, 255, cv.THRESH_BINARY_INV) # 滿足閾值設置0,反之255
ret3, thresh3 = cv.threshold(img_gray, 127, 255, cv.THRESH_MASK) # 順便演示一下,具體該用在哪些地方,後邊遇到了回來修正
ret4, thresh4 = cv.threshold(img_gray, 127, 255, cv.THRESH_OTSU) # 使用otus算法取最優閾值_只適合灰度圖像(文末說明,篇幅)
ret5, thresh5 = cv.threshold(img_gray, 127, 255, cv.THRESH_TOZERO) # 滿足保留原數據,否則爲0,與設置的最值255無關了
ret6, thresh6 = cv.threshold(img_gray, 127, 255, cv.THRESH_TOZERO_INV) # 與THRESH_TOZERO相反
ret7, thresh7 = cv.threshold(img_gray, 127, 255, cv.THRESH_TRIANGLE) # 使用三角算法取最優閾值_只適合灰度圖像(文末說明,篇幅)
ret8, thresh8 = cv.threshold(img_gray, 127, 255, cv.THRESH_TRUNC) # 滿足閾值設置255,反之保留原數據
title = ['THRESH_BINARY', 'THRESH_BINARY_INV', 'THRESH_MASK', 'THRESH_OTSU', 'THRESH_TOZERO', 'THRESH_TOZERO_INV',
'THRESH_TRIANGLE', 'THRESH_TRUNC']
img_list = [thresh1, thresh2, thresh3, thresh4, thresh5, thresh6, thresh7, thresh8]
# 字體顏色根據圖像本身來傳入對應的數據類型——彩色爲三元元組
# 灰度圖像——傳入強度即可
for i in range(0, 8): # 往圖片上寫文字——即使用的閾值類型
cv.putText(img_list[i], title[i], (25, 60), cv.FONT_HERSHEY_COMPLEX_SMALL, 1, 220, 2, cv.LINE_AA)
i = 0
while True: # 遍歷展示
cv.imshow('imag', img_list[i])
k = cv.waitKey(1000) & 0xFF
if k == 27:
break
i += 1
if i == 8:
i = 0
cv.destroyAllWindows()
彩色圖像的實例(類似灰度,只是閾值類型少了兩項)
實現還是和之前的灰度圖像的閾值操作一般無二。
import cv2 as cv
if __name__ == "__main__":
img = cv.imread('../imag_in_save/images.png')
ret1, thresh1 = cv.threshold(img, 127, 255, cv.THRESH_BINARY) # 滿足閾值設置255(我們設置的最大值)反之爲0
cv.imshow('imag', img)
cv.imshow('imag_THRESH_BINARY', thresh1)
cv.waitKey(0)
cv.destroyAllWindows()
效果:在實現效果中去體會參數變化會更直接些。
原圖
遍歷(灰度)所有情況——所有閾值類型效果展示(以及代碼)
import cv2 as cv
if __name__ == "__main__":
img = cv.imread('../imag_in_save/images.png')
ret1, thresh1 = cv.threshold(img, 127, 255, cv.THRESH_BINARY) # 滿足閾值設置255(我們設置的最大值)反之爲0
ret2, thresh2 = cv.threshold(img, 127, 255, cv.THRESH_BINARY_INV)
ret3, thresh3 = cv.threshold(img, 127, 255, cv.THRESH_MASK) # 順便演示一下
ret4, thresh4 = cv.threshold(img, 127, 255, cv.THRESH_TOZERO)
ret5, thresh5 = cv.threshold(img, 127, 255, cv.THRESH_TOZERO_INV) # 與THRESH_TOZERO相反
ret6, thresh6 = cv.threshold(img, 127, 255, cv.THRESH_TRUNC)
title = ['THRESH_BINARY', 'THRESH_BINARY_INV', 'THRESH_MASK', 'THRESH_TOZERO', 'THRESH_TOZERO_INV', 'THRESH_TRUNC']
img_list = [thresh1, thresh2, thresh3, thresh4, thresh5, thresh6]
# 字體顏色根據圖像本身來傳入對應的數據類型——彩色爲三元元組
# 灰度圖像——傳入強度即可
for i in range(0, 6): # 往圖片上寫文字——即使用的閾值類型
cv.putText(img_list[i], title[i], (25, 60), cv.FONT_HERSHEY_COMPLEX_SMALL, 1, (40, 180, 80), 2, cv.LINE_AA)
i = 0
while True: # 遍歷展示
cv.imshow('imag', img_list[i])
k = cv.waitKey(1200) & 0xFF
if k == 27:
break
i += 1
if i == 6:
i = 0
cv.destroyAllWindows()
效果:
補充:OTSU算法作用過程的簡介
這次講解就到這裏了——希望能幫助到你哪怕一點。後期有應用,我會補充這一章節的實踐操作部分。(前邊寫的文章我也會慢慢積累,然後進行修改訂正的。)