1. 程式人生 > 程式設計 >Python使用Opencv實現邊緣檢測以及輪廓檢測的實現

Python使用Opencv實現邊緣檢測以及輪廓檢測的實現

邊緣檢測

Canny邊緣檢測器是一種被廣泛使用的演算法,並被認為是邊緣檢測最優的演算法,該方法使用了比高斯差分演算法更復雜的技巧,如多向灰度梯度和滯後閾值化。

Canny邊緣檢測器演算法基本步驟:

  • 平滑影象:通過使用合適的模糊半徑執行高斯模糊來減少影象內的噪聲。
  • 計算影象的梯度:這裡計算影象的梯度,並將梯度分類為垂直、水平和斜對角。這一步的輸出用於在下一步中計算真正的邊緣。
  • 非最大值抑制:利用上一步計算出來的梯度方向,檢測某一畫素在梯度的正方向和負方向上是否是區域性最大值,如果是,則抑制該畫素(畫素不屬於邊緣)。這是一種邊緣細化技術,用最急劇的變換選出邊緣點。
  • 用滯後閾值化選擇邊緣:最後一步,檢查某一條邊緣是否明顯到足以作為最終輸出,最後去除所有不明顯的邊緣。

Opencv使用Canny邊緣檢測相對簡單,程式碼如下:

import cv2
import numpy as np

img = cv2.imread("hammer.jpg",0)
cv2.imwrite("canny.jpg",cv2.Canny(img,200,300))
cv2.imshow("canny",cv2.imread("canny.jpg"))
cv2.waitKey()
cv2.destroyAllWindows()

執行結果:

這裡寫圖片描述

Canny函式的原型為

cv2.Canny(image,threshold1,threshold2[,edges[,apertureSize[,L2gradient ]]]) 

必要引數:
第一個引數是需要處理的原影象,該影象必須為單通道的灰度圖;
第二個引數是滯後閾值1;
第三個引數是滯後閾值2。

輪廓檢測

輪廓檢測主要由cv2.findContours函式實現的。
函式的原型為

cv2.findContours(image,mode,method[,contours[,hierarchy[,offset ]]]) 

函式引數
第一個引數是尋找輪廓的影象;

第二個引數表示輪廓的檢索模式,有四種(本文介紹的都是新的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和cv2.CHAIN_APPROX_TC89_KCOS都是使用teh-Chinl chain近似演算法。

返回值

如:image,contours,hier = cv2.findContours(thresh,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)

image:是原影象

contours:影象的輪廓,以列表的形式表示,每個元素都是影象中的一個輪廓。

hier:相應輪廓之間的關係。這是一個ndarray,其中的元素個數和輪廓個數相同,每個輪廓contours[i]對應4個hierarchy元素hierarchy[i][0] ~hierarchy[i][3],分別表示後一個輪廓、前一個輪廓、父輪廓、內嵌輪廓的索引編號,如果沒有對應項,則該值為負數。

原圖:

這裡寫圖片描述

示例一

import cv2
import numpy as np

img = cv2.pyrDown(cv2.imread("hammer.jpg",cv2.IMREAD_UNCHANGED))
# threshold 函式對影象進行二化值處理,由於處理後圖像對原影象有所變化,因此img.copy()生成新的影象,cv2.THRESH_BINARY是二化值
ret,thresh = cv2.threshold(cv2.cvtColor(img.copy(),cv2.COLOR_BGR2GRAY),127,255,cv2.THRESH_BINARY)
# findContours函式查詢影象裡的圖形輪廓
# 函式引數thresh是影象物件
# 層次型別,引數cv2.RETR_EXTERNAL是獲取最外層輪廓,cv2.RETR_TREE是獲取輪廓的整體結構
# 輪廓逼近方法
# 輸出的返回值,image是原影象、contours是影象的輪廓、hier是層次型別
image,cv2.CHAIN_APPROX_SIMPLE)

for c in contours:
  # 輪廓繪製方法一
  # boundingRect函式計算邊框值,x,y是座標值,w,h是矩形的寬和高
  x,y,w,h = cv2.boundingRect(c)
  # 在img影象畫出矩形,(x,y),(x + w,y + h)是矩形座標,(0,0)設定通道顏色,2是設定線條粗度
  cv2.rectangle(img,(x,y + h),(0,0),2)

  # 輪廓繪製方法二
  # 查詢最小區域
  rect = cv2.minAreaRect(c)
  # 計算最小面積矩形的座標
  box = cv2.boxPoints(rect)
  # 將座標規範化為整數
  box = np.int0(box)
  # 繪製矩形
  cv2.drawContours(img,[box],255),3)

  # 輪廓繪製方法三
  # 圓心座標和半徑的計算
  (x,radius = cv2.minEnclosingCircle(c)
  # 規範化為整數
  center = (int(x),int(y))
  radius = int(radius)
  # 勾畫圓形區域
  img = cv2.circle(img,center,radius,2)

# # 輪廓繪製方法四
# 圍繞圖形勾畫藍色線條
cv2.drawContours(img,-1,(255,2)
# 顯示影象
cv2.imshow("contours",img)
cv2.waitKey()
cv2.destroyAllWindows()

執行結果如圖所示:

這裡寫圖片描述

示例二

import cv2
import numpy as np

img = cv2.pyrDown(cv2.imread("hammer.jpg",cv2.IMREAD_UNCHANGED))
ret,cv2.CHAIN_APPROX_SIMPLE)
# 建立新的影象black
black = cv2.cvtColor(np.zeros((img.shape[1],img.shape[0]),dtype=np.uint8),cv2.COLOR_GRAY2BGR)


for cnt in contours:
  # 輪廓周長也被稱為弧長。可以使用函式 cv2.arcLength() 計算得到。這個函式的第二引數可以用來指定物件的形狀是閉合的(True) ,還是開啟的(一條曲線)
  epsilon = 0.01 * cv2.arcLength(cnt,True)
  # 函式approxPolyDP來對指定的點集進行逼近,cnt是影象輪廓,epsilon表示的是精度,越小精度越高,因為表示的意思是是原始曲線與近似曲線之間的最大距離。
  # 第三個函式引數若為true,則說明近似曲線是閉合的,它的首位都是相連,反之,若為false,則斷開。
  approx = cv2.approxPolyDP(cnt,epsilon,True)
  # convexHull檢查一個曲線的凸性缺陷並進行修正,引數cnt是影象輪廓。
  hull = cv2.convexHull(cnt)
  # 勾畫影象原始的輪廓
  cv2.drawContours(black,[cnt],2)
  # 用多邊形勾畫輪廓區域
  cv2.drawContours(black,[approx],2)
  # 修正凸性缺陷的輪廓區域
  cv2.drawContours(black,[hull],2)
# 顯示影象
cv2.imshow("hull",black)
cv2.waitKey()
cv2.destroyAllWindows()

執行結果如圖所示:

這裡寫圖片描述

參考資料:OpenCV 3計算機視覺 Python語言實現第二版

到此這篇關於Python使用Opencv實現邊緣檢測以及輪廓檢測的實現的文章就介紹到這了,更多相關Python 邊緣檢測內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!