Extracting images using opencv and python or moviepy
I have a video (.mp4) that has ~ 8000 frames. I have a csv that tells me that I need to capture every frame in the video and the number of frames to capture.
number_of_frames in video = 8000
times is an array of type [0.004, 0.005, ... 732s]
The last time in the data is 732s. thereforeFPS = 8000 / 732 = ~10
I want to be able to extract image frames from a video at these specific moments. Then write these paths to the .csv file.
I tried several approaches: First approach (openCV):
with open('./data/driving.csv', 'w') as csvfile:
fieldnames = ['image_path', 'time', 'speed']
writer = csv.DictWriter(csvfile, fieldnames = fieldnames)
writer.writeheader()
vidcap = cv2.VideoCapture('./data/drive.mp4')
for idx, item in enumerate(ground_truth):
# set video capture to specific time frame
# multiply time by 1000 to convert to milliseconds
vidcap.set(cv2.CAP_PROP_POS_MSEC, item[0] * 1000)
# read in the image
success, image = vidcap.read()
if success:
image_path = os.path.join('./data/IMG/', str(item[0]) +
'.jpg')
# save image to IMG folder
cv2.imwrite(image_path, image)
# write row to driving.csv
writer.writerow({'image_path': image_path,
'time':item[0],
'speed':item[1],
})
This approach, however, did not give me the total number of frames I wanted. He just gave me the number of frames that would fit the video with FPS = 25. I believe my FPS = 8000 / 732s = 10.928s.
Then I tried using clippy to grab each image in a similar style:
from moviepy.editor import VideoFileClip
clip1 = VideoFileClip('./data/drive.mp4')
with open('./data/driving.csv', 'w') as csvfile:
fieldnames = ['image_path', 'time', 'speed']
writer = csv.DictWriter(csvfile, fieldnames = fieldnames)
writer.writeheader()
# Path to raw image folder
abs_path_to_IMG = os.path.join('./data/IMG/')
for idx, item in enumerate(ground_truth):
image_path = os.path.join('./data/IMG/', str(item[0]) + '.jpg')
clip1.save_frame(image_path, t = item[0])
# write row to driving.csv
writer.writerow({'image_path': image_path,
'time':item[0],
'speed':item[1],
})
However this approach didn't work either, for some reason I am capturing the last frame in the video hundreds of times.
source to share
This code works OK for fetching frames at different times:
import os
from moviepy.editor import *
def extract_frames(movie, times, imgdir):
clip = VideoFileClip(movie)
for t in times:
imgpath = os.path.join(imgdir, '{}.png'.format(t))
clip.save_frame(imgpath, t)
movie = 'movie.mp4'
imgdir = 'frames'
times = 0.1, 0.63, 0.947, 1.2, 3.8, 6.7
extract_frames(movie, times, imgdir)
What's the content of your variable ground_truth
?
source to share