常常看到有學習OpenCV不久的人提問,如何識別一些簡單的幾何形狀與它們的顏色,其實經過OpenCV的輪廓發現與幾何分析相關的函數,只需不到100行的代碼就能夠很好的實現這些簡單幾何形狀識別與對象測量相關操做。本文就會演示給你們如何經過OpenCV 輪廓發現與幾何分析相關函數實現以下功能:html
在具體代碼實現與程序演示以前,咱們先要搞清楚一些概念。java
1. 輪廓(contours) app
什麼是輪廓,簡單說輪廓就是一些列點相連組成形狀、它們擁有一樣的顏色、輪廓發如今圖像的對象分析、對象檢測等方面是很是有用的工具,在OpenCV中使用輪廓發現相關函數時候要求輸入圖像是二值圖像,這樣便於輪廓提取、邊緣提取等操做。輪廓發現的函數與參數解釋以下: ide
findContours(image, mode, method, contours=None, hierarchy=None, offset=None) - image輸入/輸出的二值圖像 - mode 迒回輪廓的結構、能夠是List、Tree、External - method 輪廓點的編碼方式,基本是基於鏈式編碼 - contours 迒回的輪廓集合 - hieracrchy 迒回的輪廓層次關係 - offset 點是否有位移
2. 多邊形逼近
多邊形逼近,是經過對輪廓外形無限逼近,刪除非關鍵點、獲得輪廓的關鍵點,不斷逼近輪廓真實形狀的方法,OpenCV中多邊形逼近的函數與參數解釋以下:函數
approxPolyDP(curve, epsilon, closed, approxCurve=None) - curve 表示輸入的輪廓點集合 - epsilon 表示逼近曲率,越小表示類似逼近越厲害 - close 是否閉合
3. 幾何距計算
圖像幾何距是圖像的幾何特徵,高階幾何距中心化以後具備特徵不變性,能夠產
生Hu距輸出,用於形狀匹配等操做,這裏咱們經過計算一階幾何距獲得指定輪廓的中心位置,計算幾何距的函數與參數解釋以下:工具
moments(array, binaryImage=None) - array表示指定輸入輪廓 - binaryImage默認爲None
整個代碼實現分爲以下幾步完成學習
#################################################### # 做者:zhigang, #################################################### import cv2 as cv import numpy as np class ShapeAnalysis: def __init__(self): self.shapes = {'triangle': 0, 'rectangle': 0, 'polygons': 0, 'circles': 0} def analysis(self, frame): h, w, ch = frame.shape result = np.zeros((h, w, ch), dtype=np.uint8) # 二值化圖像 print("start to detect lines...\n") gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY) ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV | cv.THRESH_OTSU) cv.imshow("input image", frame) out_binary, contours, hierarchy = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE) for cnt in range(len(contours)): # 提取與繪製輪廓 cv.drawContours(result, contours, cnt, (0, 255, 0), 2) # 輪廓逼近 epsilon = 0.01 * cv.arcLength(contours[cnt], True) approx = cv.approxPolyDP(contours[cnt], epsilon, True) # 分析幾何形狀 corners = len(approx) shape_type = "" if corners == 3: count = self.shapes['triangle'] count = count+1 self.shapes['triangle'] = count shape_type = "三角形" if corners == 4: count = self.shapes['rectangle'] count = count + 1 self.shapes['rectangle'] = count shape_type = "矩形" if corners >= 10: count = self.shapes['circles'] count = count + 1 self.shapes['circles'] = count shape_type = "圓形" if 4 < corners < 10: count = self.shapes['polygons'] count = count + 1 self.shapes['polygons'] = count shape_type = "多邊形" # 求解中心位置 mm = cv.moments(contours[cnt]) cx = int(mm['m10'] / mm['m00']) cy = int(mm['m01'] / mm['m00']) cv.circle(result, (cx, cy), 3, (0, 0, 255), -1) # 顏色分析 color = frame[cy][cx] color_str = "(" + str(color[0]) + ", " + str(color[1]) + ", " + str(color[2]) + ")" # 計算面積與周長 p = cv.arcLength(contours[cnt], True) area = cv.contourArea(contours[cnt]) print("周長: %.3f, 面積: %.3f 顏色: %s 形狀: %s "% (p, area, color_str, shape_type)) cv.imshow("Analysis Result", self.draw_text_info(result)) cv.imwrite("D:/test-result.png", self.draw_text_info(result)) return self.shapes def draw_text_info(self, image): c1 = self.shapes['triangle'] c2 = self.shapes['rectangle'] c3 = self.shapes['polygons'] c4 = self.shapes['circles'] cv.putText(image, "triangle: "+str(c1), (10, 20), cv.FONT_HERSHEY_PLAIN, 1.2, (255, 0, 0), 1) cv.putText(image, "rectangle: " + str(c2), (10, 40), cv.FONT_HERSHEY_PLAIN, 1.2, (255, 0, 0), 1) cv.putText(image, "polygons: " + str(c3), (10, 60), cv.FONT_HERSHEY_PLAIN, 1.2, (255, 0, 0), 1) cv.putText(image, "circles: " + str(c4), (10, 80), cv.FONT_HERSHEY_PLAIN, 1.2, (255, 0, 0), 1) return image if __name__ == "__main__": src = cv.imread("D:/javaopencv/gem_test.png") ld = ShapeAnalysis() ld.analysis(src) cv.waitKey(0) cv.destroyAllWindows()
原圖ui
運行結果:編碼
控制檯輸出:code
歡迎繼續關注本博客,學習OpenCV Python教程