Отслеживание движения в opencv python

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

Сначала я попытался с отслеживанием объектов, используя доступные алгоритмы в opencv 3 (BOOSTING, MIL, KCF, TLD, MEDIAFLOW, GOTURN (возвращает ошибку, еще не смог ее решить)) из эта ссылка, и я даже пробовал базовый алгоритм отслеживания движения, вычитая первый кадр, но ни один из них дает хороший результат. Ссылка

Я бы предпочел код с предустановленным прямоугольником, который окружает область движения после его обнаружения. Что-то вроде этого видео

Я не очень хорошо знаком с OPENCV, но я считаю, что отслеживание одиночного движения не должно быть проблемой, поскольку уже проделано много работы. Должен ли я рассмотреть другие библиотеки/API или есть лучший код/учебник, которому я могу следовать, чтобы сделать это? я хочу использовать это позже с нейронной сетью (поэтому я пытаюсь решить это с помощью python/opencv)

Спасибо за любую помощь/совет

Изменить:

Я удалил предыдущий код, чтобы сделать пост чище.

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

jimport imutils
import time
import cv2

previousFrame = None

def searchForMovement(cnts, frame, min_area):

    text = "Undetected"

    flag = 0

    for c in cnts:
        # if the contour is too small, ignore it
        if cv2.contourArea(c) < min_area:
            continue

        #Use the flag to prevent the detection of other motions in the video
        if flag == 0:
            (x, y, w, h) = cv2.boundingRect(c)

            #print("x y w h")
            #print(x,y,w,h) 
            cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 2)
            text = "Detected"
            flag = 1

    return frame, text

def trackMotion(ret,frame, gaussian_kernel, sensitivity_value, min_area):


    if ret:

        # Convert to grayscale and blur it for better frame difference
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        gray = cv2.GaussianBlur(gray, (gaussian_kernel, gaussian_kernel), 0)



        global previousFrame

        if previousFrame is None:
            previousFrame = gray
            return frame, "Uninitialized", frame, frame



        frameDiff = cv2.absdiff(previousFrame, gray)
        thresh = cv2.threshold(frameDiff, sensitivity_value, 255, cv2.THRESH_BINARY)[1]

        thresh = cv2.dilate(thresh, None, iterations=2)
        _, cnts, _ = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

        frame, text = searchForMovement(cnts, frame, min_area)
        #previousFrame = gray

    return frame, text, thresh, frameDiff




if __name__ == '__main__':

    video = "Track.avi"
    video0 = "Track.mp4"
    video1= "Ntest1.avi"
    video2= "Ntest2.avi"

    camera = cv2.VideoCapture(video1)
    time.sleep(0.25)
    min_area = 5000 #int(sys.argv[1])

    cv2.namedWindow("Security Camera Feed")


    while camera.isOpened():

        gaussian_kernel = 27
        sensitivity_value = 5
        min_area = 2500

        ret, frame = camera.read()

        #Check if the next camera read is not null
        if ret:
            frame, text, thresh, frameDiff = trackMotion(ret,frame, gaussian_kernel, sensitivity_value, min_area)

        else:
            print("Video Finished")
            break


        cv2.namedWindow('Thresh',cv2.WINDOW_NORMAL)
        cv2.namedWindow('Frame Difference',cv2.WINDOW_NORMAL)
        cv2.namedWindow('Security Camera Feed',cv2.WINDOW_NORMAL)

        cv2.resizeWindow('Thresh', 800,600)
        cv2.resizeWindow('Frame Difference', 800,600)
        cv2.resizeWindow('Security Camera Feed', 800,600)
      # uncomment to see the tresh and framedifference displays                  
        cv2.imshow("Thresh", thresh)
        cv2.imshow("Frame Difference", frameDiff)



        cv2.putText(frame, text, (10, 20), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)
        cv2.imshow("Security Camera Feed", frame)

        key = cv2.waitKey(3) & 0xFF
        if key == 27 or key == ord('q'):
            print("Bye")
            break

    camera.release()
cv2.destroyAllWindows()

На этом рисунке показано, как самый первый кадр все еще влияет на результаты разности кадров, что заставляет блок покрывать область без движения.

Результат, показывающий разницу кадров и отображение видео

Здесь показан случай, когда движение игнорируется, поскольку несуществующее движение (разница между кадрами второго и первого кадров видео) обнаруживается ложно. Когда я разрешаю множественное отслеживание, он отслеживает оба, что по-прежнему неверно, поскольку обнаруживает пустую область.

введите здесь описание изображения

