适合圈内图像。循环退出条件

时间:2015-02-02 21:58:43

标签: python image-processing optimization numpy mathematical-optimization

我正在尝试编写一些代码来检查我的圆圈是否适合二进制掩码。

所以,我有一个给定中心和半径的圆。我也有一个二进制图像,我可以绘制它,看到圆圈适合面具。情节附后:

enter image description here

所以我要做的就是找到适合这个二元模板的最佳圆圈。那么,到目前为止我所拥有的内容如下:

import numpy as np
# Start with a random radius
radius = 100
# Keep track of the best radius
best_radius = 0
# Mask is the binary mask
x, y = np.ogrid[:mask.shape[0], :mask.shape[1]]
# distance computation
distance = np.sqrt((x-r)**2 + (y-c)**2)

while True:
    # check if the distance < radius
    m = distance < radius
    # if this is true everything in the circle is in the image
    if np.all[mask[m] > 0]:
        # Update best radius
        best_radius = radius
        # Increase radius for next try
        radius += radius/2
    else:
        # decrease radius
        radius -= radius/2
        if radius <= best_radius:
            break

所以,我遇到的第一个问题是休息条件。虽然它的工作原理总是让我得到一个圆圈,它在面具内部,但并不总是最佳的。因此,在上面的示例中运行它,我得到以下最佳圆圈:

enter image description here

如您所见,半径可以增加。所以,我感觉我增加和减少半径的方式是不正确的。

另一个重要的问题是,这是一种非常愚蠢的方式,以粗暴的野蛮人的方式做到这一点。如果有人有更优雅的解决方案来分享,我将非常感激。也许,这里可以采用一些数值优化程序?

1 个答案:

答案 0 :(得分:1)

  • 计算从每个非遮罩点到(r,c)的距离。
  • 最大半径是距离的最小值。

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as patches

h, w = 600, 700
r, c = 250, 350

def make_mask():
    x, y = np.ogrid[:h, :w]
    y -= c
    x -= r
    theta = np.arctan2(y, x)
    rad = 200 + 100*(np.sin(theta+np.pi/2)**2) 
    mask = (x**2 + y**2) < rad**2
    return mask

mask = make_mask()
x, y = np.ogrid[:h, :w]
distance_sq = (x-r)**2+(y-c)**2
radius = np.sqrt((distance_sq[~mask]).min())

fig, ax = plt.subplots()
ax.imshow(mask)
ax.add_patch(patches.Circle((c,r), radius=radius))
plt.show()


yields

enter image description here