Home | History | Annotate | Download | only in video-write
      1 Creating a video with OpenCV {#tutorial_video_write}
      2 ============================
      3 
      4 Goal
      5 ----
      6 
      7 Whenever you work with video feeds you may eventually want to save your image processing result in a
      8 form of a new video file. For simple video outputs you can use the OpenCV built-in @ref cv::VideoWriter
      9 class, designed for this.
     10 
     11 -   How to create a video file with OpenCV
     12 -   What type of video files you can create with OpenCV
     13 -   How to extract a given color channel from a video
     14 
     15 As a simple demonstration I'll just extract one of the BGR color channels of an input video file
     16 into a new video. You can control the flow of the application from its console line arguments:
     17 
     18 -   The first argument points to the video file to work on
     19 -   The second argument may be one of the characters: R G B. This will specify which of the channels
     20     to extract.
     21 -   The last argument is the character Y (Yes) or N (No). If this is no, the codec used for the
     22     input video file will be the same as for the output. Otherwise, a window will pop up and allow
     23     you to select yourself the codec to use.
     24 
     25 For example, a valid command line would look like:
     26 @code{.bash}
     27 video-write.exe video/Megamind.avi R Y
     28 @endcode
     29 The source code
     30 ---------------
     31 
     32 You may also find the source code and these video file in the
     33 `samples/cpp/tutorial_code/highgui/video-write/` folder of the OpenCV source library or [download it
     34 from here ](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/HighGUI/video-write/video-write.cpp).
     35 
     36 @include cpp/tutorial_code/HighGUI/video-write/video-write.cpp
     37 
     38 The structure of a video
     39 ------------------------
     40 
     41 For start, you should have an idea of just how a video file looks. Every video file in itself is a
     42 container. The type of the container is expressed in the files extension (for example *avi*, *mov*
     43 or *mkv*). This contains multiple elements like: video feeds, audio feeds or other tracks (like for
     44 example subtitles). How these feeds are stored is determined by the codec used for each one of them.
     45 In case of the audio tracks commonly used codecs are *mp3* or *aac*. For the video files the list is
     46 somehow longer and includes names such as *XVID*, *DIVX*, *H264* or *LAGS* (*Lagarith Lossless
     47 Codec*). The full list of codecs you may use on a system depends on just what one you have
     48 installed.
     49 
     50 ![](images/videoFileStructure.png)
     51 
     52 As you can see things can get really complicated with videos. However, OpenCV is mainly a computer
     53 vision library, not a video stream, codec and write one. Therefore, the developers tried to keep
     54 this part as simple as possible. Due to this OpenCV for video containers supports only the *avi*
     55 extension, its first version. A direct limitation of this is that you cannot save a video file
     56 larger than 2 GB. Furthermore you can only create and expand a single video track inside the
     57 container. No audio or other track editing support here. Nevertheless, any video codec present on
     58 your system might work. If you encounter some of these limitations you will need to look into more
     59 specialized video writing libraries such as *FFMpeg* or codecs as *HuffYUV*, *CorePNG* and *LCL*. As
     60 an alternative, create the video track with OpenCV and expand it with sound tracks or convert it to
     61 other formats by using video manipulation programs such as *VirtualDub* or *AviSynth*.
     62 
     63 The *VideoWriter* class
     64 -----------------------
     65 
     66 The content written here builds on the assumption you
     67 already read the @ref tutorial_video_input_psnr_ssim tutorial and you know how to read video files. To create a
     68 video file you just need to create an instance of the @ref cv::VideoWriter class. You can specify
     69 its properties either via parameters in the constructor or later on via the @ref cv::VideoWriter::open function.
     70 Either way, the parameters are the same: 1. The name of the output that contains the container type
     71 in its extension. At the moment only *avi* is supported. We construct this from the input file, add
     72 to this the name of the channel to use, and finish it off with the container extension.
     73 @code{.cpp}
     74 const string source      = argv[1];            // the source file name
     75 string::size_type pAt = source.find_last_of('.');   // Find extension point
     76 const string NAME = source.substr(0, pAt) + argv[2][0] + ".avi";   // Form the new name with container
     77 @endcode
     78 -#  The codec to use for the video track. Now all the video codecs have a unique short name of
     79     maximum four characters. Hence, the *XVID*, *DIVX* or *H264* names. This is called a four
     80     character code. You may also ask this from an input video by using its *get* function. Because
     81     the *get* function is a general function it always returns double values. A double value is
     82     stored on 64 bits. Four characters are four bytes, meaning 32 bits. These four characters are
     83     coded in the lower 32 bits of the *double*. A simple way to throw away the upper 32 bits would
     84     be to just convert this value to *int*:
     85     @code{.cpp}
     86     VideoCapture inputVideo(source);                                // Open input
     87     int ex = static_cast<int>(inputVideo.get(CAP_PROP_FOURCC));     // Get Codec Type- Int form
     88     @endcode
     89     OpenCV internally works with this integer type and expect this as its second parameter. Now to
     90     convert from the integer form to string we may use two methods: a bitwise operator and a union
     91     method. The first one extracting from an int the characters looks like (an "and" operation, some
     92     shifting and adding a 0 at the end to close the string):
     93     @code{.cpp}
     94     char EXT[] = {ex & 0XFF , (ex & 0XFF00) >> 8,(ex & 0XFF0000) >> 16,(ex & 0XFF000000) >> 24, 0};
     95     @endcode
     96     You can do the same thing with the *union* as:
     97     @code{.cpp}
     98     union { int v; char c[5];} uEx ;
     99     uEx.v = ex;                              // From Int to char via union
    100     uEx.c[4]='\0';
    101     @endcode
    102     The advantage of this is that the conversion is done automatically after assigning, while for
    103     the bitwise operator you need to do the operations whenever you change the codec type. In case
    104     you know the codecs four character code beforehand, you can use the *CV_FOURCC* macro to build
    105     the integer:
    106     @code{.cpp}
    107     CV_FOURCC('P','I','M,'1') // this is an MPEG1 codec from the characters to integer
    108     @endcode
    109     If you pass for this argument minus one than a window will pop up at runtime that contains all
    110     the codec installed on your system and ask you to select the one to use:
    111 
    112     ![](images/videoCompressSelect.png)
    113 
    114 -#  The frame per second for the output video. Again, here I keep the input videos frame per second
    115     by using the *get* function.
    116 -#  The size of the frames for the output video. Here too I keep the input videos frame size per
    117     second by using the *get* function.
    118 -#  The final argument is an optional one. By default is true and says that the output will be a
    119     colorful one (so for write you will send three channel images). To create a gray scale video
    120     pass a false parameter here.
    121 
    122 Here it is, how I use it in the sample:
    123 @code{.cpp}
    124 VideoWriter outputVideo;
    125 Size S = Size((int) inputVideo.get(CAP_PROP_FRAME_WIDTH),    //Acquire input size
    126               (int) inputVideo.get(CAP_PROP_FRAME_HEIGHT));
    127 outputVideo.open(NAME , ex, inputVideo.get(CAP_PROP_FPS),S, true);
    128 @endcode
    129 Afterwards, you use the @ref cv::VideoWriter::isOpened() function to find out if the open operation succeeded or
    130 not. The video file automatically closes when the *VideoWriter* object is destroyed. After you open
    131 the object with success you can send the frames of the video in a sequential order by using the
    132 @ref cv::VideoWriter::write function of the class. Alternatively, you can use its overloaded operator \<\< :
    133 @code{.cpp}
    134 outputVideo.write(res);  //or
    135 outputVideo << res;
    136 @endcode
    137 Extracting a color channel from an BGR image means to set to zero the BGR values of the other
    138 channels. You can either do this with image scanning operations or by using the split and merge
    139 operations. You first split the channels up into different images, set the other channels to zero
    140 images of the same size and type and finally merge them back:
    141 @code{.cpp}
    142 split(src, spl);                 // process - extract only the correct channel
    143 for( int i =0; i < 3; ++i)
    144    if (i != channel)
    145       spl[i] = Mat::zeros(S, spl[0].type());
    146 merge(spl, res);
    147 @endcode
    148 Put all this together and you'll get the upper source code, whose runtime result will show something
    149 around the idea:
    150 
    151 ![](images/resultOutputWideoWrite.png)
    152 
    153 You may observe a runtime instance of this on the [YouTube
    154 here](https://www.youtube.com/watch?v=jpBwHxsl1_0).
    155 
    156 \htmlonly
    157 <div align="center">
    158 <iframe title="Creating a video with OpenCV" width="560" height="349" src="http://www.youtube.com/embed/jpBwHxsl1_0?rel=0&loop=1" frameborder="0" allowfullscreen align="middle"></iframe>
    159 </div>
    160 \endhtmlonly
    161