Этот проект посвящен обнаружению границ (краев) и обнаружению движения с помощью OpenCV на плате Raspberry Pi 4. В OpenCV обнаружение краев и обнаружение движения служат столпами обработки изображений и компьютерного зрения. Благодаря обработке изображений такие методы, как обнаружение краев, уточняют визуальные данные, выделяя особенности для улучшенного вывода изображения. Напротив, обнаружение движения в компьютерном зрении связано с интерпретацией: оно различает и понимает движение, анализируя последовательности изображений, предлагая более глубокое понимание визуальных данных.
В этом проекте мы будем использовать OpenCV на Raspberry Pi 4 для обработки видеокадров. Для обнаружения краев мы будем использовать метод обнаружения краев Canny на версиях кадров в оттенках серого. Для определения движения мы рассчитаем среднеквадратичную ошибку (MSE) между последовательными кадрами в оттенках серого - значительное изменение MSE указывает на движение. Эта настройка обеспечивает визуальное представление краев и потенциального движения в видеопотоке в реальном времени .
Необходимые компоненты
- Плата Raspberry Pi 4 Model B (или другая) (купить на AliExpress).
- Камера для Raspberry Pi (купить на AliExpress).
- SD-карта 16/32 ГБ.
- Адаптер постоянного тока 5 В, 3 А для RPi.
- ЖК-дисплей (опционально).
- Мышь и клавиатура (опционально).
Реклама: ООО "АЛИБАБА.КОМ (РУ)" ИНН: 7703380158
Подключение камеры к Raspberry Pi
Raspberry Pi Camera — периферийное устройство, разработанное Raspberry Pi Foundation для использования с серией одноплатных компьютеров Raspberry Pi. Модуль камеры позволяет добавлять возможности видео/фотосъемки в проекты Raspberry Pi.
Для этого проекта мы можем использовать 5-мегапиксельную камеру Raspberry Pi.
Просто подключите модуль камеры к плате Raspberry Pi 4 с помощью разъема камеры.
Чтобы использовать камеру, вам нужно сначала включить модуль камеры. Откройте Raspberry Pi Configuration Tool, введя sudo raspi-config
в терминале. Перейдите к Interfacing Options
> Camera
и включите его.
Что такое среднеквадратическая ошибка (MSE) и метод обнаружения границ Canny?
В этом проекте мы будем использовать метод обнаружения краев Canny для обнаружения краев и алгоритм среднеквадратической ошибки (MSE) для обнаружения движения. Вместе эти шаги позволяют алгоритму Canny надежно обнаруживать края на изображении.
Среднеквадратическая ошибка (MSE)
MSE — это часто используемая метрика для измерения разницы между двумя изображениями или сигналами. Она вычисляет среднеквадратические разницы между соответствующими значениями двух сигналов или изображений.
Низкая MSE указывает на то, что эти два изображения тесно связаны, в то время как высокая MSE предполагает значительные различия. Математически для двух изображений I и J MSE определяется как:
где m и n — размеры изображений.
Метод обнаружения краёв Canny
Метод Canny — это многошаговый алгоритм, предназначенный для обнаружения широкого спектра краев на изображениях.
Ключевые этапы метода Canny включают в себя:
- Подавление шума: изображения сглаживаются с помощью фильтра Гаусса для устранения шума.
- Вычисление градиента: величина и направление градиента вычисляются для каждого пикселя, выделяя потенциальные края.
- Подавление немаксимума: этот шаг утончает потенциальные края, гарантируя, что величина градиента максимальна в направлении края, уменьшая толщину краев.
- Двойной порог: он различает сильные, слабые и не-края, гарантируя четкость настоящих краев.
- Отслеживание краев с помощью гистерезиса: слабые края либо отбрасываются, либо повышаются до сильных краев в зависимости от их связи с сильными краями.
Настройка Raspberry Pi, установка библиотек и зависимостей
OpenCV требуется для обнаружения краев и движения, а также других задач обработки изображений, присутствующих в коде. Поэтому вам необходимо сначала установить OpenCV. Следуйте следующему руководству чтобы установить OpenCV на вашу плату Raspberry Pi.
Следующий шаг — установить picamera. Поэтому установите ее с помощью pip.
1 |
pip3 install picamera |
Настройка завершена. Теперь мы можем перейти непосредственно к нашему проекту
Код Python для Raspberry Pi для обнаружения краев и обнаружения движения с помощью OpenCV
Теперь давайте разработаем код Python, который поможет в обнаружении границ и обнаружении движения с помощью библиотеки OpenCV и камеры Raspberry Pi.
Код Python
Откройте Thonny IDE и вставьте следующий код в редактор Thonny. Сохраните этот файл под именем «Motion_detection.py» в любом месте.
Вот полный код Python.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
import cv2 import time import numpy as np CAMERA_DEVICE_ID = 0 IMAGE_WIDTH = 320 IMAGE_HEIGHT = 240 MOTION_BLUR = True cnt_frame = 0 fps = 0 def mse(image_a, image_b): err = np.sum((image_a.astype("float") - image_b.astype("float")) ** 2) err /= float(image_a.shape[0] * image_a.shape[1]) return err def lighting_compensation(frame): gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) return cv2.equalizeHist(gray) if __name__ == "__main__": try: cap = cv2.VideoCapture(CAMERA_DEVICE_ID) cap.set(3, IMAGE_WIDTH) cap.set(4, IMAGE_HEIGHT) while True: start_time = time.time() _, frame_raw = cap.read() if MOTION_BLUR: frame = cv2.GaussianBlur(frame_raw, (3,3),0) else: frame = frame_raw compensated_frame = lighting_compensation(frame) frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) edges = cv2.Canny(frame_gray, 100, 200) if cnt_frame > 0: if mse(frame_gray, frame_gray_p) > 100: print('Frame{0}: Motion Detected using MSE!'.format(cnt_frame)) cv2.imshow('Original', frame) cv2.imshow('Compensated', compensated_frame) cv2.imshow('Gray', frame_gray) cv2.imshow('Edge', edges) end_time = time.time() seconds = end_time - start_time fps = 1.0 / seconds print("Estimated fps:{0:0.1f}".format(fps)); cnt_frame += 1 frame_gray_p = frame_gray if cv2.waitKey(1) == 27: break except Exception as e: print(e) finally: cv2.destroyAllWindows() cap.release() |
Объяснение работы кода
1 2 3 4 5 6 7 8 |
import cv2 import time import numpy as np CAMERA_DEVICE_ID = 0 IMAGE_WIDTH = 320 IMAGE_HEIGHT = 240 MOTION_BLUR = True |
В этом разделе импортируются необходимые библиотеки и настраиваются некоторые базовые константы конфигурации. Мы настраиваем устройство камеры, разрешение и решаем, хотим ли мы использовать размытие движения.
1 2 |
def mse(image_a, image_b): ... |
Эта функция вычисляет среднеквадратичную ошибку между двумя изображениями. Она используется позже, чтобы определить, есть ли движение между последовательными кадрами, проверяя разницу.
1 2 |
def lighting_compensation(frame): ... |
Эта функция предназначена для улучшения качества изображений, снятых в различных условиях освещения. Она выравнивает гистограмму изображения в оттенках серого, улучшая его общую видимость.
1 2 3 4 5 |
if __name__ == "__main__": try: cap = cv2.VideoCapture(CAMERA_DEVICE_ID) cap.set(3, IMAGE_WIDTH) cap.set(4, IMAGE_HEIGHT) |
Эта часть инициализирует основную часть кода. Она настраивает захват видео с определенного устройства камеры и устанавливает разрешение видео.
1 2 3 4 5 6 7 |
while True: start_time = time.time() _, frame_raw = cap.read() ... compensated_frame = lighting_compensation(frame) frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) edges = cv2.Canny(frame_gray, 100, 200) |
Внутри цикла для каждого кадра выполняется захват кадра, при необходимости применяется размытие по Гауссу, выполняется компенсация освещения, преобразуется кадр в оттенки серого, а затем определяются края.
1 2 3 |
if cnt_frame > 0: if mse(frame_gray, frame_gray_p) > 100: print('Frame{0}: Motion Detected using MSE!'.format(cnt_frame)) |
Эта часть кода проверяет наличие движения, сравнивая текущий кадр в оттенках серого с предыдущим с помощью MSE. Если MSE выше 100, он обнаруживает движение.
1 2 3 4 5 6 |
cv2.imshow('Original', frame) ... end_time = time.time() seconds = end_time - start_time fps = 1.0 / seconds print("Estimated fps:{0:0.1f}".format(fps)); |
Обработанные кадры отображаются, а также вычисляется и печатается FPS (кадры в секунду) обработки.
1 2 3 4 5 6 |
if cv2.waitKey(1) == 27: break ... finally: cv2.destroyAllWindows() cap.release() |
Если нажать клавишу 'Esc' (со значением ASCII 27), цикл прерывается. И в конце, независимо от того, как был завершен основной цикл, код обеспечивает закрытие окон OpenCV и освобождение ресурсов.
Тестирование работы проекта
Теперь нам нужно запустить код для обнаружения границ и обнаружения движения с помощью Raspberry Pi и OpenCV.
После запуска кода откроются 4 окна, как показано ниже.
В первом окне будет показано исходное изображение. Во втором окне будет показано преобразованное изображение в оттенках серого. В третьем окне будет показано скомпенсированное изображение, которое выглядит более четким. На четвертом изображении показано обнаружение краев.
Thonny Shell отобразит расчетную частоту кадров в секунду.
Он также будет отображать статус обнаружения движения. Это означает, что всякий раз, когда объект движется или происходит изменение в кадре, в Thonny Shell будет отображаться сообщение “motion detected” («обнаружено движение»).
Заключение
Проект обнаружение краев и обнаружение движения с помощью OpenCV на Raspberry Pi — это комплексная демонстрация интеграции нескольких методов обработки изображений с использованием OpenCV в сценарии реального времени. Он захватывает видеокадры, улучшает их с помощью компенсации освещения, обнаруживает края с помощью метода обнаружения краев Canny и отслеживает изменения от кадра к кадру для обнаружения движения с помощью метода среднеквадратичной ошибки.
Более того, он отображает обработанные изображения в реальном времени и вычисляет количество кадров в секунду для оценки производительности. Это сочетание методов не только демонстрирует мощь и гибкость OpenCV, но и закладывает основу для более продвинутых систем наблюдения или мониторинга, которые могут эффективно работать в различных условиях освещения и обнаруживать движение.
20 просмотров