Ask Your Question
0

python: execute a statement if an event occurs for 60 seconds

asked 2018-11-14 01:52:21 -0600

shabdhu gravatar image

updated 2018-11-14 02:49:08 -0600

berak gravatar image

I have this opencv python code for motion detection. A rectangle box will outline the detected motion. Now i want to execute a statement(eg: print("you are standing in the frame for more than a minute"). The statement should be executed only when the person stands for more than 60 seconds.else the loop should run normally. This is my code.

# import the necessary packages
from imutils.video import VideoStream
import argparse
import datetime
import imutils
import time
import cv2

# construct the argument parser and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-v", "--video", help="path to the video file")
ap.add_argument("-a", "--min-area", type=int, default=500, help="minimum area size")
args = vars(ap.parse_args())

# if the video argument is None, then we are reading from webcam
if args.get("video", None) is None:
    vs = VideoStream(src=0).start()
    time.sleep(2.0)

# otherwise, we are reading from a video file
else:
    vs = cv2.VideoCapture(args["video"])

# initialize the first frame in the video stream
firstFrame = None
# loop over the frames of the video
while True:
    # grab the current frame and initialize the occupied/unoccupied
    # text
    frame = vs.read()
    frame = frame if args.get("video", None) is None else frame[1]
    text = "Unoccupied"

    # if the frame could not be grabbed, then we have reached the end
    # of the video
    if frame is None:
        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)

    # if the first frame is None, initialize it
    if firstFrame is None:
        firstFrame = gray
        continue
    # compute the absolute difference between the current frame and
    # first frame
    frameDelta = cv2.absdiff(firstFrame, gray)
    thresh = cv2.threshold(frameDelta, 25, 255, cv2.THRESH_BINARY)[1]

    # dilate the thresholded image to fill in holes, then find contours
    # on thresholded image
    thresh = cv2.dilate(thresh, None, iterations=2)
    cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,
        cv2.CHAIN_APPROX_SIMPLE)
    cnts = cnts[0] if imutils.is_cv2() else cnts[1]

    # loop over the contours
    for c in cnts:
        # if the contour is too small, ignore it
        if cv2.contourArea(c) < args["min_area"]:
            continue

        # compute the bounding box for the contour, draw it on the frame,
        # and update the text
        (x, y, w, h) = cv2.boundingRect(c)
        cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
        text = "Occupied"
    # 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("Security Feed", frame)
    cv2.imshow("Thresh", thresh)
    cv2.imshow("Frame Delta", frameDelta)
    key = cv2.waitKey(1) & 0xFF

    # if the `q` key is pressed, break from the lop
    if key == ord("q"):
        break

# cleanup the camera and ...
(more)
edit retag flag offensive close merge delete

Comments

i was not able to add the code in the proper format. Thats why i used SO. Kindly help me out

shabdhu gravatar imageshabdhu ( 2018-11-14 02:46:27 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
0

answered 2018-11-14 02:46:11 -0600

berak gravatar image

updated 2018-11-14 02:51:22 -0600

this is not really an opencv problem, more about general python skills, but it might go like this:

import time

timer = 0 # our variable for *absolute* time measurement
last_t = 0 # cache var

while (True):         # detection loop
    now = time.time() # in seconds 
    dt = now - last_t # diff time
    last_t = now      # cache

    # try to detect person

    if person_detected:
        timer += dt  # sum up
    else:
        timer = 0    # reset

    if timer > 60:
        print("you've been here for a minute.")
edit flag offensive delete link more

Comments

sorry for being noob. But which is the "person_detected" block in the opencv code?

shabdhu gravatar imageshabdhu ( 2018-11-14 02:49:39 -0600 )edit

i won't tell you ;) (you need to understand the opencv code, i guess)

berak gravatar imageberak ( 2018-11-14 02:54:18 -0600 )edit

I could understand and i tried adding it with the for loop. But since there might be many contours and since i have to loop over every detected contours, each time the timer is reset. Kindly help

shabdhu gravatar imageshabdhu ( 2018-11-14 03:12:44 -0600 )edit

your current absdiff / findContours approach is very brittle, and will trigger a lot of "false" detections

maybe you need a better way to detect actual humans or this

berak gravatar imageberak ( 2018-11-14 03:13:58 -0600 )edit
1

my objective is to do this with a raspberry pi3. and person detection is not my final objective. my objective is to intimate the person to stay away from an emergency exit, if he/she is blocking the exit for more than a minute.

shabdhu gravatar imageshabdhu ( 2018-11-14 03:17:23 -0600 )edit

yea, but none of this is relevant to your question about timing above.

and, since this also seems to be "indoor", you could try with a "static" image of your door, and absdiff the current video frame from that. crop the door region, sum up the diff, and take that as a measure of "clutter"

berak gravatar imageberak ( 2018-11-14 03:24:04 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2018-11-14 01:52:21 -0600

Seen: 388 times

Last updated: Nov 14 '18