如何使用opencv查找图像中所有圆的所有接触点

时间:2015-11-04 03:54:56

标签: python opencv image-processing

这是图像,我想找到这个图像中的所有接触点,我知道每个圆的中心和半径。在我看来,欧氏距离可能不是计算中心到中心的有效方法所以,我的问题是如何以有效的方式找到这张图片的所有接触点。谢谢。

enter image description here

2 个答案:

答案 0 :(得分:3)

圈'接触点将放置在从center1到center2的线上。因此,例如,如果两个圆圈都具有samze大小,您可以选择intersection = center1 + 1/2*(center2-center1)但是由于您的圈子大小不同,您可以选择以下内容:

compute dirVector = center2-center1
compute d = |dirVector|
if d < radius1 + radius2 + threshold: consider circles to intersect so now compute contact point
    gap = d - radius1 - radius2 // remark: here gap might become < 0 which is ok
    contactPoint = center1 + (radius1+gap/2)*(dirVector/d)

我已经用原始C ++代码测试了这种方法,并且我得到了这个结果:

enter image description here

绿色圆圈是您的原始图像,红色圆圈是我提取的圆圈(不完美但很简单),粉红色圆点是contact points,用于某些接触距离阈值(20像素)

这是接触距离阈值低得多的结果(5)(但请记住,我提取的圆半径比你的低一点):

enter image description here

为了提高效率(因为你必须比较每对圆圈,不管它们有多远=&gt; O(n²))你应该使用某种二进制空间分区,如:

KD-Tree

Quad-Tree

或类似的

或尝试Spatial Hashing,但这些更适合稀疏区域。

一般情况下,您可能希望搜索碰撞检测优化以加快速度(在那里您可以找到有关二进制空间分区和空间散列的更多信息)。

由于你的空间非常丰富,你也可以考虑一个简单的网格(在这种情况下类似于空间哈希):

//choose size of each grid cell to be the maximum found radius of all your circles.
gridCellSize = max diameter + contact-threshold-distance // radius was wrong I think
for each circle
    indexX = round(center.x/gridCellSize)
    indexY = round(center.y/gridCellSize)
    grid[x,y].push_back(current circle)

for each circle in a grid-cell:
    compare this circle to each other circle in the cell
    compare this circle to each circle in all surrounding cells
    ignore all circles in all other cells

对于我之前的例子我已经提取了44像素的最大半径(你的像素可能是47像素,具体取决于你用来绘制圆圈的线条大小。

因此计算出这样的网格:

enter image description here

例如,如果网格为0索引,则在网格单元格位置(1,1)中,有2个圆圈。应将它们中的每一个与同一细胞中的所有圆形和周围细胞中的每个圆形进行比较。因此,这2个圈子只会与12个圈子进行比较,而不是n-1圈子。

或以图形标记的示例:红色单元格中的所有圆圈必须与周围蓝色单元格中的每个圆圈进行比较,此外还要与红色单元格中的其他圆圈进行比较(在此示例中均为无):

enter image description here

答案 1 :(得分:1)

有几种方法可以尝试此问题:

  1. 正如您所说,圆圈的半径和中心,这意味着您有圆的边界(圆周坐标)。这意味着您可以知道哪个坐标属于哪个圆圈,因此您可以使用此信息找到交叉点。

  2. 你可以对图像进行分割,然后根据圆度进一步区分它们,圆形的斑点将它们移除。现在你将拥有所有那些不遵循圆度的斑点(因为圆圈已经连接在一起),所以你可以再次应用第1步,现在检查交叉点的点数非常少。

  3. 分水岭算法比上述方法复杂,但您可以尝试一下,为此您可以创建一个图像,您可以使用它们的中心和半径绘制所有这些圆(此图像将是二进制图像)填充所有圆圈并使用中心作为分水岭的种子应用分水岭算法,它将为您提供两个对象加入的坐标。

  4. 在我看来,你可以使用方法1或2解决问题。

    谢谢

相关问题