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坐標是正好相反的,所以要對換下位置。然后再循環坐標,分別畫出紅色邊界。