Save Images & Videos to File

In many real world computer vision applications, it is required to persist images and videos for future reference. Most common persisting method is to save the image or the video to a file. Therefore this tutorial is prepared to explain how to save images and videos to a file with OpenCV C++.

To understand this tutorial better,  please refer to Load & Display Image and Play Video from File or Camera first.


Save an Image to a File


In this section, you may learn how to save an image loaded from a file. In the same way, you can save images taken from a camera or any other methods.

//Uncomment the following line if you are compiling this code in Visual Studio
//#include "stdafx.h"

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main(int argc, char** argv)
{
 // Read the image file
 Mat image = imread("D:/My OpenCV Website/fly-agaric.jpg");

 // Check for failure
 if (image.empty())
 {
  cout << "Could not open or find the image" << endl;
  cin.get(); //wait for any key press
  return -1;
 }

 /*
 Make changes to the image as necessary
 e.g.  
  1. Change brightness/contrast of the image
  2. Smooth/Blur image
  3. Crop the image
  4. Rotate the image
  5. Draw shapes on the image
 */

 bool isSuccess = imwrite("D:/MyImage.jpg", image); //write the image to a file as JPEG 
 //bool isSuccess = imwrite("D:/MyImage.png", image); //write the image to a file as PNG
 if (isSuccess == false)
 {
  cout << "Failed to save the image" << endl;
  cin.get(); //wait for a key press
  return -1;
 }

 cout << "Image is succusfully saved to a file" << endl;

 String windowName = "The Saved Image"; //Name of the window
 namedWindow(windowName); // Create a window
 imshow(windowName, image); // Show our image inside the created window.

 waitKey(0); // Wait for any keystroke in the window

 destroyWindow(windowName); //destroy the created window

 return 0;
}
Copy and paste above code snippet into your IDE and run it. Please note that you have to replace "D:/My OpenCV Website/fly-agaric.jpg" in the code with a valid location to an image in your computer. Then your image should be saved in the specified location.


Explanation


Let's go through the above code line by line.

// Read the image file
Mat image = imread("D:/My OpenCV Website/fly-agaric.jpg");

// Check for failure
if (image.empty())
{
 cout << "Could not open or find the image" << endl;
 cin.get(); //wait for any key press
 return -1;
}
These lines of code read the image from the specified file. If the image cannot be loaded, program will exit.

More details about each OpenCV functions in the above code segment can be found in Load & Display Image.


bool isSuccess = imwrite("D:/MyImage.jpg", image); //write the image to a file as JPEG 
//bool isSuccess = imwrite("D:/MyImage.png", image); //write the image to a file as PNG
if (isSuccess == false)
{
 cout << "Failed to save the image" << endl;
 cin.get(); //wait for a key press
 return -1;
}

cout << "Image is succusfully saved to a file" << endl;
The above code segment writes the given image to the specified file. If it is failed to write the image to the file, program will exit.


bool imwrite( const String& filename, InputArray img, const std::vector& params = std::vector())

This function writes the given img object to the specified file. On success, this function will return true, otherwise it will return false.

  1. filename - File name of the output image. Please note that the extension of the filename will be used to determine to the image format. (e.g. - If the filename is MyImage.jpg, a JPEG image will be written. If the filename is MyImage.png, a PNG image will be written.). jpeg, jpg, bmp, png, tiff and tif extensions are always supported. Other image file types are supported depending on your platform and installed codecs.

  2. img - The image object to be saved. Please note that this image object should have following properties. 
      • The bit depth of the image object should be 8 bit signed or 16 bit unsigned.
      • Number of channels of the image should be 1 or 3. For 3 channel image objects, BGR channel order should be present. 
    If the bit depth or the channel order of your image object is different from the above specification, you may use Mat::convertTo and cv::cvtColor functions to convert your image.

  3. params - This is an optional parameter.



String windowName = "The Saved Image"; //Name of the window
namedWindow(windowName); // Create a window
imshow(windowName, image); // Show our image inside the created window.

waitKey(0); // Wait for any keystroke in the window

