Как найти отличия на фото у блоггеров приложения
Для того чтобы увидеть разницу между двумя изображениями, необходимо перейти на закладку Пары изображений. Между двумя миниатюрами расположена небольшая галочка "Выделить отличия". Если она не отмечена, кликните по ней для установки отметки (второй клик уберет отметку)
Когда установлена отметка "Выделить отличия" вы увидите небольшие прямоугольники на миниатюрах изображений. Эти прямоугольники подсвечивают области, которые Image Comparer посчитал различными.
При этом:
-- На идентичных изображениях с 100% степенью схожести не будут выделяться отличия.
-- Отличия могут находится в любом месте внутри прямоугольников, не обязательно в их центре.
Сразу под отметкой "Выделить отличия" находится ползунок "Изменить порог выделяемых различий". (Название ползунка появляется, когда задержать на некоторое время курсор мыши над ним.) Когда ползунок находится в крайнем правом положении, отображаемые прямоугольники показывают самые значимые отличия с точки зрения Image Comparer. При движении ползунка влево, будут появлятся дополнительные прямоугольники, отображающие менее значимые отличия. В крайнеам левом положении ползунка изображение может быть покрыто подсвечивающими прямоугольниками целиком.
При этом:
-- Для изображений без сильно значимых отличий может не отображаться ни одного прямоугольника, пока не сместить ползунок на некоторое расстояние влево.
-- Для некоторых изображений может быть такое положение ползунка, когда при его движении влево не будут появляться новые прямоугольники. Это положение, в котором все найденные отличия уже подсвечены.
-- При выборе другой пары изображений из результатов, позиция ползунка "Изменить порог выделяемых различий" будет автоматически изменяться. Image Comparer пытается автоматически настроить его значение для каждой пары, чтобы выводилось приемлемое число найденных отличий. Обычно передвижение ползунка вправо от выбранной позиции уменьшает число подсвечивающих прямоугольников, тогда как движение ползунка влево от выбранной позиции, наоборот, - увеличивает их число.
Как найти отличия на картинках в Python?
Сегодня нам предстоит решить простую детскую задачу: найти 5 отличий на двух картинках:
Архив с изображениями и готовым скриптом можно загрузить по ссылке: find_differences.zip
Однако решать мы ее будет недетским способом — с помощью Python! Поехали!
1. Откроем изображения
Из библиотеки PIL нам понадобятся 2 модуля:
Отлично! Теперь мы сможем открыть изображения! У меня изображения называются незатейливо: «1.jpg» и «2.jpg» и хранятся в одной папке со скриптом, поэтому относительный путь к этим файлам будет так же прост: «1.jpg» и «2.jpg» соответственно. Передадим относительные адреса к изображениям в качестве аргументов при открытии этих файлов с помощью функции open() модуля Image:
2. Найдем отличия на картинках в Python
Для того, чтобы найти отличия на двух изображениях с помощью Python, достаточно вызвать функцию difference() из модуля ImageChops:
Функция difference() пиксель за пикселем сравнивает переданные в качестве аргументов изображения и возвращает абсолютные значения найденных разностей между соответствующими пикселями(точнее между значениями их цветовых каналов).
На данном этапе мы уже можем вывести результат в отдельном отдельном окне с помощью той же библиотеки PIL:
Поздравляю! Отличия найдены и выводятся на экран! Однако, я предлагаю пойти дальше и при помощи библиотеки matplotlib вывести подлежащие сравнению изображения с результатом сравнения в одном окне!
3. Дополнительный вариант вывода изображений и найденных отличий на экран
Для начала импортируем библиотеку matplotlib, которая обладает превосходным набором инструментов для визуализации данных. Одним из таких полезных инструментов библиотеки matplotlib является модуль pyplot. Этот модуль содержит ряд функций, которые позволяют использовать matplotlib как Matlab. А это значит, что после импорта pyplot мы сможем создать область(фигуру) нужных размеров и разместить в ней все наши картинки. Итак, расположим строку с импортом вначале файла с кодом:
После импорта модуля pyplot создадим область (фигуру) шириной 40 дюймов и высотой 22 дюйма:
Осталось лишь написать небольшую функцию, которая будет делить область pic_box на 4 «подобласти» (2 по горизонтали и 2 по вертикали), а затем выводить изображения в заданной в переменной img_pos «подобласти». Счет номеров «подобластей» ведется слева-направо и сверху вниз. Назовем функцию show_pictures():
Функция готова! Вызовем ее для каждого из изображений, включая результирующее, а затем выведем на экран все фигуры, созданные с помощью pyplot:
Поздравляю! Наша программа отлично справляется с заданием и выводит результат на экран в одном окне со сравниваемыми изображениями!
Наверняка у каждого из Вас есть большой домашний архив фотографий, а в нем лежат собственные снимки и фотографии, которыми с Вами поделились родственники. Просматривая свою фототеку, Вы наткнулись на дубли и тут же возник вопрос – сколько же еще таких? В этой статье я поделюсь тем, как я решал свою задачу по поиску одинаковых фотографий.
Совсем недавно у меня появилась интересная задача – необходимо было найти одинаковые фотографии на разных объектах недвижимости. Т.е. к объектам недвижимости расположенных с разным местоположением крепилась одна и та же фотография, может ошибочно, может специально, но такие объекты надо было найти. И я хотел бы поделиться тем, как я решал эту задачу. Для примера у Вас может быть домашняя фототека.
Инструменты
Посмотрев просторы интернета, первым делом на глаза мне попалась библиотека OpenCV, эта библиотека имеет интерфейсы на различных языках, среди которых Python, Java, C++ и Matlab. Мне стало интересно, есть ли у Python стандартная библиотека для работы с изображениями и вот она – Pillow. Это форк PIL, которая успешно развивается и был принят в качестве замены оригинальной библиотеки. Свой выбор я остановил на ней.
Решение задачи
Начнем работу с библиотекой, и попробуем открыть файл и показать его.
Данный скрипт откроет нам изображение. Почитав документацию, я нашел функцию, которая по пикселям сравнивает два изображения и выдает разницу. Функция называется difference и находится в модуле ImageChops. Что бы показать принцип работы функции, для примера возьмем фотографию и добавим на нее какой-нибудь текст:
result.show() вернет разницу в пикселях. Так же прошу обратить внимание на result.getbbox(), функция либо вернет рамку где расходятся пиксели, либо вернет None если картинки идентичны. Если мы сравним первую картинку саму с собой, то получим полностью черное изображение.
Напишем простенькую функцию по сравнению двух картинок:
def difference_images(img1, img2): image_1 = Image.open(img1) image_2 = Image.open(img2) result=ImageChops.difference(image_1, image_2).getbbox() if result==None: print(img1,img2,'matches') returnТеперь необходимо подумать над алгоритмом перебора имеющихся изображений.
Данный алгоритм перебирает все файлы в папке и сравнивает их между собой исключая проверку между собой и файлы, которые уже были проверены на совпадение.
А если файлов для сравнения очень много и их обработка очень долгая? Можно пойти двумя способами:
- Создать миниатюры и работать с ними.
- Запустить нашу обработку в несколько потоков.
Первый способ простой, в нашу функцию difference_images добавляем несколько строк:
Второй способ уже сложнее и более интересный, потому что нужно будет управлять и потоками, и очередями, так же нужно будет переписать часть кода. Для этого нам понадобятся следующие библиотеки threading и Queue (подробней можно почитать в интернете), ниже приведен готовый код с внесенными изменениями, я постарался прокомментировать все действия что бы было понятно:
В результате мы получили готовый алгоритм для поиска одинаковых картинок, а так же постарались ускорить обработку файлов двумя способами. Завершив свою задачу, я обнаружил 1227 совпадений в выборке из 6616 картинок.
Надеюсь, моя статья была полезна. Спасибо за внимание.
Достаточно ли оптимально?
Может, для каждой картинки сперва посчитать хэши, а потом уже хэши сравнивать? По ощущениям, должно быть быстрее.
Я поэтому и удивился, ибо сам в своём проекте столкнулся с задачей мэтчинга. Тянуть полновесную OpenCV (как ещё одну зависимость) посчитал сомнительным вариантом. А вот поиск по хэшам отрабатывался быстрее.
Можно для начала сравнить размеры в байтах
Хм. Сначала сравнить размеры в байтах, а потом - сами картинки при совпадении размеров? Не уверен, если честно, что это быстрее сравнений хэшей.
Такое сравнение можно использовать в качестве пре-проверки, чтобы уменьшить размер списка сравнения.
Пример - есть список картинок "a b c A D e B a c f D g a", где:
- a и а - картинки, одинаковые и по содержанию, и по весу
- а и А - картинки, одинаковые по содержанию, но разные по весу
Если на первом шаге прогнать сравнение только по весу картинки, то будут найдены одинаковые группы "a a а", "с с" и "D D".
Убрав дубликаты, мы получим новый список - "a b c A D e B f g", который, очевидно, короче начального и для которого перебор "все со всеми" будет проходить быстрее.
Открытый вопрос - при каком количеству дубликатов в начальном списке, добавление такой пре-проверки оказывается выигрышным по времени?
Чел, но ведь две разные картинки могут иметь одинаковый размер, ты оптимизируешь не в ту сторону.
Могут, не отрицаю, но вероятность, что две разные картинки будут иметь идентичные размер в байтах чертовски мала + можно добавить сравнение по содержанию, чтобы быть уверенным, что это одинаковые картинки.
Очень не оптимально полагать на малую вероятность в решениях задач ред.
Зависит от контекста.
Я предложил использовать этот подходит в качестве начального фильтра, чтобы уменьшить общую вычислительную сложность алгоритма, и, ИМХО, такой подход имеет право на жизнь.
Использовать же его для определения конечной оценки не советую, потому-что он повышает вероятность допустить ошибку, что непозволительно.
Хорошая статейка, спасибо!
вот мой код, надеюсь он вам поможет:
import os
from PIL import Image, ImageChops
print('Введите ПОЛНЫЙ путь к папке: ', end = '')
directory_in_str = input()
Часто за собой замечаю, что при виде какой-нибудь программы, игры или сайта у меня возникают странные мысли. И мысли эти меня пугают. А думаю я всякий раз о том, как эту программу/сайт/игру можно подхачить, взломать, обойти защиту, автоматизировать, расширить функциональность. Наверное, профессиональная деформация дает о себе знать. Или это подсознательное желание использовать накопленные знания, не находящие применения на работе. Как правило, эти желания остаются на уровне мыслей, но бывают исключения. Об одном таком случае я и расскажу вам сегодня…
Было это давно. Году, эдак, в 2008. Был обычный зимний день. Ничего не предвещало бессонной ночи. Но тут я заметил, как будущая жена играет на компе в одну игру…
То была игра «Найди 5 отличий» (в оригинале «5 Spots»). При виде пользовательского интерфейса игры у меня сразу возникло вышеуказанное желание — «А можно ли написать программу, которая бы искала отличия и подсказывала игроку куда жать мышкой, а то и сама бы двигала ей и жала сама?». Как оказалось, возможно все.
Сама игра довольно старая и примитивная. Как видно из скриншота, она показывает 2 картинки с отличиями и ждет пока юзер прокликает их мышкой. Все просто. Такой подход избрал и я в своем решении:
1. юзер запускает программу-подсказчика (ПП)
2. запускает целевую игру
3. жмет волшебную комбинацию клавиш
4. в нужным местах картинки ПП подсвечивает различия
В общем, я выбрал консольное приложение как основу для ПП. Зарегистрировал комбинацию горячих клавиш Ctrl + F1 (типа, «помощь»), повесил обработчик. Но как найти отличия в 2х картинках из игры? Для начала, картинки нужно было «увидеть» программно. Тут тоже все просто — «фотографируем» окно в фокусе в память по нажатию на горячие клавиши:
Позиции картинок с отличиями в игре постоянные, размеры окна игры тоже — поэтому тут решает хардкод смещений и размеров (ведь наша ПП работает только с этой игрой). В памяти берем 2 картинки и «ксорим» их одна на другую:
ВыXORивается следующая картина:
А дальше начинается поиск отличий.
Сейчас, когда пишу эту статью, вспоминаю, что была у меня какая-то либо лаба, либо курсовой проект в универе на эту тему. На тему обработки похожих изображений. И там я написал этот алгоритм. Я прекрасно понимаю, что ничего нового не изобрел — скорее всего, у этого алгоритма даже есть какое-то специальное название. Да и не привязан он к изображениям вовсе. В общем, кто знает, что это, подскажите.
Итак, мы имеет черную картинку с нечерными пикселями в местах, где были отличия. Причем пиксели эти расположены не вплотную друг к другу, а, в общем случае, с какими-то промежутками. Но, как видно из скриншота, области отличий достаточно локализованы. Алгоритм поиска этих областей состоит в следующем:
1. проходим по картинке
2. находим нечерный пиксель
3. смотрим в его окрестность и ищем его нечерных соседей — все это помещаем в найденную область (если рассматриваемые пиксели не были обработаны ранее)
Настраиваемым параметром тут служит «размер» окрестности пикселя — на сколько далеко можно от него заглядывать. Это позволяет искать более «размазанные» области отличий. Понятное дело, что все это неидеально и, в общем случае, найденных областей будет больше, чем отличий в картинках — ведь в самих картинках-заданиях возможен шум от сжатия, затесавшийся курсор мыши или что-то еще, выглядещее как различие на программном уровне, но незаметное с точки зрения игрока. Поэтому найденные различия нужно отсортировать по площади — чем больше нечерных пикселей вмещает область, тем больше вероятность того, что это не шум, а именно различие.
Уже потом я узнал и попробовал OpenCV (возможно, и о ней будет статья). Думаю, что есть более быстрые и оптимизированные алгоритмы. Но тогда меня хватило именно на такой вариант.
Исходник поиска различий (код старый, публикую без изменений):
Дальше еще проще — подсветить найденные области на экране. Так как программа игры не использует никаких DirectX'ов (на сколько я могу судить), то тут помог простой вывод графики на окно игры. В общем-то, если бы был DirectX, то так просто «сфоткать» экран не получилось бы, не говоря уже о подсветке различий поверх игры. Но тут WinAPI рулит (функция ::Rectangle()). Результат подсветки:
От полностью программной игры пришлось отказаться — ПП и так слишком облегчала игру, если бы она еще и за тебя играла, то было бы вообще неинтересно. Но докрутить ПП до бота проще простого — зная координаты областей-отличий можно прокликать их мышкой, дождаться следующего уровня, распознать отличия и так далее…
Это все возможно, но, судя по всему, тогда меня хватило только на одну бессонную ночь.
Читайте также: