Pytthon,OpenCV轮廓属性轮廓检测及绘制

Posted 程序媛一枚~

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Pytthon,OpenCV轮廓属性轮廓检测及绘制相关的知识,希望对你有一定的参考价值。

Pytthon,OpenCV轮廓属性、轮廓检测及绘制

这篇博客将介绍OpenCV中的轮廓,轮廓的特征及属性(质心,面积,轮廓,近似轮廓,周长,最小外接圆,面积最小外接矩形,外接直角矩形,凸包);

计算轮廓属性提取物体的一些常用特性,如坚固性、等效直径、掩模图像、平均强度等;

  • 宽高比(外接矩形宽/高的比率)
  • Extent(面积/外接矩形面积的比率)
  • 坚固性(面积/凸包面积的比率)
  • 等效直径(与轮廓面积相同的圆的直径)
  • 拟合椭圆的长轴、短轴、方向;
  • 均值(平均颜色或平均强度)
  • 极值点是指物体的最上面、最下面、最右边和最左边的点

1. 效果图

外接矩形效果图如下:红色面积最小矩形,绿色外接直角矩形
在这里插入图片描述

最小外接圆效果图如下:
在这里插入图片描述

拟合椭圆效果图如下:
在这里插入图片描述

拟合线效果图如下:
在这里插入图片描述

2. 源码

2.1 轮廓属性

# 找出轮廓的不同特征,如面积、周长、质心、边界盒等
# moments矩可以计算物体的质心、面积等特征;函数cv2.moments()提供了一个计算出所有力矩值的字典。

import cv2
import numpy as np

image = cv2.imread('opencv_logo.jpg')
img = cv2.imread('opencv_logo.jpg', 0)
ret, thresh = cv2.threshold(img, 127, 255, 0)
contours, hierarchy = cv2.findContours(thresh, 1, 2)
# print(contours)

cnt = contours[0]
cv2.drawContours(image, cnt, -1, (255, 255, 255), -1)
M = cv2.moments(cnt)
# 力矩
print('力矩:', M)

# 质心
cx = int(M['m10'] / M['m00'])
cy = int(M['m01'] / M['m00'])
print('质心:', (cx, cy))
cv2.circle(image, (cx, cy), 3, (255, 255, 255), -1)

# 面积
area = cv2.contourArea(cnt)
print('面积:', area, M['m00'])

# 等高线周长也称为弧长。可以使用cv2.arcLength(cnt,True),True标识闭合区域,False表示曲线
perimeter = cv2.arcLength(cnt, True)
print('周长:', perimeter)

# 轮廓近似:它将一个轮廓形状近似为另一个具有较少顶点数的形状,具体取决于我们指定的精度。它是Douglas-Peucker算法的一个实现。
epsilon = 0.1 * cv2.arcLength(cnt, True)
# epsilon表示近似轮廓10%,True表示闭合区域
approx = cv2.approxPolyDP(cnt, epsilon, True)
print('近似轮廓:', approx)

# 凸包:cv2.convexHull()函数检查曲线的凸度缺陷并进行校正。
hull = cv2.convexHull(cnt)
print('凸包:', hull)

# 检查凸性,即检查曲线是否凸,cv2.isContourConvex()
k = cv2.isContourConvex(cnt)
print('检查是否凸:', k)

# 边框(边界矩形) cv2.boundingRect()计算得到直角矩形,(x,y)为矩形的左上角坐标,(w,h)为矩形的宽度和高度。)
x, y, w, h = cv2.boundingRect(cnt)
aspect_ratio = float(w) / h
print('宽高比: ', aspect_ratio)
cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)

# cv2.minarearct(),旋转矩形(边界矩形是以最小面积绘制的,考虑了旋转。) (中心(x,y), 宽度高度(width, height), 旋转角度);
# 使用cv2.boxPoints()得到矩形的4个角点
# 两个矩形都显示在一个图像中。绿色矩形显示法线边界矩形。红色矩形是旋转的矩形。
rect = cv2.minAreaRect(cnt)
box = cv2.boxPoints(rect)
box = np.int0(box)
cv2.drawContours(image, [box], 0, (0, 0, 255), 2)

