C++ MFC OPENCV 录制视频0KB或6KB cvCreateVideoWriter返回值为NULL

本文介绍如何使用OpenCV在Windows环境下实现摄像头视频的录制,并解决了cvCreateVideoWriter函数返回NULL及视频文件过大的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

近期由于需求需要做一个功能

打开摄像头 保存成一个视频

由于本人从来没有做过这一方面的东西,找了大量的资料和各种文章看了之后,决定用opencv来做 ,但是用了之后才发现后面的坑有点坑爹,坑爹,坑爹,重要的事情说三遍

本人用的  opencv 头文件,lib dll文件如下地址

https://download.youkuaiyun.com/download/immotal_xiaoqiang/10273752

本人编译环境VS2013 + win7 64位(联想笔记本G40) + opencv2413版本

其中如果下载了上面地址中的文件的话 环境需要配置

头文件需要包含 build\include

库文件 需要 build\x86\vc12

这里额外说下 vc9,vc10, vc11, vc12 分别表示VS2008,VS2010, VS2012, VS2013的Visual Studio使用的编译器版本

然后根据自己使用的是哪个vs包含哪个库,上面的下载地址中只有vs2012和vs2013的

下面放 源代码 

Function.h

#include <opencv2/core/core.hpp>  
#include <opencv2/highgui/highgui.hpp>  
#include <opencv2/imgproc/imgproc.hpp> 
#pragma  comment(lib,"opencv_core2413.lib")
#pragma  comment(lib,"opencv_highgui2413.lib")
#pragma  comment(lib,"opencv_imgproc2413.lib")

using namespace cv;
class CFunction
{

public:
CFunction();
~CFunction();
public:
//path-图片的路径 ,nCameraId摄像头的ID(0开始)  nIsShowWindow-是否显示窗口
int Open_Camera(char *path, int nCameraId, int nIsShowWindow);
int Close_Camera();
bool m_IsClose;

public:

};

#endif

 

Function.cpp

 

#include "stdafx.h"

#include "Function.h"

 

int g_nCameraID = 0;
BOOL g_IsClose;  //用于控制摄像头的关闭
int g_IsRet;   //用于控制打开摄像头错误后的返回
char *g_path;
int g_isShowWindow = 0; //是否显示窗口 0-不显示 1-显示
CFunction::CFunction()
{
g_IsClose = false;
g_IsRet = 0;
g_path = NULL;
};


CFunction::~CFunction()
{
}

UINT ThreadCamrea(LPVOID pParam)
{


CvCapture* m_capture = cvCaptureFromCAM(g_nCameraID);;
CvVideoWriter* m_video = NULL;
IplImage* m_frame = NULL;

int nRet = 0;
if (!m_capture) //如果不能打开摄像头给出警告
{ //打开摄像头失败
cvReleaseCapture(&m_capture);
g_IsRet = -1;
return -1;

}
else
{


m_frame = cvQueryFrame(m_capture); //首先取得摄像头中的一帧

            

//第一个参数是路径,第二个是编码,第三个参数应该是控制 录制的视频快慢  1速度最慢 值越大越快(播放的时候) 现在改为了15应该是差不多的,第四个是摄像头的大小
m_video = cvCreateVideoWriter(g_path, CV_FOURCC('D', 'I', 'V', 'X'), 15, cvSize(m_frame->width, m_frame->height)); //创建CvVideoWriter对象并分配空间

if (m_video) //如果能创建CvVideoWriter对象则表明成功
{//成功
}
else
{//失败
cvReleaseVideoWriter(&m_video);
cvReleaseCapture(&m_capture);
cvDestroyWindow("Camera Video");
g_IsRet = -1;
return -1;
}

if (g_isShowWindow)
{
cvNamedWindow("Camera Video", 1); //新建一个窗口
}


int i = 0;
while (1) // 让它循环
{
m_frame = cvQueryFrame(m_capture); //从CvCapture中获得一帧
if (!m_frame)
{//获取视频帧失败
cvReleaseVideoWriter(&m_video);
cvReleaseCapture(&m_capture);
cvDestroyWindow("Camera Video");
break;
}



cvWaitKey(10);


if (g_isShowWindow)
{
cvShowImage("Camera Video", m_frame); //显示视频内容的图片
}
nRet = cvWriteFrame(m_video, m_frame); //判断是否写入成功,如果返回的是1,表示写入成功


 
if (g_IsClose) //外部调用关闭摄像头
{
cvReleaseVideoWriter(&m_video);
cvReleaseCapture(&m_capture);
cvDestroyWindow("Camera Video");
break;
}
}
}
return nRet;
}
 

 

