Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OpenCV doesn't save the video

I'm using the following code to read a video from file, apply the canny edge algorithm and write the modified video to a file. The code compiles and runs perfectly. But, the video is not written! I'm utterly confused. Please tell me what the error is. The file is not created at all! OS: Ubuntu 12.10

Code for writing to the output file

Opening the output file

bool setOutput(const std::string &filename, int codec=0, double framerate=0.0, bool isColor=true) {

    outputFile= filename;
    extension.clear();

    if (framerate==0.0) 
        framerate= getFrameRate(); // same as input

    char c[4];
    // use same codec as input
    if (codec==0) { 
        codec= getCodec(c);
    }

    // Open output video
    return writer.open(outputFile, // filename
    codec, // codec to be used 
    framerate,      // frame rate of the video
    getFrameSize(), // frame size
    isColor);       // color video?
}

Writing the frame

void writeNextFrame (Mat& frame)
{
    writer.write (frame);
}

And there's a separate run method which executes these

like image 844
pratnala Avatar asked Nov 10 '12 15:11

pratnala


2 Answers

Whenever I encounter strange behaviors in my applications, I write a short, self contained, correct (compilable), example to help me understand what's going on.

I wrote the code below to illustrate what you should be doing. It's worth noting that it works perfectly on my Mac OS X:

#include <cv.h>
#include <highgui.h>

#include <iostream>
#include <string>

int main(int argc, char* argv[])
{
    // Load input video
    cv::VideoCapture input_cap("Wildlife.avi");
    if (!input_cap.isOpened())
    {
        std::cout << "!!! Input video could not be opened" << std::endl;
        return -1;
    }

    // Setup output video
    cv::VideoWriter output_cap("output.avi",  
                               input_cap.get(CV_CAP_PROP_FOURCC),
                               input_cap.get(CV_CAP_PROP_FPS), 
                               cv::Size(input_cap.get(CV_CAP_PROP_FRAME_WIDTH), input_cap.get(CV_CAP_PROP_FRAME_HEIGHT)));

    if (!output_cap.isOpened())
    {
        std::cout << "!!! Output video could not be opened" << std::endl;
        return -1;
    }

    // Loop to read frames from the input capture and write it to the output capture
    cv::Mat frame;
    while (true)
    {       
        if (!input_cap.read(frame))             
            break;

        output_cap.write(frame);
    }

    // Release capture interfaces   
    input_cap.release();
    output_cap.release();

    return 0;
}

Inspecting the input file with FFmpeg reveals (ffmpeg -i Wildlife.avi):

Input #0, avi, from 'Wildlife.avi':
  Metadata:
    ISFT            : Lavf52.13.0
  Duration: 00:00:07.13, start: 0.000000, bitrate: 2401 kb/s
    Stream #0.0: Video: msmpeg4v2, yuv420p, 1280x720, PAR 1:1 DAR 16:9, 29.97 tbr, 29.97 tbn, 29.97 tbc
    Stream #0.1: Audio: mp3, 44100 Hz, 2 channels, s16, 96 kb/s

and the output:

Input #0, avi, from 'output.avi':
  Metadata:
    ISFT            : Lavf52.61.0
  Duration: 00:00:07.10, start: 0.000000, bitrate: 3896 kb/s
    Stream #0.0: Video: msmpeg4v2, yuv420p, 1280x720, 29.97 tbr, 29.97 tbn, 29.97 tbc

So the only significant change between the two files is that the output generated by OpenCV doesn't have an audio stream, which is the correct behavior since OpenCV doesn't deal with audio.

Make sure your user has the proper permission to read/write/execute in the directory you are running the application. Also, the debugs I added in the code will probably assist you to find problems related to input/output capture.

like image 115
karlphillip Avatar answered Sep 18 '22 05:09

karlphillip


do you have FFMPEG library installed on your machine? On Linux FFMPEG is used to write videos; on Windows FFMPEG or VFW is used. check by command

 ffmpeg -version

try to install additional libraries sudo apt-get install libavformat-dev libswscale-dev.

And by calling writer.open you only Initializes or reinitializes video writer.You have to call the void VideoWriter::write(const Mat& image) to write the next video frame to file. I hope this will work.

like image 30
isrish Avatar answered Sep 18 '22 05:09

isrish