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

Предположим, что имеется цветное изображение формата А4, на котором может быть одна или несколько круглых печатей. Поставим задачу — определить координаты прямоугольников, ограничивающих области изображения с оттисками печати. Эта задача является задачей детекции объектов (object detection), и для её решения можно использовать разные подходы. Применим подход на основе поиска контуров с помощью преобразования Хафа. Это подход удобно использовать, поскольку у нас есть некоторые априорные знания об искомых объектах: круглая форма, преимущественно синий цвет, определенный размер.

Рассмотрим процесс решения поставленной задачи.

Шаг 1. Подключаем библиотеки opencv и numpy.

import cv2
import numpy as np

Шаг 2. Открываем исходное изображение. В качестве примера изображения используем лицензию, выданную Центробанком РФ.

im = cv2.imread('license.jpg')

Шаг 3. Выделяем области искомого цвета. Для этого преобразуем изображение из цветовой модели RGB в цветовую модель HSV (hue-saturation-value, или тон-насыщенность-значение). Если цветовую схему HSV представить в виде круга, где тон определяется углом от 0° до 360°, то можно обнаружить, что тон синей печати находится внутри сектора, приблизительно ограниченного значениями 160° и 280°.

С учетом того, что в соответствии с особенностями библиотеки opencv значение тона лежит в диапазоне от 0 до 180, выбранные нами границы примут значения 80 и 140 соответственно.

Выполняем преобразование изображения к цветовой модели HSV, задаём границы тона, насыщенности и значения, накладываем соответствующую маску на исходное изображение.

hsv = cv2.cvtColor(im, cv2.COLOR_BGR2HSV)
blue_lower = np.array([80, 30, 30])
blue_higher = np.array([140, 250, 250])
mask = cv2.inRange(hsv, blue_lower, blue_higher)
selection = cv2.bitwise_and(im, im, mask=mask)

В результате изображение selection будет содержать только те области, цвет которых соответствует заданным нам ограничениям.

Шаг 4. Преобразуем цветное изображение в серое, затем выполняем сглаживание для коррекции мелких артефактов на изображении.

gray = cv2.cvtColor(selection, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (5,5), 2)

Шаг 5. Находим круглые контуры с помощью функции HoughCircles. Предварительно рассчитываем минимальный и максимальный радиусы искомых окружностей в пикселах, а также задаем параметр minDist (минимальное расстояние между центрами контуров) равным диаметру самой маленькой печати. Отметим, что согласно ГОСТ Р 51511-2001, диаметр гербовой печати составляет от 40 до 50 мм, или от 19% до 24% от ширины листа формата А4. С учетом небольшого запаса задаём относительные диаметра печатей от 0,15 до 0,30.

h, w = gray.shape
r_min = int(w * 0.15 / 2)
r_max = int(w * 0.30 / 2)
contours = cv2.HoughCircles(blur, cv2.HOUGH_GRADIENT, dp=1, minDist=2 * r_min)

В результате переменная contours будет содержать перечень координат центров и радиусов всех обнаруженных контуров.

Шаг 6. Составляем список ограничивающих прямоугольников boxes, для чего проходим в цикле по всем обнаруженным контурам, отбираем окружности подходящего радиуса и рассчитываем координаты противоположных углов ограничивающих прямоугольников.

boxes = []
if contours is not None:
    for contour in contours[0]:
        xc, yc, r = np.uint16(np.around(contour))
        if r_min <= r <= r_max:
            x1 = xc - r
            y1 = yc - r
            x2 = xc + r
            y2 = yc + r
            boxes.append([x1, y1, x2, y2])

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

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