Самый быстрый способ вычислить разницу между двумя ARGB-целыми числами в Java? - PullRequest
3 голосов
/ 14 апреля 2011

С учетом int из DataBuffer, в который упакованы данные ARGB с масками

A = 0xFF000000 R = 0xFF0000 G = 0xFF00 B = 0xFF

Я делаю следующее, но интересно, нет ли более быстрого метода в Java?

        DataBuffer db1 = img1.getData().getDataBuffer();
        DataBuffer db2 = img2.getData().getDataBuffer();

        int x, y;
        int totalDiff = 0;
        for (int i = 0; i < WIDTH * HEIGHT; ++i) {
            x = db1.getElem(i);
            y = db2.getElem(i);

            totalDiff += Math.abs((x & 0xFF) - (y & 0xFF))
                       + Math.abs(((x & 0xFF00) >> 8) - ((y & 0xFF00) >> 8))
                       + Math.abs(((x & 0xFF0000) >> 16) - ((y & 0xFF0000) >> 16 ));
        }

Ответы [ 3 ]

3 голосов
/ 14 апреля 2011

Если вам действительно нужно ускорить процесс, вы можете проверить тип DataBuffer и предоставить оптимизированный код для конкретного типа, чтобы сохранить вызовы на getElem(i). Это немного ускорит ваш код.

Примерно так:

    DataBuffer db1 = img1.getData().getDataBuffer();
    DataBuffer db2 = img2.getData().getDataBuffer();

    int totalDiff = 0;
    int x, y;
    if (db1 instanceof DataBufferInt && db2 instanceof DataBufferInt) {
        int[] data1 = ((DataBufferInt) db1).getData();
        int[] data2 = ((DataBufferInt) db2).getData();
        for (int i = 0; i < WIDTH * HEIGHT; ++i) {
            x = data1[i];
            y = data2[i];

            totalDiff += Math.abs((x & 0xFF) - (y & 0xFF))
                + Math.abs(((x & 0xFF00) >> 8) - ((y & 0xFF00) >> 8))
                + Math.abs(((x & 0xFF0000) >> 16) - ((y & 0xFF0000) >> 16));
        }
    } else {
        for (int i = 0; i < WIDTH * HEIGHT; ++i) {
            x = db1.getElem(i);
            y = db2.getElem(i);

            totalDiff += Math.abs((x & 0xFF) - (y & 0xFF))
                    + Math.abs(((x & 0xFF00) >> 8) - ((y & 0xFF00) >> 8))
                    + Math.abs(((x & 0xFF0000) >> 16) - ((y & 0xFF0000) >> 16));
        }
    }

Edit: Другая идея, которая принесет вам НАМНОГО более высокую скорость. Если это всего лишь эвристика, этого может быть достаточно, чтобы рассчитать разницу в несколько «урезанной» версии ваших изображений. Замените ++i на i+=10 и увеличьте скорость в 10 раз. Конечно, если это имеет смысл, зависит от типов ваших изображений.

Edit: В одном из комментариев вы упомянули, что это функция пригодности для GA ... в этом случае может быть достаточно взять 100 (или просто 10?) Случайных мест из ваших изображений и сравнить пиксели в этих местах. Полученное ускорение, скорее всего, превзойдет потерю точности.

1 голос
/ 14 апреля 2011

Согласитесь с @ Arne.

Вы также можете удалить права смены

(x & 0xFF0000) >> 16) - ((y & 0xFF0000) >> 16 ). 

Вы знаете, что abs(XX0000 - YY0000) будет только в диапазоне 0-255.

Было бы полезно, если бы вы могли подсказать, что именно вы пытаетесь определить?

То есть, может ли информация о пикселях храниться более благоприятно для того, что вы пытаетесь достичь, например, как цветность (YUV, YCrCb)?

0 голосов
/ 14 апреля 2011

Если для вас приемлемо вычисление суммы квадратов, то это быстрее:

    for (int i = 0; i < WIDTH * HEIGHT; ++i) {
        x = db1.getElem(i);
        y = db2.getElem(i);
        int dr = ((x & 0xFF0000) >> 16) - ((y & 0xFF0000) >> 16 );
        int dg = ((x & 0xFF00) >> 8) - ((y & 0xFF00) >> 8);
        int db = (x & 0xFF) - (y & 0xFF);
        totalDiff += dr*dr + dg*dg + db*db;
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...