Как рассчитать количество пикселей трех изображений одновременно

Как я могу рассчитать общий пиксель трех изображений одновременно? Я был опробован с Java Swing Worker и Thread, я получил ответ, но требуется 1,30 минуты, чтобы вернуть общее количество пикселей (30 секунд для каждого изображения, размер изображения 480*303) указанного диапазона. Но мне нужно получить ответы на три изображения одновременно в течение 30 секунд.

public class ImageProcessor1 implements Runnable{
static int blackPix=0;
BufferedImage tempImg;
public static int blackPixel=0;
public ImageProcessor1(String path) throws Exception{
tempImg = ImageIO.read(new File(path));
}

private static int[] getPixelData(BufferedImage img, int x, int y) {
    int argb = img.getRGB(x, y);

    int rgb[] = new int[]{
        (argb >> 16) & 0xff, //red
        (argb >> 8) & 0xff, //green
        (argb) & 0xff //blue
    };
    System.out.println("Process1 :rgb: " + rgb[0] + " " + rgb[1] + " " + rgb[2]);
    return rgb;
}

@Override
public void run() {
     int[][] pixelData = new int[tempImg.getHeight() * tempImg.getWidth()][3];
        int[] rgb;
        int height=tempImg.getHeight();
        int width=tempImg.getWidth();
        int counter = 0;
        for (int i = 0; i < width; i++) {
            for (int j = 0; j < height; j++) {
                rgb = getPixelData(tempImg, i, j);
                if(rgb[0]<125 && rgb[0]>105 && rgb[1]<125 && rgb[1]>105 && rgb[2]<125 && rgb[2]>105)
                {
                    blackPixel+=1;
                }
            }
        }
}

}

1 ответ

Решение

Очень странно, что перебор такой маленькой картинки занимает у вас 30 секунд!

После небольшого профилирования кажется, что наличие оператора println в горячем цикле сильно замедляет работу.

После небольшой модификации вашего кода изображение размером 10500x5788 занимает ~3 сек на моем компьютере.

Модифицированная версия:

package application;

import java.awt.image.BufferedImage;
import java.io.File;
import java.util.concurrent.TimeUnit;

import javax.imageio.ImageIO;

public class ImageProcessor1 implements Runnable {

  BufferedImage tempImg;
  public static int blackPixel = 0;

  public ImageProcessor1(final String path) throws Exception {
    final long start = System.nanoTime();

    tempImg = ImageIO.read(new File(path));
    // Use tracing, profiling and sampling to proof performance issues and fixes
    System.out.println("ImageIO took " + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start)
        + " ms.");
  }

  @Override
  public void run() {
    long start = System.nanoTime();
    final int height = tempImg.getHeight();
    System.out.println("Getting height '" + height + "' took "
        + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start) + " ms.");


    start = System.nanoTime();
    final int width = tempImg.getWidth();
    System.out.println("Getting width '" + width + "' took "
        + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start) + " ms.");

    start = System.nanoTime();

    // reuse variables
    int argb;
    int red;
    int green;
    int blue;

    for (int i = 0; i < width; i++) {
      for (int j = 0; j < height; j++) {
        // HOT LOOP. Do as little as possible. No println calls!
        argb = tempImg.getRGB(i, j);

        // inline all method calls
        red = argb >> 16 & 0xff; // red
        green = argb >> 8 & 0xff; // green
        blue = argb & 0xff; // blue

        if (red < 125 && red > 105 && green < 125 && green > 105 && blue < 125 && blue > 105) {
          blackPixel += 1;
        }
      }
    }
    System.out.println("Iterating pixels took "
        + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start) + " ms.");
  }

  public static void main(final String[] args) throws Exception {
    new ImageProcessor1("big.jpg").run();
    System.out.println("Number of blackpixels = " + blackPixel);
  }

}

На более общем замечании, вы должны быть осторожны с вашим подходом, потому что вы считываете весь образ в ОЗУ, а затем обрабатываете его. Если вы сделаете это с 3 или более большими изображениями одновременно, есть вероятность ошибки OutOfMemoryError. Если это становится проблемой, вы можете прочитать изображение в качестве входного потока и обрабатывать только небольшие буферы изображения одновременно.

Чтобы увидеть, как это можно сделать, см. http://imagej.nih.gov/ij/source/ij/io/ImageReader.java.

Чтобы узнать, как накапливать выходные данные нескольких потоков, см. Раздел Как писать многопоточный код и накапливать выходные данные всех потоков в одном файле.

Другие вопросы по тегам