Trigger Event using key press? - python

I am trying to make my program take 8 pictures only when a key is pressed but I cant find a solution for it. I tried the keyboard package and whenever I would do key is pressed it would throw error.
By the way here is my code-
import numpy as np
import cv2
import time
cap = cv2.VideoCapture('morning.mp4')
img_counter = 0
start_time = time.time()
x=0
while(cap.isOpened()):
ret, frame = cap.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
cv2.imshow('frame',gray)
if cv2.waitKey(47) & 0xFF == ord('q'):
break
#here is where the image capturing comes into play
if time.time() - start_time > 14: #<---- Check if 15 sec passed
img_name = "frame_{}.png".format(x)
cv2.imwrite(img_name, frame)
print("{} written!".format(img_counter))
start_time = time.time()
x += 1
img_counter += 1
if x == 8:
break
cap.release()
cv2.destroyAllWindows()
After the comment "#here is where the image capturing comes into play" until the break statement is where I take pictures of the video and I want to trigger that part of code with a keypress. Any idea how I should go about it?

The issue is that you break while loop after keypress. You should use some boolean variable to point when script should capture images.
Code:
import numpy as np
import cv2
import time
cap = cv2.VideoCapture('morning.mp4')
img_counter = 0
start_time = time.time()
x=0
capture_images = False
while(cap.isOpened()):
ret, frame = cap.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
cv2.imshow('frame',gray)
if cv2.waitKey(47) & 0xFF == ord('q'):
capture_images = True
if capture_images:
#here is where the image capturing comes into play
if time.time() - start_time > 14: #<---- Check if 15 sec passed
img_name = "frame_{}.png".format(x)
cv2.imwrite(img_name, frame)
print("{} written!".format(img_counter))
start_time = time.time()
x += 1
img_counter += 1
if x == 8:
break
cap.release()
cv2.destroyAllWindows()

Related

cv2 module capturing frame from video every 5 seconds

I have been trying to capture a frame(screenshot) after every 5 seconds from a live .webm video stream which is constantly increasing in duration.
import cv2
import time
TIMER = int(5)
k=0
cap = cv2.VideoCapture('video.webm')
capture=int(1)
while True:
ret, img = cap.read()
cv2.imshow('a', img)
if ret:
prev = time.time()
while TIMER >= 0:
ret, img = cap.read()
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(img, str(TIMER),
(200, 250), font,
7, (0, 255, 255),
4, cv2.LINE_AA)
cv2.imshow('a', img)
cv2.waitKey(125)
cur = time.time()
if cur-prev >= 1:
prev = cur
TIMER = TIMER-1
if TIMER == 0:
ret, img = cap.read()
cv2.imshow('a', img)
cv2.waitKey(2000)
cv2.imwrite('camera' + str(capture) + '.jpg', img)
capture=capture+1
TIMER = int(5)
else:
break
cap.release()
cv2.destroyAllWindows()
Here my code captures the frame after every 5 frames, I'm not able to figure out the framerate calculation and making it work to capture frames after every 5 seconds rather than 5 frames.
If you want to utilize the fps information of the video an approach might be:
import cv2
cap = cv2.VideoCapture(r'path/to/vid')
fps = int(cap.get(cv2.CAP_PROP_FPS))
save_interval = 5
frame_count = 0
while cap.isOpened():
ret, frame = cap.read()
if ret:
frame_count += 1
if frame_count % (fps * save_interval) == 0:
cv2.imwrite(r'path/to/save/to')
# optional
frame_count = 0
# Break the loop
else:
break
cap.release()
cv2.destroyAllWindows()

cv2 motion capture, .avi files are stretched - Python

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()
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()

Get current video playing position using cv2 in Python