destroyWindow(windowName); //destroy the created window
These lines of code create  a new window and display the image in it. The program will display the image in the window until any key is pressed. After a key is pressed, the window will be destroyed.

More details about each OpenCV functions in the above code segment can be found in Load & Display Image.


Summary


In the above section, you have learnt how to
  • Load an image from a file.
  • The loaded image can be modified as you wish. But it is not explained in this tutorial as it has been explained in other tutorials. (e.g. - Filtering Images, Rotate Image & Video, etc)
  • Save the image to a file
  • Display the image in a window



Save a Video to a File


In this section, you may learn how to save a video captured by a webcam to a file. In the same way, you can save a video file after doing any modifications.

//Uncomment the following line if you are compiling this code in Visual Studio
//#include "stdafx.h"

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main(int argc, char* argv[])
{
    //Open the default video camera
    VideoCapture cap(0);

    // if not success, exit program
    if (cap.isOpened() == false)
    {
        cout << "Cannot open the video camera" << endl;
        cin.get(); //wait for any key press
        return -1;
    }

    int frame_width = static_cast<int>(cap.get(CAP_PROP_FRAME_WIDTH)); //get the width of frames of the video
    int frame_height = static_cast<int>(cap.get(CAP_PROP_FRAME_HEIGHT)); //get the height of frames of the video
    
    Size frame_size(frame_width, frame_height);
    int frames_per_second = 10;

    //Create and initialize the VideoWriter object 
    VideoWriter oVideoWriter("D:/MyVideo.avi", VideoWriter::fourcc('M', 'J', 'P', 'G'), 
                                                               frames_per_second, frame_size, true); 
    
    //If the VideoWriter object is not initialized successfully, exit the program
    if (oVideoWriter.isOpened() == false) 
    {
        cout << "Cannot save the video to a file" << endl;
        cin.get(); //wait for any key press
        return -1;
    }

    string window_name = "My Camera Feed";
    namedWindow(window_name); //create a window called "My Camera Feed"

    while (true)
    {
        Mat frame;
        bool isSuccess = cap.read(frame); // read a new frame from the video camera

        //Breaking the while loop if frames cannot be read from the camera
        if (isSuccess == false)
        {
            cout << "Video camera is disconnected" << endl;
            cin.get(); //Wait for any key press
            break;
        }

        /*
        Make changes to the frame as necessary
        e.g.  
         1. Change brightness/contrast of the image
         2. Smooth/Blur image
         3. Crop the image
         4. Rotate the image
         5. Draw shapes on the image
        */

        //write the video frame to the file
        oVideoWriter.write(frame); 

        //show the frame in the created window
        imshow(window_name, frame);

        //Wait for for 10 milliseconds until any key is pressed.  
        //If the 'Esc' key is pressed, break the while loop.
        //If any other key is pressed, continue the loop 
        //If any key is not pressed within 10 milliseconds, continue the loop 
        if (waitKey(10) == 27)
        {
            cout << "Esc key is pressed by the user. Stopping the video" << endl;
            break;
        }
    }

    //Flush and close the video file
    oVideoWriter.release();
    
    return 0;
}
Copy and paste the above code snippet into your IDE and run it. Then you should see the output of the webcam in the created window. After the 'Esc' key is pressed, the created window will be destroyed and the video output of the webcam will be saved in the given location.


Explanation


Let's go through the above code line by line.

//Open the default video camera
VideoCapture cap(0);

// if not success, exit program
if (cap.isOpened() == false)
{
    cout << "Cannot open the video camera" << endl;
    cin.get(); //wait for any key press
    return -1;
}
The above code segment opens the default webcam connected to your computer. If it is failed to open the camera, the program will exit. More details about each OpenCV functions in the above code segment can be found in Play Video from File or Camera.


int frame_width = static_cast<int>(cap.get(CAP_PROP_FRAME_WIDTH)); //get the width of frames of the video
int frame_height = static_cast<int>(cap.get(CAP_PROP_FRAME_HEIGHT)); //get the height of frames of the video

