矩
从这一刻起,你可以提取有用的数据,如面积,质心等。质心由关系给出,$$ C_{x}=\frac{M_{10}}{M_{00}} $$和 $$ C_{y}=\frac{M_{01}}{M_{00}} $$。
这可以按如下方式完成:
import cv2 as cv
img = cv.imread(r'C:\Users\yuyalong\Pictures\Saved Pictures\rectangle.jpg'
imgray = cv.cvtColor(img, cv.COLOR_BGR2GRAY
ret, thresh = cv.threshold(imgray, 127, 255, 0
# 获取轮廓点
contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE
print(99, len(contours
# 找到最内层的元素,这里是2是因为图像总共有三层
cnt = contours[2]
# 标记选中的区域
res1 = cv.drawContours(img, cnt, -1, (0, 255, 0, 3
# 计算矩
M = cv.moments(cnt
# 计算质心
cx = int(M['m10'] / M['m00']
cy = int(M['m01'] / M['m00']
# 画出质心
cv.circle(img, (cx, cy, 5, (255, 0, 0, -1
cv.imshow('img', img
cv.waitKey(0
轮廓面积
import cv2 as cv
img = cv.imread(r'C:\Users\yuyalong\Pictures\Saved Pictures\rectangle.jpg'
imgray = cv.cvtColor(img, cv.COLOR_BGR2GRAY
ret, thresh = cv.threshold(imgray, 127, 255, 0
# 获取轮廓点
contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE
print(99, len(contours
# 找到最内层的元素,这里是2是因为图像总共有三层
cnt = contours[2]
# 标记选中的区域
res1 = cv.drawContours(img, cnt, -1, (0, 255, 0, 3
# 计算矩
M = cv.moments(cnt
# 计算轮廓面积
area = cv.contourArea(cnt
print(111, area, M['m00']
轮廓周长
import cv2 as cv
img = cv.imread(r'C:\Users\yuyalong\Pictures\Saved Pictures\rectangle.jpg'
imgray = cv.cvtColor(img, cv.COLOR_BGR2GRAY
ret, thresh = cv.threshold(imgray, 127, 255, 0
# 获取轮廓点
contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE
print(99, len(contours
# 找到最内层的元素,这里是2是因为图像总共有三层
cnt = contours[2]
# 标记选中的区域
res1 = cv.drawContours(img, cnt, -1, (0, 255, 0, 3
# 计算轮廓周长
perimeter = cv.arcLength(cnt, True
print(222, perimeter
轮廓近似
epsilon = 0.01 * cv.arcLength(cnt, True
approx = cv.approxPolyDP(cnt, epsilon, True
import cv2 as cv
img = cv.imread(r'C:\Users\yuyalong\Pictures\Saved Pictures\rectangle1.jpg'
imgray = cv.cvtColor(img, cv.COLOR_BGR2GRAY
ret, thresh = cv.threshold(imgray, 127, 255, 0
# 获取轮廓点
contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE
print(99, len(contours
# 找到最内层的元素,这里是2是因为图像总共有三层
cnt = contours[2]
# 计算轮廓近似 epsilon=弧长的5%的近似曲线
epsilon = 0.05 * cv.arcLength(cnt, True
approx = cv.approxPolyDP(cnt, epsilon, True
# 绘制轮廓近似
res3 = cv.drawContours(img, [approx], -1, (0, 0, 255, 3
cv.imshow('img', img
cv.waitKey(0
下边第一幅图是 epsilon=弧长的5%的近似曲线,第二幅图是 epsilon=弧长的1%的近似曲线
凸包
hull = cv.convexHull(points[, hull[, clockwise[, returnPoints]]
参数详情:
- points:是我们传入的轮廓。
- hull:是输出,通常我们忽略它。
- clocwise:方向标志。如果为True,则输出凸包顺时针方向。否则,它逆时针方向。
- reurnPoints:默认为True。然后它返回凸包点的坐标。如果为False,则返回与凸包点对应的轮廓点的索引。
import cv2 as cv
img = cv.imread(r'C:\Users\yuyalong\Pictures\Saved Pictures\rectangle1.jpg'
imgray = cv.cvtColor(img, cv.COLOR_BGR2GRAY
ret, thresh = cv.threshold(imgray, 127, 255, 0
# 获取轮廓点
contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE
print(99, len(contours
# 找到最内层的元素,这里是2是因为图像总共有三层
cnt = contours[2]
# 凸包
hull = cv.convexHull(cnt
# 绘制凸包
res4 = cv.drawContours(img, [hull], -1, (0, 0, 0, 3
cv.imshow('img', img
cv.waitKey(0
检查凸性
k = cv.isContourConvex(cnt
边界矩形
a.直边矩形
它是一个直的矩形,它不考虑对象的旋转。因此,边界矩形的面积不是最小的。它由函数cv.boundingRect(找到。
设(x,y为矩形的左上角坐标,(w,h为宽度和高度。x,y,w,h = cv.boundingRect(cnt cv.rectangle(img,(x,y,(x+w,y+h,(0,255,0,2
import cv2 as cv img = cv.imread(r'C:\Users\yuyalong\Pictures\Saved Pictures\rectangle1.jpg' imgray = cv.cvtColor(img, cv.COLOR_BGR2GRAY ret, thresh = cv.threshold(imgray, 127, 255, 0 # 获取轮廓点 contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE print(99, len(contours # 找到最内层的元素,这里是2是因为图像总共有三层 cnt = contours[2] # 直边矩形 x, y, w, h = cv.boundingRect(cnt cv.rectangle(img, (x, y, (x + w, y + h, (0, 255, 0, 2 cv.imshow('img', img cv.waitKey(0
b.旋转矩形
rect = cv.minAreaRect(cnt box = cv.boxPoints(rect box = np.int0(box cv.drawContours(img,[box],0,(0,0,255,2
import cv2 as cv import numpy as np img = cv.imread(r'C:\Users\yuyalong\Pictures\Saved Pictures\rectangle1.jpg' imgray = cv.cvtColor(img, cv.COLOR_BGR2GRAY ret, thresh = cv.threshold(imgray, 127, 255, 0 # 获取轮廓点 contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE print(99, len(contours # 找到最内层的元素,这里是2是因为图像总共有三层 cnt = contours[2] # 旋转矩形 rect = cv.minAreaRect(cnt box = cv.boxPoints(rect box = np.int0(box cv.drawContours(img, [box], 0, (0, 0, 255, 2 cv.imshow('img', img cv.waitKey(0
最小外接圈
(x,y,radius = cv.minEnclosingCircle(cnt center = (int(x,int(y radius = int(radius cv.circle(img,center,radius,(0,255,0,2
import cv2 as cv import numpy as np img = cv.imread(r'C:\Users\yuyalong\Pictures\Saved Pictures\rectangle1.jpg' imgray = cv.cvtColor(img, cv.COLOR_BGR2GRAY ret, thresh = cv.threshold(imgray, 127, 255, 0 # 获取轮廓点 contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE print(99, len(contours # 找到最内层的元素,这里是2是因为图像总共有三层 cnt = contours[2] # 最小外接圆 (x, y, radius = cv.minEnclosingCircle(cnt center = (int(x, int(y radius = int(radius cv.circle(img, center, radius, (0, 255, 0, 2 cv.imshow('img', img cv.waitKey(0
椭圆拟合
ellipse = cv.fitEllipse(cnt cv.ellipse(img, ellipse, (0, 255, 0, 2
import cv2 as cv import numpy as np img = cv.imread(r'C:\Users\yuyalong\Pictures\Saved Pictures\rectangle1.jpg' imgray = cv.cvtColor(img, cv.COLOR_BGR2GRAY ret, thresh = cv.threshold(imgray, 127, 255, 0 # 获取轮廓点 contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE print(99, len(contours # 找到最内层的元素,这里是2是因为图像总共有三层 cnt = contours[2] # 拟合椭圆 ellipse = cv.fitEllipse(cnt cv.ellipse(img, ellipse, (0, 255, 0, 2 cv.imshow('img', img cv.waitKey(0
拟合一条线
rows,cols = img.shape[:2] [vx,vy,x,y] = cv.fitLine(cnt, cv.DIST_L2,0,0.01,0.01 lefty = int((-x*vy/vx + y righty = int(((cols-x*vy/vx+y cv.line(img,(cols-1,righty,(0,lefty,(0,255,0,2
import cv2 as cv import numpy as np img = cv.imread(r'C:\Users\yuyalong\Pictures\Saved Pictures\rectangle1.jpg' imgray = cv.cvtColor(img, cv.COLOR_BGR2GRAY ret, thresh = cv.threshold(imgray, 127, 255, 0 # 获取轮廓点 contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE print(99, len(contours # 找到最内层的元素,这里是2是因为图像总共有三层 cnt = contours[2] # 拟合一条线 rows, cols = img.shape[:2] [vx, vy, x, y] = cv.fitLine(cnt, cv.DIST_L2, 0, 0.01, 0.01 lefty = int((-x * vy / vx + y righty = int(((cols - x * vy / vx + y cv.line(img, (cols - 1, righty, (0, lefty, (0, 255, 0, 2 cv.imshow('img', img cv.waitKey(0
上边完整代码
点击查看代码
import cv2 as cv import numpy as np img = cv.imread(r'C:\Users\yuyalong\Pictures\Saved Pictures\rectangle1.jpg' imgray = cv.cvtColor(img, cv.COLOR_BGR2GRAY ret, thresh = cv.threshold(imgray, 127, 255, 0 # 获取轮廓点 contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE print(99, len(contours # 找到最内层的元素,这里是2是因为图像总共有三层 cnt = contours[2] # 标记选中的区域 # res1 = cv.drawContours(img, cnt, -1, (0, 255, 0, 3 # 计算矩 M = cv.moments(cnt # 计算质心 cx = int(M['m10'] / M['m00'] cy = int(M['m01'] / M['m00'] # 画出质心 cv.circle(img, (cx, cy, 5, (255, 0, 0, -1 # 计算轮廓面积 area = cv.contourArea(cnt print(111, area, M['m00'] # 计算轮廓周长 perimeter = cv.arcLength(cnt, True print(222, perimeter # 计算轮廓近似 epsilon=弧长的5%的近似曲线 epsilon = 0.01 * cv.arcLength(cnt, True approx = cv.approxPolyDP(cnt, epsilon, True res3 = cv.drawContours(img, [approx], -1, (0, 0, 255, 3 # 凸包 hull = cv.convexHull(cnt res4 = cv.drawContours(img, [hull], -1, (0, 0, 0, 3 # 检查凸性 k = cv.isContourConvex(cnt print(333, k # 直边矩形 x, y, w, h = cv.boundingRect(cnt cv.rectangle(img, (x, y, (x + w, y + h, (0, 255, 0, 2 # 旋转矩形 rect = cv.minAreaRect(cnt box = cv.boxPoints(rect box = np.int0(box cv.drawContours(img, [box], 0, (0, 0, 255, 2 # 最小外接圆 (x, y, radius = cv.minEnclosingCircle(cnt center = (int(x, int(y radius = int(radius cv.circle(img, center, radius, (0, 255, 0, 2 # 拟合椭圆 ellipse = cv.fitEllipse(cnt cv.ellipse(img, ellipse, (0, 255, 0, 2 # 拟合一条线 rows, cols = img.shape[:2] [vx, vy, x, y] = cv.fitLine(cnt, cv.DIST_L2, 0, 0.01, 0.01 lefty = int((-x * vy / vx + y righty = int(((cols - x * vy / vx + y cv.line(img, (cols - 1, righty, (0, lefty, (0, 255, 0, 2 cv.imshow('img', img cv.waitKey(0