You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 03:10:11