1. 程式人生 > >[Python影象處理] 七.影象閾值化處理及演算法對比

[Python影象處理] 七.影象閾值化處理及演算法對比

該系列文章是講解Python OpenCV影象處理知識,前期主要講解影象入門、OpenCV基礎用法,中期講解影象處理的各種演算法,包括影象銳化運算元、影象增強技術、影象分割等,後期結合深度學習研究影象識別、影象分類應用。希望文章對您有所幫助,如果有不足之處,還請海涵~

本篇文章主要講解Python呼叫OpenCV實現影象閾值化處理操作,包括二進位制閾值化、反二進位制閾值化、截斷閾值化、反閾值化為0、閾值化為0。全文均是基礎知識,希望對您有所幫助。 1.閾值化 2.二進位制閾值化 3.反二進位制閾值化 4.截斷閾值化 5.反閾值化為0 6.閾值化為0

PS:文章參考自己以前系列影象處理文章及OpenCV庫函式,同時部分參考網易雲視訊,推薦大家去學習。同時,本篇文章涉及到《計算機圖形學》基礎知識,請大家下來補充。

一. 閾值化

(注:該部分參考作者的論文《基於苗族服飾的影象銳化和邊緣提取技術研究》)

影象的二值化或閾值化(Binarization)旨在提取影象中的目標物體,將背景以及噪聲區分開來。通常會設定一個閾值T,通過T將影象的畫素劃分為兩類:大於T的畫素群和小於T的畫素群。 灰度轉換處理後的影象中,每個畫素都只有一個灰度值,其大小表示明暗程度。二值化處理可以將影象中的畫素劃分為兩類顏色,常用的二值化演算法如公式1所示:

