Qt调用OpenCV实现录制视频文件中的几个问题

来源:互联网 发布:淘宝店铺装修图 编辑:程序博客网 时间:2024/06/02 17:09

这几天需要做一个视频文件录制功能。用Qt调用OpenCV代码搞定。

其中线程相关的过程省略不写,与CvVideoWriter生成的部分网上有很多,也省略不写。下面只记录这个写入单帧的函数:

第一版:

//ATTENTION: 调用来自另一线程bool ETVideoController::writeVideo(const ETVideoSource &source, QSize size, CvVideoWriter *pWriter){    QImage img(source.getOneFrame());    // pImageWrite与img共享内存    IplImage* pImageWrite = cvCreateImageHeader(        cvSize(size.width(), size.height()), 8, 3);    pImageWrite->imageData = reinterpret_cast<char*>(img.bits());    cvCvtColor(pImageWrite, pImageWrite, CV_RGB2BGR);    // 写入一帧    cvWriteFrame(pWriter, pImageWrite);    cvReleaseImageHeader(&pImageWrite);    return true;}

这一版本的代码没有考虑到输入的源图像非24位图的情况,也没有考虑到输入的源图像与视频大小不一致的情况。所以录制后的视频出现了花屏的情况。为改善这一问题,我把代码改成了如下形式:

第二版:

//ATTENTION: 调用来自另一线程bool ETVideoController::writeVideo(const ETVideoSource &source, QSize size, CvVideoWriter *pWriter){    // 将图像预先转化成24位    QImage img(source.getOneFrame().convertToFormat(QImage::Format_RGB888));    img = img.scaled(size);    // pImageWrite与img共享内存    IplImage* pImageWrite = cvCreateImageHeader(        cvSize(size.width(), size.height()), 8, 3);    pImageWrite->imageData = reinterpret_cast<char*>(img.bits());    cvCvtColor(pImageWrite, pImageWrite, CV_RGB2BGR);    // 写入一帧    cvWriteFrame(pWriter, pImageWrite);    cvReleaseImageHeader(&pImageWrite);    return true;}

其中cvWriteFrame函数在调用时发生内存错误。上网各种搜索,没有找到有用的答案,初步判断因为img对象在其复制构造函数、赋值运算符调用的过程中,Qt执行的是浅复制,而对于Qt来说,它会自动判断在需要深复制的时候再进行一次深复制以使它们看起来像完全不同的对象一样。Qt这种机制使得OpenCV访问了非法的内存地址,所以造成内存出错。于是,我将代码改成了最终的版本

第三版:

//ATTENTION: 调用来自另一线程bool ETVideoController::writeVideo(const ETVideoSource &source, QSize size, CvVideoWriter *pWriter){    QImage img = source.getOneFrame();    QImage imgDest(size, QImage::Format_RGB888); // 创建一个新图片,使用指定的大小和24位格式        {        QPainter p(&imgDest); // 使用QPainter描画图片        p.drawImage(imgDest.rect(), img);    } // 析构    // pImageWrite与img共享内存    IplImage* pImageWrite = cvCreateImageHeader(        cvSize(size.width(), size.height()), 8, 3);    pImageWrite->imageData = reinterpret_cast<char*>(imgDest.bits());    cvCvtColor(pImageWrite, pImageWrite, CV_RGB2BGR);    // 写入一帧    cvWriteFrame(pWriter, pImageWrite);    cvReleaseImageHeader(&pImageWrite);    return true;}


Painter p外面的大括号是不可以省略的,因为我们利用在右大括号}处自动调用p的析构函数的特性。经调试,上述代码可以正常运行。


(■版权声明: 原创内容,转载仅限非商业用途,并需注明出处: http://blog.csdn.net/LoveASPDotNet)



原创粉丝点击