2010-08-11 19 views
1

我正在开发一个应用程序来平分图像网格并居中图像(基于它们的相似性)。到目前为止,我可以设法修复小尺寸的图像网格,但每当我尝试更大的“精灵”尺寸(例如100x100)时,我都会遇到Stack Overflow错误。C# - 寻找一个图像的边界(不是大小)

是的我使用递归,但每当一个像素被选中时,我设置一个布尔值来取消激活它,将它复制到一个列表中,并继续检查其他(全方位),直到列表被填满来自网格的图像。我不确定这是否是每次调用后的最佳方式,我会调用相同的方法7次(假设有7个相邻像素尚未检查),直到没有剩余像素检查为止,并且我可以转到网格中的下一张图片。

我试图跟踪错误发生的位置,它是在检查了1600多个像素并将它们添加到List之后。 MyPixel是含有4个变量的类:X(INT),Y(INT),颜色(色),并检查(布尔)

public void processSprite(int i, int j) 
    { 
     //OOO 
     //OXO 
     //OOO 
     pixeltemp.Add(new MyPixel(imap.pixels[i, j].x, imap.pixels[i, j].y, imap.pixels[i, j].color)); 
     imap.pixels[i, j].read = true; 
     //OOO 
     //OOX 
     //OOO 
     try 
     { 
      if (!imap.pixels[i + 1, j].read) 
      { 
       if (imap.pixels[i + 1, j].color.A == 0) //Found a Border 
       { 
        imap.pixels[i + 1, j].read = true; 
       } 
       else 
       { 
        processSprite(i + 1, j); 
       } 
      } 
     } 
     //... (code goes on) 
    } 
  • pixeltemp是像素的临时列表保持所述图像(List<MyPixel>)
  • IMAP包含整个图像(List<MyPixel>)

我想这不是一个记忆的问题,因为我的应用程序只需要大约16MB的上衣。

我的问题是,为什么我有这个“堆栈溢出”的错误,如果它不是一个无限递归?有没有更简单的方法来做到这一点?我认为我的代码看起来很丑,我不知道如何让它变得更好。

在此先感谢!

+0

我不完全按照你想要完成的。您是否尝试拍摄大图像并将其分割成多个大小相同的区块? – 2010-08-11 17:25:12

+0

@Lucas我在一个图像中有不同图片的网格。例如,一个100x100 PNG图像,大小为10x10px。假设我有一个图像网格,但它们没有对齐,并且具有不同的大小:我试图使它们的大小相同,并根据它们的像素相似性对齐它们。“ – 2010-08-11 17:50:37

回答

1

堆栈溢出不是由无限递归引起的,而是由进程可以处理的更多递归(或者说,调用堆栈)引起的。在你的情况下,每个递归调用processSprite将执行相同数量的递归调用processSprite。所以在1600个像素的最坏的情况没有找到一个边界,您的通话将树是这样的:

 
    processSprite(0, j) 
    processSprite(1, j) 
     processSprite(2, j) 
     ... 
      processSprite(1599, j) <-- That's 1600 call frames, 
            enough for an overflow. 

你会想你的算法重组为一个线性循环,做了深度优先搜索,如果你想找到最接近起点的像素,可能会采用螺旋模式。我确信已经有其他已经开发出来的其他漂亮算法来解决这个问题。

编辑:

我想我现在好多了,你试图解决的问题理解。这听起来像你有一个图像,可能包含多个图像瓷砖包围0像素,你想找到每个这些瓷砖的边界矩形。这看起来像一个有趣的问题要解决,所以我实现了它:

IEnumerable<Rectangle> FindImageTiles(Bitmap compositeImage) 
{ 
    var result = new List<Rectangle>(); 

    // Scan for a non-empty region that hasn't already been "captured" 
    for (var x = 0; x < compositeImage.Width; x++) 
    { 
     for (var y = 0; y < compositeImage.Height; y++) 
     { 
      // Only process the pixel if we don't have a rectangle that 
      // already contains this and if it's not empty 
      if (!result.Any(r => r.Contains(x, y)) 
       && compositeImage.GetPixel(x, y).A != 0) 
      { 
       // Now that we've found a point, create a rectangle 
       // surrounding that point, then expand outward until 
       // we have a bounding rectangle that doesn't intersect 
       // with the tile 
       var rect = new Rectangle(x - 1, y - 1, 2, 2); 
       bool foundBounds = false; 
       while (!foundBounds) 
       { 
        var xRange = Enumerable.Range(rect.Left, rect.Right) 
         .Where(px => px >= 0 && px < compositeImage.Width); 
        var yRange = Enumerable.Range(rect.Top, rect.Bottom) 
         .Where(py => py >= 0 && py < compositeImage.Height); 

        // Adjust the top 
        if (rect.Top >= 0 
         && xRange 
          .Select(bx => compositeImage.GetPixel(bx, rect.Top)) 
          .Any(p => p.A != 0)) 
        { 
         rect.Y--; 
         rect.Height++; 
        } 
        else if (rect.Bottom < compositeImage.Height 
         && xRange 
          .Select(bx => compositeImage.GetPixel(bx, rect.Bottom)) 
          .Any(p => p.A != 0)) 
        { 
         rect.Height++; 
        } 
        else if (rect.Left >= 0 
         && yRange 
          .Select(by => compositeImage.GetPixel(rect.Left, by)) 
          .Any(p => p.A != 0)) 
        { 
         rect.X--; 
         rect.Width++; 
        } 
        else if (rect.Right < compositeImage.Width 
         && yRange 
          .Select(by => compositeImage.GetPixel(rect.Right, by)) 
          .Any(p => p.A != 0)) 
        { 
         rect.Width++; 
        } 
        else 
        { 
         foundBounds = true; 
        } 
       } 
       result.Add(rect); 
      } 
     } 
    } 

    return result; 
} 
+0

”线性循环,可以进行深度优先搜索,如果您想要找到最接近起点的像素,可能采用螺旋模式。“好点...我不知道我怎么能知道我什么时候需要打破我的循环,但我会看看,并尝试简化它。 – 2010-08-11 17:55:05

+0

我相信我最初误解了你试图解决的问题。我添加了一些应该可以工作的代码(用来自Internet的几张图片进行测试) – Jacob 2010-08-12 02:41:29

+0

谢谢Jacob!像魅力一样工作! – 2010-08-12 15:39:57