Python下opencv使用筆記(四)(映像的閾值處理)

來源:互聯網
上載者:User

標籤:opencv   python   閾值   影像處理   

  • 映像的閾值處理一般使得映像的像素值更單一、映像更簡單。閾值可以分為全域性質的閾值,也可以分為局部性質的閾值,可以是單閾值的也可以是多閾值的。當然閾值越多是越複雜的。下面將介紹opencv下的三種閾值方法。
(一)簡單閾值

簡單閾值當然是最簡單,選取一個全域閾值,然後就把整幅映像分成了非黑即白的二值映像了。函數為cv2.threshold()
這個函數有四個參數,第一個原映像,第二個進行分類的閾值,第三個是高於(低於)閾值時賦予的新值,第四個是一個方法選擇參數,常用的有:
? cv2.THRESH_BINARY(黑白二值)
? cv2.THRESH_BINARY_INV(黑白二值反轉)
? cv2.THRESH_TRUNC (得到的映像為多像素值)
? cv2.THRESH_TOZERO
? cv2.THRESH_TOZERO_INV
該函數有兩個傳回值,第一個retVal(得到的閾值值(在後面一個方法中會用到)),第二個就是閾值化後的映像。
一個執行個體如下:

import cv2import matplotlib.pyplot as pltimg = cv2.imread(‘flower.jpg‘,0) #直接讀為灰階映像ret,thresh1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY)ret,thresh2 = cv2.threshold(img,127,255,cv2.THRESH_BINARY_INV)ret,thresh3 = cv2.threshold(img,127,255,cv2.THRESH_TRUNC)ret,thresh4 = cv2.threshold(img,127,255,cv2.THRESH_TOZERO)ret,thresh5 = cv2.threshold(img,127,255,cv2.THRESH_TOZERO_INV)titles = [‘img‘,‘BINARY‘,‘BINARY_INV‘,‘TRUNC‘,‘TOZERO‘,‘TOZERO_INV‘]images = [img,thresh1,thresh2,thresh3,thresh4,thresh5]for i in range(6):    plt.subplot(2,3,i+1),plt.imshow(images[i],‘gray‘)    plt.title(titles[i])    plt.xticks([]),plt.yticks([])plt.show()


可以看到這裡把閾值設定成了127,對於BINARY方法,當映像中的灰階值大於127的重設像素值為255.

(二)自適應閾值:

前面看到簡單閾值是一種全域性的閾值,只需要規定一個閾值值,整個映像都和這個閾值比較。而自適應閾值可以看成一種局部性的閾值,通過規定一個地區大小,比較這個點與地區大小裡面像素點的平均值(或者其他特徵)的大小關係確定這個像素點是屬於黑或者白(如果是二值情況)。使用的函數為:cv2.adaptiveThreshold()
該函數需要填6個參數:

  • 第一個原始映像
  • 第二個像素值上限
  • 第三個自適應方法Adaptive Method:
    — cv2.ADAPTIVE_THRESH_MEAN_C :領域內均值
    —cv2.ADAPTIVE_THRESH_GAUSSIAN_C :領域內像素點加權和,權 重為一個高斯視窗
  • 第四個值的賦值方法:只有cv2.THRESH_BINARY 和cv2.THRESH_BINARY_INV
  • 第五個Block size:規定領域大小(一個正方形的領域)
  • 第六個常數C,閾值等於均值或者加權值減去這個常數(為0相當於閾值 就是求得領域內均值或者加權值)
    這種方法理論上得到的效果更好,相當於在動態自適應的調整屬於自己像素點的閾值,而不是整幅映像都用一個閾值。

一個執行個體如下:

mport cv2import matplotlib.pyplot as pltimg = cv2.imread(‘flower.jpg‘,0) #直接讀為灰階映像ret,th1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY)th2 = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,11,2) #分行符號號 \th3 = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,11,2) #分行符號號 \images = [img,th1,th2,th3]plt.figure()for i in xrange(4):    plt.subplot(2,2,i+1),plt.imshow(images[i],‘gray‘)plt.show()


可以看到上述視窗大小使用的為11,當視窗越小的時候,得到的映像越細。想想一下,如果把視窗設定足夠大以後(不能超過映像大小),那麼得到的結果可能就和第二幅映像的相同了。

(三)Otsu’s二值化

我們前面說到,cv2.threshold函數是有兩個傳回值的,前面一直用的第二個傳回值,也就是閾值處理後的映像,那麼第一個傳回值(得到映像的閾值)將會在這裡用到。
前面對於閾值的處理上,我們選擇的閾值都是127,那麼實際情況下,怎麼去選擇這個127呢?有的映像可能閾值不是127得到的效果更好。那麼這裡我們需要演算法自己去尋找到一個閾值,而Otsu’s就可以自己找到一個認為最好的閾值。並且Otsu’s非常適合於映像灰階長條圖具有雙峰的情況,他會在雙峰之間找到一個值作為閾值,對於非雙峰映像,可能並不是很好用。那麼經過Otsu’s得到的那個閾值就是函數cv2.threshold的第一個參數了。因為Otsu’s方法會產生一個閾值,那麼函數cv2.threshold的的第二個參數(設定閾值)就是0了,並且在cv2.threshold的方法參數中還得加上語句cv2.THRESH_OTSU。那麼什麼是雙峰映像(只能是灰階映像才有),就是映像的灰階統計圖中可以明顯看出只有兩個波峰,比如下面一個圖的灰階長條圖就可以是雙峰圖:

好了現在對這個圖進行Otsu’s閾值處理就非常的好,通過函數cv2.threshold會自動找到一個介於兩波峰之間的閾值。一個執行個體如下:

import cv2import matplotlib.pyplot as pltimg = cv2.imread(‘finger.jpg‘,0) #直接讀為灰階映像#簡單濾波ret1,th1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY)#Otsu 濾波ret2,th2 = cv2.threshold(img,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)print ret2plt.figure()plt.subplot(221),plt.imshow(img,‘gray‘)plt.subplot(222),plt.hist(img.ravel(),256)#.ravel方法將矩陣轉化為一維plt.subplot(223),plt.imshow(th1,‘gray‘)plt.subplot(224),plt.imshow(th2,‘gray‘)


print ret2 得到的結果為122。可以看出似乎兩個結果並沒有很明顯差別(素材也不太好弄~_~!),主要是兩個閾值(127與122)太相近了,如果這兩個隔得很遠那麼會很明顯的。

著作權聲明:本文為博主原創文章,未經博主允許不得轉載。

Python下opencv使用筆記(四)(映像的閾值處理)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.