图像内的拟合圆。循环的退出条件
Fitting circle inside image. Exit condition for loop
我正在尝试编写一些代码来检查我的圆圈是否适合二进制掩码。
所以,我有一个具有给定圆心和半径的圆。我还有一个二值图像,我可以绘制它并看到圆圈适合掩码。附剧情:
所以我要做的是找到适合这个二元掩码的最佳圆。所以,我到目前为止的情况如下:
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
所以,我遇到的第一个问题是中断条件。虽然它的工作原理总是让我得到一个圆圈,它在面具内,但它并不总是最佳的。所以,运行 在上面的例子中,我得到以下最佳圆:
如您所见,半径仍然可以增加。所以,我感觉我递增和递减半径的方式不对。
另一个大问题是,这是一种非常 hacky 的方式,以一种野蛮的方式来做到这一点。如果有人可以分享更优雅的解决方案,我将不胜感激。也许,这里可以使用一些数值优化程序?
- 计算每个非屏蔽点到
(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
我正在尝试编写一些代码来检查我的圆圈是否适合二进制掩码。
所以,我有一个具有给定圆心和半径的圆。我还有一个二值图像,我可以绘制它并看到圆圈适合掩码。附剧情:
所以我要做的是找到适合这个二元掩码的最佳圆。所以,我到目前为止的情况如下:
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
所以,我遇到的第一个问题是中断条件。虽然它的工作原理总是让我得到一个圆圈,它在面具内,但它并不总是最佳的。所以,运行 在上面的例子中,我得到以下最佳圆:
如您所见,半径仍然可以增加。所以,我感觉我递增和递减半径的方式不对。
另一个大问题是,这是一种非常 hacky 的方式,以一种野蛮的方式来做到这一点。如果有人可以分享更优雅的解决方案,我将不胜感激。也许,这里可以使用一些数值优化程序?
- 计算每个非屏蔽点到
(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