【问题标题】:algorithm to get first, second, third neighbors from a coordinate从坐标中获取第一个,第二个,第三个邻居的算法
【发布时间】:2013-04-15 17:53:05
【问题描述】:

在每个像素的位图中,我正在尝试获取其第一、第二、第三...级别的邻居,直到位图结束,但我的解决方案有点慢,所以如果有任何问题,请告诉我你们有更好的算法或方法来做到这一点:

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];

}

【问题讨论】:

  • 如果像素 P 比 N 更接近边缘,你想对第 N 级邻居做什么?您只想报告边界内的像素吗?
  • 是的,但更具体地说,我正在尝试找到最近的具有相同颜色的像素。
  • 您可以使用 Min 和 Max 将您计划的Tour 剪辑到前面的 tourBoundaries,从而消除循环内的 if (tourBoundaries.Contains(... 检查。

标签: c# image algorithm image-processing


【解决方案1】:

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

例如,生成一个Dictionary&lt;Color, List&lt;Point&gt;&gt;,对于位图中的每种颜色,它都有一个该颜色的点列表。然后当你得到一个点时,你会得到颜色,然后遍历点列表以找到最接近给定点的点。

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

【讨论】:

    【解决方案2】:

    加快速度的一种方法是让您的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 结束来防止这种情况发生。

    通过使用严格的从左到右、从上到下的检查,您也许可以节省一些时间,尽管时间可能会很少。即检查Up行,然后在下一行检查左右像素,然后是下一行,以此类推,最后检查底行。这样做可能会为您提供更好的缓存一致性,因为bitMap[x-level, y]bitmap[x+level, y] 可能位于同一缓存行上,而bitmap[x-level, y]bitmap[x-level, y+1] 不太可能位于同一缓存行上。以这种方式进行内存访问所节省的成本可能不值得增加编码的复杂性。

    【讨论】:

      猜你喜欢
      • 2017-03-11
      • 1970-01-01
      • 1970-01-01
      • 2020-07-05
      • 2014-11-18
      • 1970-01-01
      • 2023-03-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多