I'm trying to get the current playing time position ( in milliseconds if possible) from a playing video using CV2 with Python.
Currently I'm using this sample code to play the video file
import cv2
import numpy as np
file_name = "2.mp4"
window_name = "window"
interframe_wait_ms = 30
cap = cv2.VideoCapture(file_name)
if not cap.isOpened():
print("Error: Could not open video.")
exit()
cv2.namedWindow(window_name, cv2.WND_PROP_FULLSCREEN)
cv2.setWindowProperty(window_name, cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)
while (True):
ret, frame = cap.read()
if not ret:
print("Reached end of video, exiting.")
break
cv2.imshow(window_name, frame)
if cv2.waitKey(interframe_wait_ms) & 0x7F == ord('q'):
print("Exit requested.")
break
cap.release()
cv2.destroyAllWindows()
Is there a way to get this value or calculate it, it has to represent what's the position (in time, i.e 12.500 seconds of 24.000 seconds video) of the playback at the request time.
Thanks!
Yes, this can be achieved by querying the video FPS using VideoCapture.get(cv2.CAP_PROP_FPS) and keeping track of the frame index.
Example:
file_name = "2.mp4"
window_name = "window"
interframe_wait_ms = 30
cap = cv2.VideoCapture(file_name)
if not cap.isOpened():
print("Error: Could not open video.")
exit()
fps = cap.get(cv2.CAP_PROP_FPS)
cv2.namedWindow(window_name, cv2.WND_PROP_FULLSCREEN)
cv2.setWindowProperty(window_name, cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)
frame_index = 0
while True:
ret, frame = cap.read()
if not ret:
print("Reached end of video, exiting.")
break
cv2.imshow(window_name, frame)
print(F"playback time: {(frame_index/fps)*1000}ms")
if cv2.waitKey(interframe_wait_ms) & 0x7F == ord('q'):
print("Exit requested.")
break
frame_index += 1
cap.release()
cv2.destroyAllWindows()

Using timer to capture webcam images

How do I get breaks during the image capture? In fact, I need 5sec in between the image.
This code captures around 15-20 images per sec, But I need to take a picture at an interval of 5sec in between images
import cv2
import time
import numpy
capture = cv2.VideoCapture(0)
capture.set(3,640)
capture.set(4,480)
img_counter = 0
frame_set = []
start_time = time.time()
while(True):
ret , frame = capture.read()
gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
frame_set.append(gray)
cv2.imshow('frame',gray)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
end_time = time.time()
elapsed = end_time - start_time
img_name = "opencv_frame_{}.png".format(img_counter)
cv2.imwrite(img_name,frame)
print("{} written!".format(img_counter))
img_counter +=1
if elapsed > 1:
capture.release()
cv2.destroyAllWindows()
time.sleep(3)
You need an if statement to check if the desired time has passed. Using the already imported time package you can do this:
import cv2
import time
capture = cv2.VideoCapture(0)
capture.set(3, 640)
capture.set(4, 480)
img_counter = 0
frame_set = []
start_time = time.time()
while True:
ret, frame = capture.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
cv2.imshow('frame', gray)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
if time.time() - start_time >= 5: #<---- Check if 5 sec passed
img_name = "opencv_frame_{}.png".format(img_counter)
cv2.imwrite(img_name, frame)
print("{} written!".format(img_counter))
start_time = time.time()
img_counter += 1
The above script will save the frame in RGB every 5 seconds to the working directory.

Taking videos with opencv after some intervals

