Extract video frames in python using OpenCV - python

I want to break my video into frames.
I am using the following code:
import cv2
import numpy as np
import os
# Playing video from file:
cap = cv2.VideoCapture('myvideo.mp4')
cap.set(cv2.CAP_PROP_FPS, 5)
try:
if not os.path.exists('data'):
os.makedirs('data')
except OSError:
print ('Error: Creating directory of data')
currentFrame = 0
while(True):
# Capture frame-by-frame
ret, frame = cap.read()
# Saves image of the current frame in jpg file
name = './data/frame' + str(currentFrame) + '.jpg'
print ('Creating...' + name)
cv2.imwrite(name, frame)
# To stop duplicate images
currentFrame += 1
if not ret: break
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()
I have set the FPS = 5 and 'myvideo.mp4' is 0:55 sec long. So, I'd expect to have 55*5 = 275 frames, but the code above gives me a lot more frames and it doesn't stop generating frames. Is something wrong in the code?

if you want a proper framerate you can do
framerate = vid.get(5)
instead of
cap.set(cv2.CAP_PROP_FPS, 5)
this will give you the exact framerate

Related

Using Python and OpenCV split and record RTSP source into multiple files

I'm using OpenCV and RTSP source to continuously record video from the RTSP source for 1 minutes.
And then start the process again and create new one.
Recording works fine for a while and then the program would only create files that are 6kb in size that are not playable.
import numpy as np
import cv2
import time
def get_output(out=None):
#Specify the path and name of the video file as well as the encoding, fps and resolution
if out:
out.release()
return cv2.VideoWriter(str(time.strftime('%d %m %Y - %H %M %S' )) + '.avi', cv2.VideoWriter_fourcc(*'MJPG'),
24, (320,240))
cap = cv2.VideoCapture("rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mp4")
next_time = time.time() + 60
out = get_output()
while True:
if time.time() > next_time:
next_time += 60
out = get_output(out)
# Capture frame-by-frame
ret, frame = cap.read()
if ret:
out.write(frame)
cv2.imshow('Frame', frame)
# Break the loop
else:
break
cap.release()
cv2.destroyAllWindows()

Cant open video with videoCapture opencv

I have following code which reads frames from video file and stores as jpg. The code works fine if I read frames from camera directly but for video file it doesn't read the frames.
cap = cv2.VideoCapture('C:/Users/lostpanda.mp4')
#cap = cv2.VideoCapture(0)
count = 0
while cap.isOpened():
ret,frame = cap.read()
print(ret,frame)
cv2.imshow('window-name', frame)
name = 'C:/Users/video_testing/video-frames/' + str(count) + '.jpg'
#cv2.imwrite("frame%d.jpg" % count, frame)
cv2.imwrite(name,frame)
count = count + 1
if cv2.waitKey(10) & 0xFF == ord('q'):
break
Thanks
You can try this instead:
import cv2
import os
# Read the video from specified path
cam =cv2.VideoCapture(r"C:/Users/lostpanda.mp4")
try:
# creating a folder named data
if not os.path.exists('video-frames'):
os.makedirs('video-frames')
# if not created then raise error
except OSError:
print ('Error: Creating directory of data')
# frame
currentframe = 0
while(True):
# reading from frame
ret,frame = cam.read()
if ret:
# if video remains continue creating images
name = './video-frames/frame' + str(currentframe)+ '.jpg'
print ('Creating...' + name)
# write extracted images
cv2.imwrite(name, frame)
#Counter to show number of frames that are being created
currentframe += 1
else:
break
# Release all space and windows once done
cam.release()
cv2.destroyAllWindows()

How can I extract frames from a video at a certain FPS?

