检查特定半径范围内所有像素的最佳方法是什么?

时间:2015-07-25 16:32:10

标签: algorithm area euclidean-distance

我目前正在开发一个应用程序来提醒用户下雨。为此,我想检查用户位置周围的某些区域是否有降雨(降雨雷达图像上强度的不同像素颜色)。我希望选中的区域是一个圆圈,但我不知道如何有效地做到这一点。

假设我想检查半径50km。我目前的想法是拍摄尺寸为100kmx100km(用户+西50km,用户+北50km,用户+南50km)的图像子集,然后检查该子集中的每个像素是否接近用户而不是50km。

我的问题是,有没有更好的解决方案用于此类问题?

4 个答案:

答案 0 :(得分:3)

如果您正在搜索的事件(下雨或其他任何事件)发生的情况相对较少,那么扫描 square 或像素并没有问题,然后,只有在检测到雨后在那个方格中,检查下雨是否在所需的50公里圈内。请注意,此处的关键点是,您不需要检查广场的每个像素是否在圈内(效率非常低),您必须搜索您的事件(雨)首先,只有当你找到它时,检查它是否落入50公里的圆圈。为了有效地实现这一点,您还必须开发一些智能策略来处理多像素"污渍"你的形象下雨。

但是,由于您正在扫描光栅图像,因此可以轻松实现众所周知的Bresenham circle algorithm以查找每条扫描线的圆的起点和终点。这样,您可以轻松地将扫描限制在所需的50公里半径范围内。

在第二个想法中,你甚至不需要Bresenham算法。对于方形中的每一行像素,计算该行与50km圆的交点(使用通常的平方根教科书公式),然后检查落在这些交点之间的所有像素。以相同的方式处理所有行,您就完成了。

P.S。不幸的是,我链接的维基百科页面根本没有提供Bresenham算法。它具有代码为Michener circle算法。米歇尔算法也适用于圆光栅化目的,但它不如Bresenham算法精确。如果您关心精确度,请在某处找到真正的Bresenham。实际上,在网上找到令人惊讶的难度:大多数搜索命中错误地将米歇尔视为布雷森汉姆。

答案 1 :(得分:1)

有,你可以修改midpoint circle algorithm给你一个每个y的数组,圆圈开始的x坐标(并且结束,由于对称性,它是相同的东西)。这个数组很容易计算,下面是伪代码。

然后你可以完全迭代正确的部分,而无需检查任何东西。

伪代码:

data = new int[radius];
int f = 1 - radius, ddF_x = 1;
int ddF_y = -2 * radius;
int x = 0, y = radius;
while (x < y)
{
    if (f >= 0)
    {
        y--;
        ddF_y += 2; f += ddF_y;
    }
    x++;
    ddF_x += 2; f += ddF_x;
    data[radius - y] = x; data[radius - x] = y;
}

答案 2 :(得分:0)

也许您可以尝试一些可以加速算法的方法。

在强力算法中,您可能会使用等式:

(x-p)^2 + (y-q)^2 < r^2
(p,q) - center of the circle, user position
r - radius (50km)

如果你想找到满足上述条件的所有像​​素(x,y)并检查它们,你的算法会转到O(n ^ 2)

我只会检查圆圈边框上的像素,而不是扫描此圆圈中的所有像素。

在这种情况下,您可以使用更聪明的方式来定义圆圈。

x = p+r*cos(a)
y = q*r*sin(a) 
a - angle measured in radians [0-2pi]

现在你可以采样一些角度,例如其中的20个,迭代并找到半径为50km的所有边界(x,y)。现在检查它们是否在雨区并提醒用户。

为了更安全,我建议你使用多个弧度(小于50公里),因为你的整个雨云可能在圆圈内,你的应用程序将无法识别他。例如,使用3个环(r = 5km,15km,30km)并做同样的事情。该算法的效率仅取决于角度数和圈数。

伪代码将是:

checkRainDanger()
  p,q <- position
  radius[] <- array of radii
  for c = 1 to length(radius)
    a=0
    while(a<2*pi)
      x = p + radius[c]*cos(a)
      y = q + radius[c]*sin(a)
      if rainZone(x,y)
        return true
      else          
        a+=pi/10
    end_while
  end_for
  return false //no danger

答案 3 :(得分:-1)

r2=r*r
for x in range(-r, +r):
  max_y=sqrt(r2-x*x)
  for y in range(-max_y, +max_y):
    # x,y is in range - check for rain