Введение
Сегодня я расскажу о том как распознать контур нужного цвета с помощью python/ opencv такая задача часто встречается в робототехнике, и всяких автоматизациях.
С помощью предложенного решения можно например различать контур линии за которую не должен выезжать робот, или обьект для коптера. Такая задача может возникнуть если нужно например

Чему научимся
Изначально я предполагаю что у человека есть python ide(подойдет практически любое) и базовое знание питона.
Установим библиотеку OpenCV с помощью следующей команды:
pip install opencv-python
И numpy:
pip install numpy
Код
Добавим необходимые библиотеки:
import cv2 import numpy as np
Создадим обьект cup куда будет идти видео. 0 — камера дефолтная, 1 — кастомная.
cap = cv2.VideoCapture(0)
_, frame = cap.read()
считывает кадр. вместо _ может быть rate — туда пойдет fps камеры, но в данном случае я этим не пользуюсь.
А теперь давайте обработаем кадр для дальнейшего удобства. Уменьшим:
frameresized = cv2.resize(frame, None, fx=2, fy=2, interpolation=cv2.INTER_CUBIC) hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) # первеод в цветовой формат BGR2HSV hsv = cv2.blur(hsv, (5, 5)) # наложение маски mask = cv2.inRange(hsv, (89, 124, 73), (255, 255, 255)) #кадр уже с маской lower_blue = np.array([38, 86, 0]) #нижняя граница необходимого цвета (в нашем случае голубого)
Рассмотрим подробнее функцию resize:
frame - кадр которой передается fx - фактор размера по оси Х fy - фактор размера по оси Y interpolation - INTER_NEAREST - интерполяция до ближайшего соседа INTER_LINEAR - билинейная интерполяция (используется по дефолту) INTER_AREA - повторная выборка с использованием отношения площади пикселя. Это может быть предпочтительный метод для прореживания изображений а когда изображение увеличина дает результат похожий на INTER_NEAREST method. INTER_CUBIC - бикубическая интерполяция 4x4 клеток пикселей INTER_LANCZOS4 - интерполяция Ланкоза 8x8 клеток пикселей
А теперь давайте на обработанном кадре распознаем контуры и отсортируем их:
contours, _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE) counturs = sorted(contours, key=cv2.contourArea, reverse=True)
А теперь давайте рассмотрим findContours подробнее:
cv.CHAIN_APPROX_NONE - найдет все точки границы контура(если контур сложный может неплохо так нагрузить комп) cv.CHAIN_APPROX_SIMPLE - найдет точки границ линии - хорошо для распознования геометрии(знаков и тд) cv.RETR_TREE - по сути просто извлекает точки и не строит между ними никаких отношений cv.RETR_EXTERNAL - возвращает только самые старшие контуры в иерахии cv.RETR_CCOMP - сторит 2 уровневую иерархию, те если у нас контур в контуре то он покажет то стариший будет на 1 , а младший на втором cv2.RETR_TREE - вернет дерево всех конутуров
Визуализация RETR_CCOMP:

Визуализация RETR_TREE:

И теперь нарисуем контуры которые нашли:
or contour in counturs: cv2.drawContours(frame, counturs[0], -1, (255, 0, 255), 3) cv2.imshow("Counturs", frame) # рисует рокно с конурами #cv2.imshow("Mask", mask) # cv2.imshow("ret",ret) #cv2.imshow("blur",blurred_frame) key = cv2.waitKey(1) #ждем нажатия ESC if key == 27: break
И по нажатию кнопки останавливаем чтение камеры и закрываем все окна:
cap.release() cv2.destroyAllWindows()
Спасибо за прочтение статьи.
Буду признателен если вы подпишитесь на мой канал в
Upd — забавно что статья набрала примерно в 8 раз меньше просмотров чем ожидалось, но при этом примерно расчетное количество " добавлено в закладки" всего в два раза больше. Так и живем.
