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
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:    

    #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    

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

    #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:    

        #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    

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

#cleanup the capture and close any open windows    
  • 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 9: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 Apr 20 '17 at 9: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 9:16

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

    # Stripped for brevity

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

    # 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).

  • 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 Apr 21 '17 at 3: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 7:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.