Введение
Сегодня я расскажу о том как распознать контур нужного цвета с помощью 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 раз меньше просмотров чем ожидалось, но при этом примерно расчетное количество " добавлено в закладки" всего в два раза больше. Так и живем.