I'm trying to run a visual behaviour experiment where a whole heap of videos in a folder play one after another. I need to do this in python because I have a TTL pulse generator which I need to run at the start and end of each video.
I'm using cv2 and to try and play the videos but for reasons I can't figure out, I can't get them to play sequentially
Attached is my code
import cv2
import os
import random
videofolderPath = '/folderwithfiles'
videos = []
playlist = []
for file in os.listdir(videofolderPath):
if file.lower().endswith(".mp4"):
path=os.path.join('/folderwithfiles/',file)
playlist.append(path)
random.shuffle(playlist)
for i in range (3):
i += 1
cap = cv2.VideoCapture(playlist[i])
print(playlist[i])
while(True):
ret, frame = cap.read()
cv2.imshow('frame',frame)
if cv2.waitKey(1) & 0xFF == ord('q') or ret==False :
cap.release()
cv2.destroyAllWindows()
break
cv2.imshow('frame',frame)
cap.release()
cv2.destroyAllWindows()
The issue I'm having is I think they're all playing at once. When I press q I do see another video behind it but am struggling to get them to play one after another.
It looks like you have an error because you try to show the video before testing if ret == False.
Also, you should update i at the end of the loop as python indexing is zero based
The fix would look like this: (note that I changed the video folder path to test your code)
import cv2
import os
import random
videofolderPath = './videos'
videos = []
playlist = []
for file in os.listdir(videofolderPath):
if file.lower().endswith(".mp4"):
path = os.path.join(videofolderPath, file)
playlist.append(path)
random.shuffle(playlist)
for i in range(3):
cap = cv2.VideoCapture(playlist[i])
print(playlist[i])
while True:
ret, frame = cap.read()
# REMOVE cv2.imshow(f'frame_{i}', frame)
if cv2.waitKey(1) & 0xFF == ord('q') or ret == False:
cap.release()
cv2.destroyAllWindows()
break
cv2.imshow('frame', frame)
cap.release()
cv2.destroyAllWindows()
i += 1 # UPDATE INDEX AT THE END
A better way of writing your code would be something like this:
import cv2
import os
if __name__ == '__main__':
video_folder = "./videos"
for video_name in os.listdir(video_folder):
if not video_name.endswith(".mp4"):
continue
video_path = os.path.join(video_folder, video_name)
video = cv2.VideoCapture(video_path)
while True:
ret, frame = video.read()
if not ret:
break
cv2.imshow("video", frame)
cv2.waitKey(1)
video.release()
cv2.destroyAllWindows()
Also, I would recommend you to look at threading to load your video in "parallel" as it is very cpu intensive
Related
I am reading an rtsp(local rtsp link) stream from my cctv camera connected on LAN.
My Main Goal :-
I want to perform some processing on the frames and want to display via m3u8 in real time or nearly real time so that i can display in the frontend using hls.js.
Currently i am trying to create video in realtime so that using ffmpeg i can create the m3u8 .
Sharing my code below.
import cv2
from moviepy.editor import *
import numpy as np
import time
url = "rtsp://username:password#192.168.1.100:10554/Streaming/channels/401"
cap = cv2.VideoCapture(url)
def make_video_file(clips):
try:
print(f"clips = {clips}")
video_clip = concatenate_videoclips(clips,method='compose')
video_clip.write_videofile("video-output.mp4",fps=30)
except Exception as e:
print(e)
FRAME_COUNTER = 0
NUMBER_OF_FRAMES = 30
CLIPS = [0 for i in range(NUMBER_OF_FRAMES)]
while True:
ret, frame = cap.read()
# print(frame)
if not ret:
continue
CLIPS.pop(0)
CLIPS.append(ImageClip(frame).set_duration(1))
if FRAME_COUNTER == NUMBER_OF_FRAMES:
try:
FRAME_COUNTER = 0
make_video_file(CLIPS)
except:
pass
cv2.imshow('frame', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
NUMBER_OF_FRAMES += 1
cap.release()
cv2.destroyAllWindows()
I'm using the below code to capture images from webcam. But i need only some no.of images to be captured on click.
# Opens the inbuilt camera of laptop to capture video.
cap = cv2.VideoCapture(0)
i = 0
while(cap.isOpened()):
ret, frame = cap.read()
# This condition prevents from infinite looping
# incase video ends.
if ret == False:
break
# Save Frame by Frame into disk using imwrite method
cv2.imwrite('Frame'+str(i)+'.jpg', frame)
i += 1
cap.release()
cv2.destroyAllWindows()```
Assuming you want 500 images add this:
...
i+=1
if (i+1)%500==0:
break
that would be easy. you can use k = cv2.waitKey(1) and check what button was pressed. here is a simple example:
import cv2
def main():
cap = cv2.VideoCapture(0)
if not cap.isOpened(): # Check if the web cam is opened correctly
print("failed to open cam")
return -1
else:
print('webcam open')
for i in range(10 ** 10):
success, cv_frame = cap.read()
if not success:
print('failed to capture frame on iter {}'.format(i))
break
cv2.imshow('click t to save image and q to finish', cv_frame)
k = cv2.waitKey(1)
if k == ord('q'):
print('q was pressed - finishing...')
break
elif k == ord('t'):
print('t was pressed - saving image {}...'.format(i))
image_path = 'Frame_{}.jpg'.format(i) # i recommend a folder and not to save locally to avoid the mess
cv2.imwrite(image_path, cv_frame)
cap.release()
cv2.destroyAllWindows()
return
if __name__ == '__main__':
main()
I tried to write a small Python program which would allow me to start the webcam and capture and save the image to a .png file:
import cv2
cap = cv2.VideoCapture(0)
for i in range(3):
ret, frame = cap.read()
cap.release()
if ret == True:
cv2.imwrite(str(i) + 'image.png', frame)
else:
print("Webcam not working")
print(ret)
but when I execute it it would only save the image once under 0image.png and then display this in the console:
Webcam not working
False
Webcam not working
False
What am I doing wrong?
The cap.release() functions helps you to free up your system , i.e. , the camera device resource, and if not done so , then it will raise errors like Device or resource busy if you try to create a new instance .
So , you need to remove the cap.release() from your loop and place it at the end of your program .
This should work .
import cv2
cap = cv2.VideoCapture(0)
for i in range(3):
ret, frame = cap.read()
if ret == True:
cv2.imwrite(str(i) + 'image.png', frame)
else:
print("Webcam not working")
print(ret)`
cap.release()
am looking devolop something simply with opencv.Am looking to play videos from the web using opencv the way you can play videos from your laptop by passing the location path now a trying to pass the video url and get it to play.so far am getting error any suggestion would be nice.
import cv2
import numpy as np
import urllib3
http = urllib3.PoolManager()
r = http.request('Get','https://www.youtube.com/watch?v=NWdrO4BoCu8&list=RDNWdrO4BoCu8&start_radio=1')
cap = cv2.VideoCapture('https://www.youtube.com/watch?v=NWdrO4BoCu8&list=RDNWdrO4BoCu8&start_radio=1')
if (cap.isOpened()== False):
print("Error opening video file")
while(cap.isOpened()):
ret, frame = cap.read()
if ret == True:
cv2.imshow('Frame', frame)
if cv2.waitKey(25) & 0xFF == ord('q'):
break
else:
break
cap.release()
cv2.destroyAllWindows()
Here you can use pafy to download the video, then use OpenCV to play the video.
url = 'https://youtu.be/W1yKqFZ34y4'
vPafy = pafy.new(url)
play = vPafy.getbest(preftype="webm")
#start the video
cap = cv2.VideoCapture(play.url)
while (True):
ret,frame = cap.read()
"""
your code here
"""
cv2.imshow('frame',frame)
if cv2.waitKey(20) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
resources for installation:
https://pypi.org/project/pafy/
I'm trying to close a video when it ends by clicking two keys (n and p) using OpenCV (Python).
However, I can't understand why it doesn't work by adding the specific line to the end of the loop.
In fact, using this specific code:
import cv2
import numpy as np
# Create a VideoCapture object and read from input file
cap = cv2.VideoCapture('randomvideo.mpg')
# Check if video opened successfully
if (cap.isOpened()== False):
print("Error opening file")
# Read until video is completed
while(cap.isOpened()):
# Capture frame-by-frame
ret, frame = cap.read()
if ret == True:
# Display the resulting frame
cv2.imshow('Frame',frame)
cv2.waitKey(25)
I can lock the video at the end of its playback, but by adding this:
# Break the loop
else:
if 0xFF == (ord('n')) or 0xFF == (ord('p')):
break
I'm not able to close it by pressing the two keys.
Any suggestions?
P.S. Is there also a way to record which key has been pressed?
Thank you in advance
You can record which key is pressed by checking the return value from cv2.waitKey(). From the documentation:
It returns the code of the pressed key or -1 if no key was pressed before the specified time had elapsed.
So you can check if n or p is pressed like this
key = cv2.waitKey(25)
if key == ord('n') or key == ord('p'):
break
Here's a working version of your code
import cv2
cap = cv2.VideoCapture('randomvideo.mpg')
if not cap.isOpened():
print("Error opening file")
while(cap.isOpened()):
ret, frame = cap.read()
if ret:
cv2.imshow('frame',frame)
key = cv2.waitKey(25)
if key == ord('n') or key == ord('p'):
break