# cv2.minEnclosingCircle()面积最小外接圆
(x, y), radius = cv2.minEnclosingCircle(cnt)
center = (int(x), int(y))
radius = int(radius)
cv2.circle(image, center, radius, (0, 255, 0), 2)

# 拟合椭圆,返回椭圆内接的旋转矩形。
ellipse = cv2.fitEllipse(cnt)
cv2.ellipse(image, ellipse, (0, 255, 0), 2)

# 拟合线
rows, cols = img.shape[:2]
[vx, vy, x, y] = cv2.fitLine(cnt, cv2.DIST_L2, 0, 0.01, 0.01)
lefty = int((-x * vy / vx) + y)
righty = int(((cols - x) * vy / vx) + y)
cv2.line(image, (cols - 1, righty), (0, lefty), (0, 255, 0), 2)
cv2.imshow("img", image)
cv2.waitKey(0)

2.2 轮廓特征

import cv2
import numpy as np

img = cv2.imread('opencv_logo.jpg', 0)
ret, thresh = cv2.threshold(img, 127, 255, 0)
contours, hierarchy = cv2.findContours(thresh, 1, 2)
# print(contours)

cnt = contours[0]

x, y, w, h = cv2.boundingRect(cnt)
aspect_ratio = float(w) / h
print('宽高比:', aspect_ratio)

area = cv2.contourArea(cnt)
x, y, w, h = cv2.boundingRect(cnt)
rect_area = w * h
extent = float(area) / rect_area
print('extent: ', extent)

area = cv2.contourArea(cnt)
hull = cv2.convexHull(cnt)
hull_area = cv2.contourArea(hull)
solidity = float(area) / hull_area
print('坚固性: ', solidity)

area = cv2.contourArea(cnt)
equi_diameter = np.sqrt(4 * area / np.pi)
print('等面积圆的直径:', equi_diameter)

(x, y), (MA, ma), angle = cv2.fitEllipse(cnt)
print('方向:', angle)
print('长轴,短轴:', MA, ma)

# Numpy以(行,列)格式给出坐标,OpenCV以(x,y)格式给出坐标。
imgray = img
mask = np.zeros(imgray.shape, np.uint8)
cv2.drawContours(mask, [cnt], 0, 255, -1)
pixelpoints = np.transpose(np.nonzero(mask))
# pixelpoints = cv2.findNonZero(mask)
print('遮罩mask: ', mask)
print('组成轮廓的所有像素点:', pixelpoints)

min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(imgray, mask=mask)
print('最小,最大,最小位置,最大位置:', min_val, max_val, min_loc, max_loc)

mean_val = cv2.mean(imgray, mask=mask)
print('平均颜色/平均强度:', mean_val)

leftmost = tuple(cnt[cnt[:, :, 0].argmin()][0])
rightmost = tuple(cnt[cnt[:, :, 0].argmax()][0])
topmost = tuple(cnt[cnt[:, :, 1].argmin()][0])
bottommost = tuple(cnt[cnt[:, :, 1].argmax()][0])
print('极值点:', leftmost, rightmost, topmost, bottommost)

参考

以上是关于Pytthon,OpenCV轮廓属性轮廓检测及绘制的主要内容,如果未能解决你的问题,请参考以下文章

opencv学习之路(29)轮廓查找与绘制——轮廓特征属性及应用

opencv学习-物体轮廓-绘制轮廓外接多边形(凸包检测)

25opencv入门轮廓查找与绘制——凸包

youcans 的 OpenCV 例程200篇195.绘制图像轮廓(cv.drawContours)

youcans 的 OpenCV 例程200篇195.绘制图像轮廓(cv.drawContours)

详解用OpenCV的轮廓检测函数findContours()得到的轮廓拓扑结构(hiararchy)矩阵的意义以及怎样用轮廓拓扑结构矩阵绘制轮廓拓扑结构图