I am new to both OpenCV and Python, and I am trying to create a simple program that will read in a video file named 'SixtyFPS.mov' and replay the video when it has reached its end. Ideally I would like to have the video loop continuously. I have not been able to find a solution for this online, however most of the answers I see involve using cap.set(cv2.CAP_PROP_POS_FRAMES, 1) or something of that nature in order to reset the frames. If anyone can explain to me how to use the cap.set feature in order to restart the video that would be greatly appreciated.
# The video 'SixtyFPS.mov' was recorded on an iPhone 7 at 60 FPS
# The video has a length of roughly 4 seconds long and so the total number
# of frames should be ~240, however my number_of_frames variable is equal to 115
# I am looking for a way to restart the video once it has reached its end but
# I have not yet discovered a good method for doing so. Any advice would be
# greatly appreciated. I am using Python 3.6.4 and OpenCV 3.3.1
# I needed to rotate the video so that it would be viewed in portrait
# orientation rather than landscape
import cv2
import numpy as np
# Load in the video
video_cap = cv2.VideoCapture('SixtyFPS.mov')
# display the total number of frames. Should be ~240 and not 115
number_of_frames = int(video_cap.get(cv2.CAP_PROP_FRAME_COUNT))
print("The total number of frames is: " + str(number_of_frames))
# Check if video opened successfully
if (video_cap.isOpened() == False):
print("Error opening video file")
frame_counter = 0
# Read until video is completed
while(video_cap.isOpened()):
# Capture frame-by-frame
ret, frame = video_cap.read()
if ret == True:
frame_counter += 1
# resize the window
resized_vid = cv2.resize(frame, (720, 1280))
# Convert the video to grayscale
grayscale_vid = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# Change the orientation from landscape to portrait by rotating
(h, w) = grayscale_vid.shape[:2]
center = (w / 2, h / 2)
M = cv2.getRotationMatrix2D(center, 270, 1.0)
rotated_video = cv2.warpAffine(grayscale_vid, M, (w, h))
# Display the rotated video
cv2.imshow('Pitch', rotated_video)
# trying to restart the video when the frame_counter
# reaches its maximum value of 110
if frame_counter >= 110:
# here is where I think I need to restart the video
# by setting the current frame to zero
# Press Q on keyboard to exit
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# Break the loop
else:
break
# When everything done, release the video capture object
video_cap.release()
# Closes all the frames
cv2.destroyAllWindows()
It's been a while since this question has been posted, but just in case someone stumbled upon this answer, this code snippet with cap.set() worked for me. I relied on the documentation that can be found here (cpp) and here (python).
import cv2
# Get video handle.
cap = cv2.VideoCapture("path/to/video")
if not cap.isOpened():
print("Cannot initialize cap.")
exit()
# Get length of the video.
video_length = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
# Initialize count.
count = 0
# Frames loop.
while True:
# Check length of the video.
if count == video_length:
# Reset to the first frame. Returns bool.
_ = cap.set(cv2.CAP_PROP_POS_FRAMES, 0)
count = 0
# Get the frame.
success, image = cap.read()
if not success:
print("Cannot read frame.")
break
# do something with the image.
cv2.imshow("Frame", image)
# Quit by pressing 'q'.
if cv2.waitKey(1) & 0xFF == ord('q'):
break
count += 1
# Post loop.
cap.release()
cv2.destroyAllWindows()
I used the above to go some n number of frames back by combining cap.get() and cap.set().
This is a general way how the video can be resized to 480 x 800 (height x width) and made to loop.
import cv2
# Change this path to your video location
path = "path_to_your_video"
cap = cv2.VideoCapture(path)
while True:
ret, img = cap.read()
if not ret:
cap = cv2.VideoCapture(path)
ret, img = cap.read()
img = cv2.resize(img, (800, 480))
cv2.imshow("Video", img)
if cv2.waitKey(1) & 0xFF == ord("q"):
break
cap.release()
cv2.destroyAllWindows()
Related
Used: OpenCV and Python3
I am using Python 3.8.2
Operating System: macOS Big Sur 11.2.3
I tried this code on VScode, it does show a video with changed speed with the cv2.imshow command but I don't know how to save that changed video in my folder:
import cv2
cap = cv2.VideoCapture('Pothole testing.mp4')
frameTime = 100
while(cap.isOpened()):
ret, frame = cap.read()
cv2.imshow('frame',frame)
if cv2.waitKey(frameTime) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
Can anyone tell me what should I add to this code so that the changed video gets saved? And preferably in the .mp4 format itself.
You can use the fps parameter of the cv2.VideoWriter() method. The fps can be calculated by simple diving your frameTime variable by 1000, as the cv2.waitKey() method takes in a number and uses it as a thousandth of a second.
Note that if the cap never closed during the while loop, the while cap.isOpened() won't be any better than while True, meaning by the time the last frame is read, an error would occur, causing the writer.release() method to never be called, thus making the resulting file unreadable.
Here is how I would do it:
import cv2
cap = cv2.VideoCapture('Pothole testing.mp4')
ret, frame = cap.read() # Get one ret and frame
h, w, _ = frame.shape # Use frame to get width and height
frameTime = 100
fourcc = cv2.VideoWriter_fourcc(*"XVID") # XVID is the ID, can be changed to anything
fps = 1000 / frameTime # Calculate fps
writer = cv2.VideoWriter("Pothole testing 2.mp4", fourcc, fps, (w, h)) # Video writing device
while ret: # Use the ret to determin end of video
writer.write(frame) # Write frame
cv2.imshow("frame", frame)
if cv2.waitKey(frameTime) & 0xFF == ord('q'):
break
ret, frame = cap.read()
writer.release()
cap.release()
cv2.destroyAllWindows()
If all you need is the resulting file and not the progress window, you can omit a few lines:
import cv2
cap = cv2.VideoCapture('Pothole testing.mp4')
ret, frame = cap.read()
h, w, _ = frame.shape
frameTime = 100
fourcc = cv2.VideoWriter_fourcc(*"XVID")
fps = 1000 / frameTime
writer = cv2.VideoWriter("Pothole testing 2.mp4", fourcc, fps, (w, h))
while ret:
writer.write(frame)
ret, frame = cap.read()
writer.release()
cap.release()
I'm a python beginner so sorry in advance for the mistakes.
I'm trying to rotate a video 180 degrees and then work with that video that I should have created.
At the moment I'm doing this:
import cv2
import numpy as np
#that's my original video - the one that I want to rotate 180 degrees
cap = cv2.VideoCapture('/Users/name/Desktop/VIDEO 12.05/PIC_P01.mp4')
frame_number = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
# Original Frames
frames = []
for i in range(frame_number):
ret, frame = cap.read()
frames.append(frame)
#here's where I try to rotate the video
new = cv2.rotate(frame, cv2.ROTATE_180)
cv2.imshow('output', new)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
#here I'm trying to write the new rotated video
newvideoR = cv2.VideoWriter('PIC_P01R.mp4',0x7634706d, 50, (360, 640))
for jj in range(len(new)):
newvideoR.write(new[jj])
newvideoR.release()
cap.release()
In the end, however, when I go to read the file I find only an empty file that I cannot open.
From this, I deduce that there is an error in the steps that I have made.
Would anyone have any advice on how am I suppose to do this?
** I've also tried to change the parameter on cv2.Videowriter (for example fps, size) but is still not working
You don't need to accumulate the frames, and write them in another loop.
You can read a frame, rotate it, and write it in the same loop.
Get width and height:
frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
Open the output video file before the loop:
newvideoR = cv2.VideoWriter('output.mp4', cv2.VideoWriter_fourcc(*"mp4v"), 50, (frame_width, frame_height))
Read the frame, rotate it and write it in a loop:
for i in range(frame_number):
ret, frame = cap.read()
new = cv2.rotate(frame, cv2.ROTATE_180)
cv2.imshow('output', new)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
newvideoR.write(new)
Release video reader and writer:
newvideoR.release()
cap.release()
Complete code sample (I named the files input.mp4 and output.mp4):
import cv2
#that's my original video - the one that I want to rotate 180 degrees
cap = cv2.VideoCapture('input.mp4')
frame_number = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
# Get width and height
frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
# here I'm trying to write the new rotated video
# Open the output video file before the loop, cv2.VideoWriter_fourcc(*"mp4v") = 0x7634706d
newvideoR = cv2.VideoWriter('output.mp4', cv2.VideoWriter_fourcc(*"mp4v"), 50, (frame_width, frame_height))
# Original Frames
#frames = []
for i in range(frame_number):
ret, frame = cap.read()
#frames.append(frame) # No need to append the original frames
#here's where I try to rotate the video
new = cv2.rotate(frame, cv2.ROTATE_180)
cv2.imshow('output', new)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
newvideoR.write(new)
newvideoR.release()
cap.release()
There is a video, that is being processed. The process can be seen in console as frame processing 1/1000, 2/1000 etc. The output video has done ok, but if i want to see the results during the run, there is a grey screen - not responding (screenshot of program running).
Code, where movi is loaded:
input_movie = cv2.VideoCapture(r"test.mp4")
length = int(input_movie.get(cv2.CAP_PROP_FRAME_COUNT))
fourcc = cv2.VideoWriter_fourcc(*'XVID')
output_movie = cv2.VideoWriter('myoutput_01.avi', fourcc, 29.97, (480, 360))
Code to show video duriing the run:
cv2.imshow('Video', frame)
How to see the process?
UPDATE
I used the while cycle, i just didn't want to include much code.
But here it is:
while True:
ret, frame = input_movie.read()
frame_number += 1
if not ret:
break
cv2.imshow('Video', frame)
rgb_frame = frame[:, :, ::-1]
face_locations = face_recognition.face_locations(rgb_frame)
face_encodings = face_recognition.face_encodings(rgb_frame, face_locations)
Looking at what you have here; I'm not sure you understood how to deal with videos in opencv-python.
input_movie = cv2.VideoCapture(r"test.mp4")
here will open the test.mp4 video (as maybe you understood).
But now, you'll need to tell to opencv to read each frame of this video using a while function and read input_movie
In general, this is how we do:
input_movie = cv2.VideoCapture(r"test.mp4")
while (input_movie.isOpened()):
ret, frame = input_movie.read() # here we extract the frame
cv2.imshow('Video',frame) # here we display it
if cv2.waitKey(1) & 0xFF == ord('q'): # by press 'q' you quit the process
break
input_movie.release() # remove input_movie from memory
cv2.destroyAllWindows() # destroy all opencv windows
more informations here https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_gui/py_video_display/py_video_display.html
my problem is the camera so slow and not smooth and that makes me a problem to realtime extract text from the label. I want to know how to make a preview of the camera more smooth like a video camera, there is a big lag between live and stream?
here is my code
index = 0
#while test_vid.isOpened():
#make_480p()
while True:
frames += 1
test_vid = cv2.VideoCapture(0)
test_vid.set(cv2.CAP_PROP_FRAME_WIDTH, 720)
test_vid.set(cv2.CAP_PROP_FRAME_HEIGHT, 640)
test_vid.set(cv2.CAP_PROP_FPS,1)
fps = test_vid.get(cv2.CAP_PROP_FPS)
print ("Frames per second using video.get(cv2.cv.CV_CAP_PROP_FPS): {0}".format(fps))
ret,frame = test_vid.read()
start = time.time()
ret, frame = test_vid.read()
rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
end = time.time()
print ("time to read a frame : {} seconds".format(end-start))
print(frame)
frame = cv2.flip(frame, 10, 0)
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
cv2.imshow("LIVE", gray)
key = cv2.waitKey(1)
if key == ord('q'):
break
name = './image_frames/frame' + str(index) + '.png'
print ('Extracting frames...' + name)
cv2.imshow('frame',frame)
cv2.imwrite(name, frame)
test_vid.release()
cv2.destroyAllWindows()
demo = Image.open("./image_frames/frame0.png")
text = pytesseract.image_to_string(demo, lang = 'eng')
print(text)
One issue is that you're recreating the VideoCapture object every frame. Move that setup code outside the loop and you should see a speedup.
# setup the video capture device
test_vid = cv2.VideoCapture(0)
test_vid.set(cv2.CAP_PROP_FRAME_WIDTH, 720)
test_vid.set(cv2.CAP_PROP_FRAME_HEIGHT, 640)
test_vid.set(cv2.CAP_PROP_FPS,1)
fps = test_vid.get(cv2.CAP_PROP_FPS)
print ("Frames per second using video.get(cv2.cv.CV_CAP_PROP_FPS): {0}".format(fps))
while test_vid.isOpened():
ret,frame = test_vid.read()
# do frame processing...
# calculate wait time based on the camera fps
# (as an extension, measure and subtract the image processing time)
key = cv2.waitKey(int(1000/fps))
if key == ord('q'):
break
I am viewing a webcam camera live feed. I would like to incorporate this into a Tkinter GUI and have a dropdown selection that allows one to change the camera index, and therefore the webcam being used, on the fly.
How can this be achieved?
Example code:
import cv2
def show_webcam(mirror=False):
cam = cv2.VideoCapture(0)
while True:
ret_val, img = cam.read()
if mirror:
img = cv2.flip(img, 1)
cv2.imshow('my webcam', img)
if cv2.waitKey(1) == 27:
break # esc to quit
cv2.destroyAllWindows()
def main():
show_webcam(mirror=True)
if __name__ == '__main__':
main()
To change camera at run time all you need to change is the index you pass in
cv2.VideoCapture(index).
Find out how many camera you will be using for your app and for 3 cameras, you can change it through changing index to 0 or 1 or 2.
Add one more parameter as index
show_webcam(mirror=True, index)
in function side you can use this
def show_webcam(mirror=False,index):
cam = cv2.VideoCapture(index)
while True:
ret_val, img = cam.read()
if mirror:
img = cv2.flip(img, 1)
cv2.imshow('my webcam', img)
if cv2.waitKey(1) == 27:
break # esc to quit
cv2.destroyAllWindows()