Russian Qt Forum
Ноябрь 22, 2024, 22:20 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Как быстро сравнить две картинки?  (Прочитано 13427 раз)
PavelVX
Гость
« : Июнь 17, 2014, 12:52 »

Добрый день!
Есть 2 jpg файлика. Один кусок другого.
Подскажите, а как можно быстро сравнить две картинки?
Подскажите также, как сохранить/загрузить картинку не изменяя её?
Пробую дубово сравнить картинки:

    QImage img1, img2;
    int globalCount=0, ecvivaletCount = 0;
    QString format = "jpg";
    QString fileName;
    fileName = QString("d:/cache/boot_logo.%1").arg(format);
    img2.load(fileName, format.toAscii());
    img1.load(fileName, format.toAscii());
    fileName = QString("d:/cache/boot_logo2.%1").arg(format);
    img1.save(fileName, format.toAscii(), 100);
    img1.load(fileName, format.toAscii());
    if ((img1.width() != img2.width()) || (img1.height() != img2.height())) return 0;
    globalCount = img1.width()*img1.height();
    for (int i=0;i<img1.width();i++)
        for (int j=0;j<img1.height();j++)
        {
            if (img1.pixel(i, j) == img2.pixel(i, j)) ecvivaletCount++;
        }
    return 100 * ecvivaletCount / globalCount;

Казалось бы, берем картинку, сохраняем, открываем. Но при сравнении получается 50% совпадения. ЧЯДНТ?
Записан
Swa
Самовар
**
Offline Offline

Сообщений: 170


Просмотр профиля
« Ответ #1 : Июнь 17, 2014, 13:23 »

А вы сравните размеры файлов boot_logo и boot_logo2, они будут разные, потому что второй файл был получен методом QImage::save, скорее всего с помощью немного другого алгоритма.
Но вам не нужно сравнивать попиксельно, ищите алгоритмы сравнения изображений, например посмотрите тут
http://habrahabr.ru/post/120562/
Записан
PavelVX
Гость
« Ответ #2 : Июнь 17, 2014, 15:23 »

За ссылки спасибо, буду читать. На хабре очень много полезного есть.
У меня картинки-то 300 на 300 пикселей. Могу и тупо перебором сделать. Но хочется-то красиво Улыбающийся
Хмм, тогда появляется вопрос: а как сохранять картинку не изменяя её??? Не писать же самому хранение потока попиксельно в qrgb.
« Последнее редактирование: Июнь 17, 2014, 15:24 от PavelVX » Записан
Swa
Самовар
**
Offline Offline

Сообщений: 170


Просмотр профиля
« Ответ #3 : Июнь 17, 2014, 16:00 »

Ну вот по этим ссылкам и будет красиво, а то, что делаете вы - это некрасивый и неработающий велосипед.

А как у вас программа работает? Зачем вы сохраняете картинку? В её изменяете в процессе?
Записан
PavelVX
Гость
« Ответ #4 : Июнь 17, 2014, 17:10 »

Все до безобразия просто: есть набор картинок на экране, нужно сравнить их с шаблонами на диске.
Но сравнение должно быть точным. Как раз в деталях и будет различие. Поэтому часть методов с хабра не подойдут.
Записан
Swa
Самовар
**
Offline Offline

Сообщений: 170


Просмотр профиля
« Ответ #5 : Июнь 17, 2014, 19:11 »

А поподробнее можно?
Записан
PavelVX
Гость
« Ответ #6 : Июнь 17, 2014, 19:46 »

Есть две картинки: на сайте и на диске.
Я делаю скриншот сайта. Если нужный фрагмент не совпадает с эталоном(на диске) мне нужно выдать предупреждение.
Поэтому я и начал реализовывать самое простое: побайтовое сравнение. Если проект пойдет в жизнь, то буду оптимизировать.
Подскажите: как мне программно сравнить побайтово две картинки? Или как сохранить без искажений?
Записан
Swa
Самовар
**
Offline Offline

Сообщений: 170


Просмотр профиля
« Ответ #7 : Июнь 17, 2014, 20:03 »

