菜鸟一枚,opencv移动侦测打开摄像头黑屏

Mario23 2015-10-24 05:49:18
先贴出一段网络上的代码
#include <stdio.h>
#include <time.h>
#include <cv.h>
#include <cxcore.h>
#include <highgui.h>

int main( int argc, char** argv )
{
//声明IplImage指针
IplImage* pFrame = NULL; //pFrame为视频截取的一帧
IplImage* pFrame1 = NULL; //第一帧
IplImage* pFrame2 = NULL;//第二帧
IplImage* pFrame3 = NULL;//第三帧

IplImage* pFrImg = NULL; //pFrImg为当前帧的灰度图
IplImage* pBkImg = NULL; //pBkImg为当前背景的灰度图
IplImage* pBkImgTran = NULL;//pBkImgTran为当前背景处理过的图像
IplImage* pFrImgTran = NULL;//pFrImgTran为当前背景处理过的图像

CvMat* pFrameMat = NULL; //pFrameMat为当前灰度矩阵
CvMat* pFrMat = NULL; //pFrMat为当前前景图矩阵,当前帧减去背景图
CvMat* bg1 = NULL;
CvMat* bg2 = NULL;
CvMat* bg3 = NULL;
CvMat* pFrMatB = NULL; //pFrMatB为二值化(0,1)的前景图
CvMat* pBkMat = NULL;
CvMat* pZeroMat = NULL; //用于计算bg1 - bg2 的值
CvMat* pZeroMatB = NULL;//用于计算 pZeroMat阈值化后来判断有多少个零的临时矩阵

CvCapture* pCapture = NULL;

int warningNum = 0; //检测到有异物入侵的次数
int nFrmNum = 0;//帧计数
int status = 0; //状态标志位

//创建窗口
cvNamedWindow("video", 1);
cvNamedWindow("background",1);//背景
cvNamedWindow("foreground",1);//前景
//使窗口有序排列
cvMoveWindow("video", 30, 0);
cvMoveWindow("background", 360, 0);
cvMoveWindow("foreground", 690, 0);

if ( argc > 2 )
{
fprintf(stderr, "Usage: bkgrd [video_file_name]\n");
return -1;
}

//打开摄像头 从摄像头取出码流可以使海康、大唐等网络或者模拟摄像头
if (argc ==2)
if ( !(pCapture = cvCaptureFromCAM(-1)))
{
fprintf(stderr, "Can not open camera.\n");
return -2;
}

//打开视频文件
if (argc == 1)
if ( !(pCapture = cvCaptureFromFile("MOV_0056.mp4")))
{
fprintf(stderr, "Can not open video file %s\n", "MOV_0056.mp4");
return -2;
}


//开始计时
time_t start,end;
time(&start); //time() 返回从1970年1月1号00:00:00开始以来到现在的秒数(有10为数字)。
printf("%d\n",start);
//逐帧读取视频
while (pFrame = cvQueryFrame( pCapture ))
{
nFrmNum++;
//如果是第一帧,需要申请内存,并初始化
if (nFrmNum == 1)
{

pBkImg = cvCreateImage(cvSize(pFrame->width, pFrame->height), IPL_DEPTH_8U,1);
pFrImg = cvCreateImage(cvSize(pFrame->width, pFrame->height), IPL_DEPTH_8U,1);
pBkImgTran = cvCreateImage(cvSize(pFrame->width,pFrame->height), IPL_DEPTH_8U,1);
pFrImgTran = cvCreateImage(cvSize(pFrame->width,pFrame->height), IPL_DEPTH_8U,1);

pBkMat = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1);
pZeroMat = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1);
pFrMat = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1);
pFrMatB = cvCreateMat(pFrame->height, pFrame->width, CV_8UC1);
pZeroMatB = cvCreateMat(pFrame->height, pFrame->width, CV_8UC1);
pFrameMat = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1);
cvZero(pZeroMat);
//转化成单通道图像再处理
cvCvtColor(pFrame, pBkImg, CV_BGR2GRAY);
//转换为矩阵
cvConvert(pFrImg, pBkMat);
}
else /* 不是第一帧的就这样处理 */
{
//pFrImg为当前帧的灰度图
cvCvtColor(pFrame, pFrImg, CV_BGR2GRAY);

//pFrameMat为当前灰度矩阵
cvConvert(pFrImg, pFrameMat);

//pFrMat为前景图矩阵,当前帧减去背景图
cvAbsDiff(pFrameMat, pBkMat, pFrMat);

//pFrMatB为二值化(0,1)的前景图
cvThreshold(pFrMat,pFrMatB, 60, 1, CV_THRESH_BINARY);

//将图像矩阵转化为图像格式,用以显示
cvConvert(pBkMat, pBkImgTran);
cvConvert(pFrMat, pFrImgTran);

//动态更新背景的方法 以0.1毫秒

cvRunningAvg(pFrameMat, pBkMat, 1, 0);

//将背景转化为图像格式,用以显示
cvConvert(pBkMat, pBkImg);



//显示图像
cvShowImage("video", pFrame);
cvShowImage("background", pBkImgTran); //显示背景
cvShowImage("foreground", pFrImgTran); //显示前景


//以上是每抓取一帧都要做的工作,下面进行危险检测
if (cvCountNonZero(pFrMatB) > 10000 && status == 0) //表示是第一帧的异物大于1W个像数点
{/* 则需要将当前帧存储为第一帧 */
pFrame1 = cvCloneImage(pFrame);
bg1 = cvCloneMat(pFrMat);
status = 1; //继续采集第2帧
}
else if (cvCountNonZero(pFrMatB) < 10000 && status == 1) // 表示第一帧的异物大于1W个像数点,而第二帧没有,则报警
{
printf("NO.%d warning!!!!\n\n",warningNum++);
status = 0;
}
else if (cvCountNonZero(pFrMatB) > 10000 && status == 1)// 表示第一帧和第二帧的异物都大于1W个像数点
{
pFrame2 = cvCloneImage(pFrame);
bg2 = cvCloneMat(pFrMat);

cvAbsDiff(bg1, bg2, pZeroMat);
cvThreshold(pZeroMat,pZeroMatB, 20, 1, CV_THRESH_BINARY);
if (cvCountNonZero(pZeroMatB) > 3000 ) //表示他们不连续,这样的话要报警
{
printf("NO.%d warning!!!!\n\n",warningNum++);
status = 0;
}
else
{
status = 2; //继续采集第3帧
}
}
else if (cvCountNonZero(pFrMatB) < 10000 && status == 2)//表示第一帧和第二帧的异物都大于1W个像数点,而第三帧没有
{
//报警
printf("NO.%d warning!!!!\n\n",warningNum++);
status = 0;
}
else if (cvCountNonZero(pFrMatB) > 10000 && status == 2)//表示连续3帧的异物都大于1W个像数点
{
pFrame3 = cvCloneImage(pFrame);
bg3 = cvCloneMat(pFrMat);

cvAbsDiff(bg2, bg3, pZeroMat);
cvThreshold(pZeroMat,pZeroMatB, 20, 1, CV_THRESH_BINARY);
if (cvCountNonZero(pZeroMatB) > 3000 ) //表示他们不连续,这样的话要报警
{
printf("NO.%d warning!!!!\n\n",warningNum++);
}
else //表示bg2,bg3连续
{
cvReleaseMat(&pBkMat);
pBkMat = cvCloneMat(pFrameMat); //更新背景
}
status = 0; //进入下一次采集过程
}

//如果有按键事件,则跳出循环
//此等待也为cvShowImage函数提供时间完成显示
//等待时间可以根据CPU速度调整
if ( cvWaitKey(2) >= 0 )
break;
}/* The End of the else */
}/* The End of th while */