У кого-нибудь есть идея, где код неверен или отсутствует? Я продолжаю пытаться, но не могу заставить его работать должным образом.

Заранее спасибо !!


person Wazaki    schedule 04.01.2018    source источник
comment
Не кидайте сразу ссылку, где ваш испробованный код?   -  person Kinght 金    schedule 04.01.2018
comment
@Silencer Я добавил это в редактирование. Спасибо за комментарий   -  person Wazaki    schedule 04.01.2018
comment
Я думаю, что вы должны сначала правильно определить проблему, а затем пробовать решения. Вы хотите сначала обнаружить движение... и, возможно, отследить этот объект? или, может быть, только обнаруживать движение на каждом шаге? Первые упомянутые вами алгоритмы предназначены только для отслеживания, а не для обнаружения, поэтому вам нужен ROI (это ваш объект для отслеживания). Кроме того, что произойдет, если вы переместите более 1 объекта? Я бы порекомендовал сначала попытаться правильно определить движение, вы можете попробовать что-то вроде это   -  person api55    schedule 04.01.2018
comment
@api55 Спасибо за ваш комментарий. Я пытаюсь следовать вашей рекомендации, и как только я получу некоторые результаты, я отредактирую и упомяну об этом. Что касается ваших вопросов, как вы сказали, это обнаружение движения и отслеживание этого объекта. В моем сценарии в комнате есть собака, и я хочу отследить ее (с помощью ограничивающего прямоугольника). Таким образом, в основном, собака движется - обнаруживается движение - создается один ограничивающий блок, который продолжает отслеживать его (игнорируя любое другое движение в видео).   -  person Wazaki    schedule 06.01.2018
comment
Итак, у вас есть 2 задачи, попробуйте выполнить правильно первую и вторую, вы можете попробовать использовать алгоритмы отслеживания с известным регионом.   -  person api55    schedule 06.01.2018
comment
@api55 Я пытался работать над кодом отслеживания движения, который казался многообещающим, однако все еще сталкивался с проблемой. Я отредактировал свой вопрос, чтобы включить более конкретные детали проблемы. Буду рад, если вы посмотрите и выскажете свое мнение. Большое спасибо !!   -  person Wazaki    schedule 07.01.2018
comment
@api55 Итак, мы никак не можем предотвратить это в коде, которым я поделился? Спасибо за pdf, я просмотрел его и, как вы сказали, это эффект ореола. У вас случайно нет реализации, которой вы можете поделиться? Спасибо за вашу помощь !! Я узнаю больше благодаря вашим комментариям   -  person Wazaki    schedule 07.01.2018
comment
Вы наконец сделали работу?? Я работаю над чем-то подобным, но не со статическим фоном... просто поделитесь кодом, если можете... большое спасибо. @ОсуманААА   -  person Lewis    schedule 29.10.2018
comment
@Lewis Я действительно не получил удовлетворительных результатов с помощью такого метода, и если ваш фон не статичен, это будет еще сложнее. В итоге я использовал YOLO для обнаружения объектов для отслеживания.   -  person Wazaki    schedule 30.10.2018


Ответы (1)


Чтобы включить обнаружение движения, я создал общие компоненты в реестре NPM и концентраторе докеров. Он обнаруживает движение на клиентской веб-камере (приложение React) и использует сервер в Python на основе открытого CV, поэтому клиент просто захватывает изображения с веб-камеры, а сервер анализирует эти изображения с помощью OPENCV. чтобы определить, есть ли движение или нет, клиент может указать функцию обратного вызова, которую сервер вызывает каждый раз, когда есть движение. Сервер - это просто изображение докера, которое вы можете извлечь и запустить, и указать его URL-адрес для клиента.

Реестр NPM (клиент)

Ссылка на реестр:

https://www.npmjs.com/settings/kunalpimparkhede/packages

Команда

npm install motion-detector-client

Образ Docker (сервер)

Ссылка на сайт

https://hub.docker.com/r/kunalpimparkhede/motiondetectorwebcam

Команда

docker pull kunalpimparkhede/motiondetectorwebcam

Вам просто нужно написать следующий код, чтобы иметь обнаружение движения

Использование:

import MotionDetectingClient from './MotionDetectingClient';

<MotionDetectingClient server="http://0.0.0.0:8080" callback={handleMovement}/>

function handleMovement(pixels) 
{
console.log("Movement By Pixel="+pixels)
}

На стороне сервера: просто запустите сервер докеров на порту 8080:

docker run --name motion-detector-server-app -P 8080:5000 motion-detector-server-app
person Kunal Pimparkhede    schedule 11.03.2021