Что делает функция cv2.Canny()?

Функция cv2.Canny() из библиотеки OpenCV реализует алгоритм обнаружения границ, разработанный Джоном Кэнни (John F. Canny) в 1986 году. Этот алгоритм считается одним из самых точных и надёжных методов детектирования краёв на изображениях, благодаря своей способности точно выделять границы при минимальном уровне ложных срабатываний и высокой устойчивости к шуму.

Назначение функции

cv2.Canny() принимает изображение и возвращает бинарную карту, где белыми пикселями (значение 255) обозначаются края (границы), а все остальные пиксели — чёрные (значение 0). Алгоритм работает с градациями серого, поэтому перед вызовом cv2.Canny() цветное изображение нужно преобразовать в grayscale.

Сигнатура функции

edges = cv2.Canny(image, threshold1, threshold2)

Параметры:

  • image — входное изображение (в оттенках серого).

  • threshold1 — нижний порог для гистерезиса.

  • threshold2 — верхний порог для гистерезиса.

Этапы алгоритма Кэнни

Алгоритм состоит из пяти ключевых шагов:

1. Применение фильтра Гаусса

Сначала изображение сглаживается с помощью гауссового размытия, чтобы уменьшить влияние шума.

blurred = cv2.GaussianBlur(gray, (5, 5), 1.4)

2. Вычисление градиента (Sobel)

Рассчитывается горизонтальный и вертикальный градиент яркости изображения с помощью операторов Собеля. Из этих градиентов вычисляется:

  • величина градиента (интенсивность перехода),

  • угол направления границы (ориентация).

Gx = Sobel_x(image)

Gy = Sobel_y(image)

magnitude = sqrt(Gx² + Gy²)

theta = arctangent(Gy / Gx)

3. Подавление немаксимумов (Non-maximum Suppression)

На этом шаге из результата удаляются все пиксели, которые не являются локальными максимумами в направлении градиента. Это делает границы "тонкими" — только 1 пиксель в ширину. Подавляются боковые размазанные границы.

4. Двойная пороговая фильтрация

Используются два порога:

  • threshold2 — высокий порог: пиксели с градиентом выше него считаются "сильными" границами.

  • threshold1 — низкий порог: пиксели между двумя порогами считаются "слабыми".

Пиксели ниже threshold1 отбрасываются. Слабые пиксели сохраняются только в том случае, если они соединены с сильными.

5. Отслеживание по гистерезису

Это ключевое отличие алгоритма Кэнни. Границы "растягиваются" за счёт соединения слабых пикселей с сильными, если они лежат в одном направлении и рядом.

Таким образом, Canny устраняет:

  • одиночные шумовые границы (они не дотягивают до порогов),

  • усиливает и объединяет настоящие границы объектов.

Пример использования

import cv2
image = cv2.imread('image.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
\# Применение детектора Кэнни
edges = cv2.Canny(gray, 100, 200)
cv2.imshow('Edges', edges)
cv2.waitKey(0)
cv2.destroyAllWindows()

Подбор порогов

  • Верхний порог должен быть в 2–3 раза выше нижнего.

  • Если threshold1 и threshold2 заданы слишком близко, результат будет "рваным".

  • Слишком высокие пороги дадут лишь самые яркие границы, пропуская тонкие детали.

  • Слишком низкие пороги дадут много ложных срабатываний.

Можно использовать cv2.Canny() в сочетании с автоматической оценкой порогов по гистограмме или cv2.mean()/cv2.medianBlur() для адаптивного выбора значений.

Сравнение с другими детекторами

Метод Устойчивость к шуму Точность границ Локализация Скорость
Оператор Собеля Средняя Низкая Средняя Высокая
--- --- --- --- ---
Laplacian Низкая Средняя Средняя Высокая
--- --- --- --- ---
Canny Высокая Очень высокая Высокая Средняя
--- --- --- --- ---

Применение в практике

  1. Обнаружение контуров объектов — извлечение форм для распознавания.

  2. Предварительная обработка перед выделением контуров (cv2.findContours).

  3. Сканирование и обработка документов — обнаружение краёв страниц и текста.

  4. Видеоанализ — отслеживание движения по границам объектов.

  5. Распознавание знаков, лиц, предметов — выделение и анализ ключевых границ.

Комбинации с другими функциями OpenCV

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (5, 5), 1.4)
edges = cv2.Canny(blurred, 50, 150)
\# Поиск контуров после Canny
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

Возможные проблемы

  • Требует ручной настройки порогов.

  • Не работает на изображениях с низкой контрастностью без предварительной коррекции.

  • Может пропускать тонкие или размытые границы, если они не проходят порог.

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