преобразование цветного изображения в массив [i] [j]

1

Я хотел бы вычислить нормированную кросс-корреляцию между двумя изображениями с помощью Java.

Моя программа работает нормально, но когда я попытался проверить мои результаты в MATLAB, я, к сожалению, не получил те же результаты, что и в моей реализации Java.

Это код, который я выполнил в MATLAB:

Img1 = rgb2gray(imread('image1.png'));
Img2 = rgb2gray(imread('image2.png'));
corr2(Img1, Img2);

Это часть моей реализации Java. Некоторые из классов были удалены для лучшего понимания:

Я не уверен, что не так с моей реализацией Java.

У меня также есть еще один вопрос. В MATLAB мне пришлось преобразовать изображение в оттенки серого, прежде чем использовать corr2. Нужно ли делать то же самое в Java?

  • 5
    Вам действительно нужно добавить свой Java-код и ваш Matlab-код к вашему вопросу. Пожалуйста, отредактируйте свой вопрос и добавьте эту информацию (не добавляйте ее в комментариях или ссылках)
  • 0
    Теперь это более понятно?
Показать ещё 2 комментария
Теги:
image-processing
image
cross-correlation

1 ответ

1
Лучший ответ

Причина, по которой это не то же самое, заключается в том, что вы не учитывали заголовки в PNG файле.

Если вы посмотрите на свой Java-код, вы читаете изображение как поток байтов в вашем методе readImage. Для PNG присутствуют заголовки, такие как размер изображения и количество битов цвета на пиксель. Вы не только захватываете данные изображения (которые, кстати, сжаты с использованием версии LZW, поэтому вы даже не читаете данные необработанных изображений), но вы также захватываете дополнительную информацию, которая собирается в вашем коде корреляции.

Смущает то, что вы отлично читаете изображение, используя тип BufferedImage в начале кода корреляции для получения строк и столбцов. Почему вы переключились на использование байтового потока в вашем методе readImage?

Таким образом, вам необходимо изменить свой метод readImage чтобы взять объект BufferedImage, или перечитать данные, подобные тому, что вы делали в методе корреляции в вашем методе readImage. Как только вы это сделаете, используйте методы BufferedImage для доступа к пикселям RGB. FWIW, если вы читаете изображение как оттенки серого, тогда каждый канал должен давать вам такую же интенсивность, чтобы вы могли работать только на одном канале. Неважно, что.... но убедитесь, что вы выполняете корреляцию на изображениях в оттенках серого. Это неоднозначно, когда вы переходите к цвету, поскольку в настоящее время нет установленного стандарта о том, как это сделать.

Используя BufferedImage, вы можете использовать метод getRGB для получения getRGB пикселя в столбце x и строке y. x перемещается слева направо, а y пересекает сверху вниз. Когда вы вызываете getRGB он возвращает одно 32-битное целое число в формате ARGB. Каждый канал имеет 8 бит. Таким образом, первые 8 бит (MSB) являются альфа-значением, а остальные 8 бит - красными, третьи 8 бит - зелеными, а окончательные 8 - синими. В зависимости от того, какой канал вы хотите, вам нужно сбросить бит и замаскировать биты, которые вам не нужны, чтобы получить нужное значение.

В качестве примера:

int rgb = img.getRGB(x, y);
int alpha = rgb >> 24 & 0xFF;
int red = rgb >> 16 & 0xFF;
int green = rgb >> 8 & 0xFF;
int blue = rgb & 0xFF;    

Для значения альфа вам нужно сдвинуть вправо на 24 бита, чтобы довести его до позиций LSB, затем с помощью 0xFF получить маску, чтобы получить только 8 бит, которые представляют альфа-значение. Точно так же вы сделали бы то же самое для красного, зеленого и синего каналов. Поскольку корреляция довольно некорректна для цветных изображений, позвольте преобразовать изображение в оттенки серого в свой метод readImage. Таким образом, нет необходимости конвертировать изображение перед запуском этого метода. Мы сделаем это в самом методе, чтобы избавить вас от хлопот.

Если вы посмотрите, как MATLAB выполняет rgb2gray, он выполняет взвешенную сумму, взвешивая каналы по-разному. Веса определяются с помощью SMPTE Rec. 601 (для тех из вас, кто хочет понять, как я это знаю, вы можете взглянуть на источник rgb2gray и прочитать первую строку матрицы преобразования. Эти коэффициенты по существу являются определением стандарта 601).

Предыдущие версии MATLAB просто добавили все каналы, разделенные на 3 и занявшие слово. Я не знаю, какую версию MATLAB вы используете, но чтобы быть в безопасности, я собираюсь использовать самое современное преобразование.

public static void readImage(BufferedImage img, int array[][], int nrows, int ncols) {
      for (int i = 0; i < nrows; i++)
           for (int j = 0; j < ncols; j++) {
                int rgb = img.getRGB(j, i);
                int red = rgb >> 16 & 0xFF;
                int green = rgb >> 8 & 0xFF;
                int blue = rgb & 0xFF;
                array[i][j] = (int) (0.299*((double)red) + 0.587*((double)green) + 
                               0.114*((double)blue) );
           }
}

Это, надеюсь, даст вам то, что вы хотите!

  • 0
    Сначала спасибо за ваш ответ :) Так что теперь я должен преобразовать мои изображения в градации серого, затем изменить метод readImage с объектом BufferedImage. Должен ли я что-то изменить в моем методе корреляции вычислений? и если я буду работать с изображениями в градациях серого, не будет необходимости использовать getRGB для доступа к пикселям?
  • 0
    Всегда пожалуйста. Вам не нужно ничего менять в вашем методе корреляции, если вы правильно читаете в пикселях. Вам нужно будет использовать getRGB для доступа к данным пикселей, так как это единственный способ получить данные изображения для вашего изображения. Вам нужно будет маскировать канал , который вы хотите от пиксельных данных , хотя. Я отредактирую свой ответ, чтобы показать вам.
Показать ещё 6 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню