How to rewind a video in OpenCV Python in 2019? - python

I know there are many similar questions asked in 2012 or something.
It is 2019, and in 2012, the only solution was to store the frames in memory or write them and then read them in reverse order.
But I was wondering, if there is a new function to read OpenCV frames in reverse order.
I am looking for a solution something like this:
if rewind == False:
ret,frame = cap.read()
else:
ret,frame = cap.read(rewind=True)
Any solution similar to this one?
or something like this:
if rewind == False:
ret,frame = cap.read()
else:
cap.goBackOneFrame()
ret,frame = cap.read()
Edit:
I tried
if rewind == False:
ret, frame = cap.read() #Read frame
counter += 1
else:
cap.set(cv2.CAP_PROP_POS_FRAMES, counter-1)
counter -= 1
ret, frame = cap.read()
and it works, but the rewind speed is slow. I think my PC is taking more time in processing it?

import cv2
# Grab the current frame.
my_check , vid = cap.read()
# use counter variable for
# Counting frames
counter = 0
check = True
frame_list = []
while(check == True):
cv2.imwrite("frame%d.jpg" %counter , vid)
check , vid = cap.read()
frame_list.append(vid)
# increment the counter by 1
counter += 1
frame_list.pop()
# looping in the List of frames.
for frame in frame_list:
# show the frame.
cv2.imshow("Frame" , frame)
if cv2.waitKey(25) and 0xFF == ord("q"):
break
cap.release()
# close any open windows
cv2.destroyAllWindows()
frame_list.reverse()
for frame in frame_list:
cv2.imshow("Frame" , frame)
if cv2.waitKey(25) and 0xFF == ord("q"):
break
cap.release()
cv2.destroyAllWindows()

Related

How to change mp4 file FPS value 30 to 5 using OpenCV

