OpenCV中如何按特定顺序获取畸变网格排列圆形的圆心
OpenCV中如何按特定顺序获取畸变网格排列圆形的圆心
嘿,针对你遇到的这个畸变网格圆形的圆心排序问题,我刚好有几个实用的方案可以分享!确实findCirclesGrid对规整网格依赖很强,一旦有畸变就容易失效,而Blob检测只会给出零散的圆心坐标,自带排序逻辑。下面是两种靠谱的解决思路:
方法一:K-means聚类分组行,再逐行排序
这个方法的核心是先把同一行的圆心归为一组,再对每行的点按x坐标排序,最后按行的上下顺序拼接结果,步骤如下:
- 准确检测所有圆心:先用Blob检测或者
HoughCircles算法提取出所有圆形的圆心坐标,得到一个(x,y)的坐标列表。 - 按y坐标聚类分组:利用K-means聚类,把y值相近的圆心划分到同一行里——你可以先观察图像预估行数,也可以用肘部法则自动确定聚类数量。
- 排序行与每行点:先按每行的平均y值从小到大排序(确定从上到下的行顺序),再对每行内的点按x坐标从小到大排序(确定左到右的顺序)。
给你一段Python示例代码参考:
import cv2 import numpy as np from sklearn.cluster import KMeans # 读取图像并检测圆心(这里用霍夫圆检测为例,可根据实际调整参数) img = cv2.imread('your_image.jpg', 0) circles = cv2.HoughCircles(img, cv2.HOUGH_GRADIENT, 1, 20, param1=50, param2=30, minRadius=10, maxRadius=50) # 提取圆心的(x,y)坐标 centers = np.uint16(np.around(circles[0])[:, :2]) # 预估图像中的行数,比如你观察到有4行 num_rows = 4 # 基于y坐标进行聚类,把同一行的点归为一类 kmeans = KMeans(n_clusters=num_rows, random_state=0).fit(centers[:, [1]]) labels = kmeans.labels_ # 确定行的上下顺序:按每行的平均y值排序 row_info = [(label, np.mean(centers[labels == label][:, 1])) for label in range(num_rows)] sorted_rows = sorted(row_info, key=lambda x: x[1]) # 逐行排序并拼接结果 ordered_centers = [] for label, _ in sorted_rows: row_points = centers[labels == label] # 按x坐标从小到大排序该行的点 sorted_row = sorted(row_points, key=lambda p: p[0]) ordered_centers.extend(sorted_row) # 最终ordered_centers就是从上到下、每行左到右的有序圆心列表
方法二:基于y值突变的行分割法
如果你的网格行间距相对规律,只是局部有畸变,可以试试这个更轻量的方法:
- 先按y值排序所有圆心:把所有圆心按y坐标从小到大排列。
- 找行的分割点:计算相邻圆心的y值差,找到那些远大于平均差值的突变点,这些点就是行与行的分隔处。
- 逐行按x排序:分割出每行后,再对每行的点按x坐标排序,最后拼接成有序列表。
示例代码片段:
# 按y坐标排序所有圆心 sorted_by_y = sorted(centers, key=lambda p: p[1]) # 计算相邻点的y值差 y_diffs = [sorted_by_y[i+1][1] - sorted_by_y[i][1] for i in range(len(sorted_by_y)-1)] # 确定换行阈值:比如差值大于平均差的2倍时认为是换行 avg_diff = np.mean(y_diffs) split_indices = [i+1 for i, diff in enumerate(y_diffs) if diff > 2 * avg_diff] # 分割成不同的行 rows = [] prev_idx = 0 for idx in split_indices: rows.append(sorted_by_y[prev_idx:idx]) prev_idx = idx rows.append(sorted_by_y[prev_idx:]) # 逐行按x排序并拼接 ordered_centers = [] for row in rows: ordered_row = sorted(row, key=lambda p: p[0]) ordered_centers.extend(ordered_row)
进阶优化:应对严重畸变
如果畸变特别严重,行的y值分布很分散,甚至不是水平的,你可以对每行的点先拟合一条直线,然后把点投影到这条直线上,再按投影距离排序——这样能更精准地还原每行的左到右顺序,避免因行倾斜导致的排序错误。
最后提醒一下:不管用哪种方法,第一步的圆心检测一定要尽量准确,多调整HoughCircles或者Blob检测的参数,确保所有圆形都被检测到,同时减少误检的干扰点。
备注:内容来源于stack exchange,提问作者Vanush Vee
相关产品推荐
相关产品推荐