I am able to extract the frames of a certain test.mp4 file using the following code:
import cv2
def get_frames():
cap = cv2.VideoCapture('test.mp4')
i = 0
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
cv2.imwrite('test_'+str(i)+'.jpg', frame)
i += 1
cap.release()
cv2.destroyAllWindows()
A lot of the frames that are extracted are useless (they're nearly identical). I need to be able to set a certain rate at which the frame extraction can be done.
I think you need to just skip frames based on a fixed cycle.
import cv2
def get_frames():
cap = cv2.VideoCapture('test.mp4')
i = 0
# a variable to set how many frames you want to skip
frame_skip = 10
# a variable to keep track of the frame to be saved
frame_count = 0
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
if i > frame_skip - 1:
frame_count += 1
cv2.imwrite('test_'+str(frame_count*frame_skip)+'.jpg', frame)
i = 0
continue
i += 1
cap.release()
cv2.destroyAllWindows()
Try below logic. Here, we are waiting for a period of time(based on frame rate) and reading the last frame.
def get_frames():
cap = cv2.VideoCapture('test.mp4')
frame_rate = 10
prev = 0
i = 0
while cap.isOpened():
time_elapsed = time.time() - prev
ret, frame = cap.read()
if not ret:
break
if time_elapsed > 1./frame_rate:
# print(time_elapsed)
prev = time.time()
cv2.imwrite('./data/sample1/test_'+str(i)+'.jpg', frame)
i += 1
cap.release()
cv2.destroyAllWindows()
As an alternative to writing your own code to do this, have you considered using FFMPEG? FFMPEG has the ability to extract all frames from a video and save them as images, it also can extract frames at a lower frame rate than the source video.
See here for a demonstration of what I think you're trying to do, and the arguments to give ffmpeg to do so.

Python -> OpenCV -> save one image and end program

I have a RaspberryPi, a few IP camera's and I would like to get a fresh image from all these camera's every 5 minutes. I have the following script, which open the RTSP feed af grabs images ALL THE TIME, talking 10-25 every second it runs.
Is there a way to open the videofeed an take only 1 image?
import cv2
import time
cap = cv2.VideoCapture('rtsp://192.168.86.81:554/11') # it can be rtsp or http $
ret, frame = cap.read()
while ret:
cv2.imwrite('images/{}.jpg'.format(time.time()), frame)
ret, frame = cap.read()
This solved my problem. I removed time as I do not need this. I will let the aboce code stand in case anybody would want to play around with this
import cv2
cap = cv2.VideoCapture('rtsp://192.168.86.81:554/11') # it can be rtsp or http stream
ret, frame = cap.read()
if cap.isOpened():
_,frame = cap.read()
cap.release() #releasing camera immediately after capturing picture
if _ and frame is not None:
cv2.imwrite('images/latest.jpg', frame)
import cv2
import time
from datetime import datetime
import getpass
#imagesFolder = "C:/Users/<user>/documents"
# https://stackoverflow.com/questions/842059/is-there-a-portable-way-to-get-the-current-username-in-python
imagesFolder = "C:/Users/" + getpass.getuser() + "/documents"
#cap = cv2.VideoCapture("rtsp://192.168.86.81:554/11")
# Use public RTSP Streaming for testing, but I am getting black frames!
cap = cv2.VideoCapture("rtsp://192.168.86.81:554/11")
frameRate = cap.get(5) #frame rate
count = 0
while cap.isOpened():
start_time = time.time()
frameId = cap.get(1) # current frame number
ret, frame = cap.read()
if (ret != True):
break
filename = imagesFolder + "/image_" + str(datetime.now().strftime("%d-%m-%Y_%I-%M-%S_%p")) + ".jpg"
cv2.imwrite(filename, frame)
# Show frame for testing
cv2.imshow('frame', frame)
cv2.waitKey(1)
count += 1
#Break loop after 5*60 minus
if count > 5*60:
break
elapsed_time = time.time() - start_time
# Wait for 60 seconds (subtract elapsed_time in order to be accurate).
time.sleep(60 - elapsed_time)
cap.release()
print ("Done!")
cv2.destroyAllWindows()

Save multiple images with OpenCV and Python

I'm using OpenCV and Python to take images. However currently I can only take one picture at a time. I would like to have OpenCV to take multiple pictures. This is my current code.
import cv2.cv as cv
import time
cv.NamedWindow("camera", 1)
capture = cv.CaptureFromCAM(0)
while True:
img = cv.QueryFrame(capture)
cv.ShowImage("camera", img)
cv.SaveImage('pic.jpg', img)
if cv.WaitKey(10) == 27:
break
Your code overwrite a file. Save to different file each time.
For example:
import cv2.cv as cv
import time
cv.NamedWindow("camera", 1)
capture = cv.CaptureFromCAM(0)
i = 0
while True:
img = cv.QueryFrame(capture)
cv.ShowImage("camera", img)
cv.SaveImage('pic{:>05}.jpg'.format(i), img)
if cv.WaitKey(10) == 27:
break
i += 1
A minimal example of what you'd like to do, based on the c++ binded interface.
import cv2
cpt = 0
maxFrames = 5 # if you want 5 frames only.
try:
vidStream = cv2.VideoCapture(0) # index of your camera
except:
print "problem opening input stream"
sys.exit(1)
while cpt < maxFrames:
ret, frame = vidStream.read() # read frame and return code.
if not ret: # if return code is bad, abort.
sys.exit(0)
cv2.imshow("test window", frame) # show image in window
cv2.imwrite("image%04i.jpg" %cpt, frame)
cpt += 1
A full example of script, able to read from a camera index, or a file. Includes some failsafes and some information about read device.
usage: record.py [source] [target folder]
#!/usr/bin/env python
import cv2
import sys
import os
cpt = 0
maxFrames = 30
try:
targetDir = sys.argv[2]
except:
targetDir = "" # if no argument, then use current directory
try: # read input. eval if to transform video index to int
vidStream = cv2.VideoCapture(eval(sys.argv[1]))
except:
print "problem opening input stream"
sys.exit(1)
if not vidStream.isOpened():
print "capture stream not open"
sys.exit(1)
# informations in case the input is a video file.
nFrames = vidStream.get(cv2.cv.CV_CAP_PROP_FRAME_COUNT)
print "frame number: %s" %nFrames
fps = vidStream.get(cv2.cv.CV_CAP_PROP_FPS)
print "FPS value: %s" %fps
# note that we could use frame number here, or "while 1"
# so we could read from a live written file or capture devide.
while cpt < maxFrames:
ret, frame = vidStream.read() # read frame and return code.
if not ret:
print "end of stream"
sys.exit(0)
cv2.imshow("test window", frame) # show image in window
cv2.imwrite(os.path.join(targetDir, "image_%04i.jpg" %cpt), frame)
cpt += 1
keyPressed = cv2.waitKey(1) # time to wait between frames
if keyPressed != -1: # if user pressed a key, stop recording.
sys.exit(0)
change the name of the image to be saved to " [image name] [a number which increase after every loop] "
By doing this your image will be stored with a new name after every loop.. otherwise all the images will overwrite the same name !
import cv2.cv as cv
import time
cv.NamedWindow("camera", 1)
capture = cv.CaptureFromCAM(0)
num = 0
while True:
img = cv.QueryFrame(capture)
cv.ShowImage("camera", img)
cv.SaveImage('pic'+str(num)+'.jpg', img)
if cv.WaitKey(10) == 27:
break
num += 1
now your images will be saved as pic0.jpg, pic1.jpg, pic2.jpg and so on..
i think this wil helpful...
import cv2
vid = cv2.VideoCapture("video.mp4")
d = 0
ret, frame = vid.read()
while ret:
ret, frame = vid.read()
filename = "images/file_%d.jpg"%d
cv2.imwrite(filename, frame)
d+=1
this will save every frame with different name.

Categories

Resources