简单的图像处理算法导致Processing卡顿
Simple image processing algorithm causes Processing to freeze
我在 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 数组占用更多 space。
通过查看我的 mac 的 console.app,我发现最初有这个错误:"java.lang.OutOfMemoryError: GC overhead limit exceeded"。从网络上的其他 suggestions/sources,我尝试将内存分配从 256mb 增加到 4000mb(这样做感觉毫无意义,因为我对算法的分析表明它们应该具有相同的复杂性,但我还是尝试了)。这并没有停止冻结,而是将错误更改为 "JavaNativeFoundation error occurred obtaining Java exception description" 和 "java.lang.OutOfMemoryError: Java heap space" 的组合。
然后我尝试将处理指向我的本地 jdk,希望利用 64 位 jdk 而不是内置 32 位 jdk 的处理。在 Processing.app/Contents 中,我执行了以下命令:
mv Java java-旧
ln -s /Library/Java/JavaVirtualMachines/jdk1.7.0_79.jdk Java
在此尝试后处理不会开始,并在我的控制台中出现以下错误:
"com.apple.xpc.launchd[1]: (org.processing.app.160672[13559]) Service exited with abnormal code: 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");
}
您正在进入一个无限循环,这使得 println()
语句不可靠。修复无限循环,您的打印语句将再次起作用。
看看这个 while
循环:
while(i<94){
println(arr[i][0]+" "+arr[i][1]);
}
什么时候 i
会变成 >=
94?
您永远不会递增 i
,因此它的值始终是 0
。您可以通过在 while
循环中添加 println()
语句来证明这一点:
while(i<94){
println("i: " + i);
println(arr[i][0]+" "+arr[i][1]);
}
您可能想在 while
循环中递增 i
。或者只使用 for
循环。
我在 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 数组占用更多 space。
通过查看我的 mac 的 console.app,我发现最初有这个错误:"java.lang.OutOfMemoryError: GC overhead limit exceeded"。从网络上的其他 suggestions/sources,我尝试将内存分配从 256mb 增加到 4000mb(这样做感觉毫无意义,因为我对算法的分析表明它们应该具有相同的复杂性,但我还是尝试了)。这并没有停止冻结,而是将错误更改为 "JavaNativeFoundation error occurred obtaining Java exception description" 和 "java.lang.OutOfMemoryError: Java heap space" 的组合。 然后我尝试将处理指向我的本地 jdk,希望利用 64 位 jdk 而不是内置 32 位 jdk 的处理。在 Processing.app/Contents 中,我执行了以下命令: mv Java java-旧 ln -s /Library/Java/JavaVirtualMachines/jdk1.7.0_79.jdk Java 在此尝试后处理不会开始,并在我的控制台中出现以下错误: "com.apple.xpc.launchd[1]: (org.processing.app.160672[13559]) Service exited with abnormal code: 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");
}
您正在进入一个无限循环,这使得 println()
语句不可靠。修复无限循环,您的打印语句将再次起作用。
看看这个 while
循环:
while(i<94){
println(arr[i][0]+" "+arr[i][1]);
}
什么时候 i
会变成 >=
94?
您永远不会递增 i
,因此它的值始终是 0
。您可以通过在 while
循环中添加 println()
语句来证明这一点:
while(i<94){
println("i: " + i);
println(arr[i][0]+" "+arr[i][1]);
}
您可能想在 while
循环中递增 i
。或者只使用 for
循环。