I am beginner in python and also in opencv. I want to take video of some interval with opencv videocapture function let say 10 seconds and then system should go to sleep mode for some time let say for 6 seconds .then it takes video of 10 second .Both video should be saved in separate file.my problem is that when i call first function it save the first video but on call of video2 function it doesn't save the video.sorry for bad arrangement of code . i am new user to so.
import cv2
import time
def delay(delay_time):
timeout = delay_time # [seconds]
timeout_start = time.time()
print(time.strftime("%c"))
while time.time() < timeout_start + timeout:
test = 0
if test == 3:
break
test -= 1
print(time.strftime("%c"))
def video1():
cap = cv2.VideoCapture(0)
if (cap.isOpened() == False):
print("Unable to read camera feed")
frame_width = int(cap.get(3))
frame_height = int(cap.get(4))
out = cv2.VideoWriter('Data/output1.avi',
cv2.VideoWriter_fourcc('M', 'J', 'P', 'G'), 10, (frame_width, frame_height))
while time.time() < time_start + closing_time:
ret, frame = cap.read()
if ret == True:
out.write(frame)
cv2.imshow('frame', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
else:
break
cap.release()
out.release()
def video2():
cap = cv2.VideoCapture(0)
if (cap.isOpened() == False):
print("Unable to read camera feed")
frame_width = int(cap.get(3))
frame_height = int(cap.get(4))
out = cv2.VideoWriter('Data/output2.avi',
cv2.VideoWriter_fourcc('M', 'J', 'P', 'G'), 10, (frame_width, frame_height))
while time.time() < time_start + closing_time:
ret, frame = cap.read()
if ret == True:
out.write(frame)
cv2.imshow('frame', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
else:
break
cap.release()
out.release()
cv2.destroyAllWindows()
cv2.destroyAllWindows()
print(time.strftime("%c"))
video1()
delay(6)
print(time.strftime("%c"))
video2()
Your code has so many indentation problems that I can't even point to 1 location and say this is a problem. So I rearranged your code here. Also you didn't even define time_start or closing_time in your code. But I'm assuming your real code has them and the problem is just the second video not outputting right. Well that is because you have to define time_start in the beginning of video1 and video2. If you don't re-define time_start, by the time you get to video2 this while time.time() < time_start + closing_time: has already been exhausted and will be False. So no real video is being written to file.
import cv2
import time
def delay(delay_time):
timeout = delay_time # [seconds]
timeout_start = time.time()
print(time.strftime("%c"))
while time.time() < timeout_start + timeout:
test = 0
if test == 3:
break
test -= 1
print(time.strftime("%c"))
def video1():
time_start = time.time()
cap = cv2.VideoCapture(0)
if (cap.isOpened() == False):
print("Unable to read camera feed")
frame_width = int(cap.get(3))
frame_height = int(cap.get(4))
print(frame_width,frame_height)
out = cv2.VideoWriter('output1.avi',
cv2.VideoWriter_fourcc('M', 'J', 'P', 'G'), 10, (frame_width, frame_height))
while time.time() < time_start + closing_time:
ret, frame = cap.read()
if ret == True:
out.write(frame)
#cv2.imshow('frame', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
else:
break
cap.release()
out.release()
def video2():
time_start = time.time()
cap = cv2.VideoCapture(0)
if (cap.isOpened() == False):
print("Unable to read camera feed")
frame_width = int(cap.get(3))
frame_height = int(cap.get(4))
print(frame_width,frame_height)
out = cv2.VideoWriter('output2.avi',
cv2.VideoWriter_fourcc('M', 'J', 'P', 'G'), 10, (frame_width, frame_height))
while time.time() < time_start + closing_time:
ret, frame = cap.read()
if ret == True:
out.write(frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
else:
break
cap.release()
out.release()
print(time.strftime("%c"))
closing_time = 10
video1()
delay(6)
print(time.strftime("%c"))
video2()
# this loop is here because sometimes cv2 has problems destroying windows
# if you call it once. so to be safe I call it 10 times
for _ in range(10):
cv2.destroyAllWindows()
This should do the trick it does what you asked in the question, the code is below:
`
import cv2
import time
import numpy as np
cap=cv2.VideoCapture(0)
fourcc=cv2.VideoWriter_fourcc(*'XVID')
out=cv2.VideoWriter('output1.avi', fourcc, 20.0, (640, 48))
start_time=time.time()
while True:
ret, frame=cap.read()
out.write(frame)
cv2.imshow('frame', frame)
if time.time()-start_time>=10:
break
cap.release()
out.release()
time.sleep(6)
cap2=cv2.VideoCapture(0)
fourcc2=cv2.VideoWriter_fourcc(*'XVID')
out2=cv2.VideoWriter('output2.avi', fourcc2, 20.0, (640, 48))
start_time2=time.time()
while True:
ret, frame=cap2.read()
out2.write(frame)
cv2.imshow('frame', frame)
if time.time()-start_time2>=10:
break
cap2.release()
out.release()
`

Categories