Russian Qt Forum

Qt => 2D и 3D графика => Тема начата: PavelVX от Июнь 17, 2014, 12:52



Название: Как быстро сравнить две картинки?
Отправлено: 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% совпадения. ЧЯДНТ?


Название: Re: Как быстро сравнить две картинки?
Отправлено: Swa от Июнь 17, 2014, 13:23
А вы сравните размеры файлов boot_logo и boot_logo2, они будут разные, потому что второй файл был получен методом QImage::save, скорее всего с помощью немного другого алгоритма.
Но вам не нужно сравнивать попиксельно, ищите алгоритмы сравнения изображений (https://www.google.com/search?num=100&newwindow=1&site=&source=hp&q=%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC+%D1%81%D1%80%D0%B0%D0%B2%D0%BD%D0%B5%D0%BD%D0%B8%D1%8F+%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9), например посмотрите тут
http://habrahabr.ru/post/120562/ (http://habrahabr.ru/post/120562/)


Название: Re: Как быстро сравнить две картинки?
Отправлено: PavelVX от Июнь 17, 2014, 15:23
За ссылки спасибо, буду читать. На хабре очень много полезного есть.
У меня картинки-то 300 на 300 пикселей. Могу и тупо перебором сделать. Но хочется-то красиво :)
Хмм, тогда появляется вопрос: а как сохранять картинку не изменяя её??? Не писать же самому хранение потока попиксельно в qrgb.


Название: Re: Как быстро сравнить две картинки?
Отправлено: Swa от Июнь 17, 2014, 16:00
Ну вот по этим ссылкам и будет красиво, а то, что делаете вы - это некрасивый и неработающий велосипед.

А как у вас программа работает? Зачем вы сохраняете картинку? В её изменяете в процессе?


Название: Re: Как быстро сравнить две картинки?
Отправлено: PavelVX от Июнь 17, 2014, 17:10
Все до безобразия просто: есть набор картинок на экране, нужно сравнить их с шаблонами на диске.
Но сравнение должно быть точным. Как раз в деталях и будет различие. Поэтому часть методов с хабра не подойдут.


Название: Re: Как быстро сравнить две картинки?
Отправлено: Swa от Июнь 17, 2014, 19:11
А поподробнее можно?


Название: Re: Как быстро сравнить две картинки?
Отправлено: PavelVX от Июнь 17, 2014, 19:46
Есть две картинки: на сайте и на диске.
Я делаю скриншот сайта. Если нужный фрагмент не совпадает с эталоном(на диске) мне нужно выдать предупреждение.
Поэтому я и начал реализовывать самое простое: побайтовое сравнение. Если проект пойдет в жизнь, то буду оптимизировать.
Подскажите: как мне программно сравнить побайтово две картинки? Или как сохранить без искажений?


Название: Re: Как быстро сравнить две картинки?
Отправлено: Swa от Июнь 17, 2014, 20:03
Вам нужно почитать про форматы изображений.
Если кратко, то изображения могут храниться в разных форматах. Самый простой формат - bmp, в нем каждый пиксель картинки описывается тремя числами - красная, синяя и зеленая компоненты. Т.о. два изображения формата bmp можно сравнять попиксельно (с учетом того, что они имеют одинаковую битность).
Все остальные форматы - это форматы с потерей информации. То есть когда вы сохраняете изображение в формате jpg то некоторые пиксели меняют данные о цвете, но так, что человеческому глазу это едва заметно. Компьютер же оперирует не образами на картинке, а числами, соответственно он считает эти два изображения разными. Кроме того, при сохранении изображения в формате jpg алгоритму можно передать разные опции сжатия, соответственно изображения, полученные с разными параметрами, будут отличаться (опять же, для компьютера).

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


Название: Re: Как быстро сравнить две картинки?
Отправлено: m_ax от Июнь 17, 2014, 20:10
Вообще то у QImage уже есть оператор равенства..

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



Название: Re: Как быстро сравнить две картинки?
Отправлено: PavelVX от Июнь 18, 2014, 04:40
Вообще то у QImage уже есть оператор равенства..

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


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


Название: Re: Как быстро сравнить две картинки?
Отправлено: Igors от Июнь 18, 2014, 08:57
Самый простой формат - bmp, в нем каждый пиксель картинки описывается тремя числами - красная, синяя и зеленая компоненты. Т.о. два изображения формата bmp можно сравнять попиксельно (с учетом того, что они имеют одинаковую битность).
Все остальные форматы - это форматы с потерей информации.
Почти наоборот - только jpg по умолчанию "химичит", остальные сохраняют "один в один", т.е. без потерь. Проще всего сохранять в png.

Вообще каждый формат имеет опции (под-форматы), но они используются довольно редко. По дефаулту png точно lossless


Название: Re: Как быстро сравнить две картинки?
Отправлено: PavelVX от Июнь 18, 2014, 09:44
Ну с bmp фокус прокатил. Все сравнивается корректно. С другими форматами эксперементировать не буду. Смысла нет. Потом только оптимизация поможет :)
И кстати, img1==img2 отрабатывается порядка в два раза быстрее, чем по пиксельное сравнение. Поэтому, в начале, проверяю на равенство, если нет, то процент из по пиксельного сравнения.
Кстати, с ходу не нашел в методах: а как делать наложение на другое изображение по маске(AND, OR, XOR)?


Название: Re: Как быстро сравнить две картинки?
Отправлено: Igors от Июнь 18, 2014, 10:08
Кстати, с ходу не нашел в методах: а как делать наложение на другое изображение по маске(AND, OR, XOR)?
Это не в QImage а в рисовании, см QPainter::setCompositionMode


Название: Re: Как быстро сравнить две картинки?
Отправлено: Hrundel от Июль 16, 2014, 18:06
При этом желательно быть уверенным, что сверяемые изображения не содержат Watermark. Иначе два визуально одинаковых изображения могут быть обозначены как неодинаковые. Но, тут уже больше зависит от цели, что нужно - сравнивать визуальную картинку или фактические различия данных?


Название: Re: Как быстро сравнить две картинки?
Отправлено: deMax от Август 13, 2014, 14:16
Почти наоборот - только jpg по умолчанию "химичит", остальные сохраняют "один в один", т.е. без потерь. Проще всего сохранять в png.
Для векторной графики png даже лучше будет, и весит иногда меньше. Еще jpeg2000 в режиме без потерь был.

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