//销毁窗口
cvDestroyWindow("video");
cvDestroyWindow("background");
cvDestroyWindow("foreground");

//释放图像和矩阵
cvReleaseImage(&pFrImg);
cvReleaseImage(&pBkImg);

cvReleaseMat(&pFrameMat);
cvReleaseMat(&pFrMat);
cvReleaseMat(&pBkMat);

cvReleaseCapture(&pCapture);

return 0;
}
我用的是opencv3.0,vs2012,系统的话win7和8都试过。每一次编译都能成功,也有跳出对话框来选择要开启的摄像头,但是每次打开后三个窗口都是黑屏的,没有影像,不知道是什么原因。求大家教教我!
...全文
800 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
loong460 2016-05-11
  • 打赏
  • 举报
回复
好像是win7的问题,换成xp试试。 从别的地方看到的一段话:“opencv默认的是采用VFW模块来进行相机通信的,VFW已经很老了,微软一直打算用directshow来替代它,win7里面,可能已经没有fvw模块了。” 或者用pCapture = cvCreateCameraCapture(0)
Mario23 2015-10-31
  • 打赏
  • 举报
回复
引用 2 楼 zhao4zhong1 的回复:
使用驱动精灵升级能升级的驱动。
试过了,并没有提示摄像头驱动。况且使用的是无驱动的摄像头。不知道还有什么好方法
赵4老师 2015-10-26
  • 打赏
  • 举报
回复
使用驱动精灵升级能升级的驱动。
Mario23 2015-10-26
  • 打赏
  • 举报
回复
求大神

64,282

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