{Y=0gray<TY=255gray>=T\begin{cases} Y=0,gray<T\\ Y=255,gray>=T\\ \end{cases}

當灰度Gray小於閾值T時,其畫素設定為0,表示黑色;當灰度Gray大於或等於閾值T時,其Y值為255,表示白色。 Python OpenCV中提供了閾值函式threshold()實現二值化處理,其公式及引數如下圖所示: retval, dst = cv2.threshold(src, thresh, maxval, type)

常用的方法如下表所示,其中函式中的引數Gray表示灰度圖,引數127表示對畫素值進行分類的閾值,引數255表示畫素值高於閾值時應該被賦予的新畫素值,最後一個引數對應不同的閾值處理方法。
對應OpenCV提供的五張圖如下所示,第一張為原圖,後面依次為:二進位制閾值化、反二進位制閾值化、截斷閾值化、反閾值化為0、閾值化為0。
二值化處理廣泛應用於各行各業,比如生物學中的細胞圖分割、交通領域的車牌設別等。在文化應用領域中,通過二值化處理將所需民族文物影象轉換為黑白兩色圖,從而為後面的影象識別提供更好的支撐作用。下圖表示影象經過各種二值化處理演算法後的結果,其中“BINARY”是最常見的黑白兩色處理。

二. 二進位制閾值化

該方法先要選定一個特定的閾值量,比如127。新的閾值產生規則如下: dst(x,y)={maxValifsrc(x,y)>thresh0otherwise dst(x,y) = \begin{cases} maxVal, if src(x,y)>thresh\\ 0,otherwise\\ \end{cases} (1) 大於等於127的畫素點的灰度值設定為最大值(如8位灰度值最大為255) (2) 灰度值小於127的畫素點的灰度值設定為0 例如,163->255,86->0,102->0,201->255。

關鍵字為 cv2.THRESH_BINARY,完整程式碼如下:

#encoding:utf-8
import cv2  
import numpy as np  

#讀取圖片
src = cv2.imread('test.jpg')

#灰度影象處理
GrayImage = cv2.cvtColor(src,cv2.COLOR_BGR2GRAY)

#二進位制閾值化處理
r, b = cv2.threshold(GrayImage, 127, 255, cv2.THRESH_BINARY)
print r

#顯示影象
cv2.imshow("src", src)
cv2.imshow("result", b)

#等待顯示
cv2.waitKey(0)
cv2.destroyAllWindows()

輸出為兩個返回值,r為127,b為處理結果(大於127設定為255,小於設定為0)。如下圖所示:

三. 反二進位制閾值化

該方法與二進位制閾值化方法相似,先要選定一個特定的灰度值作為閾值,比如127。新的閾值產生規則如下: dst(x,y)={0ifsrc(x,y)>threshmaxValotherwise dst(x,y) = \begin{cases} 0, if src(x,y)>thresh\\ maxVal,otherwise\\ \end{cases} (1) 大於127的畫素點的灰度值設定為0(以8位灰度圖為例) (2) 小於該閾值的灰度值設定為255 例如,163->0,86->255,102->255,201->0。

關鍵字為 cv2.THRESH_BINARY_INV,完整程式碼如下:

#encoding:utf-8
import cv2  
import numpy as np  

#讀取圖片
src = cv2.imread('test.jpg')

#灰度影象處理
GrayImage = cv2.cvtColor(src,cv2.COLOR_BGR2GRAY)

#反二進位制閾值化處理
r, b = cv2.threshold(GrayImage, 127, 255, cv2.THRESH_BINARY_INV)
print r

#顯示影象
cv2.imshow("src", src)
cv2.imshow("result", b)

#等待顯示
cv2.waitKey(0)
cv2.destroyAllWindows()

輸出結果如下圖所示:

該方法得到的結果正好與二進位制閾值化方法相反,亮色元素反而處理為黑色,暗色處理為白色。

四. 截斷閾值化

該方法需要選定一個閾值,影象中大於該閾值的畫素點被設定為該閾值,小於該閾值的保持不變,比如127。新的閾值產生規則如下: dst(x,y)={thresholdifsrc(x,y)>threshsrc(x,y)otherwise dst(x,y) = \begin{cases} threshold, if src(x,y)>thresh\\ src(x,y),otherwise\\ \end{cases} (1) 大於等於127的畫素點的灰度值設定為該閾值127 (2) 小於該閾值的灰度值不改變 例如,163->127,86->86,102->102,201->127。

關鍵字為 cv2.THRESH_TRUNC,完整程式碼如下:

#encoding:utf-8
import cv2  
import numpy as np  

#讀取圖片
src = cv2.imread('test.jpg')

#灰度影象處理
GrayImage = cv2.cvtColor(src,cv2.COLOR_BGR2GRAY)

#截斷閾值化處理
r, b = cv2.threshold(GrayImage, 127, 255, cv2.THRESH_TRUNC)
print r

#顯示影象
cv2.imshow("src", src)
cv2.imshow("result", b)

#等待顯示
cv2.waitKey(0)
cv2.destroyAllWindows()

輸出結果如下圖所示::

該處理方法相當於把影象中比較亮(大於127,偏向於白色)的畫素值處理為閾值。

五. 反閾值化為0

該方法先選定一個閾值,比如127,接著對影象的灰度值進行如下處理: dst(x,y)={0ifsrc(x,y)>threshsrc(x,y)otherwise dst(x,y) = \begin{cases} 0, if src(x,y)>thresh\\ src(x,y),otherwise\\ \end{cases} (1) 大於等於閾值127的畫素點變為0 (2) 小於該閾值的畫素點值保持不變 例如,163->0,86->86,102->102,201->0。

關鍵字為 cv2.THRESH_TOZERO_INV,完整程式碼如下:

#encoding:utf-8
import cv2  
import numpy as np  

#讀取圖片
src = cv2.imread('test.jpg')

#灰度影象處理
GrayImage = cv2.cvtColor(src,cv2.COLOR_BGR2GRAY)

#反閾值化為0處理
r, b = cv2.threshold(GrayImage, 127, 255, cv2.THRESH_TOZERO_INV)
print r

#顯示影象
cv2.imshow("src", src)
cv2.imshow("result", b)

#等待顯示
cv2.waitKey(0)
cv2.destroyAllWindows()

輸出結果如下圖所示:

六. 閾值化為0

該方法先選定一個閾值,比如127,接著對影象的灰度值進行如下處理: dst(x,y)={src(x,y)ifsrc(x,y)>thresh0otherwise dst(x,y) = \begin{cases} src(x,y), if src(x,y)>thresh\\ 0,otherwise\\ \end{cases} (1) 大於等於閾值127的畫素點,值保持不變 (2) 小於該閾值的畫素點值設定為0 例如,163->163,86->0,102->0,201->201。

關鍵字為 cv2.THRESH_TOZERO,完整程式碼如下:

#encoding:utf-8
import cv2  
import numpy as np  

#讀取圖片
src = cv2.imread('test.jpg')

#灰度影象處理
GrayImage = cv2.cvtColor(src,cv2.COLOR_BGR2GRAY)

#閾值化為0處理
r, b = cv2.threshold(GrayImage, 127, 255, cv2.THRESH_TOZERO)
print r

#顯示影象
cv2.imshow("src", src)
cv2.imshow("result", b)

#等待顯示
cv2.waitKey(0)
cv2.destroyAllWindows()

輸出結果如下圖所示:

該演算法把比較亮的部分不變,比較暗的部分處理為0。

完整五個演算法的對比程式碼如下所示:

#encoding:utf-8
import cv2  
import numpy as np  
import matplotlib.pyplot as plt

#讀取影象
img=cv2.imread('test.jpg')
lenna_img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
GrayImage=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)  

#閾值化處理
ret,thresh1=cv2.threshold(GrayImage,127,255,cv2.THRESH_BINARY)  
ret,thresh2=cv2.threshold(GrayImage,127,255,cv2.THRESH_BINARY_INV)  
ret,thresh3=cv2.threshold(GrayImage,127,255,cv2.THRESH_TRUNC)  
ret,thresh4=cv2.threshold(GrayImage,127,255,cv2.THRESH_TOZERO)  
ret,thresh5=cv2.threshold(GrayImage,127,255,cv2.THRESH_TOZERO_INV)

#顯示結果
titles = ['Gray Image','BINARY','BINARY_INV','TRUNC','TOZERO','TOZERO_INV']  
images = [GrayImage, thresh1, thresh2, thresh3, thresh4, thresh5]  
for i in xrange(6):  
   plt.subplot(2,3,i+1),plt.imshow(images[i],'gray')  
   plt.title(titles[i])  
   plt.xticks([]),plt.yticks([])  
plt.show()


#灰度影象處理
GrayImage = cv2.cvtColor(src,cv2.COLOR_BGR2GRAY)

#閾值化為0處理
r, b = cv2.threshold(GrayImage, 127, 255, cv2.THRESH_TOZERO)
print r

titles = ['Source Image','Gray Image','Laplacian Image','Robert Image','Prewitt Image','Sobel Image']  
images = [lenna_img, GrayImage, Laplacian, Robert, Prewitt, Sobel]  
for i in np.arange(6):  
   plt.subplot(3,2,i+1),plt.imshow(images[i],'gray')  
   plt.title(titles[i])  
   plt.xticks([]),plt.yticks([])  
plt.show()

輸出結果如下圖所示:

希望文章對大家有所幫助,如果有錯誤或不足之處,還請海涵。最近經歷的事情太多,有喜有悲,關閉了朋友圈,希望通過不斷學習和寫文章來忘記煩勞,將憂鬱轉換為動力。哎,總感覺自己在感動這個世界,幫助所有人,而自己卻…誰有關心秀璋?晚安。 (By:Eastmount 2018-10-30 晚上10點 https://blog.csdn.net/Eastmount/)