[英]Finding the nearest (geometrically) non-zero value in a map/2d array
I have a 2-dimensional array representing selective data from a picture. 我有一个二维数组,表示来自图片的选择性数据。 All the uninteresting data is set to 0. From two indices, I need to find the closest value - geometrically- that is not 0 to the indices (which represent coordinates).
所有无用的数据都设置为0。从两个索引中,我需要找到最接近的值-几何上-到索引(代表坐标)不为0的值。
My method so far is to examine, in circles,the values centered on the point of interest, increasing the radius after every circle pass where no non-zero values are found. 到目前为止,我的方法是以圆为单位检查以兴趣点为中心的值,并在每经过一个没有非零值的圆通过后增加半径。
This method's complexity appears to be exponential, and the program takes a very long time when the nearest point is further than ~25 pixels away. 该方法的复杂度似乎是指数级的,并且当最近点的距离超过约25个像素时,程序将花费很长时间。
Do you have an advice for a different method/an existing algorithm to accomplish this? 您对采用其他方法/现有算法有什么建议吗?
Edit: Per request, my current code is below: 编辑:每个请求,我当前的代码如下:
int height;
int width;
ushort[,] _2dfat;
private ushort getAssociatedFat(int centerX, int centerY)
{
int radiusmax = (int)Math.Ceiling(Math.Sqrt(Math.Pow(height,2) + Math.Pow(width, 2) + 1));
return getAssociatedFat(1, centerX, centerY,radiusmax);
}
private ushort getAssociatedFat(int radius, int centerX, int centerY,int radiusmax) //RECURSIVE METHOD: requires extensive analysis and testing
{
ushort max=circleSym8(centerX, centerY, radius);
if (max != 0) return max;
else if (radius <= radiusmax)
return getAssociatedFat(radius + 1, centerX, centerY, radiusmax);
else
{
MessageBox.Show("WARNING: empty fat array/image");
return 0;
}
}
private ushort getMax(ushort max, int x, int y)
{
try
{
if (_2dfat[y, x] == 0) return max;
else if (_2dfat[y, x] > max) return _2dfat[y, x];
else return max;
}
catch (IndexOutOfRangeException) { return max; }
}
private ushort circleSym8(int xCenter, int yCenter, int radius)
{
int x, y, r2;
r2 = radius * radius;
ushort max=0;
max=getMax(max, xCenter, yCenter + radius);
max = getMax(max, xCenter, yCenter - radius);
max = getMax(max, xCenter + radius, yCenter);
max = getMax(max, xCenter - radius, yCenter);
y = radius;
x = 1;
y = (int)(Math.Sqrt(r2 - 1) + 0.5);
while (x < y)
{
max = getMax(max, xCenter + x, yCenter + y);
max = getMax(max, xCenter + x, yCenter - y);
max = getMax(max, xCenter - x, yCenter + y);
max = getMax(max, xCenter - x, yCenter - y);
max = getMax(max, xCenter + y, yCenter + x);
max = getMax(max, xCenter + y, yCenter - x);
max = getMax(max, xCenter - y, yCenter + x);
max = getMax(max, xCenter - y, yCenter - x);
x += 1;
y = (int)(Math.Sqrt(r2 - x * x) + 0.5);
}
if (x == y)
{
max = getMax(max, xCenter + x, yCenter + y);
max = getMax(max, xCenter + x, yCenter - y);
max = getMax(max, xCenter - x, yCenter + y);
max = getMax(max, xCenter - x, yCenter - y);
}
return max;
}
You could store the interesting data as points in a Quadtree or kd-tree and perform range searches that way. 您可以将有趣的数据作为点存储在四叉树或kd树中,并以这种方式执行范围搜索。 Those data structures are optimized for the sort of lookups you're performing and would reduce the complexity of each search.
这些数据结构已针对您正在执行的查找进行了优化,并会降低每次搜索的复杂性。
I envision a sufficient Quadtree implementation providing the following: 我设想了一个足够的Quadtree实现,它提供了以下内容:
// Given some point in the quadtree, walk upwards and outwards
// returning points found ordered by distance
var nearestNeighbor = quadTree.Neighbors(point)
.OrderBy(pp => point.Distance(pp))
.First();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.