如何基于Y轴坐标值将OpenCV检测的圆形坐标按行聚类?
按行聚类旋转后的圆形坐标DataFrame
我有一个存储X、Y坐标的DataFrame,这些坐标是OpenCV Python检测到的圆形,它们构成清晰的行列结构,我希望将它们按行聚类。不过有时这些坐标会出现轻微旋转(顺时针或逆时针均可)。请问最简单的按行分组方式是什么?
示例DataFrame:
import pandas as pd sample=pd.DataFrame({ 'X_center': {72: 0.098054, 137: 0.112574, 254: 0.14442, 322: 0.113445, 365: 0.113445, 370: 0.188365, 384: 0.158165, 386: 0.173459, 401: 0.040267, 405: 0.128303, 408: 0.128352, 415: 0.174039, 451: 0.187688, 454: 0.159326, 482: 0.158213, 500: 0.024828, 519: 0.010309, 603: 0.08489, 606: 0.188946, 613: 0.128932, 684: 0.114026, 688: 0.141709, 717: 0.172878, 738: 0.143113, 816: 0.054787, 824: 0.157778, 841: 0.187639, 876: 0.069064, 890: 0.128448, 908: 0.024247, 937: 0.186865, 939: 0.083293, 964: 0.069306, 974: 0.098587, 976: 0.158794, 1035: 0.171474, 1037: 0.084842, 1097: 0.143016, 1100: 0.159181, 1106: 0.054835, 1111: 0.173652, 1189: 0.114413, 1199: 0.113639, 1209: 0.025312, 1214: 0.084067, 1283: 0.156326, 1313: 0.127142, 1447: 0.099313, 1494: 0.142145, 1535: 0.083922, 1557: 0.174426, 1580: 0.172733, 1607: 0.114413, 1618: 0.039009, 1626: 0.055609, 1820: 0.0997, 1866: 0.043945, 1877: 0.070322, 1890: 0.084842, 1909: 0.128448, 1951: 0.173217, 1952: 0.144275, 1978: 0.052221, 1988: 0.112235, 2002: 0.127384, 2063: 0.009825, 2106: 0.129174, 2113: 0.005033, 2137: 0.158939, 2182: 0.010357}, 'Y_center': {72: 0.118009, 137: 0.101591, 254: 0.197024, 322: 0.118112, 365: 0.150077, 370: 0.148589, 384: 0.117599, 386: 0.148999, 401: 0.199025, 405: 0.117137, 408: 0.13371, 415: 0.180605, 451: 0.116983, 454: 0.196614, 482: 0.13335, 500: 0.060595, 519: 0.198923, 603: 0.18235, 606: 0.1804, 613: 0.165623, 684: 0.165829, 688: 0.054284, 717: 0.117394, 738: 0.118266, 816: 0.182863, 824: 0.101796, 841: 0.085428, 876: 0.150539, 890: 0.149615, 908: 0.038122, 937: 0.053207, 939: 0.118676, 964: 0.166855, 974: 0.150077, 976: 0.149666, 1035: 0.037917, 1037: 0.166496, 1097: 0.149359, 1100: 0.165469, 1106: 0.166496, 1111: 0.164802, 1189: 0.181632, 1199: 0.133915, 1209: 0.18312, 1214: 0.134582, 1283: 0.038019, 1313: 0.102258, 1447: 0.166034, 1494: 0.086455, 1535: 0.150128, 1557: 0.196408, 1580: 0.101539, 1607: 0.197383, 1618: 0.120062, 1626: 0.198102, 1820: 0.197435, 1866: 0.038481, 1877: 0.198102, 1890: 0.197281, 1909: 0.08589, 1951: 0.133043, 1952: 0.181683, 1978: 0.087276, 1988: 0.039251, 2002: 0.054797, 2063: 0.15136, 2106: 0.197075, 2113: 0.082555, 2137: 0.181016, 2182: 0.167317}}
实操方法:PCA投影+K-means聚类
针对旋转后的行列结构,最简单的分组方式是通过**主成分分析(PCA)**找到垂直于行的方向,将点投影到该方向后做聚类,具体步骤如下:
1. 核心思路
旋转后,同一行的点在垂直于行的方向上的位置高度一致,PCA能自动识别这个垂直方向,投影后的数据会形成明显的簇,直接用K-means就能完成分组。
2. 代码实现
import pandas as pd import numpy as np from sklearn.decomposition import PCA from sklearn.cluster import KMeans # 提取坐标矩阵 coords = sample[['X_center', 'Y_center']].values # 拟合PCA,获取主成分 pca = PCA(n_components=2) pca.fit(coords) # 第二主成分是垂直于行的方向 vertical_axis = pca.components_[1] # 计算每个点在垂直轴上的投影值 projections = coords.dot(vertical_axis) # 假设已知行数为6(可根据实际数据调整,或用肘部法确定K值) n_rows = 6 # 对投影值做K-means聚类 kmeans = KMeans(n_clusters=n_rows, random_state=42) sample['row_group'] = kmeans.fit_predict(projections.reshape(-1, 1)) # 查看分组结果 print(sample[['X_center', 'Y_center', 'row_group']])
3. 简化替代方案(已知行数时)
如果明确知道行数,也可以直接对投影值做分箱,无需K-means:
sample['projection'] = projections # 按投影值排序后分箱 sample = sample.sort_values('projection') sample['row_group'] = pd.qcut(sample['projection'], q=n_rows, labels=False)
效果说明
- 不管数据怎么旋转,PCA都会自动捕捉到行列的垂直方向,保证同一行的点投影值聚集。
- 一维数据的聚类计算速度极快,结果稳定,适合处理这类规则结构的坐标数据。
内容的提问来源于stack exchange,提问作者datasciencefordummies
相关产品推荐
相关产品推荐

