2013-04-22 159 views
2

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

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

如果像素P比N更靠近边缘,那么您想如何处理第N级邻居?你想仅报告边界内的像素吗? – Floris 2013-04-22 18:06:57

+0

是你的问题,但更具体的 即时通讯寻找具有相同颜色的最近像素。 – elios264 2013-04-22 18:09:13

+0

你可以使用Min和Max来将你的计划图片剪辑到tourBoundaries前面,这样你就可以消除循环内的if(tourBoundaries.Contains(...)。 – mbeckish 2013-04-22 18:28:00

回答

6

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

例如,生成一个Dictionary<Color, List<Point>>这对于位图中的每一种颜色都有其是色点的列表。然后,当你得到一个点时,你会得到颜色,然后遍历点列表以找到距离给定点最近的点。

这是您的图像上的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来防止该情况。

你也许可以节省一些时间,但它很可能会很小,用严格的左到右,上到下的检查。也就是检查Up行,然后在下一行检查左右像素,然后检查下一行等,最后检查最下面一行。这样做可能会给你更好的缓存一致性,因为它很可能是bitMap[x-level, y]bitmap[x+level, y]将在同一高速缓存行,而这是极不可能的,bitmap[x-level, y]bitmap[x-level, y+1]将在同一高速缓存行。通过这种方式进行内存访问所节省的成本可能不值得增加编码的复杂性。

相关问题