OpenCV & Virsual C++:从相机中保存帧数据,然后保存到 Jpg

Posted

技术标签:

【中文标题】OpenCV & Virsual C++:从相机中保存帧数据,然后保存到 Jpg【英文标题】:OpenCV & Virsual C++: save Frame data from Camera and then save to Jpg 【发布时间】:2011-02-08 21:09:55 【问题描述】:

我是 OpenCVC++ 初学者。我的学生项目有问题。我的导师想从相机中抓取帧并将抓取的帧保存为 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;

【问题讨论】:

【参考方案1】:

如果你使用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;

【讨论】:

Many Manythanks Etarion。现在我更清楚了。对不起,我忘了说我正在使用 Virtual C++,MFC。但它可以工作。如果有任何机会,你也知道如何修改原始风格中的代码?如何管理 IplImage 指针以避免重用每个帧的内存?再次感谢 Etarion,祝你有美好的一天!【参考方案2】:

您有多核/多 CPU 系统吗?然后,您可以将 1 秒的任务分摊到 16 核并节省 16 帧/秒!

或者您可以在 GPU 上使用 Cuda/OpenCL 编写自己的优化 jpeg 例程。

如果您需要它运行更长时间,您可以将原始图像数据转储到磁盘,然后再将其读回并转换为 jpeg。 5Mpixel * 3color * 10fps 是 150Mb/s(感谢 etarion!),您可以使用两个磁盘和 windows Raid 来做到这一点。

编辑:如果您只需要做 10 帧,那么只需将它们缓冲在内存中,然后按照其他答案所示将它们写出来。

【讨论】:

2500x2000 RGB8 是 150Mb/s,而不是 50 - 仍然可行,但“普通”驱动器会阻塞 - 我们使用 SSD 来完成这项任务(转储原始图像数据)(也因为我们的平台是移动,可能会振动)。 @etarion - 是的,我们转储了原始拜耳模式数据,因此只有一个字节/像素 - 然后将其读回并转换为颜色。我忘了!【参考方案3】:

由于您已经知道如何检索帧,请查看以下答案:

openCV: How to split a video into image sequence?

这个问题有点不同,因为它从 AVI 文件而不是网络摄像头中检索帧,但是将帧保存到磁盘的方法是相同的!

【讨论】:

如果您正在寻找将帧保存到视频文件中的方法,请检查:***.com/questions/3400908/… 为什么用错误的标签重新标记?显然不是 C - C 没有new 感谢 Karlphillip,它真的给我敲响了警钟! @etarion 如果您检查历史记录,C 标签已经存在。我决定保留他的原始标签并添加一些标签以帮助人们更轻松地找到这个问题。但感谢标记它 C++ 的人。 @etarion 抱歉,这是我的第一个问题,我没有检查 C 标签是自动生成的。我更改了它。

以上是关于OpenCV & Virsual C++:从相机中保存帧数据,然后保存到 Jpg的主要内容,如果未能解决你的问题,请参考以下文章

C++ & OpenCV 断言失败

OpenCV && C++ 03 - Save an Image to a File

如何在文件夹opencv&&qt c++中加载图像[关闭]

Microsoft Virsual 获取设备列表

C++ OpenCV:检测两行而不是一行(Canny & findContours)

C++ & OpenCV 零散学习总结