openCV學習筆記(3)邊緣檢測和模板匹配


1.canny邊緣檢測算法

原理:https://www.cnblogs.com/mightycode/p/6394810.html

1)使用高斯濾波,濾除噪聲
2)計算圖像中每個像素點的梯度和方向
3)應用非極大值抑制,以消除邊緣帶來的雜散影響
4)應用雙閾值,檢測和確定真實和潛在邊緣
5)通過抑制孤立的弱邊緣完成邊緣檢測

import cv2 as cv
import numpy as np
#canny邊緣檢測算法
def cvshow(img):
    cv.imshow("img",img)
    cv.waitKey(0)
    cv.destroyAllWindows()
img = cv.imread("lena.jpg")
img1 = cv.Canny(img,50,100)
img2= cv.Canny(img,50,200)
res = np.hstack((img1,img2))
cvshow(res)#左邊細節比右邊多

 

 

 2.輪廓檢測

cv.findContours(img,mode,method)返回一個兩個參數的列表 contours:檢測到的輪廓   和  hierarchy:各個輪廓的繼承關系

一般我們使用在contours就可以了

img:是你要檢測的圖像,必須是灰度圖或者二值圖像才行
mode 輪廓模式
。RETR_EXTERNAL 只檢測最外面的輪廓
。RETR_LIST 檢測所有輪廓並保存到一張鏈表中
。RETR_CCOMP 檢測所有輪廓,並將他們分成兩層,頂層是外部邊界,第二層是空洞的邊界
。RETR_TREE 檢測所有輪廓,並重構輪廓的嵌套層次
mothod 輪廓靠近方法
。CHAIN_APPROX_NONE 以Freeman鏈碼方式輸出輪廓 (就是保存了所有輪廓的點)
。CHAIN_APPROX_SIMPLE 壓縮水平的垂直的和斜線部分(就是將點簡化連接成線)

邊緣檢測的一般步驟:

1.原圖像

2.轉化到灰度圖

3.轉化成二值圖像

4.使用findContours做邊緣檢測

5.使用drawContours畫出來

比如這里我們讀進來一張這張圖片,對他進行邊緣檢測

import cv2 as cv
import numpy as np
#canny邊緣檢測算法
def cvshow(img):
    cv.imshow("img",img)
    cv.waitKey(0)
    cv.destroyAllWindows()
img = cv.imread("graph.jpg")
cvshow(img)
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
thresh = cv.threshold(gray,150,255,cv.THRESH_BINARY_INV)[1]#簡便方法
cvshow(thresh)
contours = cv.findContours(thres,cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE)[0]#簡便方法 #contours,heriarchy
= cv.findContours(thresh,cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE) print(np.shape(contours)) res = cv.drawContours(img,contours,-1,(0,0,255),1) cvshow(res)

結果:它一共檢測到6個輪廓,這里你用cv.RETR_TREE的話會檢測12個(內輪廓外輪廓)

 

 

 比如這是使用cv.RETR_TREE檢測的

 

 

 這個是使用cv.RETR_EXTERNAL檢測的

在contours中包含了這些輪廓的坐標信息,我們可以利用這些坐標信息進一步畫出該圖像的外界矩形

輪廓近似

epsilon = 0.15*cv.arcLength(cnt,True)#修改數值,數值越小越接近邊緣
approx = cv.approxPolyDP(cnt,epsilon,True)
draw_img = img.copy()
res = cv.drawContours(draw_img,[approx],0,(0,0,255),3)
imshow(res)

 

 

 外界矩形

contours, hierarchy=cv.findContours(thresh, cv.RETR_TREE,cv.CHAIN_APPROX_NONE )
draw_img = img.copy()
res = cv.drawContours(draw_img,contours,-1,(0,0,255),2)
cnt = contours[0]#cnt為第1個輪廓的位置點信息
x,y,w,h = cv.boundingRect(cnt)//boundingRect計算輪廓的垂直邊界最小矩形,矩形是與圖像上下邊界平行的
img = cv.rectangle(img,(x,y),(x+w,y+h),(0,0,255),2)#畫出矩形

外接圓

(x,y),radius = cv.minEnclosingCircle(cnt)#圓心和半徑
center = (int(x),int(y))
radius = int(radius)
img = cv.circle(img,center,radius,(0,0,255),2)

 

模板匹配

 

 

 

在這個版本的執行中如果報錯depth == CV_8U || depth == CV_32F) && type == _templ.type() && _img.dims() <= 2 in function 'cv::mat 就執行cv.COLOR_BGR2RGB將你的照片轉換為RGB

模板匹配的6種方法

# All the 6 methods for comparison in a list
methods = ['cv.TM_CCOEFF', 'cv.TM_CCOEFF_NORMED', 'cv.TM_CCORR',
            'cv.TM_CCORR_NORMED', 'cv.TM_SQDIFF', 'cv.TM_SQDIFF_NORMED']

 

 

 

使用方法

res = cv.matchTemplate(people,template,cv.TM_CCOEFF)#參數為匹配對象,匹配模板,和匹配方法
res.shape
#結果為(A-a+1)*(B-b+1)   

6種方法對比

for meth in methods:
    img2 = people.copy()
    method = eval(meth)
    print(method)
    res = cv.matchTemplate(people,template,method)
    min_val,max_val,min_loc,max_loc = cv.minMaxLoc(res)#匹配的最小值,最大值,位置
    
    if method in [cv.TM_SQDIFF,cv.TM_SQDIFF_NORMED]:
        top_left = min_loc
    else :
        top_left = max_loc
    bottom_right = (top_left[0]+w,top_left[1]+h)
    
    cv.rectangle(img2,top_left,bottom_right,(0,0,255),2)
    plt.subplot(121),plt.imshow(res,cmap="gray")
    plt.xticks([]),plt.yticks([])
    plt.subplot(122),plt.imshow(img2,cmap="gray")
    plt.suptitle(meth)
    plt.show()

 

 

 多模板匹配

img_rgb = cv.imread('images/mario.jpg')
img_gray = cv.cvtColor(img_rgb, cv.COLOR_BGR2GRAY)
template = cv.imread('images/mario_coin.jpg',0)
w, h = template.shape[::-1]
res = cv.matchTemplate(img_gray,template,cv.TM_CCOEFF_NORMED)
threshold = 0.85#達到相似程度,越大相似要求越高
loc = np.where( res >= threshold)
for pt in zip(*loc[::-1]):
    cv.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (0,0,255), 2)
cvshow('res.png',img_rgb)
plt.subplot(121),pltshow(img_gray)
plt.subplot(122),pltshow(img_rgb)
#loc[::-1]將輸出的索引變換成x,y坐標,因為索引和x,y坐標是正好相反的,所以要對換下位置。然后再循環坐標,分別畫出紅色邊界。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM