Как обнаружить контуры на изображении?
Обнаружение контуров на изображении — это важная задача в компьютерном зрении, направленная на выделение замкнутых границ объектов. Контур представляет собой последовательность точек, соединённых таким образом, чтобы образовывать границу между разными областями изображения. В OpenCV для этого используется функция cv2.findContours() в сочетании с другими методами предварительной обработки.
Общий процесс обнаружения контуров
Чтобы корректно найти контуры, изображение должно быть подготовлено:
-
Преобразование в оттенки серого (grayscale).
-
Фильтрация шума (например, с помощью гауссового размытия).
-
Бинаризация (пороговое преобразование) или детекция границ (например, cv2.Canny()).
-
Вызов cv2.findContours() на обработанном изображении.
Пример пошагово
import cv2
\# Загрузка изображения
image = cv2.imread('example.jpg')
\# Преобразование в градации серого
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
\# Размытие (для удаления шума)
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
\# Детектор границ (или можно использовать threshold)
edges = cv2.Canny(blurred, 50, 150)
\# Поиск контуров
contours, hierarchy = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
\# Отрисовка контуров
contoured_image = image.copy()
cv2.drawContours(contoured_image, contours, -1, (0, 255, 0), 2)
cv2.imshow('Contours', contoured_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
Аргументы функции cv2.findContours()
contours, hierarchy = cv2.findContours(image, mode, method)
-
image — бинарное изображение (только 0 и 255). Контуры ищутся по белым пикселям.
-
mode — способ поиска контуров:
-
cv2.RETR_EXTERNAL — только внешние контуры.
-
cv2.RETR_LIST — все контуры без иерархии.
-
cv2.RETR_TREE — все контуры с полной иерархией вложенности.
-
cv2.RETR_CCOMP — внешние и внутренние уровни отдельно.
-
-
method — способ аппроксимации контуров:
-
cv2.CHAIN_APPROX_NONE — сохраняются все точки.
-
cv2.CHAIN_APPROX_SIMPLE — удаляются избыточные точки на прямых.
-
Результат cv2.findContours()
-
contours — список массивов NumPy, каждый из которых содержит координаты точек одного контура.
-
hierarchy — массив, описывающий иерархические отношения между контурами (родитель, потомок и т.д.).
Бинаризация как альтернатива Canny
Если изображение хорошо контрастное, можно применить простое пороговое преобразование:
ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
contours, _ = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
Или адаптивное пороговое преобразование:
adaptive = cv2.adaptiveThreshold(
gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
cv2.THRESH_BINARY, 11, 2
)
contours, _ = cv2.findContours(adaptive, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
Как анализировать контуры
После нахождения контуров можно извлекать полезные характеристики:
- **Площадь
**
area = cv2.contourArea(cnt)
- **Периметр
**
perimeter = cv2.arcLength(cnt, True)
- **Аппроксимация
**
approx = cv2.approxPolyDP(cnt, 0.02 \* perimeter, True)
- **Ограничивающий прямоугольник
**
x, y, w, h = cv2.boundingRect(cnt)
- **Минимальный охватывающий круг
**
(x, y), radius = cv2.minEnclosingCircle(cnt)
- **Моменты контура (для определения центра масс)
**
M = cv2.moments(cnt)
cx = int(M\["m10"\] / M\["m00"\])
cy = int(M\["m01"\] / M\["m00"\])
Удаление мелких шумов
Иногда cv2.findContours() возвращает много маленьких "мусорных" контуров. Их можно отфильтровать по площади:
filtered = \[cnt for cnt in contours if cv2.contourArea(cnt) > 100\]
Иерархия контуров
Если используется cv2.RETR_TREE или cv2.RETR_CCOMP, hierarchy покажет вложенность:
\[Next, Previous, First_Child, Parent\]
Например, это важно для распознавания фигур с отверстиями (например, буквы O, A, P).
Применения в задачах компьютерного зрения
-
Распознавание символов — предварительное выделение областей.
-
Подсчёт объектов — по количеству контуров.
-
Анализ формы объектов — извлечение геометрических признаков.
-
Выделение ROI (областей интереса).
-
Отслеживание движения — если применять к последовательности кадров.
-
Контурная сегментация — в медицинских изображениях, спутниковых снимках.
Возможные проблемы
-
cv2.findContours() работает только с чёрно-белыми изображениями (0 и 255), иначе результат будет непредсказуем.
-
Очень шумные или плохо освещённые изображения могут привести к множеству ложных контуров.
-
Для сложных объектов необходимо комбинировать Canny, размытие, морфологические операции (cv2.dilate, cv2.erode) для улучшения результата.
Обнаружение контуров является ключевым этапом во многих алгоритмах обработки изображений и машинного зрения. В сочетании с предобработкой и анализом формы контуры позволяют эффективно находить и анализировать объекты на изображениях.