OpenCV & Virsual C ++: сохранить данные кадра с камеры, а затем сохранить в формате JPG - PullRequest
2 голосов
/ 09 февраля 2011

Я OpenCV и C ++ новичок. У меня проблема с моим студенческим проектом. Мой репетитор хочет взять кадры с камеры и сохранить полученные кадры в jpg. Итак, сначала я использовал "cvCreateCameraCapture,cvQueryFrame,cvSaveImage", и все было в порядке. Но кадр относительно большой, около 2500x2000, и для сохранения одного кадра требуется около 1 секунды. Но моему репетитору требуется, по крайней мере, сохранять 10 кадров в секунду.

Затем у меня появились идеи сначала сохранить исходные данные, и после процесса захвата я могу сохранить их в Jpg. Поэтому я написал следующий тестовый код. Но проблема в том, что все сохраненные изображения одинаковы, и кажется, что они просто взяты из данных последнего захваченного фрейма. Я думаю, проблема в моих плохих знаниях c ++, особенно указателей. очень надеюсь получить помощь здесь.

Заранее спасибо!

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;
}

Ответы [ 3 ]

1 голос
/ 09 февраля 2011

Если вы используете C ++, почему бы вам не использовать интерфейс C ++ opencv? Причина, по которой вы получаете N раз одно и то же изображение, заключается в том, что при захвате повторно используется память для каждого кадра, если вы хотите сохранить кадры, вам необходимо их скопировать. Пример для интерфейса C ++:

#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;
}
0 голосов
/ 09 февраля 2011

Поскольку вы уже знаете, как извлечь кадр, проверьте ответ:

openCV: Как разделить видео на последовательность изображений?

Этот вопрос немного отличается, поскольку он извлекает кадры из файла AVI вместо веб-камеры, но способ сохранить кадр на диск тот же!

0 голосов
/ 09 февраля 2011

Есть ли у вас многоядерная / многопроцессорная система? Тогда вы можете выполнить 1-секундные задачи на 16 ядрах и сэкономить 16 кадров в секунду!

Или вы можете написать свою собственную оптимизированную подпрограмму jpeg на GPU в Cuda / OpenCL.

Если вам нужно, чтобы он работал дольше, вы можете записать необработанные данные изображения на диск, затем прочитать их позже и преобразовать в формат JPEG. 5Mpixel * 3color * 10fps - это 150Mb / s (спасибо etarion!), Что вы можете сделать с двумя дисками и окнами Raid.

edit: Если вам нужно только сделать 10 кадров, просто поместите их в буфер и запишите их, как показывает другой ответ.

...