Время прочтения: 4 мин.

Множество объектов на изображении можно опознать по их форме, например, печати в сканах документов, как правило, круглые, развороты паспорта четырёхугольные и т.д. Зная простые свойства искомого объекта и отсутствие этих свойств у других объектов изображения, можно свести задачу детектирования на изображении к задаче поиска объекта, чей контур содержит в себе какое-то количество углов. Говоря проще: хочешь найти на фотографии стола книгу – найди что-то с четырьмя сторонами.

Подобный подход был продемонстрирован в статье, где, с помощью преобразования Хафа для поиска окружностей, был произведён поиск печатей среди всего синего на скане документа. Данный подход можно использовать не только для анализа синих объектов на изображении, однако нужно быть готовым к подбору оптимальных параметров функции поиска.

Однако, преобразование Хафа для окружностей хорошо применимо, очевидно, к окружностям и не найдёт печати или другие объекты, содержащие углы. Для задачи поиска изображений с «угловатым» контуром может прекрасно подойти использование детектора границ Кэнни. Примерный алгоритм:

  1. преобразовать изображение в градации серого,
  2. размыть изображение, чтобы очистить от шумов,
  3. применить оператор Кэнни для поиска границ,
  4. «закрыть» границы объектов
  5. найти контуры объектов

Пронаблюдаем работу алгоритма по изложенным выше шагам, используя для обработки opencv:

Рисунок 1 – исходное изображение

Загрузим изображение и применим функцию для перевода в градации серого:

import cv2 as cv
src = cv.imread('test.jpg')
gr = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
Рисунок 2 – изображение в градациях серого

В данном случае, границы объектов чёткие и тонкие, размытие сделает только хуже, поэтому этот шаг нам не требуется:

bl = cv.medianBlur(gr, 5)
Рисунок 3 – размытие изображения

Далее, выделим границы объектов оператором Кэнни:

canny = cv.Canny(bl, 10, 250)
Рисунок 4 – границы объектов изображения

«Закроем границы»:

kernel = cv.getStructuringElement(cv.MORPH_RECT, (7, 7))
closed = cv.morphologyEx(canny, cv.MORPH_CLOSE, kernel)
Рисунок 5 – закрытие границ объектов

Найдём контуры и выделим нужные объекты:

contours = cv.findContours(closed.copy(), cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)[0]
for cont in contours:
        #сглаживание и определение количества углов
        sm = cv.arcLength(cont, True)
        apd = cv.approxPolyDP(cont, 0.02*sm, True)
        #выделение контуров
        if len(apd) == 4:
            cv.drawContours(src, [apd], -1, (0,255,0), 4)
cv.imwrite('result.jpg', src)
Рисунок 6 – объекты с четырьмя углами
Рисунок 7 – объекты с тремя углами
Рисунок 8 – объекты с пятью углами

Также, возможен и поиск окружностей, которые выделяются как восьмиугольники:

Рисунок 9 – объекты с восемью углами

Можно искать и в более сложных условиях:

Рисунок 10 – различные объекты на изображении

Таким образом, был реализован простой алгоритм для поиска на изображении объектов с замкнутыми контурами.