【问题标题】:Simple image processing algorithm causes Processing to freeze简单的图像处理算法导致处理冻结
【发布时间】:2016-11-04 10:47:43
【问题描述】:

我在 Processing 中编写了一个算法来执行以下操作:

1. Instantiate a 94 x 2 int array
2. Load a jpg image of dimensions 500 x 500 pixels
3. Iterate over every pixel in the image and determine whether it is black or white then change a variable related to the array
4. Print the contents of the array

由于某种原因,该算法立即冻结。我已经在其中添加了打印语句,表明它甚至在尝试加载图像之前就冻结了。鉴于我已经编写了另一个非常相似的算法,它执行起来没有复杂性,这让我特别困惑。另一种算法读取图像,对指定大小的每个图块的颜色进行平均,然后在使用平均颜色平均的区域上打印矩形,从而有效地对图像进行像素化。两种算法都加载图像并检查其每个像素。有问题的主要不同之处在于它不绘制任何东西。我要说的是,拥有一个数组是不同的,但是像素化算法将所有颜色保存在一个颜色数组中,它应该比 int 数组占用更多的空间。

通过查看我的 mac 的 console.app,我发现原来有这个错误:“java.lang.OutOfMemoryError:GC 开销限制超出”。从网络上的其他建议/资源中,我尝试将内存分配从 256mb 提高到 4000mb(这样做感觉毫无意义,因为我对算法的分析表明它们应该具有相同的复杂性,但我还是尝试了)。这并没有停止冻结,而是将错误更改为“JavaNativeFoundation error occurred getting Java exception description”和“java.lang.OutOfMemoryError: Java heap space”的组合。 然后我尝试将处理指向我的本地 jdk,希望利用 64 位 jdk 而不是处理内置的 32 位 jdk。从 Processing.app/Contents 我执行了以下命令: mv Java java-old ln -s /Library/Java/JavaVirtualMachines/jdk1.7.0_79.jdk Java 此尝试后处理将无法开始,并在我的控制台中出现以下错误: “com.apple.xpc.launchd[1]: (org.processing.app.160672[13559]) 服务退出异常代码:1”

以下是我的代码: 首先是不合规算法

int squareSize=50;
int numRows = 10;
int numCols = 10;
PFont myFont;
PImage img;

//33-126
void setup(){
  size(500,500);
  count();
}

void count(){
  ellipseMode(RADIUS);
  int[][] asciiArea = new int[94][2];
  println("hello?");
  img=loadImage("countingPicture.jpg");
  println("image loaded");
  for(int i=0; i<(500/squareSize); i++){
    for(int j=0; j<(500/squareSize); j++){
      int currentValue=i+j*numCols;
      if(currentValue+33>126){
        break;
      }
      println(i+", "+j);
      asciiArea[currentValue][0]=currentValue+33;
      asciiArea[currentValue][1]=determineTextArea(i,j,squareSize);
      //fill(color(255,0,0));
      //ellipse(i*squareSize,j*squareSize,3,3);
    }
  }
  println("done calculating");
  displayArrayContents(asciiArea);
}

int determineTextArea(int i, int j, int squareSize){
  int textArea = 0;
  double n=0.0;
  while(n < squareSize*squareSize){
    n+=1.0;
    int xOffset = (int)(n%((double)squareSize));
    int yOffset = (int)(n/((double)squareSize));
    color c = img.get(i*squareSize+xOffset, j*squareSize+yOffset);
    if(red(c)!=255 || green(c)!=255 || blue(c)!=255){
      println(red(c)+" "+green(c)+" "+blue(c));
      textArea++;        
    }    
  }
  return textArea;
}

void displayArrayContents(int[][] arr){
  int i=0;
  println("\n now arrays");
  while(i<94){
    println(arr[i][0]+" "+arr[i][1]);
  }
}

有效的像素化算法:

PImage img;
int direction = 1;
float signal;
int squareSize = 5;
int wideness = 500;
int highness = 420;
int xDimension = wideness/squareSize;
int yDimension= highness/squareSize;

void setup() {
  size(1500, 420);
  noFill();
  stroke(255);
  frameRate(30);
  img = loadImage("imageIn.jpg");
  color[][] colors = new color[xDimension][yDimension];
  for(int drawingNo=0; drawingNo < 3; drawingNo++){
  for(int i=0; i<xDimension; i++){
    for(int j=0; j<yDimension; j++){
      double average = 0;
      double n=0.0;
      while(n < squareSize*squareSize){
        n+=1.0;
        int xOffset = (int)(n%((double)squareSize));
        int yOffset = (int)(n/((double)squareSize));
        color c = img.get(i*squareSize+xOffset, j*squareSize+yOffset);
        float cube = red(c)*red(c) + green(c)*green(c) + blue(c)*blue(c);
        double grayValue = (int)(sqrt(cube)*(255.0/441.0));
        double nAsDouble = (double)n;
        average=(grayValue + (n-1.0)*average)/n;
        average=(grayValue/n)+((n-1.0)/(n))*average;
      }
      //average=discretize(average);
      println(i+" "+j+" "+average);
      colors[i][j]=color((int)average);
      fill(colors[i][j]);
      if(drawingNo==0){ //stroke(colors[i][j]); }
      stroke(210);}
      if(drawingNo==1){ stroke(150);  }
      if(drawingNo==2){ stroke(90); }
      //stroke(colors[i][j]);
      rect(drawingNo*wideness+i*squareSize,j*squareSize,squareSize,squareSize);
    }
  }
  }
  save("imageOut.jpg");
}

【问题讨论】:

    标签: image memory processing


    【解决方案1】:

    您正在进入一个无限循环,这使得println() 语句不可靠。修复无限循环,您的打印语句将再次起作用。

    看看这个while循环:

    while(i<94){
        println(arr[i][0]+" "+arr[i][1]);
    }
    

    i 什么时候会变成&gt;= 94?

    你永远不会增加i,所以它的值总是0。您可以通过在 while 循环中添加 println() 语句来证明这一点:

    while(i<94){
        println("i: " + i);
        println(arr[i][0]+" "+arr[i][1]);
    }
    

    您可能想在while 循环内增加i。或者只使用for 循环。

    【讨论】:

    • 哎呀!多么尴尬。很好的收获,谢谢。尽管如此,我还是不明白为什么它不会在无限循环之前打印语句。您能否对此提供更多见解?
    • @AustinWehn 我自己也不太确定。但是 Processing 通常不能很好地处理无限循环(整个编辑器都冻结了),所以我对 println() 也不能很好地工作并不感到惊讶。
    • 谢谢@KevinWorkman。另一件事,您是否有在可以调试的模式下使用处理的经验?我想我看到了一些关于通过 Eclipse 运行它的信息,但我想知道这是否值得麻烦。有点惊讶的是,Processing 一开始就没有调试。
    • @AustinWehn 是的,我有通过 Eclipse 运行处理的经验。但是 Processing 确实在编辑器中内置了一个调试器——它是左上角的小蝴蝶按钮,就在模式下拉菜单旁边。
    猜你喜欢
    • 2016-12-23
    • 2017-02-14
    • 2020-07-29
    • 1970-01-01
    • 2021-09-30
    • 2017-06-07
    • 2012-06-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多