2

I am an OpenCV and C++ beginner. I've got a problem with my student project.My Tutor wants to grab frames from a Camera and save the grabbed frames into jpg. So first I used "cvCreateCameraCapture,cvQueryFrame,cvSaveImage" and it worded ok. But the frame is relative big,about 2500x2000,and it takes about 1 second to save one Frame. But my Tutor requires at least to save 10 Frames per second.

Then I came out the ideas to save raw data first and after grabbing process I can save them into Jpg. So I wrote following test code.But the problem is that all the saved Images are the same and it seems they are just from the data of the last grabbed frame.I guess the problem is about my poor knowledge of c++ especially pointers.So I really hope to get help here.

Thanks in advance!

void COpenCVDuoArryTestDlg::OnBnClickedButton1()
{
IplImage* m_Frame=NULL;
TRACE("m_Frame initialed");
CvCapture * m_Video=NULL;
m_Video=cvCreateCameraCapture(0);
IplImage**Temp_Frame= (IplImage**)new IplImage*[100]; 
for(int j=0;j<100;j++){

Temp_Frame[j]= new IplImage [112];

}
TRACE("Tempt_Frame initialed\n");

cvNamedWindow("video",1);
int t=0;

while(m_Frame=cvQueryFrame(m_Video)){ 

    for(int k=0;k<m_Frame->nSize;k++){
Temp_Frame[t][k]= m_Frame[k];

    }

cvWaitKey(30);
t++;

if(t==100){
break;
}

}


for(int i=0;i<30;i++){
CString ImagesName;

ImagesName.Format(_T("Image%.3d.jpg"),i);

if(cvWaitKey(20)==27) {
break;
}
else{

cvSaveImage(ImagesName, Temp_Frame[i]);

}    
}    

cvReleaseCapture(&m_Video);
cvDestroyWindow("video");
TRACE("cvDestroy works\n");

delete []Temp_Frame;
}
Jav_Rock
  • 22,059
  • 20
  • 123
  • 164
Xisanyi
  • 49
  • 1
  • 7

3 Answers3

1

If you use C++, why don't you use the C++ opencv interface? The reason you get N times the same image is that the capture reuses the memory for each frame, if you want to store the frames you need to copy them. Example for the C++ interface:

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

using namespace cv;

int main(int, char**)
{
    VideoCapture cap(0); // open the default camera
    if(!cap.isOpened())  // check if we succeeded
        return -1;

    Mat edges;
    namedWindow("image",1);
    std::vector<cv::Mat> images(100);
    for(int i = 0; i < 100;++i) { 
        // this is optional, preallocation so there's no allocation
        // during capture
        images[i].create(480, 640, CV_8UC3);
    }
    for(int i = 0; i < 100;++i)
    {
        Mat frame;
        cap >> frame; // get a new frame from camera
        frame.copyTo(images[i]);
    }
    cap.release();
    for(int i = 0; i < 100;++i)
    {
        imshow("image", images[i]);
        if(waitKey(30) >= 0) break;
    }
    // the camera will be deinitialized automatically in VideoCapture destructor
    return 0;
}
etarion
  • 16,935
  • 4
  • 43
  • 66
  • Many Manythanks Etarion.Now I got more clear.and sorry I forgot to metion that I am using Virtual C++ ,MFC.But it works.If by any chance,do you also know how to modify the code in the original fasion?How I manage the IplImage pointers to avoid reusing the memory for each frames? Thanks again Etarion and I wish you a good day there! – Xisanyi Feb 09 '11 at 12:54
0

Do you have a multicore/multiple CPU system? Then you could farm out the 1second tasks across 16cores and save 16frames/second !

Or you could write your own optimized jpeg routine on the GPU in Cuda/OpenCL.

If you need it to run for longer you could dump the raw image data to disk, then read it back in later and convert to jpeg. 5Mpixel * 3color * 10fps is 150Mb/s (thanks etarion!) which you can do with two disks and windows Raid.

edit: If you only need to do 10frames then just buffer them in memory and then write them out as the other answer shows.

Martin Beckett
  • 94,801
  • 28
  • 188
  • 263
  • 2500x2000 RGB8 is 150Mb/s, not 50 - still doable, but "normal" drives will choke on that - we use SSDs for this task (dumping out raw image data) (also because our platform is mobile and might be vibrating). – etarion Feb 08 '11 at 22:58
  • @etarion - Yes we dump the raw Bayer pattern data so only one byte/pixel - then read it back in and convert to color. I forgot! – Martin Beckett Feb 08 '11 at 23:17
0

Since you already know how to retrieve a frame, check this answer:

openCV: How to split a video into image sequence?

This question is a little different because it retrieves frames from an AVI file instead of a webcam, but the way to save a frame to the disk is the same!

Community
  • 1
  • 1
karlphillip
  • 92,053
  • 36
  • 243
  • 426
  • And if you are searching for a way to save the frames into a video file, check this: http://stackoverflow.com/questions/3400908/how-to-save-output-video-into-a-file-in-opencv/3402114#3402114 – karlphillip Feb 09 '11 at 12:53
  • Why do you retag with wrong tags? It's obviously not C - C doesn't have `new`. – etarion Feb 09 '11 at 13:01
  • Thanks Karlphillip,it really rings bell to me! – Xisanyi Feb 09 '11 at 13:20
  • @etarion If you check the history the C tag was already there. I decided to preserve his original tag and added some to help people find this question more easily. But thanks to whoever tagged it C++. – karlphillip Feb 09 '11 at 13:33
  • @etarion sorry,it was my first question,and I did not check the C tag was automaticly generated.I changed it. – Xisanyi Feb 09 '11 at 14:00