响应式手机网站怎么做/在百度上怎么发布信息
近期由于需求需要做一个功能
打开摄像头 保存成一个视频
由于本人从来没有做过这一方面的东西,找了大量的资料和各种文章看了之后,决定用opencv来做 ,但是用了之后才发现后面的坑有点坑爹,坑爹,坑爹,重要的事情说三遍
本人用的 opencv 头文件,lib dll文件如下地址
https://download.csdn.net/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.csdn.net/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可以等待转换完成后再返回