Как найти отличия на картинках в Python?

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

отличия на картинках в Python
отличия на картинках в Python

Архив с изображениями и готовым скриптом можно загрузить по ссылке: find_differences.zip

Однако решать мы ее будет недетским способом — с помощью Python! Поехали!

1. Откроем изображения

Для открытия изображений предлагаю воспользоваться замечательной библиотекой, созданной для обработки графики, под названием Pillow или PIL (расшифровывается как «Python Imaging Library»).

Если библиотека не установлена, это легко исправить с помощью кода: pip3 install PIL

Из библиотеки PIL нам понадобятся 2 модуля:

  • Модуль Image, содержащий основные функции для работы с изображениями, такие как загрузка или создание новых изображений
  • Модуль ImageChops — содержит функции, выполняющие различные операции с каналами. А так как отличия на изображениях можно выявить путем вычисления попиксельной разницы между этими картинками, то модуль ImageChops с функцией difference() могут помочь нам в решении текущей задачи. О функции difference() я еще расскажу ниже, а сейчас займемся импортом библиотеки с нужными модулями:
from PIL import Image, ImageChops

Отлично! Теперь мы сможем открыть изображения! У меня изображения называются незатейливо: «1.jpg» и «2.jpg» и хранятся в одной папке со скриптом, поэтому относительный путь к этим файлам будет так же прост: «1.jpg» и «2.jpg» соответственно. Передадим относительные адреса к изображениям в качестве аргументов при открытии этих файлов с помощью функции open() модуля Image:

from PIL import Image, ImageChops

# сохраним первое изображение в переменной img1
img1 = Image.open('1.jpg')
# сохраним второе изображение в переменной img2
img2 = Image.open('2.jpg')

2. Найдем отличия на картинках в Python

Для того, чтобы найти отличия на двух изображениях с помощью Python, достаточно вызвать функцию difference() из модуля ImageChops:

from PIL import Image, ImageChops
img1 = Image.open('1.jpg')
img2 = Image.open('2.jpg')

# попиксельно сравним и найдем разницу в изображениях
differences = ImageChops.difference(img1, img2)

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

На данном этапе мы уже можем вывести результат в отдельном отдельном окне с помощью той же библиотеки PIL:

from PIL import Image, ImageChops
img1 = Image.open('1.jpg')
img2 = Image.open('2.jpg')

# попиксельно сравним и найдем разницу в изображениях
differences = ImageChops.difference(img1, img2)

#  если отличия найдены, выведем их в отдельном окне на экран
if differences.getbbox():
    differences.show()

Поздравляю! Отличия найдены и выводятся на экран! Однако, я предлагаю пойти дальше и при помощи библиотеки matplotlib вывести подлежащие сравнению изображения с результатом сравнения в одном окне!

У нас появился Telegram-канал для изучающих Python! Подписывайтесь по ссылке: «Кодим на Python! Вместе «питонить» веселее! 😉

3. Дополнительный вариант вывода изображений и найденных отличий на экран

Для начала импортируем библиотеку matplotlib, которая обладает превосходным набором инструментов для визуализации данных. Одним из таких полезных инструментов библиотеки matplotlib является модуль pyplot. Этот модуль содержит ряд функций, которые позволяют использовать matplotlib как Matlab. А это значит, что после импорта pyplot мы сможем создать область(фигуру) нужных размеров и разместить в ней все наши картинки. Итак, расположим строку с импортом вначале файла с кодом:

from PIL import Image, ImageChops
import matplotlib.pyplot as plt
     ...           ...

После импорта модуля pyplot создадим область (фигуру) шириной 40 дюймов и высотой 22 дюйма:

from PIL import Image, ImageChops
import matplotlib.pyplot as plt

img1 = Image.open('1.jpg')
img2 = Image.open('2.jpg')
diff = ImageChops.difference(img1, img2)
differences = ImageChops.difference(img1, img2)

pic_box = plt.figure(figsize=(40, 22))  

Осталось лишь написать небольшую функцию, которая будет делить область pic_box на 4 «подобласти» (2 по горизонтали и 2 по вертикали), а затем выводить изображения в заданной в переменной img_pos «подобласти». Счет номеров «подобластей» ведется слева-направо и сверху вниз. Назовем функцию show_pictures():

from PIL import Image, ImageChops
import matplotlib.pyplot as plt

img1 = Image.open('1.jpg')
img2 = Image.open('2.jpg')
diff = ImageChops.difference(img1, img2)
differences = ImageChops.difference(img1, img2)

pic_box = plt.figure(figsize=(40, 22))  

def show_pictures(box, img, img_pos):
    # делим область на 4 части(2х2) и добавляем оси для вывода изображения в позиции img_pos
    box.add_subplot(2,2,img_pos)
    # добавляем вывод изображения
    plt.imshow(img)
    # отключаем отображение осей на экране
    plt.axis('off')

Функция готова! Вызовем ее для каждого из изображений, включая результирующее, а затем выведем на экран все фигуры, созданные с помощью pyplot:

from PIL import Image, ImageChops
import matplotlib.pyplot as plt

img1 = Image.open('1.jpg')
img2 = Image.open('2.jpg')
diff = ImageChops.difference(img1, img2)
differences = ImageChops.difference(img1, img2)

pic_box = plt.figure(figsize=(40, 22))
# box - область для вывода изображений
# img - изображение, которое нужно вывести
# img_pos - номер "подобласти", в которой нужно вывести изображение 
def show_pictures(box, img, img_pos):
    # делим область на 4 части(2х2) и добавляем оси для вывода изображения в позиции img_pos
    box.add_subplot(2,2,img_pos)
    # добавляем вывод изображения
    plt.imshow(img)
    # отключаем отображение осей на экране
    plt.axis('off')
show_pictures(pic_box, img1, 1)
show_pictures(pic_box, img2, 2)
show_pictures(pic_box, differences, 3)
# выводим все фигуры на экран
plt.show()

отличия на картинках в Python

Поздравляю! Наша программа отлично справляется с заданием и выводит результат на экран в одном окне со сравниваемыми изображениями!

Добавить комментарий