简体   繁体   English

ArrayLists的堆栈溢出错误

[英]Stack Overflow error with ArrayLists

I'm trying to write some code to look through an image file for groups of pixels that are the same color. 我正在尝试编写一些代码以通过图像文件查找具有相同颜色的像素组。

The way I do this is I iterate through the image (in the form of a 1d integer array with the color's hash code) by pixel to find a pixel of the color that I'm searching for. 我这样做的方法是逐像素遍历图像(以带有颜色哈希码的1d整数数组的形式),以查找要搜索的颜色的像素。 Once one is found, I do a dfs to find adjacent pixels of the same color and add them to a new object I called a Blob. 找到一个像素后,我将执行dfs来查找相同颜色的相邻像素,并将其添加到一个称为Blob的新对象中。 I use a boolean array to keep track of which pixels have already been added so I don't add identical blobs. 我使用布尔数组来跟踪已经添加了哪些像素,因此我不会添加相同的斑点。

I'm using ArrayList for each Blob object to keep track of the pixel numbers. 我为每个Blob对象使用ArrayList来跟踪像素数。 And then I use another ArrayList of Blobs to store the different groups. 然后,我使用另一个Blob的ArrayList来存储不同的组。

When I try to run this on a simple example, a picture with the top half white and the bottom half bottom, I get a stack overflow error when I try to use a picture that's too large. 当我尝试在一个简单的示例(具有上半部白色和下半部底部的图片)上运行时,当尝试使用太大的图片时出现堆栈溢出错误。 Specifically, when I try to do this with a 320x240 image, I get the stackoverflow once 2752 pixels are added to the blob. 具体来说,当我尝试使用320x240图像执行此操作时,一旦将2752像素添加到Blob中,就会出现stackoverflow。

Am I just not using the right data structure for what I want to do? 我只是在为自己想做的事情使用正确的数据结构吗? I read that ArrayLists can store Integer.maxValue objects in them. 我读到ArrayLists可以在其中存储Integer.maxValue对象。

My code is pasted below. 我的代码粘贴在下面。 Any help is greatly appreciated. 任何帮助是极大的赞赏。

//blobfind tests code to find similar pixels of a minimum size and groups them together for analysis later  
//purpose is to identify color coded objects through the webcam  

//util for ArrayList  
import java.util.*;  
import java.awt.Color;  
import java.io.*;  

public class Blobfind2 {  

  //width and height of image in pixels  
  private int width;  
  private int height;  
  //hash code for the color being searched for  
  private int colorCode;  
  //minimum blob size to be added  
  private int minPixels;  
  //image in form of array of hashcodes for each pixel  
  private int[] img;  
  //keeping track of which pixels have been added to a blob  
  private boolean[] added;  
  //keeping track of which pixels have been visited when looking for a new blob  
  private boolean[] visited;  

  //debugging variable  
  private int count;  

  public Blobfind2(int inwidth, int inheight, int inCCode, int inminPixels, int[] inimage)   {
    width = inwidth;  
    height = inheight;  
    colorCode = inCCode;  
    minPixels = inminPixels;  
    img = inimage;  
    count = 0;  
  }    

  //takes hashCodeof color, minimum pixel number, and an image in the form of integer array  
  public ArrayList findColor() {  
    //makes an arraylist of "blobs"  
    ArrayList bloblist = new ArrayList();  
    //keep track of which pixels have been added to a blob  
    boolean[] added = new boolean[width * height];  
    //checks through each pixel  
    for (int i = 0; i < img.length; i++) {  
      //if it matches and is not part of a blob, we run dfs to collect all the pixels in   that blob
      if ((img[i] == colorCode) && (added[i] == false)) {  
        //visited keeps track of which pixels in the blob have been visited  
        //refreshed each time a new blob is made  
        boolean[] visited = new boolean[width*height];  
        Blob currBlob = new Blob();  
        dfs(img, currBlob, i, Color.white.hashCode(), added, visited);  
        //adds the blob to the bloblist if it is of a certain size  
        if (currBlob.mass() >= minPixels) {  
          bloblist.add(currBlob);                          
        }  
      }  
    }  
    return bloblist;  
  }  

  //recursive algorithm to find other members of a blob  
  public void dfs (int[] img, Blob blob, int currPixel, int colorCode, boolean[] added,    boolean[] visited) {  
    //System.out.print(currPixel + " - " + count + " ");   
    count++;  
    //check current pixel, this only happens on the first pixel  
    if (visited[currPixel] == false) {  
      blob.add(img[currPixel]);  
      added[currPixel] = true;  
      visited[currPixel] = true;  
    }  
    //checks down pixel  
    if ((currPixel + width < height*width) && (visited[currPixel + width] == false)) {  
      if (img[currPixel + width] == colorCode) {  
        blob.add(img[currPixel + width]);  
        currPixel = currPixel + width;  
        added[currPixel] = true;  
        visited[currPixel] = true;  
        dfs(img, blob, currPixel, colorCode, added, visited);  
      }  
    }  
    //checks up pixel  
    if ((currPixel - width > 0) && (visited[currPixel - width] == false)) {  
      if (img[currPixel - width] == colorCode) {  
        blob.add(img[currPixel - width]);  
        currPixel = currPixel - width;  
        added[currPixel] = true;  
        visited[currPixel] = true;  
        dfs (img, blob, currPixel, colorCode, added, visited);  
      }  
    }  
    //checks right pixel  
    if ((currPixel + 1 < width * height) && (visited[currPixel + 1] == false) && (((currPixel + 1) % width) != 0)) {  
      if (img[currPixel + 1] == colorCode) {  
        blob.add(img[currPixel + 1]);  
        currPixel = currPixel + 1;  
        added[currPixel] = true;  
        visited[currPixel] = true;  
        dfs(img, blob, currPixel, colorCode, added, visited);  
      }  
    }  
    //checks left pixel  
    if ((currPixel - 1 > 0) && (visited[currPixel - 1] == false) && (((currPixel - 1) % width) != width - 1)) {  
      if (img[currPixel - 1] == colorCode) {  
        blob.add(img[currPixel - 1]);  
        currPixel = currPixel - 1;  
        added[currPixel] = true;  
        visited[currPixel] = true;  
        dfs(img, blob, currPixel, colorCode, added, visited);  
      }  
    }  
    return;  
  }  

  //test case, makes a new image thats half black and half white  
  //should only return one blob of size width*height/2  
  public static void main(String[] args) {  
   int width = 320;  
   int height = 240;  
   //builds the image  
   int[] img = new int[width * height];  
   for (int i = 0; i < img.length; i++) {  
     if (i < img.length/4) {  
       img[i] = Color.white.hashCode();  
     } else {  
       img[i] = Color.black.hashCode();  
     }  
   }  

   //runs blobfind  
   Blobfind2 bf = new Blobfind2(width, height, Color.white.hashCode(), 1, img);  
   ArrayList bloblist = bf.findColor();  
   System.out.println(bloblist.size());  
   //need to typecast things coming out of arraylists  
   Blob firstblob = (Blob)bloblist.get(0);  
   System.out.println(firstblob.mass());  
  }  

 private class Blob {  
   private ArrayList pixels = new ArrayList();  
   private Blob() {  
   }  
   private int mass() {  
     return pixels.size();  
   }  
   private void add(int i) {  
     pixels.add(i);  
   }  
   private ArrayList getBlob() {  
     return pixels;  
   }  
 }  

}   

The stack overflow error has nothing to do with whether you use an List , or a Map , or any other particular data structure. 堆栈溢出错误与使用ListMap或任何其他特定数据结构无关。 Those constructs are allocated on the heap. 这些结构在堆上分配。 You are seeing your stack overflow error because you make recursive function calls. 您正在看到堆栈溢出错误,因为您进行了递归函数调用。 Each recursive function call allocates memory on the stack. 每个递归函数调用都会在堆栈上分配内存。 You can increase your -Xss value (eg java -Xss8m HelloWorld) or you can re-write your algorithm to be non-recursive (assuming your algorithm is correct). 您可以增加-Xss的值(eg java -Xss8m HelloWorld) ,也可以将算法重新编写为非递归的(假设您的算法正确)。

This looks very similar to a flood-fill algorithm. 这看起来与洪水填充算法非常相似。 The recursive implementation might blow the stack (eg make too many recursive calls) for large blobs, simply because you have to explore 4 neighbours for every pixel. 递归实现可能会使大型Blob崩溃(例如,进行过多的递归调用),仅仅是因为您必须为每个像素探索4个邻居。 Worst case is an image all in the same blob! 最坏的情况是图像全部在同一斑点中!

I would try making the stack explicit. 我会尝试使堆栈明确。 You want to avoid the recursion and use a simple loop based approach instead. 您要避免递归,而应使用基于循环的简单方法。

public void dfs () {
     Stack<Pixel> pixels = new Stack<Pixel>();
     pixels.push(currentPixel);

     while (!pixels.isEmpty()) {
         Pixel x = pixels.pop();

         // Do whatever processing on this pixel
         Pixel upPixel = getUpPixel();
         if (upPixel == colorCode) {
             pixels.push(upPixel);
         }

         // And so on
     }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM