问题定义:
按照顺时针或者逆时针提取多边形的各个顶点
问题解决:
针对一个凸多边形,假设多边形的中心为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 ]]