Tuesday, 21 October 2014

Creating a video from PDF slides with ffmpeg and ImageMagick

To illustrate the role of autocontext in [1], I created a video from the successive probability maps obtained in the segmentation of the left ventricle in 3D echocardiography. This post is a quick overview of the bash and LaTeX code I used for this video. The XKCD style for beamer is presented in a previous blog post.



The slides are first converted from PDF to PNG using ImageMagick, then each slide is transformed into a single movie in order to easily control the time spent on each frame (-t option of ffmpeg), as well as the insertion of other movies.

#!/bin/bash

set -x
set -e

mkdir -p tmp_movie

# get the number of slides
nb_pages=`pdfinfo presentation.pdf | grep Pages | sed 's/[^0-9]*//'`

# convert PDF to PNG
/usr/bin/convert -density 400 presentation.pdf -resize 1024x768 -colorspace sRGB -type TrueColorMatte -depth 8 tmp_movie/slide.png

concat=""
for((i=0;i<$nb_pages;i++))
do
    # we do not want to spend the same amount of time on all slides
    if [ "$i" -eq "0" ]
    then
        duration=6
    elif [ "$i" -eq "61" ]
    then
        duration=10
    elif [ "$i" -eq "62" ]
    then
        duration=4
    else
        duration=0.5
    fi
  
    # convert PNG to MPG
    ffmpeg -qscale 1 -loop 1 -f image2 -i tmp_movie/slide-${i}.png  -t $duration tmp_movie/slide-${i}.mpg
    concat=$concat"tmp_movie/slide-${i}.mpg|"
done

# remove last character
concat=${concat%?}

# concatenate all videos
ffmpeg -qscale 1 -i concat:"${concat}"  MICCAI2014_CETUS.mpg

# convert video format
ffmpeg -i MICCAI2014_CETUS.mpg -qscale 1 MICCAI2014_CETUS.mp4
ffmpeg -i MICCAI2014_CETUS.mpg -s 512x384 -qscale 1 MICCAI2014_CETUS_resized.mp4

It is a very similar script which I used for a previous video.

Notes:

Videos can be integrated in LaTeX Beamer presentations with the multimedia package. The resulting PDF works in Okular, but not in Evince. Details can be found Chapter 14 of the Beamer user guide.

Overlay LATEX legend on a PNG image:

Set the background and font colors of your Beamer slide:
\setbeamercolor{background canvas}{bg=black}
\setbeamercolor{normal text}{fg=white}

then do the overlay using transparency in ImageMagick:
pdflatex legend.tex
convert -density 400 legend.pdf -resize 1024x768 -colorspace sRGB -type TrueColorMatte -depth 8 legend.png
convert legend.png -transparent black legend.png
convert background.png legend.png -gravity center -composite  output.png

LaTeX for loop:

The following code uses LaTeX for loops and counters to generates all the movie frames from a set of PNG images. 

\newcounter{mycounter}
\foreach \iter in {1, ..., 3} {
   \setbeamercolor{background canvas}{bg=black}
   \setcounter{mycounter}{0}

       \foreach \frameid in {1, ..., 20} {
       \stepcounter{mycounter}

       \begin{frame}
           \frametitle{\color{white}\iter\textsuperscript{\ifnum\iter=1 st
           \else\ifnum\iter=2 nd
           \else\ifnum\iter=3 rd
           \else\ifnum\iter>3 th
           \fi\fi\fi\fi} autocontext iteration}

           \centering\scriptsize

           \begin{tikzpicture}[every node/.style={anchor=south west,inner sep=0pt},decoration=penciline]

\node (fig1) at (0,0) { \includegraphics[width=0.75\textwidth]{movie_Patient17/iter\iter_Patient17_frame\ifnum\value{mycounter}<10 0\fi\arabic{mycounter}.png}};

\begin{scope}[x={(fig1.south east)},y={(fig1.north west)}]
    % \draw[help lines,xstep=.1,ystep=.1] (0,0) grid (1,1);
    % \foreach \x in {0,1,...,9} { \node [anchor=north] at (\x/10,0) {0.\x}; }
    % \foreach \y in {0,1,...,9} { \node [anchor=east] at (0,\y/10) {0.\y}; }

    \node[anchor=north west] (fig2) at (0.55,0.45) { \includegraphics[width=0.3\textwidth]{autocontext_Patient17/iter\iter_Patient17_frame\ifnum\value{mycounter}<10 0\fi\arabic{mycounter}.png}}; 

    \node (zplane1) at (0.05,0.96) {\color{white}Z direction};
    \node (yplane1) at (0.7,1.02) {\color{white}Y direction};
    \node (xplane1) at (0.15,-0.05) {\color{white}X direction};
    \node [text width=2cm] (pplane1) at (0.95,0.25) {\color{white}Classification probabilities Y direction};
\end{scope}
           \end{tikzpicture}
       \end{frame}
    }
}

I considered using a GUI such as Pitivi or OpenShot, but it seemed easier to make LaTeX slides and turn them into a movie than getting started with a new software. Besides, scripts have the obvious advantage that I just have a few lines and parameters to adjust to create the same video with a different subject (here Patient17 was used).

References:

[1] Keraudren, K., Oktay, O., Shi, W., Hajnal, J.V., & Rueckert, D.: Endocardial 3D Ultrasound Segmentation using Autocontext Random Forests, CETUS Challenge, MICCAI 2014.
PDF poster slides

No comments:

Post a Comment