如何顺时针或者逆时针记录多边形的每个点
问题定义:
按照顺时针或者逆时针提取多边形的各个顶点
问题解决:
针对一个凸多边形,假设多边形的中心为C,多边形的任意一个顶点为A
做一个辅助点,假设有一条水平线通过中心点C,并在c点右边设一个B点
这样,可以通过 与 的夹角确定A点的角度,这样根据不同位置的顶点就能得到其夹角。
具体python实现:
# -*- coding: utf-8 -*-
import numpy as np
import cv2
import cv2 as cv
from sklearn.cluster import DBSCAN
import copy
def obtain_corners(mask):
dst = cv.cornerHarris(mask,5,5,0.04)
# 设置阈值,将角点绘制出来,阈值根据图像进行选择
pos = np.where(dst>0.001*dst.max())
x = pos[1]
y = pos[0]
epsilon = 2
min_samples=1
ou = np.concatenate((x.reshape(-1,1),y.reshape(-1,1)), axis=1)
db = DBSCAN(eps=epsilon, min_samples=min_samples).fit(ou)
_labels = db.labels_
points_poly = np.zeros([0,2], dtype=np.float32)
for i in range(_labels.max()+1):
vv = np.mean(ou[np.where(_labels == i)[0], :], 0)
points_poly = np.concatenate((points_poly, vv.reshape(1,2)), axis=0)
return points_poly
def dot_product_angle(v1, v2):
if np.linalg.norm(v1) == 0 or np.linalg.norm(v2) == 0:
print("Zero magnitude vector!")
else:
vector_dot_product = np.dot(v1, v2)
arccos = np.arccos(vector_dot_product / (np.linalg.norm(v1) * np.linalg.norm(v2)))
angle = np.degrees(arccos)
return angle
return 0
def obtain_vector(a, b, center):
aa = copy.deepcopy(a)
bb = copy.deepcopy(b)
aa[0] = center[0] - aa[0]
aa[1] = center[1] - aa[1]
bb[0] = center[0] - bb[0]
bb[1] = center[1] - bb[1]
return aa, bb
# load image
large = cv2.imread('ss_big.png', 0)
# obtain corners
points_poly = obtain_corners(large)
_, temp_bin = cv2.threshold(large, 126, 255, cv2.THRESH_BINARY)
num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(temp_bin, connectivity=8)
# obtain the center
center = centroids[1, :]
# save angle
angle = []
b = np.array([center[0] + 10, center[1]], dtype=np.float32)
for i in range(points_poly.shape[0]):
aa, bb = obtain_vector(points_poly[i,:], b, center)
angle_ = dot_product_angle(aa, bb)
#print(points_poly[i,:])
if points_poly[i,1] > center[1]:
angle_ += 180
angle.append(angle_)
index_ = np.argsort(np.array(angle, dtype=np.float32))
# sorted by angle
pos_poly = points_poly[index_,:]
print(pos_poly)
结果:
[[1761.5 651.125 ]
[1562.43636364 592.49090909]
[1489.41666667 514.9375 ]
[1527.11111111 310.44444444]
[1499.36363636 272.04545455]
[1261.42857143 219.03571429]
[1224.15 234.15 ]
[1180. 416.66666667]
[ 890.18181818 395.42424242]
[1638.48484848 1105.84848485]
[1432.53061224 1043.44897959]
[1360.25 1078.85 ]
[1303.54166667 1246.16666667]
[1240.48 1267.46 ]
[ 965.09090909 1175.6969697 ]
[1015.73076923 1001.42307692]
[ 978.5 904.55555556]
[ 793.65714286 833.8 ]]