1. opencv二值化的cv2.threshold函數
目的:将整幅圖像分成了非黑即白的二值圖像。
1.1 簡單門檻值:
簡單門檻值當然是最簡單,選取一個全局門檻值,然後就把整幅圖像分成了非黑即白的二值圖像了。
函數為cv2.threshold(),這個函數有四個參數,第一個原圖像,第二個進行分類的門檻值,第三個是高于(低于)門檻值時賦予的新值,第四個是一個方法選擇參數,常用的有:
• cv2.THRESH_BINARY(黑白二值)
• cv2.THRESH_BINARY_INV(黑白二值反轉)
• cv2.THRESH_TRUNC (得到的圖像為多像素值)
• cv2.THRESH_TOZERO
• cv2.THRESH_TOZERO_INV
傳回值:該函數有兩個傳回值,第一個retVal(得到的門檻值值(在後面一個方法中會用到)),第二個就是門檻值化後的圖像。
調用例子:
1.2 自适應門檻值
前面看到簡單門檻值是一種全局性的門檻值,隻需要規定一個門檻值值,整個圖像都和這個門檻值比較。而自适應門檻值可以看成一種局部性的門檻值,通過規定一個區域大小,比較這個點與區域大小裡面像素點的平均值(或者其他特征)的大小關系确定這個像素點是屬于黑或者白(如果是二值情況)。使用的函數為: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相當于門檻值 就是求得領域内均值或者權重值)
這種方法理論上得到的效果更好,相當于在動态自适應的調整屬于自己像素點的門檻值,而不是整幅圖像都用一個門檻值。
th2 = cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_MEAN_C,\
cv2.THRESH_BINARY,11,2) #換行符号\
1.3 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會自動找到一個介于兩波峰之間的門檻值。
ret1,th1 = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
#Otsu 濾波
ret2,th2 = cv2.threshold(gray,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
print(ret2)
2. cv2.findContours() 輪廓檢測
函數原型:
此函數參數:
第一個參數是輸入的圖檔;注意輸入的圖檔必須為二值圖檔。若輸入的圖檔為彩色圖檔,必須先進行灰階化和二值化
第二個參數表示輪廓的檢索模式,有四種(本文介紹的都是新的cv2接口):
cv2.RETR_EXTERNAL表示隻檢測外輪廓
cv2.RETR_LIST檢測的輪廓不建立等級關系
cv2.RETR_CCOMP建立兩個等級的輪廓,上面的一層為外邊界,裡面的一層為内孔的邊界資訊。如果内孔内還有一個連通物體,這個物體的邊界也在頂層。
cv2.RETR_TREE建立一個等級樹結構的輪廓。
第三個參數method為輪廓的近似辦法
cv2.CHAIN_APPROX_NONE存儲所有的輪廓點,相鄰的兩個點的像素位置差不超過1,即max(abs(x1-x2),abs(y2-y1))==1
cv2.CHAIN_APPROX_SIMPLE壓縮水準方向,垂直方向,對角線方向的元素,隻保留該方向的終點坐标,例如一個矩形輪廓隻需4個點來儲存輪廓資訊
cv2.CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS使用teh-Chinl chain 近似算法
傳回值:
v2.findContours()函數傳回兩個值,一個是輪廓本身,還有一個是每條輪廓對應的屬性。
示例:
contours:
cv2.findContours()函數首先傳回一個list,list中每個元素(本例為2個)都是圖像中的一個輪廓資訊,list中每個元素(輪廓資訊)類型為ndarray。len(contours[1]) 表示第一個輪廓儲存的元素個數,即該輪廓中儲存的點的個數。本例第一個輪廓為矩形,輪廓中有4個點,這是因為當參數mode 設定成: cv2.CHAIN_APPROX_SIMPLE ,輪廓中并不是存儲輪廓上所有的點,而是隻存儲可以用直線描述輪廓的點的個數,比如一個“正立”的矩形,隻需4個頂點就能描述輪廓了。
print(type(contours)) # 輸出為:<class 'list'>
print(type(contours[0])) # 輸出為:<class 'numpy.ndarray'>
print(len(contours)) # 圖像中輪廓的數量
print(len(contours[1])) # 輪廓1(矩形)中的元素(點)的數量
hierarchy:
該函數還可傳回一個可選的hiararchy結果,這是一個ndarray,其中的元素個數和輪廓個數相同,每個輪廓contours[i]對應4個hierarchy元素hierarchy[i][0] ~hierarchy[i][3],分别表示後一個輪廓、前一個輪廓、父輪廓、内嵌輪廓的索引編号,如果沒有對應項,則該值為負數。
3. 繪制輪廓cv2.drawContours()
原型:
示例:
第一個參數是指明在哪幅圖像上繪制輪廓;
第二個參數是輪廓本身,在Python中是一個list。
第三個參數指定繪制輪廓list中的哪條輪廓,如果是-1,則繪制其中的所有輪廓。後面的參數很簡單。其中thickness表明輪廓線的寬度,如果是-1(cv2.FILLED),則為填充模式。繪制參數将在以後獨立詳細介紹。