目的:求得无序点集的最小外接多边形
- cv.approxPolyDP该函数输入的点击为有序点集才能得到外接多边形;
- 本文得到的mask可作为分割标签。
算法详解
- 找到一个边界点:xmax,xmin, ymax,ymin都可以
- 找第二个边界点,例如:1步骤中找到ymin后,遍历所有点,寻找到一点,使这点与ymin的线段与水平的夹角最小;
- 针对上两个边界点AB,找下一个边界点C 使脚ABC最大,接近180度;可以使用余弦定理
- 当找到的边界点为最初的ymin时,结束查找,把以上边界点按次序导出
代码
import math
import cv2
import numpy as np
poly = []
def compute_theta(cor1, cor2, cor3, cor4):
'''
cor: [x,y], 计算向量 cor1->cor2和cor3->cor4的夹角
'''
a1_x = cor2[0] - cor1[0]
a1_y = cor2[1] - cor1[1]
a2_x = cor4[0] - cor3[0]
a2_y = cor4[1] - cor3[1]
c_theta = (a1_x * a2_x + a1_y * a2_y) / (math.sqrt(a1_x * a1_x + a1_y * a1_y) * math.sqrt(a2_x * a2_x + a2_y * a2_y))
theta = math.acos(c_theta) * 180 / math.pi
return theta
# 返回点集最上面的两个点,作为开始
def get_start_pts(lines):
min_value = 9999
for pt in lines:
if pt[1] < min_value:
min_value = pt[1]
startp1 = pt
min_value = 9999
for pt in lines:
if pt[1] < min_value and pt[1]!=startp1[1]:
min_value = pt[1]
startp2 = pt
poly.append(startp1)
poly.append(startp2)
return startp1,startp2
# 迭代求取角度最大的点
def get_polygon(lines,pt1,pt2):
if len(poly) > 1 and poly[0][0] == poly[-1][0] and poly[0][1] == poly[-1][1]:
return
max_theta = 0
next_pt = []
for pt in lines:
if (pt[0] == pt1[0] and pt[1] == pt1[1]) or (pt[0] == pt2[0] and pt[1] == pt2[1]): # 排除送进来的两个点
continue
theta = compute_theta(pt2,pt1,pt2,pt)
if theta > max_theta:
max_theta = theta
next_pt = pt
poly.append(next_pt)
get_polygon(lines,pt2,next_pt)
return
img = cv2.imread('court-detection/input/0000000001.jpg')
mask = np.zeros_like(img)
f = open('court-detection/input/0000000001.txt') # 图片中的直线,起点终点
files = f.read().splitlines()
lines = [] # 无序点集
for i in files:
x1 = int(i.split(',')[0])
y1 = int(i.split(',')[1])
x2 = int(i.split(',')[2])
y2 = int(i.split(',')[3])
lines.append([x1,y1])
lines.append([x2,y2])
p1,p2 = get_start_pts(lines)
get_polygon(lines,p1,p2)
cv2.fillConvexPoly(mask, np.array(poly,dtype=np.int32), (1,1,1))
mask = (mask[...,0])[...,None]
cv2.imshow('w',mask*255)
cv2.waitKey(0)
cv2.imshow('w',img*mask)
cv2.waitKey(0)
结果展示
原图:
mask:
结果:
最后,代码图片txt在我的百度云盘,有用的话希望读者点个赞收藏一下哦:
链接: https://pan.baidu.com/s/1cfffEwZCOy8uTZ5wMAiwsA 提取码: cwqp