OpenCV-圖像閾值-簡單閾值、自適應閾值、Otsu’s 二值化


  • 簡單閾值(全局閾值)

  函數:threshold(src, thresh, maxval, type, dst=None),返回兩個值retVal(閾值) 和 threshImg(處理后的圖像)

    函數中四個參數分別是原圖像、閾值、最大值、閾值類型 

  閾值類型一般分為五種: 
    cv2.THRESH_BINARY:大於閾值的部分像素值變為maxval,其他變為0 
    cv2.THRESH_BINARY_INV:大於閾值的部分變為0,其他部分變為最大值 
    cv2.THRESH_TRUNC:大於閾值的部分變為閾值,其余部分不變 
    cv2.THRESH_TOZERO:大於閾值的部分不變,其余部分變為0 
    cv2.THRESH_TOZERO_INV:大於閾值的部分變為0,其余部分不變

 1 import numpy as np  2 import cv2  3 from matplotlib import pyplot as plt  4 
 5 # 讀取灰度圖
 6 img = cv2.imread("../image/sight.jpg", 0)  7 
 8 ret1, thresh1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)  9 ret2, thresh2=cv2.threshold(img, 127, 255, cv2.THRESH_BINARY_INV) 10 ret3, thresh3=cv2.threshold(img, 127, 255, cv2.THRESH_TRUNC) 11 ret4, thresh4=cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO) 12 ret5, thresh5=cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO_INV) 13 
14 titles = ['Original Image','BINARY','BINARY_INV','TRUNC','TOZERO','TOZERO_INV'] 15 images = [img, thresh1, thresh2, thresh3, thresh4, thresh5] 16 for i in range(6): 17     plt.subplot(2,3,i + 1),plt.imshow(images[i], 'gray') 18  plt.title(titles[i]) 19  plt.xticks([]), plt.yticks([]) 20 plt.show()

結果:

  •  自適應閾值

  在前面的部分我們使用是全局閾值,整幅圖像采用同一個數作為閾值。當時這種方法並不適應與所有情況,尤其是當同一幅圖像上的不同部分的具有不同亮度時。這種情況下我們需要采用自適應閾值。此時的閾值是根據圖像上的每一個小區域計算與其對應的閾值。因此在同一幅圖像上的不同區域采用的是不同的閾值,從而使我們能在亮度不同的情況下得到更好的結果。

  adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C, dst=None)
  這種方法需要我們指定六個參數,返回值只有一個。

    • Adaptive Method- 指定計算閾值的方法。
      – cv2.ADPTIVE_THRESH_MEAN_C:閾值取自相鄰區域的平均值
      – cv2.ADPTIVE_THRESH_GAUSSIAN_C:閾值取值相鄰區域的加權和,權重為一個高斯窗口。
    • Block Size - 鄰域大小(用來計算閾值的區域大小)。
    • C - 這就是是一個常數,閾值就等於的平均值或者加權平均值減去這個常數。

代碼:

 1 import numpy as np  2 import cv2  3 from matplotlib import pyplot as plt  4 
 5 # 讀取灰度圖
 6 img = cv2.imread("../image/sight.jpg", 0)  7 
 8 # 中值濾波,用來平滑圖像,去除噪聲
 9 img = cv2.medianBlur(img, 5) 10 
11 # 簡單閾值
12 ret, thresh1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY) 13 
14 # 自適應,閾值取相鄰區域的平均值
15 thresh2 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 2) 16 
17 # 自適應,閾值取值相鄰區域的加權和,權重為一個高斯窗口。
18 thresh3 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2) 19 
20 
21 titles = ['Original Image', 'Global Thresholding (v = 127)', 22 'Adaptive Mean Thresholding', 'Adaptive Gaussian Thresholding'] 23 images = [img, thresh1, thresh2, thresh3] 24 for i in range(4): 25     plt.subplot(2,2,i+1),plt.imshow(images[i],'gray') 26  plt.title(titles[i]) 27  plt.xticks([]),plt.yticks([]) 28 plt.show()

結果:

如果不進行濾波處理,會出現噪聲,如下圖所示:

  •  Otsu’s 二值化

  在使用全局閾值時,只能通過不停的嘗試來確定一個效果比較好的閾值。如果是一副雙峰圖像(簡單來說雙峰圖像是指圖像直方圖中存在兩個峰)呢?我們豈不是應該在兩個峰之間的峰谷選一個值作為閾值?這就是 Otsu 二值化要做的。簡單來說就是對一副雙峰圖像自動根據其直方圖計算出一個閾值。(對於非雙峰圖像,這種方法得到的結果可能會不理想)。 

  函數還是 cv2.threshold(),但是需要多傳入一個參數( flag): cv2.THRESH_OTSU。這時要把閾值設為 0。然后算法會找到最優閾值,這個最優閾值就是返回值 retVal。如果不使用 Otsu 二值化,返回的retVal 值與設定的閾值相等。

  算法分類的原理是讓背景和目標之間的類間方差最大,因為背景和目標之間的類間方差越大,說明構成圖像的兩部分的差別越大,錯分的可能性越小。 

代碼:

import numpy as np import cv2 from matplotlib import pyplot as plt # 讀取灰度圖
img = cv2.imread("../image/girl.jpg", 0) # 全局閾值
ret1, th_img1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY) # Otsu’s 二值化
re2, th_img2 = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) # Otsu’s 二值化之前先對圖像進行高斯濾波處理,平滑圖像,去除噪聲 # (5,5)為高斯核大小,0為標准差
blur = cv2.GaussianBlur(img, (5, 5), 0) re3, th_img3 = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) images = [img, 0, th_img1, img, 0, th_img2, blur, 0, th_img3] titles = ['Original Noisy Image','Histogram','Global Thresholding (v=127)', 'Original Noisy Image','Histogram',"Otsu's Thresholding", 'Gaussian filtered Image','Histogram',"Otsu's Thresholding"] for i in range(3): plt.subplot(3,3,i*3+1),plt.imshow(images[i*3],'gray') plt.title(titles[i*3]), plt.xticks([]), plt.yticks([]) plt.subplot(3,3,i*3+2),plt.hist(images[i*3].ravel(),256) plt.title(titles[i*3+1]), plt.xticks([]), plt.yticks([]) plt.subplot(3,3,i*3+3),plt.imshow(images[i*3+2],'gray') plt.title(titles[i*3+2]), plt.xticks([]), plt.yticks([]) plt.show()

結果: 高斯濾波后在進行二值化處理,會有明顯的去除噪聲的效果。(打印后看到, Otsu’s 二值化自動選取的閾值為122)

 


免責聲明!

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



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