Код сравнения изображений не работает должным образом

  • Автор темы Dbc-server
  • Обновлено
  • 12, May 2024
  • #1
Я все еще новичок в программировании и столкнулся с проблемой с кодом Java.

Буду очень благодарен за предложения и комментарии.

Проблема заключается в следующем: Я нашел в Интернете Java-код, предназначенный для сравнения двух изображений и выделения различий между ними.

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

Однако это приводит к проблеме, заключающейся в том, что даже малейшее смещение угла камеры или условий освещения между двумя изображениями приводит к разным значениям RGB пикселей, из-за чего код выделяет их как разницу, даже если изображения в основном идентичны.

Код написан ниже, и я добавил ссылку на фотографии, показывающие примеры результатов работы кода.

Что бы вы предложили изменить в коде? Заранее благодарим вас за помощь. Код: импортировать java.awt.image.BufferedImage; импортировать java.io.File; импортировать java.io.IOException; импортировать javax.imageio.ImageIO; общественный класс PictureOverlayTest { /*
  • Четыре переменных: три для нужных BufferedImages, одна строка для
  • Путь третьего изображения, которого еще нет.


*/ частное изображение BufferedImage1; частное изображение BufferedImage2; частное изображение BufferedImage3; частная строка pathImage3; public PictureOverlayTest (String filePathAndName1, String filePathAndName2, Строка filePathAndName3) выдает IOException { /*
  • Конструктор, чтобы этот метод можно было использовать повторно и в чистоте. Потребности
  • три струны. Пути и имена файлов всех трех изображений. Изображение 1
  • и 2 уже должны существовать, изображение 3 будет создано, если все
  • требования соблюдены. Конструктор создает первые два буферизованных
  • изображения, устанавливает все необходимые переменные и запускает функцию checkAndCompare().
  • метод


*/ Файл файл = новый файл (filePathAndName1); this.image1 = ImageIO.read(файл); файл = новый файл (filePathAndName2); this.image2 = ImageIO.read(файл); this.pathImage3 = filePathAndName3; проверитьИСравнить(); } Private void checkAndCompare() выдает IOException { /*
  • Эта функция создает синий цвет, сравнивает размеры обоих
  • изображения, и если они одинаковые, создается третье изображение. Затем это
  • циклически перебирает два изображения и сравнивает каждый пиксель. Если пиксели
  • одинаковы, третье изображение в этой точке получает синий пиксель


*/

Цвет синий = Цвет.синий;

Желтый цвет = Цвет.желтый;

если (image1.getHeight() == image2.getHeight()

& & image1.getWidth() == image2.getWidth()) {

image3 = новый BufferedImage(image1.getWidth(), image1.getHeight(),

изображение1.getType());

for (int y = 0; y < image1.getHeight(); y++) {

for (int x = 0; x < image1.getWidth(); x++) {

int colorImage1 = image1.getRGB(x, y);

int colorImage2 = image2.getRGB(x, y);

если (colorImage1 == colorImage2) {

image3.setRGB(x, y, blue.getRGB());

} еще {

image3.setRGB(x, y,жёлтый.getRGB());

// Какой бы цвет вы ни выбрали.

По умолчанию он черный. } } } сохранитьКартину3(); System.out.println("Сообщение: сравнение изображений завершено"); } еще {

System.out.println("Ошибка: размеры изображения не совпадают"); } } Private void savePicture3() выдает IOException { /*
  • Этот метод сохраняет созданное изображение в файл на вашем компьютере.
  • Оператор if() используется для проверки успешности файла.
  • создано во избежание нежелательных ошибок. Имейте в виду, что вы
  • необходимо изменить «bmp» в ImageIO.write() на любой формат, который вы хотите
  • на самом деле хочу


*/

Файл файл = новый файл (pathImage3);

если (file.createNewFile()) {

ImageIO.write(изображение3, «bmp», файл);

}

}

}

импортировать java.io.IOException;