Size frame_size(frame_width, frame_height);
int frames_per_second = 10;

//Create and initialize the VideoWriter object 
VideoWriter oVideoWriter("D:/MyVideo.avi", VideoWriter::fourcc('M', 'J', 'P', 'G'), 
                                                           frames_per_second, frame_size, true); 

//If the VideoWriter object is not initialized successfully, exit the program                                                    
if (oVideoWriter.isOpened() == false) 
{
    cout << "Cannot save the video to a file" << endl;
    cin.get(); //wait for any key press
    return -1;
}
This code segment obtains the width and the height of the video frames of the webcam. Using the obtained information, the VideoWriter object is constructed and initialized. If the initialization is failed, the program will exit.


VideoWriter(const String& filename, int fourcc, double fps, Size frameSize, bool isColor = true)
This is one of the available overloaded constructors of the VideoWriter object. It constructs and initializes the VideoWriter object in order to write video frames to a given file.

  1. filename - Name of the file to write video frames.

  2. fourcc - 4-character code of the codec which is used to compress the video. The complete list of codes can be found in this page. But most of the codecs listed in this page might not work in your computer. These are some popular codecs which might work for you.
    • VideoWriter::fourcc('P', 'I', 'M', '1') for MPEG-1
    • VideoWriter::fourcc('M', 'J', 'P', 'G') for Motion JPEG
    • VideoWriter::fourcc('M', 'P', '4', '2') for MPEG-4 variation of Microsoft

  3. fps - Frames per second of the written video stream.

  4. frameSize - Size of the video frames written to this video stream

  5. isColor - Always pass true to this argument


while (true)
{
    Mat frame;
    bool isSuccess = cap.read(frame); // read a new frame from the video camera 

    //Breaking the while loop if frames cannot be read from the camera
    if (isSuccess == false)
    {
        cout << "Video camera is disconnected" << endl;
        cin.get(); //Wait for any key press
        break;
    }

    /*
    Make changes to the frame as necessary
    e.g.  
     1. Change brightness/contrast of the image
     2. Smooth/Blur image
     3. Crop the image
     4. Rotate the image
     5. Draw shapes on the image
    */

    //write the video frame to the file
    oVideoWriter.write(frame); 

    //show the frame in the created window
    imshow(window_name, frame);

    //Wait for for 10 milliseconds until any key is pressed.  
    //If the 'Esc' key is pressed, break the while loop.
    //If any other key is pressed, continue the loop 
    //If any key is not pressed within 10 milliseconds, continue the loop 
    if (waitKey(10) == 27)
    {
        cout << "Esc key is pressed by the user. Stopping the video" << endl;
        break;
    }
}
In each iteration of the above while loop, the program performs following tasks.
  • Read a frame from the camera.
  • Write the frame to the file.
  • Display the frame in a window.
The while loop will break if the Esc key is pressed or the program fails to read a frame from the camera.

void write(const Mat& image)
Write the frame to the file. The size of the frame should be same as the size you specified during the initialization of the VideoWriter object.


//Flush and close the video file
oVideoWriter.release();
This function flushes and closes the video file. This function is also executed within the destructor the the VideoWriter object.


Summary


In this section, you have learnt how to 
  • Open the camera
  • Initialize the VideoWriter object
  • Read frames from the camera
  • Write frames to a file
  • Flush and close the video file


2 comments:

  1. Hi, many thanks to these nice tutorials! Is there a way to control the bitrate of the saved video? With your code I was able to read a video from disc, cut it into a desired length and save it to disc. But the saved video has a very high bitrate (799999 kbit/s), whereas the loaded video only has 18000 kbit/s..

    ReplyDelete
    Replies
    1. Try some other codecs
      1. VideoWriter::fourcc('P', 'I', 'M', '1') for MPEG-1
      2. VideoWriter::fourcc('M', 'J', 'P', 'G') for Motion JPEG
      3. VideoWriter::fourcc('M', 'P', '4', '2') for MPEG-4 variation of Microsoft

      Delete