15-轮廓检测
邊緣是零零散散的,而輪廓是一個整體
cv2.findContours(img,mode,method)
img:輸入圖像對象名稱
mode:輪廓檢索模式
method:輪廓逼近方法
CHAIN_APPROX_NONE:以Freeman鏈碼的方式輸出輪廓,所有其他方法輸出多邊形(頂點的序列) CHAIN_APPROX_SIMPLE:壓縮水平的、垂直的和斜的部分,也就是,函數(shù)只保留他們的終點部分為了更高的精確率,盡量最好使用二值圖像
import cv2 import numpy as np from matplotlib import pyplot as pltdef show_photo(name,picture):#圖像顯示函數(shù)cv2.imshow(name,picture)cv2.waitKey(0)cv2.destroyAllWindows()#做之前需要對照片進行二值處理 img = cv2.imread('E:\Jupyter_workspace\study\data/cfx.png') gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#轉(zhuǎn)換為灰度圖 ret, thresh = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)#對圖像進行二值處理,小于127為0,大于127為255 show_photo('thresh',thresh)binary, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)show_photo('binary',binary)#就是作完二值操作的結(jié)果np.array(contours).shape#是一群list結(jié)構(gòu)的輪廓點,保存一些輪廓的信息 #結(jié)果為:(2,)#hierarchy是一個層級,把結(jié)果全部保存到層級里面二值處理后的圖像
binary參數(shù)實則就是二值處理后的圖像
繪制輪廓
cv2.drawContours(draw_img,contours,-1,(0,0,255),2)
參數(shù)1:一個照片對象名稱 參數(shù)2:輪廓是什么 參數(shù)3:畫第幾個輪廓,-1表示把所有的輪廓都畫出來 參數(shù)4:(B,G,R)畫輪廓的線是什么顏色的 參數(shù)5:線條的寬度 import cv2 import numpy as np from matplotlib import pyplot as pltdef show_photo(name,picture):#圖像顯示函數(shù)cv2.imshow(name,picture)cv2.waitKey(0)cv2.destroyAllWindows()#做之前需要對照片進行二值處理 img = cv2.imread('E:\Jupyter_workspace\study\data/cfx.png') show_photo('img ',img )gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#轉(zhuǎn)換為灰度圖 ret, thresh = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)#對圖像進行二值處理,小于127為0,大于127為255 binary, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)draw_img = img.copy()#注意一定要copy要不然會對原圖進行改變!!! res = cv2.drawContours(draw_img,contours,-1,(0,0,255),2)#-1表示顯示所有輪廓,(0,0,225)BGR表示紅色,2為輪廓粗細 show_photo('-1 is All',res)draw_img = img.copy()#注意一定要copy要不然會對原圖進行改變!!! res = cv2.drawContours(draw_img,contours,0,(0,0,255),2)#0表示顯示第0個輪廓,(0,0,225)BGR表示紅色,2為輪廓粗 show_photo('zero',res)draw_img = img.copy()#注意一定要copy要不然會對原圖進行改變!!! res = cv2.drawContours(draw_img,contours,1,(0,0,255),2)#1表示顯示第1個輪廓,(0,0,225)BGR表示紅色,2為輪廓粗 show_photo('one',res)原圖:
顯示所有輪廓(里外)
顯示第0個輪廓(外)
顯示第1個輪廓(內(nèi))
輪廓特征
import cv2 import numpy as np from matplotlib import pyplot as pltdef show_photo(name,picture):#圖像顯示函數(shù)cv2.imshow(name,picture)cv2.waitKey(0)cv2.destroyAllWindows()img = cv2.imread('E:\Jupyter_workspace\study\data/cfx.png') gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#轉(zhuǎn)換為灰度圖 ret, thresh = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)#對圖像進行二值處理,小于127為0,大于127為255 binary, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)cnt = contours[0]#contours存放所有輪廓的信息,這里取第一個輪廓cv2.contourArea(cnt)#第一個輪廓所對應(yīng)的面積 #結(jié)果為:20909.0cv2.arcLength(cnt,True)#第一個輪廓所對應(yīng)的周長,True表示閉合的 #結(jié)果為:612.0輪廓近似
輪廓近似:舉例子拿曲線AB進行近似計算
1,首先直線連接AB,再曲線AB上找到離AB直線最遠的一點C,點C到直線AB的距離為d1 2,用戶需要自定義一個值epsilon作為閾值 3,將d1與閾值epsilon進行比較;若d1 < epsilon可直接將直線AB代替曲線AB,近似結(jié)束若d1 > epsilon則,連接直線AC和直接BC在曲線AC上找離直線AC最短的一點D,點D到直線AC的距離為d2若d2 < epsilon可直接將直線AC代替曲線AC若d2 > epsilon則做同樣的操作在曲線BC上找離直線BC最短的一點E,點E到直線BC的距離為d3同樣的操作 import cv2 import numpy as np from matplotlib import pyplot as pltdef show_photo(name,picture):#圖像顯示函數(shù)cv2.imshow(name,picture)cv2.waitKey(0)cv2.destroyAllWindows()img = cv2.imread('E:\Jupyter_workspace\study\data/lunkuo.png') show_photo('img ',img )gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) ret, thresh = cv2.threshold(gray,127,255,cv2.THRESH_BINARY) binary, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)cnt = contours[0]draw_img = img.copy() res =cv2.drawContours(draw_img,[cnt],-1,(0,0,255),2) show_photo('res',res)原圖:
輪廓近似后效果
近似函數(shù):
cv2.approxPolyDP(cnt,epsilon,True)
參數(shù)1:傳入要近似的輪廓 參數(shù)2:自定義一個值來進行輪廓比較,一般是按周長的百分比進行設(shè)置的 參數(shù)3:輪廓是否封閉 import cv2 import numpy as np from matplotlib import pyplot as pltdef show_photo(name,picture):#圖像顯示函數(shù)cv2.imshow(name,picture)cv2.waitKey(0)cv2.destroyAllWindows()img = cv2.imread('E:\Jupyter_workspace\study\data/lunkuo.png') show_photo('img ',img )gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) ret, thresh = cv2.threshold(gray,127,255,cv2.THRESH_BINARY) binary, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)epsilon = 0.1*cv2.arcLength(cnt,True)#倍數(shù)越小越接近本身輪廓 approx = cv2.approxPolyDP(cnt,epsilon,True)draw_img = img.copy() res =cv2.drawContours(draw_img,[approx],-1,(0,0,255),2) show_photo('res',res)原圖:
近似函數(shù)處理過后的圖像:
邊界矩形
獲得輪廓的邊緣矩形:cv2.boundingRect(cnt)
參數(shù):指定操作的對象是哪個輪廓 返回值:輪廓對應(yīng)的邊緣矩形的x,y坐標和w,h寬高值 import cv2 import numpy as np from matplotlib import pyplot as pltdef show_photo(name,picture):#圖像顯示函數(shù)cv2.imshow(name,picture)cv2.waitKey(0)cv2.destroyAllWindows()img = cv2.imread('E:\Jupyter_workspace\study\data/lunkuo1.png') show_photo('img',img)#原圖gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) res, thresh = cv2.threshold(gray,127,255,cv2.THRESH_BINARY) binary, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) cnt = contours[0]#這里的輪廓取得是第0個,當然也可以取其他的輪廓x, y, w, h = cv2.boundingRect(cnt) img = cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2) show_photo('img',img)area = cv2.contourArea(cnt)#輪廓面積 x, y, w, h = cv2.boundingRect(cnt) rect_area = w * h #輪廓對應(yīng)的邊緣矩形的面積,寬×高為對應(yīng)邊緣矩形的面積 extent = float(area) / rect_area print('輪廓面積與邊界矩形之比',extent) #結(jié)果為:輪廓面積與邊界矩形之比 0.5113636363636364原圖:
獲取第0個輪廓邊界矩形:
外接圓
import cv2 import numpy as np from matplotlib import pyplot as pltdef show_photo(name,picture):#圖像顯示函數(shù)cv2.imshow(name,picture)cv2.waitKey(0)cv2.destroyAllWindows()img = cv2.imread('E:\Jupyter_workspace\study\data/lunkuo1.png') show_photo('img',img)gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) res, thresh = cv2.threshold(gray,127,255,cv2.THRESH_BINARY) binary, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) cnt = contours[0]#對輪廓0操作,當然也可以換成其他的輪廓x, y, w, h = cv2.boundingRect(cnt) (x,y),radius = cv2.minEnclosingCircle(cnt) center = (int(x),int(y)) radius = int(radius) img = cv2.circle(img,center,radius,(0,255,0),2)#(B,G,R),2為輪廓粗細程度 show_photo('img',img)原圖:
對第0輪廓進行外接圓操作:
總結(jié)
- 上一篇: 一辆保时捷多少钱啊?
- 下一篇: 16-模板匹配