I want to change the framerate of an mp4 file from 30 to 5.I tried set(cv2.CAP_PROP_FPS, 10).But it did not work. I can't find a way to do this with ffmpeg. Please help me to do this.Thank you.
import cv2
cap = cv2.VideoCapture('./data/video/7e2.mp4')
fps = int(cap.get(cv2.CAP_PROP_FPS))
print('fps :'+str(fps))
if (cap.isOpened()== False):
print("Error opening video stream or 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()
If you are reading a file then file will not be modified and FPS of the original file will be unchanged. cv2.VideoCapture( ) opens file in read mode. To save a video file you need to use VideoWriter and then open the output file using
video.open(out_filename,VideoWriter::fourcc('M','P','4','V'),FPS, Size(FRAME_WIDTH,FRAME_HEIGHT),true)
And then finally use write function to enter each frame.
So your code will look like this:
cv::VideoWriter video;
video.open(out_filename,VideoWriter::fourcc('M','P','4','V'),FPS, Size(FRAME_WIDTH,FRAME_HEIGHT),true)
In loop {
... Read Each Frame
video.write(frame);
(I have given C++ code, Python code will be similar)
I am providing you the complete code. It should work.
import cv2
cap = cv2.VideoCapture('./data/video/7e2.mp4')
fps = int(cap.get(cv2.CAP_PROP_FPS))
print('fps :'+str(fps))
# Change the FPS whatever you want
FPS=5;
frame_width = int(cap.get(3))
frame_height = int(cap.get(4))
writer = cv2.VideoWriter('outpy.avi',cv2.VideoWriter_fourcc('M','J','P','G'), FPS, (frame_width,frame_height) )
if (cap.isOpened()== False):
print("Error opening video stream or file")
while(cap.isOpened()):
ret, frame = cap.read()
if ret == True:
cv2.imshow('Frame',frame)
writer.write( frame)
if cv2.waitKey(25) & 0xFF == ord('q'):
break
else:
break
writer.release()
cap.release()
cv2.destroyAllWindows()

How to differentiating and storing the differentiated frames in a specified place

Have attached the source code for frame differentiating and storing the differentiated frames in a specified place but am getting an error in indentation of error..post this problem as a question in stack overflow..i am restricted to question for a particular period..upload the code too
filename.py
import cv2
import os
import glob
def extractFrames(pathIn, pathOut):
os.mkdir(pathOut)
cap = cv2.VideoCapture(pathIn)
count = 0
while (cap.isOpened()):
# Capture frame-by-frame
ret, frame = cap.read()
current_frame_gray = cv2.cvtColor(current_frame, cv2.COLOR_BGR2GRAY)
previous_frame_gray = cv2.cvtcolor(previous_frame, cv2.COLOR_BGR2GRAY)
frame_diff = cv2.absdiff(current_frame_gray,previous_frame_gray)
if ret == True:
print('Read %d frame: ' % count, ret)
cv2.imwrite(os.path.join(pathOut, "frame{:d}.jpg".format(count)), frame_diff) # save frame as JPEG file
count += 1
else:
break
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()
def main():
extractFrames('C:/Users/yaazmoha/Desktop/BE PROJECT/INPUT/Tiger in field(1080P_HD).mp4', 'fd3')
if __name__=="__main__":
main()
Fixed your code. You had some indentation errors. Since Python does not use braces like C++, it requires proper indentation to separate code.
import cv2
import os
import glob
def extractFrames(pathIn, pathOut):
os.mkdir(pathOut)
cap = cv2.VideoCapture(pathIn)
count = 0
while (cap.isOpened()):
# Capture frame-by-frame
ret, current_frame = cap.read()
current_frame_gray = cv2.cvtColor(current_frame, cv2.COLOR_BGR2GRAY)
if count > 1:
previous_frame_gray = cv2.cvtcolor(previous_frame, cv2.COLOR_BGR2GRAY)
frame_diff = cv2.absdiff(current_frame_gray,previous_frame_gray)
if ret == True:
print('Read %d frame: ' % count, ret)
cv2.imwrite(os.path.join(pathOut, "frame{:d}.jpg".format(count)), frame_diff) # save frame as JPEG file
count += 1
else:
break
previous_frame = current_frame
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()
def main():
extractFrames(r"C:\Users\mathesn\Downloads\Wildlife.mp4", 'fd3')
if __name__=="__main__":
main()
I took liberties to fix other sections of your code. But there are some other fixes that this code needs, like creating a directory only if it doesn't exist, maintaining a colored version of the frame so that cv2.cvtColor() does not fail, etc., but I''ll leave those to you.

OpenCV (Python) not updating frame when read() is called

I am trying to pull individual frames at specified times from an RTSP feed.
This works fine for video streaming:
vcap = cv2.VideoCapture(RTSP_URL)
while(1):
ret, frame = vcap.read()
cv2.imshow('VIDEO', frame)
cv2.waitKey(1)
But if I want to take an image every second and save it by doing something like this:
vcap = cv2.VideoCapture(RTSP_URL)
for t in range(60):
ret, frame = vcap.read()
if ret:
cv2.imwrite("{}.jpg".format(t), frame)
time.sleep(1);
Every image will look exactly the same as the first image. In every instance ret == True.
(Also this was working fine for me a week ago and then ipython did something that required me to do a re-install)
cv2.waitKey(1000) wouldn't do anything if you didn't show image with cv2.imshow(). Try:
vcap = cv2.VideoCapture(RTSP_URL)
for t in range(60):
ret, frame = vcap.read()
cv2.imwrite('{}.jpg'.format(t), frame)
# this will activate the waitKey funciton
cv2.imshow('preview', frame)
cv2.waitKey(1000)
On another note, iPython/jupyter doesn't play well with the cv2's imshow and the whole GUI functionality. If, for example, you can't break the loop by keypress
if (cv2.waitKey(1000) == 27 & 0xff): break;
Alright, after endless messing with it over the last few days, 1 second is not fast enough for the feed for whatever reason.
This will work:
vcap = cv2.VideoCapture(RTSP_URL)
for t in range(60):
ret, frame = vcap.read()
if ret and t % 1000 == 0:
cv2.imwrite("{}.jpg".format(t), frame)
time.sleep(0.001)

cv2.VideoCapture.read() gets old frame after time.sleep()

I tried to capture (stereo) images with Python's opencv and two cameras so therefore every 5 seconds an image should be saved. But the problem here is that an old frame is saved.
The minified code is as follows:
cap = cv2.VideoCapture(0)
for i in range(20):
time.sleep(5)
print "Taking image %d:" % i
ret, frame = cap.read()
cv2.imwrite("image %d" % i, frame)
print " image done." if ret else " Error while taking image..."
cap.release()
cv2.destroyAllWindows()
To check this, I changed the position of the camera after each taken image. But nevertheless an image from an old position is saved (actually not the same, but I assume some frames after the last saved image). After 5 (or more) images finally the captured location in the image does also change.
So, is there any problem with time.sleep? I guess that I'm not getting the actual frame, but a buffered one. If this is the case, how could I fix it and capture the actual frame?
VideoCapture is buffering.
If you always want the actual frame, do this:
while True:
cap = cv2.VideoCapture(0)
ret, frame = cap.read()
cap.release()
cv2.imshow(" ", frame)
if cv2.waitKey(2000) != -1:
break
you need to count the elapsed time, but not stop read frames. like this:
import cv2
import time
cap = cv2.VideoCapture(0)
preframe_tm = time.time()
i = 0
while True:
ret, frame = cap.read()
elapsed_time = time.time() - preframe_tm
if elapsed_time < 5:
continue
preframe_tm = time.time()
i += 1
print("Taking image %d:" % i)
cv2.imwrite("image_%d.jpg" % i, frame)
if i >= 20:
break
cap.release()
cv2.destroyAllWindows()

OpenCV: how to restart a video when it finishes?

I'm playing a video file, but how to play it again when it finishes?
Javier
If you want to restart the video over and over again (aka looping it), you can do it by using an if statement for when the frame count reaches cap.get(cv2.cv.CV_CAP_PROP_FRAME_COUNT) and then resetting the frame count and cap.set(cv2.cv.CV_CAP_PROP_POS_FRAMES, num) to the same value. I'm using OpenCV 2.4.9 with Python 2.7.9 and the below example keeps looping the video for me.
import cv2
cap = cv2.VideoCapture('path/to/video')
frame_counter = 0
while(True):
# Capture frame-by-frame
ret, frame = cap.read()
frame_counter += 1
#If the last frame is reached, reset the capture and the frame_counter
if frame_counter == cap.get(cv2.cv.CV_CAP_PROP_FRAME_COUNT):
frame_counter = 0 #Or whatever as long as it is the same as next line
cap.set(cv2.cv.CV_CAP_PROP_POS_FRAMES, 0)
# Our operations on the frame come here
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# Display the resulting frame
cv2.imshow('frame',gray)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()
It also works to recapture the video instead of resetting the frame count:
if frame_counter == cap.get(cv2.cv.CV_CAP_PROP_FRAME_COUNT):
frame_counter = 0
cap = cv2.VideoCapture(video_name)
You don't need to reopen the current capture. All you need to do is to reset position to the beginning of the file and to continue the cycle instead of breaking it.
if (!frame)
{
printf("!!! cvQueryFrame failed: no frame\n");
cvSetCaptureProperty(capture, CV_CAP_PROP_POS_AVI_RATIO , 0);
continue;
}
Nevertheless there is a significant delay as if you were reopened it...
See http://docs.opencv.org/2.4.6/modules/highgui/doc/reading_and_writing_images_and_video.html?highlight=cvqueryframe#videocapture-set
Easiest Way-:
cap = cv2.VideoCapture("path")
while True:
ret, image = cap.read()
if ret == False:
cap = cv2.VideoCapture("path")
ret, image = cap.read()
Close the current capture and open it again:
// play video in a loop
while (1)
{
CvCapture *capture = cvCaptureFromAVI("video.avi");
if(!capture)
{
printf("!!! cvCaptureFromAVI failed (file not found?)\n");
return -1;
}
IplImage* frame = NULL;
char key = 0;
while (key != 'q')
{
frame = cvQueryFrame(capture);
if (!frame)
{
printf("!!! cvQueryFrame failed: no frame\n");
break;
}
cvShowImage("window", frame);
key = cvWaitKey(10);
}
cvReleaseImage(&frame);
cvReleaseCapture(&capture);
}
This code is not complete and haven't been tested. It serves only for illustration purposes.

Categories