Подтвердить что ты не робот

Более быстрый способ извлечь гистограмму из изображения

Я ищу более быстрый способ извлечь данные гистограммы из изображения. В настоящее время я использую этот фрагмент кода, который требует около 1200 мс для изображения в формате 6mpx JPEG:

        ImageReader imageReader = (ImageReader) iter.next();
        imageReader.setInput(is);
        BufferedImage image = imageReader.read(0);
        int height = image.getHeight();
        int width = image.getWidth();
        Raster raster = image.getRaster();
        int[][] bins = new int[3][256];

        for (int i = 0; i < width; i++) 
            for (int j = 0; j < height; j++) {
                bins[0][raster.getSample(i, j, 0)]++;
                bins[1][raster.getSample(i, j, 1)]++;
                bins[2][raster.getSample(i, j, 2)]++;

            }

Есть ли у вас какие-либо предложения?

4b9b3361

Ответ 1

Вы делаете много вызовов метода getSamples, и они, в свою очередь, делают звонки и звонки и т.д.

Я часто работаю с фотографиями, и типичный трюк, чтобы получить скорость, - это манипулировать непосредственно базовым int [] (в этом случае ваш BufferedImage должен быть подкреплен int []).

Разница между доступом к int [] и выполнением, скажем, getRGB может быть огромной. Когда я пишу гигантский, я имею в виду на два порядка (попробуйте сделать getRGB на OS X 10.4 против int [x], и вы увидите первичную прибыль).

Также нет вызова три раза getSamples. Я бы просто получил один int, соответствующий вашему ARGB-пикселю, а затем bithift, чтобы получить полосы RGB (вы делаете одну гистограмму для R, G и B-компонента правильно?).

Вы можете получить доступ к массиву пикселей, выполнив что-то вроде этого:

final int[] a = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();

Также вы можете делать то, что хотите сделать, с одним циклом, зацикливая на все пиксели.

Вместо:

for ( int x = 0; x < width; x++ ) {
    for ( int y = 0; y < height; y++ ) {
        ....

Вы можете сделать:

for ( int p = 0; p < width*height; p++ ) {

Теперь, если вы хотите получить более страстные оптимизации, не так эффективны, насколько это возможно:

  • Использование разворачивания цикла (итерация более 6 миллионов пикселей является одним из редких случаев, когда это может помочь)

  • инвертировать цикл: for (p = width * height - 1; p >= 0; p -)

Ответ 2

Вы можете использовать getSamples (int x, int y, int w, int h, int b, double [] dArray) метод Возможно, этот метод имеет внутреннюю оптимизацию. Кроме того, вы можете попробовать поменять ширину и высоту.

for (int i = 0; i < width; i++) 
   for (int j = 0; j < height; j++) {
   }
}

И

for (int i = 0; i < height; i++) 
   for (int j = 0; j < width; j++) {
   }
}

Между этими двумя вариантами разница производительности будет огромной. Это влияние кэша процессора