Из этой статьи вы узнаете, как создать Python-скрипт для подсчёта количества книг на изображении с помощью OpenCV.
Прим. перев. Также советуем обратить внимание на наше руководство по созданию бота для мессенджера на Python и посмотреть видеокурс, в котором рассказывается о написании автопилота для GTA V — там тоже используется OpenCV.Что мы будем делать?
Взглянем на изображение, на котором будем искать книги:
Мы видим, что на изображении находятся четыре книги, а также отвлекающие вещи, такие как кружка кофе, чашка Starbucks, несколько магнитов и конфета.
Наша цель заключается в том, чтобы найти четыре книги на изображении, при этом не определив никакой другой предмет как книгу.
Какие библиотеки нам понадобятся?
Чтобы написать систему для поиска и обнаружения книг на изображениях, мы будем использовать OpenCV для работы с компьютерным зрением и обработки изображений. Нам также необходимо установить NumPy для корректной работы OpenCV.
Команды для установки:
pip3 install imutils
pip3 install numpy
pip3 install opencv-python
Поиск книг на изображениях с помощью Python и OpenCV
Прим. перев. Вы можете заметить, что исходный код в нашей статье отличается от кода в оригинале. Автор, вероятно, использовал установку необходимых библиотек через репозитории. Мы предлагаем использовать pip, что гораздо проще. Во избежание появления ошибок рекомендуем использовать версию кода, приведенную в нашей статье.Откройте свой любимый редактор кода, создайте новый файл с именем find_books.py
и начнем:
# -*- coding: utf-8 -*-
# импортируйте необходимые пакеты
import numpy as np
import cv2
# загрузите изображение, смените цвет на оттенки серого и уменьшите резкость
image = cv2.imread("example.jpg")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (3, 3), 0)
cv2.imwrite("gray.jpg", gray)
Начнем с импорта библиотеки OpenCV. Загрузка изображения с диска обрабатывается функцией cv2.imread
. Здесь мы просто загружаем его с диска, а затем преобразуем цветовую гамму из RGB в оттенки серого.
Мы также немного размываем изображение, чтобы уменьшить высокочастотные шумы и повысить точность нашего приложения. После выполнения кода изображение должно выглядеть так:
Мы загрузили изображение с диска, преобразовали его в оттенки серого и немного размыли.
Теперь давайте определим края (т.е. контуры) объектов на изображении:
# распознавание контуров
edged = cv2.Canny(gray, 10, 250)
cv2.imwrite("edged.jpg", edged)
Теперь наше изображение выглядит следующим образом:
Мы нашли контуры объектов на изображениях. Однако, как вы видите, некоторые из контуров не закрыты — между контурами существуют промежутки. Чтобы убрать промежутки между белыми пикселями изображения, мы применим операцию «закрытия»:
# создайте и примените закрытие
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (7, 7))
closed = cv2.morphologyEx(edged, cv2.MORPH_CLOSE, kernel)
cv2.imwrite("closed.jpg", closed)
Теперь пробелы в контурах закрыты:
Следующим шагом является фактическое обнаружение контуров объектов на изображении. Для этого мы будем использовать функцию cv2.findContours
:
# найдите контуры в изображении и подсчитайте количество книг
cnts = cv2.findContours(closed.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
total = 0
Рассмотрим геометрию книги.
Книга представляет собой прямоугольник. У прямоугольника четыре вершины. Поэтому, если мы рассмотрим контур и обнаружим, что он имеет четыре вершины, то мы можем предположить, что это книга, а не другой предмет на изображении.
Чтобы проверить, является ли контур книгой или нет, нам нужно выполнить цикл по каждому контуру:
# цикл по контурам
for c in cnts:
# аппроксимируем (сглаживаем) контур
peri = cv2.arcLength(c, True)
approx = cv2.approxPolyDP(c, 0.02 * peri, True)
# если у контура 4 вершины, предполагаем, что это книга
if len(approx) == 4:
cv2.drawContours(image, [approx], -1, (0, 255, 0), 4)
total += 1
Для каждого из контуров мы вычисляем периметр, используя cv2.arcLength
, а затем аппроксимируем (сглаживаем) контур, используя cv2.approxPolyDP
.
Причина, по которой мы аппроксимируем контур, заключается в том, что он может не быть идеальным прямоугольником. Из-за зашумления и теней на фото вероятность того, что у книги будет ровно 4 вершины, невелика. Аппроксимируя контур, мы решаем эту проблему.
Наконец, мы проверяем, что у аппроксимируемого контура действительно четыре вершины. Если это так, то мы рисуем контур вокруг книги, а затем увеличиваем счётчик общего количества книг.
Завершим этот пример, показывая полученное изображение и количество найденных книг:
# показываем результирующее изображение
print("Я нашёл {0} книг на этой картинке".format(total)
cv2.imwrite("output.jpg", image))
На данном этапе наше изображение будет выглядеть так:
Терминал показывает, что мы успешно нашли четыре книги на изображении, игнорируя другие предметы:
Подведем итоги
В этой статье вы научились находить книги на изображениях, используя простые методы обработки изображений и компьютерного зрения с помощью Python и OpenCV.
Наш подход состоял в том, чтобы:
- Загрузить изображение с диска и преобразовать его в оттенки серого.
- Немного размыть изображение.
- Применить детектор контуров Canny для обнаружения объектов на изображении.
- Закрыть любые промежутки в контурах.
- Найти контуры объектов на изображении.
- Применить контурную аппроксимацию, чтобы определить, был ли контур прямоугольником и, следовательно, книгой.
Вы можете скачать исходный код скрипта и изображение, которое используется в этой статье.
Перевод статьи «A guide to finding books in images using Python and OpenCV»