【问题标题】:Algorithm to find Circle in Array在数组中查找圆的算法
【发布时间】:2016-11-22 10:30:57
【问题描述】:

我有一个包含 600x600 整数值的数组。 这些值代表一个圆圈。 例如:0 是在圈外,>=1 是圈内。 这是一个简短的例子:

0000110000000
0001111000000
0011111200000
0112112110000
1111111111000
0111411110000
0011131100000
0000110000000
0000000000000
0000000000000

圆在数组中的位置和大小不同。 现在,我正在寻找一种快速算法来找到圆的中心和半径。 快,因为我必须处理许多数组。

【问题讨论】:

  • 你给出的例子在正常情况下没有中间或半径,
  • 在开始寻找算法之前,您需要先解决中间和半径的含义。这取决于您是否希望将整数或双精度值作为中心和半径的值。你如何处理分数以及你允许多少模糊等等。有几种算法可以做到这一点,但它们都带有假设。
  • 您可以使用Circle Hough Transform
  • 同意@LURD - 如果这是一个模糊问题,那么霍夫圆变换可能是最好的答案。在OpenCV中实现,省了很多工作。

标签: arrays algorithm delphi pascal


【解决方案1】:

叠加一个网格,遍历它,(小矩阵:每行和每列,大矩阵每 X 行和每列)并找到发生变化的点(0 -> >=1,反之亦然)。

如果您的网格足够对称且足够密集,则这些点的平均值等于中心。

找到的点到中心的平均距离( sqrt(sqr(x-xm)+sqr(y-ym))) 是半径的度量。

对于较大的数据集,单独遍历行可能就足够了,并且您只扫描第 X 行。如果您使用真实图像,则可能需要考虑噪点和亮度变化。

【讨论】:

  • 谢谢Marco,我会试试的
【解决方案2】:

可以更快地做到这一点。实际上,根据您的样本,是否存在圆形或正方形并不重要(我们不能估计)。

假设有一个基于 0 的二维数组,半径将只是非零(非空)行(或列)的计数除以 2。

算法。

  1. 查找非零行的数量及其第一个(顶部)索引。 将此数字除以 2 并添加索引小于最低非零行的零行数。现在您知道了radiusy 坐标。

  2. 找到第一(左)非零列并将半径添加到其索引。现在你有了x 坐标。

在提供的示例中。

  1. 非零行数为 8。radius 为 8 / 2 = 4。非零行之前有 0 行(即第一个非零行的 ID)为 0)。所以y 坐标是 0 + 4 = 4。
  2. 第一个非零列左侧有 0 个空列(或第一个非零列的 ID 为 0)。 x 坐标将为 4 + 0 = 4。

要知道列是否为零,您可以使用如下函数:

IsEmpty := true;
for i := 0 to High(Column) do
if Column[i] > 0 then
  begin
    IsEmpty := false;
    Break;
  end;

【讨论】:

  • 扫描行,然后列是两次。 a(稍微少一点,因为您可能会在非零时中止)。
  • @MarcovandeVoort 您不会扫描所有行和所有列。您只扫描行直到找到非零之后的第一个空行,并且您只扫描列直到找到第一个非零行。我的意思是,当找到必要的行或列时,您会破坏主要(外部)循环(我的答案中未显示)。在给定的示例中,将只有 9 行扫描和 (5;4;3;2;1;2;3;5;13) 迭代和 1 列扫描 5 迭代。这将只给我们 43 次比较操作的迭代。是不是太多了?所以实际上这个算法在给定数组中的传递少于 1 次。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-19
  • 2015-03-29
  • 2012-09-04
相关资源
最近更新 更多