算法从坐标中获取第一,第二,第三个邻居

时间:2013-04-22 18:03:26

标签: c# image algorithm image-processing

在每个像素的位图中,我试图获得它的第一个,第二个,第三个......级别的邻居,直到位图结束,但我的解决方案有点慢,所以让我知道是否有任何你们有更好的算法或方法:

example

private IEnumerable<Point> getNeightboorsOfLevel(int level, Point startPos, Point[,] bitMap)
{
    var maxX = bitMap.GetLength(0);
    var maxY = bitMap.GetLength(1);
    if (level > Math.Max(maxX, maxY)) yield break;

    int startXpos = startPos.X - level;
    int startYpos = startPos.Y - level;
    int sizeXY = level * 2;

    var plannedTour = new Rectangle(startXpos, startYpos, sizeXY, sizeXY);
    var tourBoundaries = new Rectangle(0, 0, maxX, maxY);

    for(int UpTour  = plannedTour.X; UpTour<plannedTour.Width; UpTour++) 
        if (tourBoundaries.Contains(UpTour,plannedTour.Y)) 
            yield return bitMap[UpTour,plannedTour.Y];

    for(int RightTour  = plannedTour.Y; RightTour<plannedTour.Height;RightTour++)
        if (tourBoundaries.Contains(plannedTour.Right,RightTour)) 
            yield return bitMap[plannedTour.Right,RightTour];

    for(int DownTour  = plannedTour.X; DownTour<plannedTour.Width;DownTour++)
        if (tourBoundaries.Contains(DownTour,plannedTour.Bottom)) 
            yield return bitMap[DownTour,plannedTour.Bottom];

    for (int LeftTour = plannedTour.Y; LeftTour < plannedTour.Height; LeftTour++)
        if (tourBoundaries.Contains(plannedTour.X,LeftTour)) 
            yield return bitMap[plannedTour.X,LeftTour];

}

2 个答案:

答案 0 :(得分:6)

好吧,如果这太慢了,你可能想改变你的方法。

例如,生成Dictionary<Color, List<Point>>,其中位图中的每种颜色都有一个作为该颜色的点列表。然后,当您获得一个点时,您将获得颜色,然后浏览点列表以找到与给定点最接近的点。

这是对图像进行1次预计算,然后将复杂度更改为相同颜色的点数。我现在假设它很慢,因为你必须看很多点,因为很难找到一个颜色相同的点。

答案 1 :(得分:0)

加快速度的一种方法是让plannedTour包含边界。例如:

var plannedTour = new Rectangle(
    Math.Max(0, startPos.X - level),
    Math.Max(0, startPos.Y - level),
    Math.Min(maxX, startPos.X + level),
    Math.Min(maxY, startPos.Y + level));

预先计算边界并防止您必须在每次循环迭代时进行检查。例如,它还可以为您保存整个Left游览。

如果这样做,则需要if语句来防止检查边界之外的区域。例如:

if (plannedTour.Y >= minY)
{
    // do Up tour.
}
if (plannedTour.X <= maxX)
{
    // do Right tour
}
if (plannedTour.Y <= maxY)
{
    // do Down tour
}
if (plannedTour.X >= minX)
{
    // do Left tour
}

一个小的优化是消除你正在检查的四个额外像素。它看起来好像你正在检查每个角落两次。您可以通过在plannedTour.Y+1开始向左和向右导览并在plannedTour.Bottom-1结束来阻止此操作。

通过使用严格的从左到右,从上到下的检查,您可以节省一些时间,尽管它可能很小。也就是说,检查向上行,然后在下一行检查左右像素,然后检查下一行等,最后检查底行。这样做可能会为您提供更好的缓存一致性,因为bitMap[x-level, y]bitmap[x+level, y]可能位于同一缓存行中,而bitmap[x-level, y]bitmap[x-level, y+1]极不可能在同一个缓存行上。通过这种方式进行内存访问所带来的节省可能不值得增加编码的复杂性。