为了方便讲解,我们先来创建一个多边形做演示
第一步:创建图像,并绘制一个六边形。代码和生成图像如下:
# Create an image
r = 100
src = np.zeros((4*r, 4*r), dtype=np.uint8)
# Create a sequence of points to make a contour
vert = [None]*6
vert[0] = (3*r//2, int(1.34*r))
vert[1] = (1*r, 2*r)
vert[2] = (3*r//2, int(2.866*r))
vert[3] = (5*r//2, int(2.866*r))
vert[4] = (3*r, 2*r)
vert[5] = (5*r//2, int(1.34*r))
# Draw it in src
for i in range(6):
cv.line(src, vert[i], vert[(i+1)%6], ( 255 ), 3)
cv.imshow("src", src)
第二步:查找轮廓,计算图像上的点到轮廓的距离
# Get the contours
_, contours, _ = cv.findContours(src, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
# Calculate the distances to the contour
raw_dist = np.empty(src.shape, dtype=np.float32)
for i in range(src.shape[0]):
for j in range(src.shape[1]):
raw_dist[i,j] = cv.pointPolygonTest(contours[1], (j,i), True)
注意cv.RETR_TREE查找轮廓后轮廓是从外到内的排列顺序,那么contours[1]就是六边形的内边轮廓
第三步:获取轮廓内部距离轮廓最远的点(作为内切圆圆心)和最小距离(作为内切圆半径),绘制内切圆
# 获取最大值即内接圆半径,中心点坐标
minVal, maxVal, _, maxDistPt = cv.minMaxLoc(raw_dist)
minVal = abs(minVal)
maxVal = abs(maxVal)
result = cv.cvtColor(src,cv.COLOR_GRAY2BGR)
cv.circle(result,maxDistPt, np.int(maxVal),(0,255,0), 2, cv.LINE_8, 0)
cv.imshow('result', result)
最终效果:
当然,如果你还想获取外接圆,直接调用函数cv2.minEnclosingCircle(即可),下面是代码演示和效果:
center, radius = cv.minEnclosingCircle(contours[0])
cv.circle(result,(int(center[0]),int(center[1])),int(radius),(0,0,255),2)
完整代码:
import cv2 as cv
import numpy as np
# Create an image
r = 100
src = np.zeros((4*r, 4*r), dtype=np.uint8)
# Create a sequence of points to make a contour
vert = [None]*6
vert[0] = (3*r//2, int(1.34*r))
vert[1] = (1*r, 2*r)
vert[2] = (3*r//2, int(2.866*r))
vert[3] = (5*r//2, int(2.866*r))
vert[4] = (3*r, 2*r)
vert[5] = (5*r//2, int(1.34*r))
# Draw it in src
for i in range(6):
cv.line(src, vert[i], vert[(i+1)%6], ( 255 ), 3)
cv.imshow("src", src)
# Get the contours
_, contours, _ = cv.findContours(src, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
# Calculate the distances to the contour
raw_dist = np.empty(src.shape, dtype=np.float32)
for i in range(src.shape[0]):
for j in range(src.shape[1]):
raw_dist[i,j] = cv.pointPolygonTest(contours[1], (j,i), True)
# 获取最大值即内接圆半径,中心点坐标
minVal, maxVal, _, maxDistPt = cv.minMaxLoc(raw_dist)
minVal = abs(minVal)
maxVal = abs(maxVal)
result = cv.cvtColor(src,cv.COLOR_GRAY2BGR)
center,radius = cv.minEnclosingCircle(contours[0])
cv.circle(result,(int(center[0]),int(center[1])),int(radius),(0,0,255),2)
cv.circle(result,maxDistPt, np.int(maxVal),(0,255,0), 2, cv.LINE_8, 0)
cv.imshow('result', result)
cv.waitKey(0)
cv.destroyAllWindows()