一:獲取圖像的外接矩形boundingRect和幾何距moments
import cv2 as cv import numpy as np def measure_object(image): gray = cv.cvtColor(image,cv.COLOR_BGR2GRAY) #轉灰度圖像 ret, binary = cv.threshold(gray,0,255,cv.THRESH_OTSU|cv.THRESH_BINARY_INV) #獲取二值化圖像 print("thresold value:",ret) cv.imshow("binary image",binary) outImage,contours,hireachy = cv.findContours(binary,cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE) for i,contour in enumerate(contours): area = cv.contourArea(contour) #獲取每個輪廓面積 x,y,w,h = cv.boundingRect(contour) #獲取輪廓的外接矩形 rate = min(w,h)/max(w,h) #獲取外接矩形寬高比,可以起到一定的篩選作用 print("rectangle rate:%s"%rate) mm = cv.moments(contour) #求取輪廓的幾何距 print(type(mm)) print(mm) cx = mm['m10']/mm['m00'] cy = mm['m01']/mm['m00'] cv.circle(image,(np.int(cx),np.int(cy)),2,(0,255,255),-1) #根據幾何距獲取的中心點,畫出中心圓 cv.rectangle(image,(x,y),(x+w,y+h),(0,0,255),2) #根據輪廓外接矩形返回數據,畫出外接矩形 print("contour area:",area) cv.imshow("measure_object",image) src = cv.imread("./dg.png") #讀取圖片 cv.namedWindow("input image",cv.WINDOW_AUTOSIZE) #創建GUI窗口,形式為自適應 cv.imshow("input image",src) #通過名字將圖像和窗口聯系 measure_object(src) cv.waitKey(0) #等待用戶操作,里面等待參數是毫秒,我們填寫0,代表是永遠,等待用戶操作 cv.destroyAllWindows() #銷毀所有窗口
mm-->{'m02': 3301.25, 'm12': 233530.03333333333, 'm30': 6934377.600000001, 'mu11': -10.721153846156085, 'm21': 1265395.2, 'nu02': 0.08336283484212434, 'm01': 252.5, 'mu30': -12.458842864260077, 'nu21': 0.003451665836783194, 'mu12': 11.46577909273492, 'nu12': 0.006828369938345303, 'mu02': 31.698717948717785, 'mu21': 5.795825115486707, 'm03': 43556.350000000006, 'nu30': -0.007419782588937784, 'm20': 97840.41666666666, 'm00': 19.5, 'm10': 1381.0, 'nu20': 0.09806301522275791, 'mu03': -11.52064431294275, 'm11': 17871.458333333332, 'nu03': -0.0068610445623109115, 'mu20': 37.2884615384537, 'nu11': -0.028195013402119877}
二:多邊形逼近approxPolyDP
import cv2 as cv import numpy as np def measure_object(image): gray = cv.cvtColor(image,cv.COLOR_BGR2GRAY) #轉灰度圖像 ret, binary = cv.threshold(gray,0,255,cv.THRESH_OTSU|cv.THRESH_BINARY) #獲取二值化圖像 cv.imshow("binary image",binary) dst = cv.cvtColor(binary,cv.COLOR_GRAY2BGR) outImage,contours,hireachy = cv.findContours(binary,cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE) for i,contour in enumerate(contours): mm = cv.moments(contour) #求取輪廓的幾何距 cx = mm['m10']/mm['m00'] cy = mm['m01']/mm['m00'] cv.circle(dst,(np.int(cx),np.int(cy)),2,(0,255,255),-1) #畫出中心點 approxCurve = cv.approxPolyDP(contour,4,True) #4是與閾值的間隔大小,越小越易找出,True是是否找閉合圖像 print(approxCurve.shape) if approxCurve.shape[0] >= 7: cv.drawContours(dst,contours,i,(0,255,0),2) #畫出輪廓 elif approxCurve.shape[0] == 4: cv.drawContours(dst,contours,i,(0,0,255),2) else: cv.drawContours(dst,contours,i,(255,0,0),2) cv.imshow("measure_object",dst) src = cv.imread("./lk.png") #讀取圖片 cv.namedWindow("input image",cv.WINDOW_AUTOSIZE) #創建GUI窗口,形式為自適應 cv.imshow("input image",src) #通過名字將圖像和窗口聯系 measure_object(src) cv.waitKey(0) #等待用戶操作,里面等待參數是毫秒,我們填寫0,代表是永遠,等待用戶操作 cv.destroyAllWindows() #銷毀所有窗口
相關知識補充
(一)相關函數方法
cv.contourArea(contour) #獲取每個輪廓面積
cv.boundingRect(contour) #獲取輪廓的外接矩形
cv.moments(contour) #求取輪廓的幾何距
cv.arcLength(contour,True) #求取輪廓的周長,指定閉合
(二)approxPolyDP輪廓逼近方法
approxCurve = cv.approxPolyDP(contour,4,True) #4是與閾值的間隔大小,越小越易找出,True是是否找閉合圖像
def approxPolyDP(curve, epsilon, closed, approxCurve=None): # real signature unknown; restored from __doc__
第一個參數curve:輸入的點集,直接使用輪廓點集contour
第二個參數epsilon:指定的精度,也即是原始曲線與近似曲線之間的最大距離。
第三個參數closed:若為true,則說明近似曲線是閉合的,反之,若為false,則斷開。
第四個參數approxCurve:輸出的點集,當前點集是能最小包容指定點集的。畫出來即是一個多邊形;
返回值
approxCurve:輸出的點集,當前點集是能最小包容指定點集的。畫出來即是一個多邊形;
print(approxCurve) #打印每個輪廓的特征點 print(approxCurve.shape) #打印該點集的shape,第一個數是代表了點的個數,也就是邊長連接逼近數
[[[138 208]] [[138 234]] [[265 234]] [[264 207]]] (4, 1, 2) #矩形,四個點逼近圖像 [[[124 154]] [[124 183]] [[325 183]] [[325 154]]] (4, 1, 2) [[[ 61 125]] [[ 9 279]] [[114 280]]] (3, 1, 2) #3是三角形 [[[123 102]] [[111 118]] [[117 128]] [[129 131]] [[139 124]] [[141 114]] [[134 104]]] (7, 1, 2) #7,8,9都是圓形類 [[[303 78]] [[291 87]] [[289 99]] [[298 111]] [[310 113]] [[322 105]] [[324 91]] [[314 79]]] (8, 1, 2) [[[308 28]] [[298 35]] [[295 48]] [[303 59]] [[314 61]] [[325 54]] [[327 39]]] (7, 1, 2) [[[198 21]] [[165 38]] [[153 75]] [[170 107]] [[185 116]] [[210 119]] [[244 100]] [[254 63]] [[235 31]]] (9, 1, 2) [[[ 27 21]] [[ 27 87]] [[101 87]] [[101 21]]] (4, 1, 2) [[[418 15]] [[416 190]] [[454 192]] [[455 16]]] (4, 1, 2) [[[359 14]] [[346 58]] [[345 138]] [[356 190]] [[363 192]] [[374 156]] [[376 82]] [[369 24]]] (8, 1, 2)