Counting frames in a video using OpenCV... (Python) - python

I am using a loop to access all frames of a video file using Python and OpenCV. While accessing each frame, I add the index of the frame in a list.
However I compare the size of the list and the number of frames that I get using the
Frames = cap.get(cv2.cv.CV_CAP_PROP_FRAME_COUNT)
command and the size of the list is constantly one less element than the number of the frames of the video reytned by cap.get...
Any ideas why is this happening ?
Here is the code I use:
# -*- coding: utf-8 -*-
import cv2
def faceExtraction(inputFile, extractionRate):
cap = cv2.VideoCapture(inputFile)
fps = cap.get(cv2.cv.CV_CAP_PROP_FPS)
Frames = cap.get(cv2.cv.CV_CAP_PROP_FRAME_COUNT)
print 'Frames='+str(Frames)
# if not os.path.exists("registered_face"):
# os.makedirs("registered_face")
frame_counter = 0
outputFrameIndices=[]
while(cap.isOpened()):
frame_counter=frame_counter+1
ret, frame = cap.read() # read current frame
outputFrameIndices.append(frame_counter)
if frame is None:
break
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# print 'FACE NOT FOUND: frame '+ str(frame_counter)
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()
print 'number of frames: ' + str(len(outputFrameIndices))
############## Executing Main App ###########
faceExtraction('Video Filename blah blah',5)
The output my code produces is:
Frames=930.0
number of frames: 929
whereas it should be
Frames=930.0
number of frames: 930

Found the error... Python starts index counters from zero...

Related

Read video URLs from a list for a period of time and release streams, OpenCV Python

