轮廓可以简单理解成 具有相同颜色或灰度的 连续的点 连成的曲线;
轮廓在形状分析、物体检测、物体识别 中很有用;
注意:
1.为了准确,需要使用 二值化 图像,故需进行 阈值化处理 或 canny 边缘检测
2.opencv 中与轮廓相关的函数 会改变原始图像
轮廓检测与绘制
def findContours(image, mode, method, contours=None, hierarchy=None, offset=None)
image 是源图像,二值图;
mode 是轮廓检索模式,可以是 list、tree、external;
method 是轮廓点的编码方式,基本是链式编码;
contours 返回的轮廓集合;
hieracrchy 返回的轮廓层次关系;
offset 点是否有位移;
输出等高线和层次结构
def drawContours(image, contours, contourIdx, color, thickness=None, lineType=None, hierarchy=None, maxLevel=None, offset=None)
image是源图像,contours是所有等高线,contourIdx是第几个等高线,-1代表所有等高线
color 代表颜色,thickness代表厚度或宽度,-1代表全部填充为 color
示例
img = cv.imread('imgs/fs3.jpg') ## 轮廓检测 imgray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) ret, imgthresh = cv.threshold(imgray, 127, 255, 0) contours, hierarchy = cv.findContours(imgthresh, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE) # 输入必须是二值图 print(len(contours)) ## 画轮廓 # 画出所有轮廓 # cv.drawContours(img, contours, -1, (0, 255, 0), 1) # 画出第4个轮廓 # cv.drawContours(img, contours, 3, (0, 255, 0), 1) # 画出第4个轮廓 cnt = contours[5] cv.drawContours(img, [cnt], 0, (0, 255, 0), 3) # 线条加粗 cv.imshow('img', img) # cv.waitKey(0)
轮廓属性
轮廓面积
轮廓周长
边界矩形
轮廓矩和质心
## 轮廓面积 for ind, val in enumerate(contours): area = cv.contourArea(val) if area > 0: print(ind, area) break cnt = contours[5] ## 轮廓周长 perimeter = cv.arcLength(cnt, True) print(perimeter) ## 边界矩形 x, y, w, h = cv.boundingRect(cnt) img = cv.rectangle(img, (x, y), (x + w, y + h), (255, 0, 255), 2) ## 轮廓矩和质心 M = cv.moments(cnt) # 矩 print(M) cx = int(M['m10']/M['m00']) # 质心 cy = int(M['m01']/M['m00']) cv.circle(img, (cx, cy), 5, (10, 255, 100), 8) # 质心可视化 cv.imshow('img', img) cv.waitKey(0)
画在一起了
几何形状识别
多边形逼近:通过对轮廓外形无限逼近,删除非关键点、得到轮廓的关键点,不断逼近轮廓真实形状的方法
def approxPolyDP(curve, epsilon, closed, approxCurve=None)
curve:轮廓,检测到的某个轮廓,也就是一个点集;
epsilon:逼近曲率,越小,表示逼近的越厉害,越小,就会删掉更多非关键点
closed:是否闭合
多边形逼近后,判断多边形拐角个数,3个代表三角形,4个代表矩形,4-10代表多边形,大于10代表圆形
示例
img = cv.imread('imgs/flower.jpg') gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) cv.imshow('gray', gray) cv.waitKey(0) ret, binary = cv.threshold(gray, 80, 255, cv.THRESH_BINARY) cv.imshow('binary', binary) cv.waitKey(0) contours, hierarchy = cv.findContours(binary, mode=cv.RETR_TREE, method=cv.CHAIN_APPROX_SIMPLE) for ind, c in enumerate(contours): imgcopy = img.copy() cv.drawContours(imgcopy, contours, ind, (0, 0, 255), 2) ### 轮廓逼近 epsilon = cv.arcLength(contours[ind], True) # 周长 if epsilon < 200: continue approx = cv.approxPolyDP(contours[ind], epsilon / 50, True) # 比周长小一点 ### 几何形状 corners = len(approx) print(corners) # 3个拐角代表三角形,4个矩形,4-10多边形,大于10圆形 # cv.imshow('img', np.hstack([gray, binary])) cv.imshow('img', imgcopy) cv.waitKey(0)
输出 花的轮廓和几何形状
参考资料:
https://www.cnblogs.com/mrfri/p/8550328.html OpenCV+python轮廓
https://www.cnblogs.com/zhangxiaoman/p/12390742.html Python-Opencv 轮廓常用操作
https://mp.weixin.qq.com/s/brp1yyPiCyQa-sDu2_mHHQ OpenCV中几何形状识别与测量