python 16bit grayscale video from series of images

Viewed 1011

I have a dataset of grayscale images of type uint16 and I would like to save it as a video file, the output should be lossless video file of type uint16, i tried this code,

video = cv2.VideoWriter(file_name, 0, fps, (w, h), isColor=False)
for frame in frames:
  video.write(frame)
video.release()
cv2.destroyAllWindows()

but opencv support only uint8, anyone know a good way to do it?

1 Answers

You can do it with FFMPEG. The FFV1 codec is lossless and supports gray16le pixel format (images in 16UC1). You can make a .avi video.

ffmpeg -i depth_%06d.tif -c:v ffv1 -vf -crf 0 output_ffv1.avi

However, your images must be in gray16le format (saving images as .tif will work). If your images are in PNG they probably won't be in gray16le format but in grey format (this won't work if you want to get images from the video later). You can check with ffprobe.

ffprobe -i depth_image.png

Output must have something like:

Stream 0:0: Video: tiff, gray16le, 1280x720, 25 tbr, 25 tbn, 25 tbc

Once you have your video (.avi), you can check the pixel format again with ffprobe, it must be gray16le too.

Stream 0:0: Video: ffv1 (FFV1 / 0x31564646), gray16le, 1280x720, 45067 kb/s, 25 fps, 25 tbr, 25 tbn, 25 tbc

Now, if you want to get the images back from the video. You can use ffmpeg-python. This extracts unit16 arrays from the video. Then you can save this array as PNG or TIFF or whatever you need.

import ffmpeg
def extract_frame(input_vid, frame_num):
   out, _ = (
       ffmpeg
       .input(input_vid)
       .filter_('select', 'gte(n,{})'.format(frame_num))
       .output('pipe:', format='rawvideo', pix_fmt='gray16le', vframes=1)
       .run(capture_stdout=True, capture_stderr=True)
   )
   return np.frombuffer(out, np.uint16).reshape([720, 1280])
 
for i in range($totalFrameNumber):
   frame = extract_frame('test_ffv1.avi',i)

Change $totalFrameNumber for the total number of frames in your .avi video.

Related