如何在Python中利用Opencv對(duì)邊緣進(jìn)行檢測(cè)?針對(duì)這個(gè)問題,這篇文章詳細(xì)介紹了相對(duì)應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問題的小伙伴找到更簡(jiǎn)單易行的方法。
站在用戶的角度思考問題,與客戶深入溝通,找到新巴爾虎右網(wǎng)站設(shè)計(jì)與新巴爾虎右網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗(yàn),讓設(shè)計(jì)與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個(gè)性化、用戶體驗(yàn)好的作品,建站類型包括:成都網(wǎng)站制作、成都網(wǎng)站設(shè)計(jì)、外貿(mào)營(yíng)銷網(wǎng)站建設(shè)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣、域名注冊(cè)、虛擬空間、企業(yè)郵箱。業(yè)務(wù)覆蓋新巴爾虎右地區(qū)。Canny邊緣檢測(cè)器是一種被廣泛使用的算法,并被認(rèn)為是邊緣檢測(cè)最優(yōu)的算法,該方法使用了比高斯差分算法更復(fù)雜的技巧,如多向灰度梯度和滯后閾值化。
Canny邊緣檢測(cè)器算法基本步驟:
平滑圖像:通過使用合適的模糊半徑執(zhí)行高斯模糊來減少圖像內(nèi)的噪聲。
計(jì)算圖像的梯度:這里計(jì)算圖像的梯度,并將梯度分類為垂直、水平和斜對(duì)角。這一步的輸出用于在下一步中計(jì)算真正的邊緣。
非較大值抑制:利用上一步計(jì)算出來的梯度方向,檢測(cè)某一像素在梯度的正方向和負(fù)方向上是否是局部較大值,如果是,則抑制該像素(像素不屬于邊緣)。這是一種邊緣細(xì)化技術(shù),用最急劇的變換選出邊緣點(diǎn)。
用滯后閾值化選擇邊緣:最后一步,檢查某一條邊緣是否明顯到足以作為最終輸出,最后去除所有不明顯的邊緣。
Opencv使用Canny邊緣檢測(cè)相對(duì)簡(jiǎn)單,代碼如下:
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()
運(yùn)行結(jié)果:
Canny函數(shù)的原型為
cv2.Canny(image, threshold1, threshold2[, edges[, apertureSize[, L2gradient ]]])
必要參數(shù):
第一個(gè)參數(shù)是需要處理的原圖像,該圖像必須為單通道的灰度圖;
第二個(gè)參數(shù)是滯后閾值1;
第三個(gè)參數(shù)是滯后閾值2。
輪廓檢測(cè)主要由cv2.findContours函數(shù)實(shí)現(xiàn)的。
函數(shù)的原型為
cv2.findContours(image, mode, method[, contours[, hierarchy[, offset ]]])
函數(shù)參數(shù)
第一個(gè)參數(shù)是尋找輪廓的圖像;
第二個(gè)參數(shù)表示輪廓的檢索模式,有四種(本文介紹的都是新的cv2接口):
cv2.RETR_EXTERNAL表示只檢測(cè)外輪廓 。
cv2.RETR_LIST檢測(cè)的輪廓不建立等級(jí)關(guān)系。
cv2.RETR_CCOMP建立兩個(gè)等級(jí)的輪廓,上面的一層為外邊界,里面的一層為內(nèi)孔的邊界信息。如果內(nèi)孔內(nèi)還有一個(gè)連通物體,這個(gè)物體的邊界也在頂層。
cv2.RETR_TREE建立一個(gè)等級(jí)樹結(jié)構(gòu)的輪廓。
第三個(gè)參數(shù)method為輪廓的逼近方法
cv2.CHAIN_APPROX_NONE存儲(chǔ)所有的輪廓點(diǎn),相鄰的兩個(gè)點(diǎn)的像素位置差不超過1,即max(abs(x1-x2),abs(y2-y1))==1。
cv2.CHAIN_APPROX_SIMPLE壓縮水平方向,垂直方向,對(duì)角線方向的元素,只保留該方向的終點(diǎn)坐標(biāo),例如一個(gè)矩形輪廓只需4個(gè)點(diǎn)來保存輪廓信息。
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:圖像的輪廓,以列表的形式表示,每個(gè)元素都是圖像中的一個(gè)輪廓。
hier:相應(yīng)輪廓之間的關(guān)系。這是一個(gè)ndarray,其中的元素個(gè)數(shù)和輪廓個(gè)數(shù)相同,每個(gè)輪廓contours[i]對(duì)應(yīng)4個(gè)hierarchy元素hierarchy[i][0] ~hierarchy[i][3],分別表示后一個(gè)輪廓、前一個(gè)輪廓、父輪廓、內(nèi)嵌輪廓的索引編號(hào),如果沒有對(duì)應(yīng)項(xiàng),則該值為負(fù)數(shù)。
原圖:
示例一
import cv2 import numpy as np img = cv2.pyrDown(cv2.imread("hammer.jpg", cv2.IMREAD_UNCHANGED)) # threshold 函數(shù)對(duì)圖像進(jìn)行二化值處理,由于處理后圖像對(duì)原圖像有所變化,因此img.copy()生成新的圖像,cv2.THRESH_BINARY是二化值 ret, thresh = cv2.threshold(cv2.cvtColor(img.copy(), cv2.COLOR_BGR2GRAY), 127, 255, cv2.THRESH_BINARY) # findContours函數(shù)查找圖像里的圖形輪廓 # 函數(shù)參數(shù)thresh是圖像對(duì)象 # 層次類型,參數(shù)cv2.RETR_EXTERNAL是獲取最外層輪廓,cv2.RETR_TREE是獲取輪廓的整體結(jié)構(gòu) # 輪廓逼近方法 # 輸出的返回值,image是原圖像、contours是圖像的輪廓、hier是層次類型 image, contours, hier = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) for c in contours: # 輪廓繪制方法一 # boundingRect函數(shù)計(jì)算邊框值,x,y是坐標(biāo)值,w,h是矩形的寬和高 x, y, w, h = cv2.boundingRect(c) # 在img圖像畫出矩形,(x, y), (x + w, y + h)是矩形坐標(biāo),(0, 255, 0)設(shè)置通道顏色,2是設(shè)置線條粗度 cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2) # 輪廓繪制方法二 # 查找最小區(qū)域 rect = cv2.minAreaRect(c) # 計(jì)算最小面積矩形的坐標(biāo) box = cv2.boxPoints(rect) # 將坐標(biāo)規(guī)范化為整數(shù) box = np.int0(box) # 繪制矩形 cv2.drawContours(img, [box], 0, (0, 0, 255), 3) # 輪廓繪制方法三 # 圓心坐標(biāo)和半徑的計(jì)算 (x, y), radius = cv2.minEnclosingCircle(c) # 規(guī)范化為整數(shù) center = (int(x), int(y)) radius = int(radius) # 勾畫圓形區(qū)域 img = cv2.circle(img, center, radius, (0, 255, 0), 2) # # 輪廓繪制方法四 # 圍繞圖形勾畫藍(lán)色線條 cv2.drawContours(img, contours, -1, (255, 0, 0), 2) # 顯示圖像 cv2.imshow("contours", img) cv2.waitKey() cv2.destroyAllWindows()
運(yùn)行結(jié)果如圖所示:
示例二
import cv2 import numpy as np img = cv2.pyrDown(cv2.imread("hammer.jpg", cv2.IMREAD_UNCHANGED)) ret, thresh = cv2.threshold(cv2.cvtColor(img.copy(), cv2.COLOR_BGR2GRAY) , 127, 255, cv2.THRESH_BINARY) # findContours函數(shù)查找圖像里的圖形輪廓 # 函數(shù)參數(shù)thresh是圖像對(duì)象 # 層次類型,參數(shù)cv2.RETR_EXTERNAL是獲取最外層輪廓,cv2.RETR_TREE是獲取輪廓的整體結(jié)構(gòu) # 輪廓逼近方法 # 輸出的返回值,image是原圖像、contours是圖像的輪廓、hier是層次類型 image, contours, hier = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 創(chuàng)建新的圖像black black = cv2.cvtColor(np.zeros((img.shape[1], img.shape[0]), dtype=np.uint8), cv2.COLOR_GRAY2BGR) for cnt in contours: # 輪廓周長(zhǎng)也被稱為弧長(zhǎng)??梢允褂煤瘮?shù) cv2.arcLength() 計(jì)算得到。這個(gè)函數(shù)的第二參數(shù)可以用來指定對(duì)象的形狀是閉合的(True) ,還是打開的(一條曲線) epsilon = 0.01 * cv2.arcLength(cnt, True) # 函數(shù)approxPolyDP來對(duì)指定的點(diǎn)集進(jìn)行逼近,cnt是圖像輪廓,epsilon表示的是精度,越小精度越高,因?yàn)楸硎镜囊馑际鞘窃记€與近似曲線之間的較大距離。 # 第三個(gè)函數(shù)參數(shù)若為true,則說明近似曲線是閉合的,它的首位都是相連,反之,若為false,則斷開。 approx = cv2.approxPolyDP(cnt, epsilon, True) # convexHull檢查一個(gè)曲線的凸性缺陷并進(jìn)行修正,參數(shù)cnt是圖像輪廓。 hull = cv2.convexHull(cnt) # 勾畫圖像原始的輪廓 cv2.drawContours(black, [cnt], -1, (0, 255, 0), 2) # 用多邊形勾畫輪廓區(qū)域 cv2.drawContours(black, [approx], -1, (255, 255, 0), 2) # 修正凸性缺陷的輪廓區(qū)域 cv2.drawContours(black, [hull], -1, (0, 0, 255), 2) # 顯示圖像 cv2.imshow("hull", black) cv2.waitKey() cv2.destroyAllWindows()
關(guān)于如何在Python中利用Opencv對(duì)邊緣進(jìn)行檢測(cè)問題的解答就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道了解更多相關(guān)知識(shí)。