OpenCV學習之路(六)圖像閾值

在這一章我們將要學習圖像閾值的相關知識,包括簡單閾值,自適應閾值, Otsu’s 二值化 。

簡單閾值

構造函數爲:

cv2.threshold(img,thresh,maxval,type,dst=None)

參數解釋:

  • img是等待進行處理的圖像
  • thresh是一個標記,凡是高於(低於)這個閾值的像素值都會被賦予黑色(或者白色)
  • maxval這個值就是高於或者低於thresh時要賦予的值
  • type這裏控制的是閾值化操作的類型
    • cv2.THRESH_BINARY
    • cv2.THRESH_BINARY_INV
    • cv2.THRESH_TRUNC
    • cv2.THRESH_TOZERO
    • cv2.THRESH_TOZERO_INV
    具體這五種操作有什麼不同,我們還是得用例子來說明。

原圖
在這裏插入圖片描述

ret,mask=cv2.threshold(img,127,255,cv2.THRESH_BINARY_INV)

可以看出cv2.THRESH_BINARY_INV表示小於‘127’的賦值‘255’
在這裏插入圖片描述

ret,mask=cv2.threshold(img,127,255,cv2.THRESH_BINARY)

可以看出cv2.THRESH_BINARY表示大於‘127’的地方賦值‘255’
在這裏插入圖片描述

ret,mask=cv2.threshold(img,127,255,cv2.THRESH_TRUNC)

這個就很迷惑了,第三個參數好像沒用,大於第二個參數都被賦值賦成127了
在這裏插入圖片描述

ret,mask=cv2.threshold(img,127,0,cv2.THRESH_TOZERO)

小於127的全被黑了
在這裏插入圖片描述

ret,mask=cv2.threshold(img,127,0,cv2.THRESH_TOZERO_INV)

大於127的全黑
在這裏插入代碼片

自適應閾值

簡單閾值對整張圖像只有一個閾值,這必然是不精準的,在圖像各個部位光照不同的情況下就會產生很大誤差,這時候我們就需要用自適應閾值。此時的閾值是根據圖像上的 每一個小區域計算與其對應的閾值。

cv2.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C)
  • src:原圖像

  • maxValue:當閾值類型(thresholdType)採用cv2.THRESH_BINARY和cv2.THRESH_BINARY_INV時像素點被賦予的新值

  • adaptiveMethod:自適應閾值的計算方法,包括兩種:

    1. cv2.ADPTIVE_THRESH_MEAN_C:閾值取自相鄰區域的平均值
    2. cv2.ADPTIVE_THRESH_GAUSSIAN_C:閾值取值相鄰區域的加權和,權重爲一個高斯窗口。
  • thresholdType:閾值分割類型,共5種,同cv2.threshold()的閾值分割類型參數

  • blockSize:用來計算閾值的鄰域大小

  • C:常數,adaptiveMethod方法計算出的數值減去這個常數C就爲閾值

import numpy as np
import cv2
img=cv2.imread('D://zopencv//jianpan.jpg',cv2.IMREAD_GRAYSCALE)
mask=cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,11,3)
th1 = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_MEAN_C,\ cv2.THRESH_BINARY,11,2)
th1 = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,\ cv2.THRESH_BINARY,11,2)

cv2.imshow('mask1',th1)
cv2.imshow('mask2,th2)
cv2.waitKey(0)
cv2.destroyAllWindows()

在這裏插入圖片描述

Otsu 二值化

在第一部分中我們提到過 retVal,當我們使用 Otsu 二值化時會用到它。 那麼它到底是什麼呢? 在使用全局閾值時,我們就是隨便給了一個數來做閾值,那我們怎麼知道 我們選取的這個數的好壞呢?答案就是不停的嘗試。如果是一副雙峯圖像(簡 單來說雙峯圖像是指圖像直方圖中存在兩個峯)呢?我們豈不是應該在兩個峯 之間的峯谷選一個值作爲閾值?這就是 Otsu 二值化要做的。簡單來說就是對 一副雙峯圖像自動根據其直方圖計算出一個閾值。(對於非雙峯圖像,這種方法 得到的結果可能會不理想)。 這裏用到到的函數還是 cv2.threshold(),但是需要多傳入一個參數 (flag):cv2.THRESH_OTSU。這時要把閾值設爲 0。然後算法會找到最 優閾值,這個最優閾值就是返回值 retVal。如果不使用 Otsu 二值化,返回的 retVal 值與設定的閾值相等。

ret2,th2 = cv2.threshold(img,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)

很明顯我不咋明白。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章