3

I am doing a project based on a motion based detection program.

It detects changes in the background as "motion" so I'd like a way to recapture a new first frame every few minutes to replace the current one to fix this issue.

I am using a Raspberry Pi 2B and a Logitech Webcam.

The code I am using is based on Pyimagesearch.

This is my version of the code:

import sys
sys.path.append('/usr/local/lib/python3.4/site-packages')
import numpy as np
import cv2
import imutils
from imutils import contours
from skimage import measure
import datetime
import time

#capture feed from webcam    
cap = cv2.VideoCapture(0)    
#intialize first frame of video stream    
firstframe = None    
avg = None

#loop frames of video/stream    
while (cap.isOpened()):    
    #grab the current frame and initialize the occupied and unoccupied    
    (grabbed, frame) = cap.read()    
    text = "Unoccupied"

    #if the frame could not be grabbed, then we have reached the end of the vid    
    if not grabbed:    
        break

    #resize the frame, convert it to grayscale, and blur it    
    frame = imutils.resize(frame, width=500)    
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)    
    gray = cv2.GaussianBlur(gray, (21,21), 0)    
    gray = cv2.medianBlur(gray, 5)   

    #if first frame is None, initialize it    
    if firstframe is None:    
        firstframe = gray    
        continue

    if avg is None:    
        print ("[INFO] starting background model...")
        avg = gray.copy().astype("float")    
        cap    
        continue

    #compute the absolute difference between the current frame and the firstframe    
    cv2.accumulateWeighted(gray, avg, 0.5)
    frameDelta = cv2.absdiff(firstframe, gray)    
    thresh = cv2.threshold(frameDelta, 70, 255, cv2.THRESH_BINARY)[1]   

    #perform a series of erosions and dilations to remove any small    
    # blobs of noise from the thresholded image    
    # then from the threshold image find contours    
    thresh = cv2.erode(thresh, None, iterations=2)    
    thresh = cv2.dilate(thresh, None, iterations=4)    
    (_,cnts,hierarchy) = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)        

    #loop over the contours    
    for (i,c) in enumerate(cnts):    
        #if the contour is too small, ignore it    
        if cv2.contourArea(c) < 500:    
            continue  

        #compute the bounding box for the contour, draw it on frame, and update the text    
        #And print the time of object detection    
        (x, y, w, h) = cv2.boundingRect(c)    
        cv2.rectangle(frame, (x,y), (x+w,y+h), (0,255,0), 2)    
        cv2.putText(frame, "#{}".format(i + 1), (x, y - 15),    
        cv2.FONT_HERSHEY_SIMPLEX, 0.45, (0, 0, 255), 2)    
        text = "Occupied"    
        print("Object detected at " + time.strftime("%I:%M:%S"))

    #draw the text and timestamp on the frame    
    cv2.putText(frame, "Room Status: {}". format(text), (10,20),    
                cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)   

    cv2.putText(frame, datetime.datetime.now().strftime("%A %d %B %Y %I:%M:%S%p"),    
                (10, frame.shape[0] - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.35,(0,0,255), 1)    
    #show the frame and record if the user presses a key    
    cv2.imshow('frame',frame)    
    cv2.imshow('Thresh',thresh)    
    cv2.imshow('FrameDelta',frameDelta)    

    #if 'q' is pressed break from loop    
    if cv2.waitKey(1) & 0xFF == ord('q'):    
        break    

#cleanup the capture and close any open windows    
cap.release()    
cv2.destroyAllWindows()
Aurora0001
  • 18,490
  • 13
  • 53
  • 168
  • if firstframe is None or counter > 300 (pseudo code) ? with a counter of number of frame processed, and reinitialize the counter before the continue ? – Tensibai Apr 20 '17 at 09:04
  • @Tensibai - im a beginner with only 6 weeks experience with OpenCV so i am still unsure of how to count the frames of the live stream or video feed – Marciano Ng Apr 20 '17 at 09:14
  • 1
    Each iteration of your loop process a frame, so I'd just count the number of iteration and use this to reset the first frame every 300 frames for example. – Tensibai Apr 20 '17 at 09:16

1 Answers1

4

I'd do something like this (untested):

# loop frames of video/stream and count them
counter = 0   
while cap.isOpened():    

    # Stripped for brevity

    #if first frame is None or too old, initialize it    
    if firstframe is None or counter > 3000:    
        firstframe = gray    
        counter = 0
        continue

    # Stripped for brevity

    #if 'q' is pressed break from loop    
    if cv2.waitKey(1) & 0xFF == ord('q'):    
        break   

    # Increment the frame counter
    counter += 1

I'm not a python developer, so my syntax here may not be correct.
The idea is to increment a counter at each frame, and set the firstframe to current frame when the counter exceed 3000, so it should be reset every 120 second at 25 frame per seconds (3000 / 25).

Helmar
  • 8,430
  • 6
  • 35
  • 84
Tensibai
  • 506
  • 2
  • 8
  • I have tried this code for some reason the frame Framedelta's screen turns completely back it only detects object from the bottom few pixels anything above that is completely black – Marciano Ng Apr 21 '17 at 03:40
  • @MarcianoNg I'm sorry, I can't help more on debugging, it was just to showcase the idea on how to reset the comparison frame. – Tensibai Apr 21 '17 at 07:42