Reputation: 353
I extracted the video frames into a folder called "images". After getting images saved in my folder, I use the following code to create the video again. I get the video but the frames are ordered randomly, how can I arrange them in sequential order? thanks for the post
import cv2
import os
image_folder = 'images'
video_name = 'video.avi'
images = [img for img in os.listdir(image_folder) if img.endswith(".jpg")]
frame = cv2.imread(os.path.join(image_folder, images[0]))
height, width, layers = frame.shape
video = cv2.VideoWriter(video_name, 0, 1, (width,height))
for image in images:
video.write(cv2.imread(os.path.join(image_folder, image)))
cv2.destroyAllWindows()
video.release()
please advise, how do I fix this? I'd like the videos to be at the same rate as the original video, and frames to be in sequential order.
Upvotes: 5
Views: 2268
Reputation: 780
images
list and look at the order of your images? Are they sorted?What's the filename of your images? It's helpful to choose an increasing number like 00001.jpg
and 00002.jpg
instead of 1.jpg
and 2.jpg
this can mess up sorting.
for filename in sorted([e for e in path.iterdir() if e.is_file() and str(e).endswith(".png")]):
print(filename)
img = cv2.imread(str(filename))
img_array.append(img)
Or just using:
for filename in sorted(os.listdir(path))
Upvotes: 3
Reputation: 576
This works fine with me
import cv2
import os
image_folder = 'c:\\m\\'
video_name = 'c:\\m\\avideo.avi'
images = [img for img in os.listdir(image_folder) if img.endswith(".jpg")]
frame = cv2.imread(os.path.join(image_folder, images[0]))
height, width, layers = frame.shape
#1 fps
#video = cv2.VideoWriter(video_name, 0, 1, (width,height))
#25 fps
video = cv2.VideoWriter(video_name, 0, 25, (width,height))
for image in images:
video.write(cv2.imread(os.path.join(image_folder, image)))
cv2.destroyAllWindows()
video.release()
materials and result Here
Upvotes: 0
Reputation: 422
It seems you need natural sorting, so try natsort library:
from natsort import natsorted
images = natsorted(images)
Install using pip:
pip install natsort
Upvotes: 0
Reputation: 26
Try glob
for listing files and sort the list. I have edited your code using glob. (Assuming your filenames of images are in the sequence you want)
import cv2
import os
import glob
video_name = 'video.avi'
images = glob.glob('images/*.jpg')
images.sort()
frame = cv2.imread(images[0])
height, width, layers = frame.shape
video = cv2.VideoWriter(video_name, 0, 1, (width,height))
for image in images:
video.write(cv2.imread(image))
cv2.destroyAllWindows()
video.release()
Upvotes: 0
Reputation: 1
Maybe you could try instead of saving images and load them again, make video captures from your source video and pass it to out object (demo_output.avi in this case) ...something like this:
import cv2
cap = cv2.VideoCapture('path to video/video.mp4')
fourcc = cv2.VideoWriter_fourcc(*'XVID')
ret, frame = cap.read()
fps_video=cap.get(cv2.CAP_PROP_FPS)
height,width = frame.shape[:2]
out = cv2.VideoWriter('demo_output.avi',fourcc, fps_video, (width,height)) ##can be set with your width,height values
while ret:
frame = cv2.resize(frame, None, fx=1.0, fy=1.0, interpolation=cv2.INTER_AREA)
out.write(frame)
ret, frame = cap.read()
cap.release()
out.release()
cv2.destroyAllWindows()
UPDATE:
If you want images and then save video file:
import cv2
import os
import numpy as np
vidcap = cv2.VideoCapture('path to video/video.mp4')
success,image = vidcap.read()
fps_video = vidcap.get(cv2.CAP_PROP_FPS)
height,width = image.shape[:2]
count = 0
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
vidcap.release()
lista = [[x[5:-4],x] for x in os.listdir() if x.endswith('jpg')]
result=[]
for x in lista:
t1,t2 = np.int(x[0]),x[1]
result.append([t1,t2])
result.sort()
#recording video back
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('demo_output.avi',fourcc, fps_video, (width,height)) ##can be set with your width,height values
for img in result:
frame = cv2.imread(img[1])
out.write(frame)
out.release()
Upvotes: 0
Reputation: 616
If your requirement needs you to store the frames, try this
import cv2
import os
image_folder = 'images'
video_name = 'video.avi'
images = [img for img in os.listdir(image_folder) if img.endswith(".jpg")]
frame = cv2.imread(os.path.join(image_folder, images[0]))
height, width, layers = frame.shape
video = cv2.VideoWriter(video_name, 0, 1, (width,height))
for i in range(len(images)):
video.write(cv2.imread(os.path.join(image_folder, 'a'+str(i)+'.jpg')))
cv2.destroyAllWindows()
video.release()
Upvotes: 0