общественный класс Main {

public static void main(String[] args) {

// TODO Автоматически сгенерированная заглушка метода

пытаться {

Тест PictureOverlayTest = новый PictureOverlayTest(

"C:\\Users\\Rabee Taha\\Desktop\\Java Test Pics\\test1.png",

"C:\\Users\\Rabee Taha\\Desktop\\Java Test Pics\\test2.png",

"C:\\Users\\Rabee Taha\\Desktop\\Java Test Pics\\test3.png");

} catch (IOException e) {

// TODO Автоматически сгенерированный блок catch

е.printStackTrace();

}

}

}

Вот ссылка на примеры изображений результата ( https://postimg.cc/gallery/rkXfPr7

)

Dbc-server


Рег
27 Feb, 2011

Тем
93

Постов
186

Баллов
711
  • 19, May 2024
  • #2
«Код предназначен для сравнения двух изображений и выделения различий между ними.

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

Однако это приводит к проблеме, заключающейся в том, что даже малейшее смещение угла камеры или условий освещения между двумя изображениями приводит к разным значениям RGB пикселей, из-за чего код выделяет их как разные, даже если изображения в основном идентичны».

Код делает именно то, что должен.

Небольшое изменение угла камеры или освещения при переходе от одного изображения к другому показывает, что изображения разные.

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

Vfrcbv2


Рег
04 Nov, 2011

Тем
65

Постов
201

Баллов
546
  • 09, Jun 2024
  • #3
Вместо того, чтобы делать двоичный вывод, я бы предложил использовать оттенки серого для различий между ними.

как бы тепловую карту.

Затем вы могли бы подать заявку.

использовали ли вы когда-нибудь радио CB / Ham? У них есть функция под названием «шумоподавитель», которая представляет собой ограничение уровня сигнала, предназначенное для подавления шума.

По сути, вы можете установить порог того, насколько сильно происходят изменения.

8-битная тепловая карта в оттенках серого или даже 10-битная тепловая карта RG была бы/могла бы быть гораздо более полезной, и, потеряв несколько битов, вы автоматически получите значительное уменьшение разницы, которое будет выброшено в мусор.

Java не мой конек — прошло уже полтора десятилетия с тех пор, как я писал на нем что-нибудь серьезное — но логика была бы примерно такой:

 final int
greyBitDepth = 8, // max reliable is 31 bits
greySHR = 31 - greyBitDepth,
squelch = 16, // ignore differences of 16 or less
width = image1.getWidth(),
height = image1.getHeight();

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

int
pixel1_temp = image1.getRGB(x, y),
pixel2_temp = image2.getRGB(x, y),
diff = Math.max(squelch, (
Math.abs(
(pixel1_temp & 0xFF) - (pixel2_temp & 0xFF)
) * 489626272 +
Math.abs(
((pixel1_temp >>= 8) &0xFF) - ((pixel2_temp >>= 8) & 0xFF)
) * 2521145802 +
Math.abs(
((pixel1_temp >>= 8) &0xFF) - ((pixel2_temp >>= 8) & 0xFF)
) * 1284195221
) >> greySHR);
/*
The multiplies above are the Luma component of YCrCb converted to
0..0x7FFFFFFF, allowing us to avoid expensive floating point divides
and multiplies.
*/

Color grey = new Color(diff, diff, diff);
image3.setRGB(x, y, grey.getRGB());

}
}


Код (разметка): Имейте в виду, я догадываюсь, что прошли годы.

но это заменило бы ваш внутренний цикл, чтобы дать вам оттенки серого различий с шумоподавлением. Более надежная версия может уменьшать разрешение исходных изображений с небольшим размытием, чтобы учесть небольшие движения камеры.

Аналогичным образом, на предмет изменений с течением времени может быть выбрано более одного кадра, поэтому такие вещи, как дневной свет с течением времени, игнорируются/подавляются.

Хотя на этом этапе, возможно, придется заняться сложным искусственным интеллектом, чтобы все действительно работало правильно.
 

Huk


Рег
11 Feb, 2016

Тем
56

Постов
210

Баллов
500
Тем
403,760
Комментарии
400,028
Опыт
2,418,908