I have a video URL list I want to open / process using OPenCV. Example list below
cam_name,address
Cam_01,vid1.mp4
Cam_02,vid1.mp4
Cam_03,vid1.mp4
I want to open the first camera/address, stream for 60 seconds, release and start the second, release and so on. When get to the last stream in the list e.g. Cam_03, start the list again, back to Cam_01.
I dont need to Thread, a I just need to start a stream and stop after a period of time etc.
Code so far:
# this calls the OpenCV stream
def main(cam_name, camID):
main_bret(cam_name, camID)
df = 'cams_list.txt'
df = pd.read_csv(df)
for index, row in df.iterrows():
main(row['cam_name'], row['address'])
########################################
main_bret(cam_name, camID):
vid = cv2.VideoCapture(camID)
while(True):
ret, frame = vid.read()
cv2.imshow(cam_name, frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
vid.release()
cv2.destroyAllWindows()
How to I construct the loop to stream for 60 seconds, release and move to the next in the list.. and repeat when finished the list?
What is happing now, e.g. if just streaming a mp4, will finish the video, then start the next. Just need it to stop streaming after 60 seconds.
I have tried adding sleep() etc around cv2.waitKey(1) but it runs everything for that period, not individual streams. I guess I am not putting the sleep in the correct place.
tks
I'm not sure I understood every detail of your program, but this is what I have:
df = 'cams_list.txt'
df = pd.read_csv(df)
def main_bret(cam_name, camID):
vid = cv2.VideoCapture(camID)
ret, frame = vid.read()
cv2.imshow(cam_name, frame)
cv2.waitKey(60_000)
vid.release()
cv2.destroyAllWindows()
index = 0
upper_index = df.shape[0]
while True:
main_bret(df.iloc[index]["cam_name"], df.iloc[index]["address"])
index = index + 1
if index >= upper_index:
index = 0
It's easier to iterate over and over through a list with a while so I get rid of the for loop.
The "waitKey" function waits 60 seconds (60000 ms) and then it deletes the window.
I hope I was helpful.

Repeating a video on loop using OpenCV and Python

I am trying to create a simple program that will play a video using OpenCV on repeat until the waitKey is pressed. The video will play once and then give an error message "(-215:Assertion failed) size.width>0 && size.height>0 in function 'cv::imshow'". I was getting this message earlier but fixed it by changing the file location. I'm almost positive that the issue comes from the fact that when the video ends the next frame is nonexistent so it cant be read, as breaking the while loop when the frame is None doesn't give an error. Every solution I have tried has failed. Any help?
import cv2
import numpy as np
cap = cv2.VideoCapture('video_file_location')
while True:
_, frame = cap.read()
cv2.imshow('frame',frame)
if cv2.waitKey(1) == 27:
break
cap.release()
cv2.destroyAllWindows()
Try putting the cv2.VideoCapture() into the loop and the frame should only show when the return is True and that is your problem in your code
import cv2
import numpy as np
while True:
#This is to check whether to break the first loop
isclosed=0
cap = cv2.VideoCapture('videoplayback.mp4')
while (True):
ret, frame = cap.read()
# It should only show the frame when the ret is true
if ret == True:
cv2.imshow('frame',frame)
if cv2.waitKey(1) == 27:
# When esc is pressed isclosed is 1
isclosed=1
break
else:
break
# To break the loop if it is closed manually
if isclosed:
break
cap.release()
cv2.destroyAllWindows()

Getting specific frames from VideoCapture opencv in python

I have the following code, which continuously fetches all the frames from a video by using VideoCapture library in opencv in python:
import cv2
def frame_capture:
cap = cv2.VideoCapture("video.mp4")
while not cap.isOpened():
cap = cv2.VideoCapture("video.mp4")
cv2.waitKey(1000)
print "Wait for the header"
pos_frame = cap.get(cv2.cv.CV_CAP_PROP_POS_FRAMES)
while True:
flag, frame = cap.read()
if flag:
# The frame is ready and already captured
cv2.imshow('video', frame)
pos_frame = cap.get(cv2.cv.CV_CAP_PROP_POS_FRAMES)
print str(pos_frame)+" frames"
else:
# The next frame is not ready, so we try to read it again
cap.set(cv2.cv.CV_CAP_PROP_POS_FRAMES, pos_frame-1)
print "frame is not ready"
# It is better to wait for a while for the next frame to be ready
cv2.waitKey(1000)
if cv2.waitKey(10) == 27:
break
if cap.get(cv2.cv.CV_CAP_PROP_POS_FRAMES) == cap.get(cv2.cv.CV_CAP_PROP_FRAME_COUNT):
# If the number of captured frames is equal to the total number of frames,
# we stop
break
But I want to grab a specific frame in a specific timestamp in the video.
How can I achieve this?
You can use set() function of VideoCapture.
You can calculate total frames:
cap = cv2.VideoCapture("video.mp4")
total_frames = cap.get(7)
Here 7 is the prop-Id. You can find more here http://docs.opencv.org/2.4/modules/highgui/doc/reading_and_writing_images_and_video.html
After that you can set the frame number, suppose i want to extract 100th frame
cap.set(1, 100)
ret, frame = cap.read()
cv2.imwrite("path_where_to_save_image", frame)
this is my first post so please don't rip into me if I don't follow protocol completely. I just wanted to respond to June Wang just in case she didn't figure out how to set the number of frames to be extracted, or in case anyone else stumbles upon this thread with that question:
The solution is the good ol' for loop:
vid = cv2.VideoCapture(video_path)
for i in range(start_frame, how_many_frames_you_want):
vid.set(1, i)
ret, still = vid.read()
cv2.imwrite(f'{video_path}_frame{i}.jpg', still)

OpenCV frame count wrong for interlaced videos, workaround?

Working with the code sample from How does QueryFrame work? I noticed that the program used a lot of time to exit if it ran to the end of the video. I wanted to exit quickly on the last frame, and I verified that it's a lot quicker if I don't try to play past the end of the video, but there are some details that don't make sense to me. Here's my code:
import cv2
# create a window
winname = "myWindow"
win = cv2.namedWindow(winname, cv2.CV_WINDOW_AUTOSIZE)
# load video file
invideo = cv2.VideoCapture("video.mts")
frames = invideo.get(cv2.cv.CV_CAP_PROP_FRAME_COUNT)
print "frame count:", frames
# interval between frame in ms.
fps = invideo.get(cv2.cv.CV_CAP_PROP_FPS)
interval = int(1000.0 / fps)
# play video
while invideo.get(cv2.cv.CV_CAP_PROP_POS_FRAMES) < frames:
print "Showing frame number:", invideo.get(cv2.cv.CV_CAP_PROP_POS_FRAMES)
(ret, im) = invideo.read()
if not ret:
break
cv2.imshow(winname, im)
if cv2.waitKey(interval) == 27: # ASCII 27 is the ESC key
break
del invideo
cv2.destroyWindow(winname)
The only thing is that the frame count returned is 744, while the last played frame number is 371 (counting from 0, so that's 372 frames). I assume this is because the video is interlaced, and I guess I need to account for that and divide interval by 2 and frames by 2. But the question is, how do I figure out that I need to do this? There doesn't seem to be a property to check this:
http://docs.opencv.org/modules/highgui/doc/reading_and_writing_images_and_video.html#videocapture-get

Save Video as Frames OpenCV{PY}

I would like to create a program which saves .jpg images taken from the webcam(frames).
What my program do for now is, opening a webcam, taking one and only one frame, and then everything stops.
What i would like to have is more than one frame
My error-code is this one:
import numpy as np
import cv2
cap = cv2.VideoCapture(0)
count = 0
while True:
# Capture frame-by-frame
ret, frame = cap.read()
# Our operations on the frame come here
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
cv2.imwrite("frame%d.jpg" % ret, frame) # save frame as JPEG file
count +=1
# Display the resulting frame
cv2.imshow('frame',gray)
if cv2.waitKey(10):
break
Actually it sounds like you are always saving your image with the same name
because you are concatenating ret instead of count in the imwrite method
try this :
name = "frame%d.jpg"%count
cv2.imwrite(name, frame) # save frame as JPEG file
use this -
count = 0
cv2.imwrite("frame%d.jpg" % count, frame)
count = count+1
When no key is pressed and the time delay expires, cv2.waitKey returns -1. You can check it in the doc.
Basically, all you have to do is changing slightly the end of your program:
# Display the resulting frame
cv2.imshow('frame',gray)
if cv2.waitKey(10) != -1:
break
Though this is late I have to say that prtkp's answer is what you needed... the , ret value you use to enumerate your images is wrong. Ret is only a boolean... so while it detects the image it its placing a one there for the name of the image...
I just used this... with a c=0 on the header
cv2.imwrite("img/frame %d.jpg" % c,img)
c=c+1

Categories

Resources