INT 21h

Hi, I am Vladimir Smagin, sysadmin. Telegram Email GPG

OpenCV: детектим движение в дампах с камер наблюдения

№ 8620 В разделе "Программирование" от March 21st, 2018,

Встала задача отслеживания движения рядом с конкретной областью. Камера хоть и умеет сама детектить движение, но делает это очень топорно и в последствии теряя записи. Было принято решение написать программу, которая обрабатывает видео файлы и находит движение в указанных мной областях. Выбор пал на библиотеку OpenCV, позволяющую очень удобно работать с видео и графикой, она универсальная, имеет биндинг для python и работает под Linux и Windows.

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

Здесь задается область обнаружения и параметры поиска. Координаты области задаются двумя точками [x1, y1, x2, y2] по которым вырезается прямоугольник. weightAlarm задает минимальный размер объекта, а lightingAlarm минимальную яркость в разности фреймов.

coord = [366, 790, 462, 884]
weightAlarm = 250
lightingAlarm = 30
skipFrames = 6

Весь алгоритм строится на сравнении 3 изображений, хранящихся в t0, t1 и t2.

def findDifference(t0, t1, t2):
    d1 = cv2.absdiff(t2, t1)
    d2 = cv2.absdiff(t1, t0)
    return cv2.bitwise_and(d1, d2)

Каждый следующий фрейм перемещается по переменным в поиске различий. Цикл проходит по всему видеофайлу фрейм за фреймом, попутно пропуская обработку ненужных фреймов и при нахождении различий сохраняя полностью фрейм в отдельный файл.

while(cap.isOpened()):
    frameNum += 1
    if frameNum >= framesCount:
        break
    else:
        ret, frame = cap.read()

    if frameSkip <= skipFrames:
        frameSkip += 1
        continue
    else:
        frameSkip = 0


    imgROI = cropRegionOfInterest(frame, coord)
    t0 = t1
    t1 = t2
    t2 = cv2.cvtColor(imgROI, cv2.COLOR_BGR2GRAY)

    diffImage = findDifference(t0, t1, t2)

    cv2.imshow('Movement', diffImage)
    if getWeight(diffImage, lightingAlarm) > weightAlarm:
        print('I found! Frame {}'.format(frameNum))
        name = "out/frame%d.jpg" % frameNum
        cv2.imwrite(name, frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

Вызов imshow не обязателен и если его убрать это сохранит достаточно много процессорного времени. Обработка видео длительностью 2 часа 10 минут заняла чуть более 10 минут при размере области 96х94 пикселя со скважностью 6. Не знаю как вам, а я считаю результат неплохим и его можно улучшить.

Тестовое видео

Область обнаружения:

Результат:

weightAlarm = 250
lightingAlarm = 30
skipFrames = 6

UPDATE! Сегодня класс начал поддерживать несколько охранных зон.

Проход по 2 охранным зонам:

Processing: /media/Documents/tmp/detect_motion/20180320112608-20180320160500_2.mp4
FPS: 25 Frames count: 7848 Length: 00:05:14
Movement! Frame 856, time 00:00:34, zone zone 1
Movement! Frame 864, time 00:00:35, zone zone 1
Movement! Frame 872, time 00:00:35, zone zone 1
Movement! Frame 880, time 00:00:35, zone zone 1
Movement! Frame 888, time 00:00:36, zone zone 1
Movement! Frame 896, time 00:00:36, zone zone 1
Movement! Frame 904, time 00:00:36, zone zone 1
Movement! Frame 6632, time 00:04:25, zone zone 1
Movement! Frame 6640, time 00:04:26, zone zone 1
Movement! Frame 6648, time 00:04:26, zone zone 1
Movement! Frame 7840, time 00:05:14, zone zone 2

real 0m31,290s

А еще было бы круто распараллелить обработку на несколько ядер процессора, а не молотить все на одном.

Вот вам репозиторий с полным кодом https://git.blindage.org/21h/detect-motion

Нет комментариев »

Leave a Reply

Your email address will not be published. Required fields are marked *

*


© Vladimir Smagin, 2005-2018. Копирование материалов без разрешения запрещено. GPG 0x29AE91B1A37721C3
Яндекс.Метрика