OpenCV для детектирования дорожных знаков

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

Принцип работы программы заключается в следующем: на вход подается изображение, где предварительно мы ожидаем детектировать дорожный знак. При этом работа с видео такая же, так как в таком случае видео покадрово передается в программу и дальнейший алгоритм не отличается. Обычно все изображения, привычные нашему глазу, находятся в формате RGB. С ним неудобно работать, так как падение тени или свечение солнца будут сильно искажать оттенки цвета. А работа программы основана именно на определении цвета. Поэтому первым шагом будет переход в цветовое пространство HSV. Здесь мы уже будем накладывать цветовой фильтр, который будет разрешать только те цвета, которые встречаются в дорожных знаках. Чтобы в контурах не было разрывов, сгладим разрешенные пиксели. Далее рисуем контуры вокруг разрешенных пикселей. Чтобы не было много лишних, можно поставить ограничения по площади контура, например, в данном случае контур должен находиться в пределе от 400 до 10000 пикселей.

def detectionRED(frame, spisok): """ В качестве аргумента функция принимает кадр, переводит в цветовой формат hsv, накладывает маску только красного цвета, сглаживает области и находит контуры. Цикл оставляет контуры, подходящие по размеру, и отрисовывает их. Функция возвращает кадр, с нарисованными контурами""" cv.imshow('img', frame) frame_hsv = cv.cvtColor(frame, cv.COLOR_BGR2HSV) cv.imshow('frame0', frame_hsv) frame_mask = cv.inRange(frame_hsv, (0, 162, 67), (255, 255, 255)) cv.imshow('frame1', frame_mask) frame_dilate = cv.dilate(frame_mask, None, iterations=2) cv.imshow('frame2', frame_dilate) contours, hierarchy = cv.findContours(frame_dilate.copy(), cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE) sort = spisok for i in contours: area = cv.contourArea(i) if 400 < area < 10000: # можно регулировать дальность sort.append(i) cv.drawContours(frame, sort, -1, (0, 23, 44), 2) return frame, sort

Поэтапно все действия с изображением представлены на фото ниже.

OpenCV для детектирования дорожных знаков

Остается только вырезать дорожные знаки с изображения и сохранить отдельным файлом.

def detectionIMAGE(image_name): """ Функция принимает в качестве аргумента название изображения. Передает в функции отрисовывания контуров и возвращает изображение с нарисованными контурами. Для выхода нажмите кнопку "Esc". """ start_time = time.time() image = cv.imread(image_name) print(type(image)) cadr = cv.imread(image_name) spisok = [] frame, sort = dtRED(image, sort) while True: cv.drawContours(frame, sort, -1, (0, 234, 135), 2) cv.imshow('frame', frame) (x, y, w, h) = cv.boundingRect(sort[0]) detect = cadr[y:y + h, x:x + w] cv.imshow('q', detect) (x, y, w, h) = cv.boundingRect(sort[1]) detect = cadr[y:y + h, x:x + w] cv.imshow('r', detect) (x, y, w, h) = cv.boundingRect(sort[2]) detect = cadr[y:y + h, x:x + w] cv.imshow('u', detect) end_time = time.time() if cv.waitKey(1) == 27: break print('Время выполнения:', end_time - start_time) return frame
OpenCV для детектирования дорожных знаков

Считаю результат очень хорошим, потому что даже в ночное время, программа отлично отработала и смогла детектировать знак, находящийся на заднем фоне. К примеру, нейросеть, обученная на датасете OpenImageV4, на этом изображении смогла найти только знаки на переднем фоне. При этом, в нашем случае не требуется высоких вычислительных мощностей и ядер CUDA и, соответственно, время работы сильно уменьшается, особенно на маломощных и портативных устройствах. Время работы программы составило меньше секунды.

OpenCV для детектирования дорожных знаков

При этом нейросеть, построенная на архитектуре SSD, работала значительно дольше и распознала два знака как один.

OpenCV для детектирования дорожных знаков
OpenCV для детектирования дорожных знаков

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

66 показов
2.2K2.2K открытий
Начать дискуссию