Search code examples
image-processingffmpegpython-imaging-librarylibtiff

Python and ffmpeg create different tiff stacks


Hello everybody out there with an interest in image processing,

Creating a multipage tiff file (tiff stack) out of a grayscale movie can be achieved without programming using ffmpeg and tiffcp (the latter being part of Debian's libtiff-tools):

ffmpeg -i movie.avi frame%03d.tif
tiffcp frame*.tif stack.tif

Programming it in Python also seemed to be feasible to me using the OpenCV and tifffile libraries:

import numpy as np
import cv2
import tifffile

cap = cv2.VideoCapture('movie.avi')

success, frame = cap.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

image = np.zeros((300, 400, 500), 'uint8')  # pre-allocate some space
i = 0;

while success:
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    image[i,:,:] = gray[80:480,0:500]
    success, frame = cap.read()

cap.release()
tifffile.imsave('image.tif',image,photometric='minisblack')

However, the results differ in size. Looking at the histogram of the Python solution, I realized that it differes from the ffmpeg solution.

Thanks to the answer below, I compared the output files with the file:

user@ubuntu:~$ file ffmpeg.tif tifffile.tif 
ffmpeg.tif: TIFF image data, little-endian
tifffile.tif:  TIFF image data, little-endian, direntries=17, height=400, bps=8, compression=none, PhotometricIntepretation=BlackIsZero, description={"shape": [300, 400, 500]}, width=500

In addition, I compared the files with ffmpeg:

user@ubuntu:~$ ffmpeg -i ffmpeg.tif -i tifffile.tif 
[tiff_pipe @ 0x556cfec95d80] Stream #0: not enough frames to estimate rate; consider increasing probesize
Input #0, tiff_pipe, from 'ffmpeg.tif':
  Duration: N/A, bitrate: N/A
    Stream #0:0: Video: tiff, gray, 500x400 [SAR 1:1 DAR 5:4], 25 tbr, 25 tbn, 25 tbc
[tiff_pipe @ 0x556cfeca6b40] Stream #0: not enough frames to estimate rate; consider increasing probesize
Input #1, tiff_pipe, from 'tifffile.tif':
  Duration: N/A, bitrate: N/A
    Stream #1:0: Video: tiff, gray, 500x400 [SAR 1:1 DAR 5:4], 25 tbr, 25 tbn, 25 tbc

Which additional diagnostics could I use in order to pin down the problem?


Solution

  • compression algorith

    By default ffmpeg uses the packbits compression algorithm for TIFF output. This can be changed with the -compression_algo option, and other accepted values are raw, lzw, and deflate:

    ffmpeg -i input.avi -compression_algo lzw output_%04d.tif
    

    pixel format

    Another difference may be caused by the pixel format (color space and chroma subsampling). See ffmpeg -h encoder=tiff for a list of supported pixel formats. Which pixel format gets used depends on your input, and the log/console output will indicate the selected pixel format.

    comparing outputs

    I don't know what defaults are used by tifffile, but you can run ffmpeg -i ffmpeg.tif -i tifffile.tif and file ffmpeg.tif tifffile.tif to view details which may explain the discrepancy.