1

I have some graphs within a folder called jupyter with jpg format, I want to put them together to make a video out of them, but when I run the code, it does not save and show the video.

import cv2
import os
from os.path import isfile, join
def convert_pictures_to_video(pathIn, pathOut, fps, time):
    frame_array=[]
    files= [f for f in os.listdir(pathIn) if isfile(join(pathIn,f))]
    for i in range (len(files)):
        filename=pathIn+files[i]
        img=cv2.imread(filename)
        height, width, layers=img.shape
        size=(width,height)
        for k in range (time):
        frame_array.append(img)
out=cv2.VideoWriter(pathOut, cv2.VideoWriter_fourcc(*'mp4v'),fps,size)

    for i in range(len(frame_array)):
        out.write(frame_array[i])
    cv2.destroyAllWindows()
    out.release()

pathIn='/Users/jupyter/'
pathOut='/Users/jupyter/video.avi'
fps=1
time=20
convert_pictures_to_video(pathIn, pathOut, fps, time
Community
  • 1
  • 1
Sam
  • 87
  • 1
  • 7
  • You have a typo there, read again. You need `release`. – Powercoder Sep 16 '20 at 19:27
  • Do not use OpenCV to create videos. The backend to create the videos is horribly bloated - you have no control on the quality factor which tends to create really large file sizes. I recommend `moviepy` instead: https://stackoverflow.com/a/62434934/3250829 – rayryeng Sep 17 '20 at 14:31
  • Thanks, I edited the typo but still does not work. – Sam Sep 18 '20 at 15:10
  • @rayryeng Why not directly use something like ffmpeg rather than yet another wrapper though? – matanster Nov 17 '21 at 17:08
  • 1
    @matanster You could. I've done this in the past where I've set up a pipe that directly uses FFMPEG but I suggested moviepy for those who don't really know how to use FFMPEG. – rayryeng Nov 17 '21 at 17:20

1 Answers1

3
    1. You want to create a .avi file from your images. Therefore you should initialize fourcc to MJPG.
    • fourcc = cv2.VideoWriter_fourcc('M', 'J', 'P', 'G') 
      
    • You should use mp4v when you want to create a .mp4 file

      • fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v') 
        
    1. All Images's size and the VideoWriter size must be same.

      For instance: All my images are with the size (300, 167). Therefore:

      • out = cv2.VideoWriter('video.avi', fourcc, 25, (300, 167), isColor=True)
        
      • Since, I'm going to create colorful images, I set the isColor variable to true

    1. I prefer glob for gathering all images:

      • for img in sorted(glob.glob("ball_tracking/*.png")):
            img = cv2.imread(img)
            img = cv2.resize(img, (300, 167))
            out.write(img)
        

Code:


import cv2
import glob

fourcc = cv2.VideoWriter_fourcc('M', 'J', 'P', 'G')

out = cv2.VideoWriter('video.avi', fourcc, 25, (300, 167), isColor=True)

for img in sorted(glob.glob("ball_tracking/*.png")):
    img = cv2.imread(img)
    img = cv2.resize(img, (300, 167))
    out.write(img)

out.release()

Update


  • If the quality is really bad, you could do two-things. For slowing the video you can lower the frame-rate.

      1. Changing .avi to .mp4
      • fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v') 
        
      1. You can change the image size. For instance, if all of you images are the same size. Then get the first images' height and width and set it to the video's size.
      •  (h, w) = cv2.imread(glob("<your-path-here>*.png")[0]).shape[:2]
        
      • If your images are not same you can still use the above code, but the quality may not be improved.

      1. You could lower the frame-rate for slower video. For instance: 25 to 2.
      • out = cv2.VideoWriter('video.avi', fourcc, 2, (w, h), isColor=True)
        

Updated Code:


import cv2
import glob

fourcc = cv2.VideoWriter_fourcc('M', 'P', '4', 'V')
(h, w) = cv2.imread(glob("<your-path-here>*.png")[0]).shape[:2]

out = cv2.VideoWriter('video.mp4', fourcc, 2, (w, h), isColor=True)

for img in sorted(glob.glob("<your-path-here>*.png")):
    img = cv2.imread(img)
    img = cv2.resize(img, (w, h))
    out.write(img)

out.release()
Ahmet
  • 7,527
  • 3
  • 23
  • 47
  • I can run it without any error, but it does not show any results and the output is not saved, time of the run in less than a second which does not make sense. In addition, my files should be uploaded in order, like, image1.png, image2.png,... – Sam Oct 15 '20 at 20:53
  • You made the necessary changes right? I mean you changed `ball_tracking/*.png` to your current directory, and you are sure about all the files extensions are `.png`? I've tested the code before placing here. – Ahmet Oct 15 '20 at 21:00
  • Absolutely, yes, I changed it, I realized it was saved in another directory, so it works, I have 2 concerns: the quality is very bad, 2- The video is very quick, can I make it slower? – Sam Oct 16 '20 at 15:48
  • I've updated my code. If you want you could look at it. – Ahmet Oct 16 '20 at 16:04
  • Thanks a lot, I solved the resolution problem by changing the numbers in "cv2.resize(img, (1200, 668))", when I run the update code I get this error:"TypeError: 'module' object is not callable". In addition, I need to read the images in order, like image1.png, image2.png, ... – Sam Oct 16 '20 at 16:18
  • Yes I did change it – Sam Oct 16 '20 at 17:51
  • It was solved, I just need to know how I can read the images in order. – Sam Oct 16 '20 at 18:16