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

OpenCV中如何按特定顺序获取畸变网格排列圆形的圆心

OpenCV中如何按特定顺序获取畸变网格排列圆形的圆心

嘿,针对你遇到的这个畸变网格圆形的圆心排序问题,我刚好有几个实用的方案可以分享!确实findCirclesGrid对规整网格依赖很强,一旦有畸变就容易失效,而Blob检测只会给出零散的圆心坐标,自带排序逻辑。下面是两种靠谱的解决思路:

方法一:K-means聚类分组行,再逐行排序

这个方法的核心是先把同一行的圆心归为一组,再对每行的点按x坐标排序,最后按行的上下顺序拼接结果,步骤如下:

  1. 准确检测所有圆心:先用Blob检测或者HoughCircles算法提取出所有圆形的圆心坐标,得到一个(x,y)的坐标列表。
  2. 按y坐标聚类分组:利用K-means聚类,把y值相近的圆心划分到同一行里——你可以先观察图像预估行数,也可以用肘部法则自动确定聚类数量。
  3. 排序行与每行点:先按每行的平均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值突变的行分割法

如果你的网格行间距相对规律,只是局部有畸变,可以试试这个更轻量的方法:

  1. 先按y值排序所有圆心:把所有圆心按y坐标从小到大排列。
  2. 找行的分割点:计算相邻圆心的y值差,找到那些远大于平均差值的突变点,这些点就是行与行的分隔处。
  3. 逐行按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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.16 09:54:31