So Im trying to make my webcam capture motion, and I how to register motion is going fine but with all these nested while loops my save files are dragged to 30 min long and not 10 sec like intended. I can't figure out what Im doing wrong.
What I mean by dragged out is that I record for 10 sec, but when I go into my files to review the footage it's 30 mins of just some frames.
The idea is to make it register motion and then record for 10 seconds and save the recording as a .avi file.
import cv2
from datetime import datetime
import time
vid_capture = cv2.VideoCapture(0)
fourcc = cv2.VideoWriter_fourcc(*'XVID')
ret, cur_frame = vid_capture.read()
prev_frame = cur_frame
capture_duration = 10
motion = False
while True:
frame_diff = cv2.absdiff(cv2.cvtColor(cur_frame, cv2.COLOR_BGR2GRAY), cv2.cvtColor(prev_frame, cv2.COLOR_BGR2GRAY))
if frame_diff.max() > 150:
motion = True
if motion:
start_time = time.time()
name = str(datetime.now().date()) "_" str(datetime.now().time().hour) "-" str(datetime.now().time().minute) "-" str(datetime.now().time().second) ".avi"
out = cv2.VideoWriter(name, fourcc, 20.0, (640,480))
ret, cur_frame = vid_capture.read()
while time.time() - start_time < capture_duration:
if ret:
out.write(cur_frame)
cv2.imshow('Input', cur_frame)
else:
break
out.release()
cv2.destroyAllWindows()
motion = False
prev_frame = cur_frame.copy()
ret, cur_frame = vid_capture.read()
if cv2.waitKey(1) == 27:
break
vid_capture.release()
CodePudding user response:
Your code may run very fast and it may create ie. 100 frames every second.
But 20.0
in VideoWriter
doesn't write it video with speed 20 frames per second but it only inform players that they have to display 20 frames per second. But if you create 100 frames per second so finally it wll need 5 seconds instead of 1 second to display it (100frames/20FPS = 5seconds
).
You have to slow down to create new frame every 50ms
- (1000ms/20FPS
) - you can try waitKey(50)
.
EDIT:
Because code may need some time to create frame so it may need little smaller dealy in waitKey
- i.e. 48
- or you may try to measure time inside loop and use
waitKey( 50 - (loop_end-loop_start) )
You run inner while
-loop which all time write the same frame - you should use ret, cur_frame = vid_capture.read()
inside this while
-loop
Shorter:
name = datetime.now().strftime("%Y-%m-%d_%H-%M-%S.avi")
motion = (frame_diff.max() > 150)
I see one possible problem: cv2.waitKey
not work when window is closed - because system sends keys/mouse events only to active window, and when window is closed then cv2
may not get keys/mouse events.
from datetime import datetime
import time
import cv2
vid_capture = cv2.VideoCapture(0)
fourcc = cv2.VideoWriter_fourcc(*'XVID')
ret, cur_frame = vid_capture.read()
prev_frame = cur_frame
capture_duration = 10
while True:
frame_diff = cv2.absdiff(cv2.cvtColor(cur_frame, cv2.COLOR_BGR2GRAY), cv2.cvtColor(prev_frame, cv2.COLOR_BGR2GRAY))
motion = (frame_diff.max() > 150)
if motion:
name = datetime.now().strftime("%Y-%m-%d_%H-%M-%S.avi")
print(name)
out = cv2.VideoWriter(name, fourcc, 20.0, (640,480))
start_time = time.time()
while time.time() - start_time <= capture_duration:
ret, cur_frame = vid_capture.read()
if ret:
out.write(cur_frame)
cv2.imshow(name, cur_frame)
if cv2.waitKey(50) == 27:
break
else:
break
out.release()
cv2.destroyAllWindows()
prev_frame = cur_frame.copy()
ret, cur_frame = vid_capture.read()
if cv2.waitKey(1) == 27:
break
vid_capture.release()