i1000123
i1000123

Reputation: 83

Displaying video using vector<Mat> not working proplerly

I am trying to display video for in a separate function for this i am using vector i push_back each frame in and then pass this vector to function but my function displays a single frame repetitively. My code is below. Please tell me what i am doing wrong.

// newproject.cpp : Defines the entry point for the console application.

#include "stdafx.h"
#include "highgui.h"
#include <stdio.h>
#include <cv.h>
#include <highgui.h>
#include <stdio.h>
#include <conio.h>
#include <opencv2/imgproc/imgproc.hpp>  // Gaussian Blur
#include <opencv2/core/core.hpp>        // Basic OpenCV structures (cv::Mat, Scalar)
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include <conio.h>

using namespace cv;
using namespace std;

class frameprocessing{

Mat hsv_base;
MatND hist_base;

public:
    void hsv_histogram(Mat Frame)
    {
        cvtColor( Frame, hsv_base, CV_BGR2HSV );
        int h_bins = 50; 
        int s_bins = 32;
        int histSize[] = { h_bins, s_bins };

        float h_ranges[] = { 0, 256 };
        float s_ranges[] = { 0, 180 };

        const float* ranges[] = { h_ranges, s_ranges };
        int channels[] = { 0, 1 };
        calcHist( &hsv_base, 1, channels, Mat(), hist_base, 2, histSize, ranges, true, false );
    }
};

class video{    

    Mat frame;
    string filename;
    double dWidth;
    double dHeight;

public:
    video()
    {

    }

    video(string videoname)
    {

        vector<Mat> videoframes;
        std::vector<Mat>::iterator it;
        it = videoframes.begin();
        filename = videoname;
        VideoCapture capture(filename); 
        if( !capture.isOpened() )
        {
            exit(0);
        }
        dWidth   = capture.get(CV_CAP_PROP_FRAME_WIDTH); //get the width of frames of the video
        dHeight = capture.get(CV_CAP_PROP_FRAME_HEIGHT); //get the height of frames of the video

        frameprocessing obj;

        for( ; ; )
        {
            capture >> frame;
            if(frame.empty())
                break;

            obj.hsv_histogram(frame);
            videoframes.push_back(frame);
        }
        displayvideo(videoframes);
    //  waitKey(0); // key press to close window
    }

    void writer()
    {
        Size frameSize(static_cast<int>(dWidth), static_cast<int>(dHeight));
        VideoWriter oVideoWriter ("D:/MyVideo.avi", CV_FOURCC('P','I','M','1'), 20, frameSize, true); //initialize the VideoWriter object 
        if ( !oVideoWriter.isOpened() ) //if not initialize the VideoWriter successfully, exit the program
        {
            cout << "ERROR: Failed to write the video" << endl;
            exit(0);
        }
    }
    void displayvideo(vector<Mat> videoframe)
    {
        Mat tempframe;
        while(!videoframe.empty()) //Show the image captured in the window and repeat
        {
            tempframe = videoframe.back();
            imshow("video", tempframe);
            videoframe.pop_back();
            waitKey(20); // waits to display frame
        }
    //  waitKey(0);
    }

    void displayframe(Mat frame)
    {
        imshow("video", frame);
        waitKey(20); // waits to display frame
    }
};

int _tmain(int argc, _TCHAR* argv[])
{
    video obj("video.avi");
    //obj.readvideo();
}

Upvotes: 0

Views: 299

Answers (1)

Haris
Haris

Reputation: 14043

You need to copy or clone your frame to another Mat then push to your vector, change your code like

        for( ; ; )
          {    
            capture >> frame;
            if(frame.empty())
                break;

            Mat tmp=frame.clone();
            obj.hsv_histogram(tmp);
            videoframes.push_back(tmp);
           }

In your code your passing the same pointer allocated for frame to your vector every time, so you will get array of Mat pointing single(same) memory location in your vector. To know more about OpenCV Mat and memory allocation See documantation

Upvotes: 1

Related Questions