I want to extract frames from 3 videos into 3 different folder. Each folder has the frames of their corresponding video file. I am able to access my objective for only the 3rd video. How can I extract the frames for the first 2 videos as well
I have made the folders having names as per the video files till now. Developed the code for frame extraction but can extract only from the last video. Below is my code
import cv2
import glob
from glob import glob
import os
import shutil
def extractFrames(m,n):
if not os.path.exists:
os.makedirs(n)
vid_files=glob(m)
print(vid_files)
for v_f in range(len(vid_files)):
v1=os.path.basename(vid_files[v_f])
print(v1)
vid_name = os.path.splitext(v1)[0]
print(vid_name)
output = n +'\\video_' + vid_name
os.makedirs(output)
print(output)
vidcap = cv2.VideoCapture(vid_files[v_f])
print(vidcap)
success,image = vidcap.read()
seconds = 2
fps = vidcap.get(cv2.CAP_PROP_FPS) # Gets the frames per second
multiplier = fps * seconds
count=0
while success:
img_name = vid_name + '_f' + str(count) + ".jpg"
image_path = output + "/" + img_name
frameId = int(round(vidcap.get(1)))
success,image = vidcap.read()
if frameId % multiplier == 0:
cv2.imwrite(filename = image_path, img = image)
count+=1
vidcap.release()
cv2.destroyAllWindows()
print('finished processing video {0} with frames {1}'.format(vid_files[v_f], count))
return output
x=("C:\\Python36\\videos\\*.mp4")
y=("C:\\Python36\\videos\\videos_new")
z=extractFrames(x,y)
If there are 3 videos namely video1,video2,video3. I want to extract the corresponding frames into their specific folders i.e video1 folder,video2 folder, video3 folder. Currently I am able to extract the frames for only the 3rd video into folder video3. How can I do it for video1 and video2 as well
Your indentation on the part from vidcap = ... down is off. Therefor only the last file in the for-loop is used.
import cv2
import glob
from glob import glob
import os
import shutil
def extractFrames(m,n):
if not os.path.exists:
os.makedirs(n)
vid_files=glob(m)
print(vid_files)
for v_f in range(len(vid_files)):
v1=os.path.basename(vid_files[v_f])
print(v1)
vid_name = os.path.splitext(v1)[0]
print(vid_name)
output = n +'\\video_' + vid_name
os.makedirs(output)
print(output)
vidcap = cv2.VideoCapture(vid_files[v_f])
print(vidcap)
success,image = vidcap.read()
seconds = 2
fps = vidcap.get(cv2.CAP_PROP_FPS) # Gets the frames per second
multiplier = fps * seconds
count=0
while success:
img_name = vid_name + '_f' + str(count) + ".jpg"
image_path = output + "/" + img_name
frameId = int(round(vidcap.get(1)))
success,image = vidcap.read()
if frameId % multiplier == 0:
cv2.imwrite(filename = image_path, img = image)
count+=1
vidcap.release()
cv2.destroyAllWindows()
print('finished processing video {0} with frames {1}'.format(vid_files[v_f], count))
return output # indent this less
x=("C:\\Python36\\videos\\*.mp4")
y=("C:\\Python36\\videos\\videos_new")
z=extractFrames(x,y)
Related
I need to extract video frames in a folder. I have 90 videos in a folder and would like to extract each video frames in a seperate folder one time.
How could I do that?
Below is the code I tried so far but it works for one video only. I would like to do this for all the videos in a folder one time:
import os
import numpy as np
import cv2
from glob import glob
def create_dir(path):
try:
if not os.path.exists(path):
os.makedirs(path)
except OSError:
print(f"ERROR: creating directory with name {path}")
def save_frame(video_path, save_dir, gap=1):
name = video_path.split("/")[-1].split(".")[0]
save_path = os.path.join(save_dir, name)
create_dir(save_path)
cap = cv2.VideoCapture(video_path)
idx = 0
while True:
ret, frame = cap.read()
if ret == False:
cap.release()
break
if idx == 0:
cv2.imwrite(f"{save_path}/{idx}.png", frame)
else:
if idx % gap == 0:
cv2.imwrite(f"{save_path}/{idx}.png", frame)
idx += 1
if __name__ == "__main__":
video_paths = glob("D:/test_/crops/*")
save_dir = "save"
for path in video_paths:
save_frame(path, save_dir, gap=1)
import os
import numpy as np
import cv2
from glob import glob
def create_dir(path):
try:
if not os.path.exists(path):
os.makedirs(path)
except OSError:
print(f"ERROR: creating directory with name {path}")
def save_frame(video_path, save_dir, gap=1):
name = video_path.split("/")[-1].split(".")[0]
save_path = os.path.join(save_dir, name)
create_dir(save_path)
cap = cv2.VideoCapture(video_path)
idx = 0
while True:
ret, frame = cap.read()
if ret == False:
cap.release()
break
if idx == 0:
cv2.imwrite(f"{save_path}/{idx}.png", frame)
else:
if idx % gap == 0:
cv2.imwrite(f"{save_path}/{idx}.png", frame)
idx += 1
if __name__ == "__main__":
video_paths = glob("D:/test_/crops/*")
save_dir = "save"
for path in video_paths:
save_frame(path, save_dir, gap=1)
I have a function for extracting frames from videos. I have a csv file which has the names of the videos already processed. I want to check if the name of a newly added video file is present in the csv file. If present then exit the code else process the function to extract frames from the new video
def extractFrames(m):
global vid_name
vid_files=glob(m)
for v_f in range(len(vid_files)):
print("path of video========>>>>.",vid_files[v_f])
#latest_file=max(vid_files, key=os.path.getctime)
#print(latest_file)
v1=os.path.basename(vid_files[v_f])
try:
vid_name = os.path.splitext(v1)[0]
vidcap = cv2.VideoCapture(vid_files[v_f])
except cv2.error as e:
print(e)
except:
print('error')
#condition
fsize=os.stat(vid_files[v_f])
print('=============size of video ===================:' , fsize.st_size)
try:
if (fsize.st_size > 1000):
fps = vidcap.get(cv2.CAP_PROP_FPS) # OpenCV2 version 2 used "CV_CAP_PROP_FPS"
frameCount = int(vidcap.get(cv2.CAP_PROP_FRAME_COUNT))
duration = frameCount/fps
minutes = int(duration/60)
print('fps = ' + str(fps))
print('number of frames = ' + str(frameCount))
print('duration (S) = ' + str(duration))
if (duration > 1):
success,image = vidcap.read()
count=0
success=True
while success:
img_name = vid_name + '_f' + str(count) + ".jpg"
success,image = vidcap.read()
if count % 10 == 0 or count ==0:
target_non_target(img_name, image)
count+=1
vidcap.release()
cv2.destroyAllWindows()
except:
print("error")
print('finished processing video ', vid_files[v_f])
with open("C:\\multi_cat_3\\models\\research\\object_detection\\my_imgs"+'/video_info.csv', 'a') as csv_file:
fieldnames = ['Video_Name','Process']
file_is_empty = os.stat("C:\\multi_cat_3\\models\\research\\object_detection\\my_imgs"+'/video_info.csv').st_size == 0
writer = csv.DictWriter(csv_file, fieldnames=fieldnames)
if file_is_empty:
writer.writeheader()
writer.writerow({'Video_Name':vid_name,'Process':'done'})
if __name__ == "__main__":
x="C:\\Python36\\videos\\*.mp4"
extractFrames(x)
Suppose a folder has 2 videos V1 and V2 from which frames have already been extracted and the names V1 and V2 are added in the csv file. Now when i add video V3 the code should check if V3 exists already in the csv. If it exists then the code should be skipped else frames from V3 should be processed and V3 should be added in the csv file after extraction of the frames
Without the details you have code like this
def extractFrames(m):
# do stuff
vid_files=glob(m)
for v_f in range(len(vid_files)):
#find vid_name
#do stuff
save_as_done(vid_name)
if __name == '__main__':
x="C:\\Python36\\videos\\*.mp4"
extractFrames(x)
If you pass in a list of things that have been done, something like
done = ['first.mp4', 'second.mp4']
you can check if a filename has been done like this:
>>> 'first.mp4' in done
True
So, if you save the filenames (fully pathed) of what you've done to a file and load them into a list, like this
def load_done_list():
with open('video_info.csv') as f: #or full path, maybe pass in the file name?
return f.readlines()
you can check the list
def extractFrames(m, done):
# do stuff
vid_files=glob(m)
for v_f in range(len(vid_files)):
#find vid_name
if vid_name not in done: #,--- check if done already
#do stuff
save_as_done(vid_name)
if __name == '__main__':
x="C:\\Python36\\videos\\*.mp4"
done = load_done_list() #<--- You need to load this into a list
extractFrames(x, done) #<--- and pass it in to your function
This need something that just saves the filenames as they are done:
def save_as_done(vid_name):
with open('video_info.csv', 'a') as f: #maybe pass in the file name so you only define it once?
f.write(vid_name + '\n')
I haven't filled in all the details, but have shown where you can do loading and saving and checking.
The written file only has the filenames in - there doesn't seem much point in having "done" on the end of each line.
This will keep opening and closing the file as the files are processed. This may slow thing down but might not matter: you could pass in a file handle to write to, to keep it open. You have options.
I think you might need a function to get the list completed/done videos from the csv file.
Something like this, might need to tweak a bit for the header row.
def get_completed_videos():
completed_videos = []
with open(".../video_info.csv") as csv_file:
for row in csv.reader(csv_file):
completed_videos.append(row[0])
return completed_videos
Then exclude them in the extracting func
def extractFrames(m):
global vid_name
vid_files=glob(m)
complete_videos = get_completed_videos()
new_vid_files = [x for x in vid_files if x not in complete_videos]
...
def extractFrames(m,done):
global vid_name
vid_files=glob(m)
for v_f in range(len(vid_files)):
print("path of video========>>>>.",vid_files[v_f])
v1=os.path.basename(vid_files[v_f])
vid_name = os.path.splitext(v1)[0]
if vid_name not in done:
try:
vidcap = cv2.VideoCapture(vid_files[v_f])
except cv2.error as e:
print(e)
except:
print('error')
#condition
fsize=os.stat(vid_files[v_f])
print('=============size of video ===================:' , fsize.st_size)
try:
if (fsize.st_size > 1000):
fps = vidcap.get(cv2.CAP_PROP_FPS) # OpenCV2 version 2 used "CV_CAP_PROP_FPS"
frameCount = int(vidcap.get(cv2.CAP_PROP_FRAME_COUNT))
duration = frameCount/fps
minutes = int(duration/60)
print('fps = ' + str(fps))
print('number of frames = ' + str(frameCount))
print('duration (S) = ' + str(duration))
if (duration > 1):
success,image = vidcap.read()
count=0
success=True
while success:
img_name = vid_name + '_f' + str(count) + ".jpg"
success,image = vidcap.read()
if count % 10 == 0 or count ==0:
target_non_target(img_name, image)
count+=1
vidcap.release()
cv2.destroyAllWindows()
except:
print("error")
print('finished processing video ', vid_files[v_f])
with open("C:\\multi_cat_3\\models\\research\\object_detection\\my_imgs\\"+'video_info.csv', 'a') as csv_file:
fieldnames = ['Video_Name','Process']
file_is_empty = os.stat("C:\\multi_cat_3\\models\\research\\object_detection\\my_imgs\\"+'video_info.csv').st_size == 0
writer = csv.DictWriter(csv_file, fieldnames=fieldnames)
if file_is_empty:
writer.writeheader()
writer.writerow({'Video_Name':vid_name,'Process':'done'})
if __name__ == "__main__":
x="C:\\Python36\\videos\\*.mp4"
y="C:\\multi_cat_3\\models\\research\\object_detection\\my_imgs\\video_info.csv"
done=list(y)
extractFrames(x,done)
I'm trying to read Videos, resize them and write them with a different codec, using OpenCV for Python3. The original frame rate should stay the same.
This works fine if I'm using MJPG as codec, but for other codecs the frame rate of the output is set to 600 fps. (I tried XVID, DIVX, WMV1, WMV2)
Is it possible to write Videos with those codecs with the original frame rate?
import os
import numpy as np
import cv2
codec = 'XVID'
new_size = (256, 256)
for root, dirs, files in os.walk("UCF-101"):
new_root = root.replace('UCF-101', 'UCF-101_resized_' + codec)
if not os.path.exists(new_root):
os.makedirs(new_root)
for file in files:
cap = cv2.VideoCapture(root + '/' + file)
fps = cap.get(cv2.CAP_PROP_FPS)
fourcc = cv2.VideoWriter_fourcc(*codec)
out = cv2.VideoWriter(new_root + '/' + file, fourcc, fps, new_size, isColor=True)
while(cap.isOpened()):
ret, frame = cap.read()
if ret == True:
frame = cv2.resize(src=frame, dst=frame, dsize=new_size)
out.write(frame)
else:
break
cap.release()
out.release()
print('wrote ' + new_root + '/' + file)
Try changing your file extension to output file name with .mp4, not avi
codec = 'x264'
Replace if ret == True: with if frame is not None:
I'm trying to sorting the jpgs (ascending numerically) in my directory to generate a video for opencv, but I'm having a a hard time finding a solution:
images = []
for f in os.listdir('.'):
if f.endswith('.jpg'):
images.append(f)
images[]:
['img_0.jpg', 'img_1.jpg', 'img_10.jpg', 'img_100.jpg', 'img_101.jpg', 'img_102.jpg', ... 'img_99.jpg']
import cv2
vidcap = cv2.VideoCapture('big_buck_bunny_720p_5mb.mp4')
success,image = vidcap.read()
count = 0
success = True
while success:
cv2.imwrite("frame%d.jpg" % count, image) # save frame as JPEG file
success,image = vidcap.read()
print('Read a new frame: ', success)
count += 1
You can use Os:
from os import listdir
from os.path import isfile, join
jpgfiles = [f for f in listdir('.') if isfile(join('.', f)) and f.endswith(".txt")]
jpgfiles.sort()
I have such a loop to write video files from images:
for a in range(len(events)):
c_videos = []
first = events[a][0]
last = events[a][1]
c_videos = video_ids[numpy.where(numpy.logical_and(timestamps >= first, timestamps <= last))]
video_name = "/export/students/sait/9-may-video-dataset/video-" + str(events[a][2]) + ".avi"
video = cv2.VideoWriter(video_name,-1,1,(width,height))
for b in range(len(c_videos)):
img_file = "/export/students/sait/9-may-results/rgb-" + str(c_videos[b]) + ".ppm"
img = cv2.imread(img_file)
video.write(img)
cv2.destroyAllWindows()
video.release()
But I cannot become successful in creating videos. I don't see any created video file under the destination directory.
How can I fix this problem?