Сравнение двух изображений проблема - PullRequest
3 голосов
/ 01 июня 2011

Я хочу сравнить два изображения побайтно.Оба они являются 8-битными BMP-изображениями и имеют размер 40000 байт.Первое изображение генерируется в памяти как массив байтов, второе считывается из файла в объект Image.

Я использую MemoryStream экземпляров для сравнения:

    byte[] generatedImage = new byte[40000];
    // some unrelated logic of image generation ...
    MemoryStream imageStream1 = new MemoryStream(generatedImage);

    // loaded image, 200x200 bmp - 40000 bytes
    MemoryStream imageStream2 = new MemoryStream();
    Image loadedImage = Image.FromFile("image.bmp");
    loadedImage.Save(imageStream2, ImageFormat.Bmp);

Проблема в том, что поток памяти загруженного изображения imageStream2 содержит больше , чем 40000 байт, насколько я понимаю, он также содержит некоторую информацию о самом BMP.Таким образом, второй поток создается с Length, равным 41078 и Position, равным 1278. Я бы понял, если бы Position был 1078, но это не так, и с позиции осталось менее 40000 байтов.

В моем алгоритме мне нужно сравнивать изображения как можно быстрее, поэтому я отказался от идеи создания растровых изображений и сравнения с помощью метода GetPixel.Для сравнения я использую MemoryStream.ReadByte метод.

Как я могу получить "настоящие" байты BMP со второго Stream?Можно ли в этом случае сравнивать изображения на байтовой основе?

Ответы [ 4 ]

3 голосов
/ 01 июня 2011

Вот пост о сравнении изображений в C # довольно быстро. Он начинается с довольно медленной версии (которая все же лучше, чем GetPixel) и заканчивается версией, которая в 25 раз быстрее:

http://danbystrom.se/2008/12/14/improving-performance/

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

Одно слово предостережения, однако. Он оптимизирован для работы только с 32-битными изображениями. Если у вас есть образы 24bpp (которые по умолчанию загружаются в формате .jpg), вам нужен более «сложный» код или просто преобразовать его в 32bpp. «Сложность» заключается в том, что тогда вы не можете выполнить все сравнения в одном цикле, а вместо этого циклически построчно и сравнивать каждую строку отдельно.

2 голосов
/ 01 июня 2011

http://en.wikipedia.org/wiki/BMP_file_format#Bitmap_file_header

Считайте 4 байта со смещением 10, чтобы получить смещение данных пикселей.Прочитайте 4 байта со смещением 2, чтобы получить размер всего объекта, включая заголовок.Вычтите первое из второго, чтобы получить размер пиксельных данных.

0 голосов
/ 01 июня 2011

Сравнение изображений побайтово не является хорошим решением вашей проблемы.В этой ситуации вы можете использовать реализацию одного из алгоритмов хеширования.

« Хеш-функция » получает значение переменной длины и выдает выходной сигнал с постоянной длиной.Например, алгоритм SHA256 получает входное значение и генерирует 256-битный выход.Обратите внимание, что хэши двух наборов данных идентичны тогда и только тогда, когда соответствующие данные совпадают, и любое незначительное изменение данных приводит к значительному изменению значения хеш-функции, так что это отличный способ при сравнении большого объема данных.Для получения дополнительной информации прочитайте раздел «Хэш во Flash» этой статьи: http://www.codeproject.com/KB/GDI-plus/comparingimages.aspx?msg=3503625&display=Mobile

0 голосов
/ 01 июня 2011

Я бы не сравнивал их на уровне байтов.Вместо этого я бы положил их в Bitmap.Итерируйте по всему пикселю, вызывая GetPixel(x,y) со всеми возможными значениями от нуля до Width или Height.

...