Вам нужно почитать про форматы изображений.
Если кратко, то изображения могут храниться в разных форматах. Самый простой формат - bmp, в нем каждый пиксель картинки описывается тремя числами - красная, синяя и зеленая компоненты. Т.о. два изображения формата bmp можно сравнять попиксельно (с учетом того, что они имеют одинаковую битность).
Все остальные форматы - это форматы с потерей информации. То есть когда вы сохраняете изображение в формате jpg то некоторые пиксели меняют данные о цвете, но так, что человеческому глазу это едва заметно. Компьютер же оперирует не образами на картинке, а числами, соответственно он считает эти два изображения разными. Кроме того, при сохранении изображения в формате jpg алгоритму можно передать разные опции сжатия, соответственно изображения, полученные с разными параметрами, будут отличаться (опять же, для компьютера).

Делайте тогда так, что и изображения у вас на диске, и скриншот делала бы ваша программа и сохраняла эти изображения в одинаковом формате (bmp). Потом от каждой картинки (на диске) считаете хеш, как описано в статье по ссылке. Если хеши совпадают, то с большой вероятностью изображения одинаковые. Тогда уже можно их сравнить попиксельно, чтобы убедиться в этом. Такой  метод позволит сократить время поиска совпадения (числа сравнивать быстрее чем большой массив чисел)
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #8 : Июнь 17, 2014, 20:10 »

Вообще то у QImage уже есть оператор равенства..

Так что можно проще:
Код
C++ (Qt)
img1 == img2
 

Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
PavelVX
Гость
« Ответ #9 : Июнь 18, 2014, 04:40 »

Вообще то у QImage уже есть оператор равенства..

Так что можно проще:
Код
C++ (Qt)
img1 == img2
 


Спору нет, знак равенства есть. Но как я уже показал выше, берем одно и тоже изображение, сохраняем, читаем, получаем уже немного другое изображение Улыбающийся
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #10 : Июнь 18, 2014, 08:57 »

Самый простой формат - bmp, в нем каждый пиксель картинки описывается тремя числами - красная, синяя и зеленая компоненты. Т.о. два изображения формата bmp можно сравнять попиксельно (с учетом того, что они имеют одинаковую битность).
Все остальные форматы - это форматы с потерей информации.
Почти наоборот - только jpg по умолчанию "химичит", остальные сохраняют "один в один", т.е. без потерь. Проще всего сохранять в png.

Вообще каждый формат имеет опции (под-форматы), но они используются довольно редко. По дефаулту png точно lossless
Записан
PavelVX
Гость
« Ответ #11 : Июнь 18, 2014, 09:44 »

Ну с bmp фокус прокатил. Все сравнивается корректно. С другими форматами эксперементировать не буду. Смысла нет. Потом только оптимизация поможет Улыбающийся
И кстати, img1==img2 отрабатывается порядка в два раза быстрее, чем по пиксельное сравнение. Поэтому, в начале, проверяю на равенство, если нет, то процент из по пиксельного сравнения.
Кстати, с ходу не нашел в методах: а как делать наложение на другое изображение по маске(AND, OR, XOR)?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #12 : Июнь 18, 2014, 10:08 »

Кстати, с ходу не нашел в методах: а как делать наложение на другое изображение по маске(AND, OR, XOR)?
Это не в QImage а в рисовании, см QPainter::setCompositionMode
Записан
Hrundel
Гость
« Ответ #13 : Июль 16, 2014, 18:06 »

При этом желательно быть уверенным, что сверяемые изображения не содержат Watermark. Иначе два визуально одинаковых изображения могут быть обозначены как неодинаковые. Но, тут уже больше зависит от цели, что нужно - сравнивать визуальную картинку или фактические различия данных?
Записан
deMax
Хакер
*****
Offline Offline

Сообщений: 600



Просмотр профиля
« Ответ #14 : Август 13, 2014, 14:16 »

Почти наоборот - только jpg по умолчанию "химичит", остальные сохраняют "один в один", т.е. без потерь. Проще всего сохранять в png.
Для векторной графики png даже лучше будет, и весит иногда меньше. Еще jpeg2000 в режиме без потерь был.

p.s. А зачем вообще сравнивать картинки, может лучше сравнить исходные файлы html+jpg?
И чтобы много не хранить можно использовать хэш суммы, это покажет что есть изменения, правда не скажет какие. Места будет копейки занимать.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.092 секунд. Запросов: 22.