//打开摄像头

int CFunction::Open_Camera(char *path, int nCameraId, int nIsShowWindow)
{
if (path == NULL)
{
return -1;
}
g_path = path;
g_nCameraID = nCameraId;
g_isShowWindow = nIsShowWindow;
g_IsClose = false;
int nRet = 0;
g_IsRet = 0;
  CWinThread *pThread = AfxBeginThread(ThreadCamrea, NULL);
Sleep(3000);
  if (!pThread)
  {//线程创建失败
  return -1;
  }
  else
  {
// 线程创建成功
if (g_IsRet != 0)
{
return g_IsRet;
}
 
  }
return 1;


}

//关闭摄像头
int CFunction::Close_Camera()
{
int nRet = 0;

g_IsClose = true;
return nRet;

}

 

调用步骤  

调用 打开摄像头 Open_Camera("D:\\1.avi", 0,1);

 

遇到的问题:

cvCreateVideoWriter这个函数一直返回NULL 导致录制的视频是0KB

解决办法1:

把CV_FOURCC('D', 'I', 'V', 'X') 换成 1

m_video = cvCreateVideoWriter(g_path, CV_FOURCC('D', 'I', 'V', 'X'), 15, cvSize(m_frame->width, m_frame->height)); 

m_video = cvCreateVideoWriter(g_path, 1, 15, cvSize(m_frame->width, m_frame->height)); 

换成1之后 D:\1.avi是生成了,但是avi这个文件太大,大概是10秒的视频有100多M,很显然不符合项目中的需求

 

这就有了新的解决办法,从网上看了2天的资料有人说安装

 ffdshow编解码器,有人说安装ffmpeg编解码器,我安装了ffdshow然后并没有什么卵用

后来发现应该是少了DLL,真是坑爹

 

我原本的依赖DLL如下

opencv_highgui2413.dll

opencv_core2413.dll

 

后来发现少了一个DLL   opencv_ffmpeg2413.dll 后来才发现原来是少了这个DLL所以导致了cvCreateVideoWriter(g_path, CV_FOURCC('D', 'I', 'V', 'X'), 15, cvSize(m_frame->width, m_frame->height));  一直返回NULL,

 

加上opencv_ffmpeg2413.dll后 cvCreateVideoWriter也返回正常了,生成的avi文件1秒大概只有500KB左右,虽然还是有点不符合项目中的需求,但是现在暂时自己没有好的解决办法,如果后面找到好的解决办法,后面再补充

 

另外需要注意的是 while中 如果先写入视频在 调用cvShowImage的话 会造成摄像头打开正常 也能写入视频,但是摄像头打开的界面是灰色的

 

20190311 后续解决方法

录像过大问题 用H264解码器来操作 项目里面

m_video = cvCreateVideoWriter(g_path, CV_FOURCC('D', 'I', 'V', 'X'), 15, cvSize(m_frame->width, m_frame->height)); 

编码用'X', '2', '6', '4' 编码工具下载地址如下:https://download.youkuaiyun.com/download/immotal_xiaoqiang/11010927

测试下来大概是70KB/s的样子

2,opencv avi转mp4 问题

用ffmpeg.exe来进行转换  ------ ffmpeg.exe可以自行到百度去下载对应的32或者64位

命令为

D:\ffmpeg.exe -i D:\1.avi  D:\1.mp4 -y

解释为 D盘下面放的ffmpeg.exe 空格

-i (-i 是显示信息) 空格

D:\1.avi (需要转换的原始avi文件)空格

D:\1.mp4(需要转换出来mp4文件名称) 空格

-y (-y是)有时候用通过cmd调用ffmpeg命令后会提示-y/n 的提示 -y是去掉提示(个人猜测)

C++ 通过调用CMD命令来调用ffmpeg.exe后 用SHELLEXECUTEINFO可以等待转换完成后再返回

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值