MFC+Opencv3 摄像头读取+灰度直方图+帧数对比

本文介绍如何使用MFC在VS中创建一个对话框程序,实现实时摄像头监控及灰度图像直方图显示。通过C++编程,文章详细展示了初始化过程、摄像头帧读取、图像处理及灰度直方图绘制等步骤。

1.在vs下创建一个基于对话框的MFC程序。

布局如下图

2.进行初始化

在C***Dlg类中的OnInitDialog()函数中添加如下代码

                        

        CWnd  *pWnd1 = GetDlgItem(IDC_PIC1);     //获取显示摄像头画面的窗口类(参数为控件ID)
        CWnd  *pWnd2 = GetDlgItem(IDC_PIC2);      //获取显示直方图的窗口类
        pWnd1->GetClientRect(&rect1);            //GetClientRect为获得控件自身的坐标大小
	pWnd2->GetClientRect(&rect2);            
	namedWindow("gray", WINDOW_AUTOSIZE);        //设置灰度图显示的窗口名  
	namedWindow("src", WINDOW_AUTOSIZE);         //设置画面显示窗口名
	HWND hWndl = (HWND)cvGetWindowHandle("src");    //hWnd 表示窗口句柄,获取窗口句柄
	HWND hWnd2 = (HWND)cvGetWindowHandle("gray");
	HWND hParent1 = ::GetParent(hWndl);             //GetParent函数获取子窗口的父窗口句柄
	HWND hParent2 = ::GetParent(hWnd2);
	::SetParent(hWndl,pWnd1->m_hWnd);                //设置窗口的父类,也就是将两个窗口与两个控件绑定在一起
	::SetParent(hWnd2, pWnd2->m_hWnd);
	capture.open(0);                              //打开默认摄像头
	capture >> frame;                               //获取第一帧
	resize(frame, frame, Size(rect1.Width(), rect1.Height()));      //调节大小与控件大小一致
	::ShowWindow(hParent1, SW_HIDE);   //隐藏两窗口的父窗口,如不隐藏,将会显示两个窗口,这个原因有待大神讲解
	::ShowWindow(hParent2, SW_HIDE);
	imshow("src", frame);          //在对话框中显示窗口
	cvtColor(frame, frame,COLOR_RGB2GRAY);      //转为灰度图
	grayHist(frame);                  //绘制灰度图,并显示
然后对上面的一些变量在类中做出声明,全部为public

        static BOOL isClose;              //程序是否结束
VideoCapture capture;         //视频类
Mat frame, next;                    //用于显示的帧数
CRect rect1,rect2;                 //控件大小
int Max;                                   //获取两帧灰度图变化的最大值
void grayHist(Mat src);          //灰度图的显示
void frameVar(Mat src,Mat next);         //获取两帧灰度图变化的最大值
CString m_diff;                             //这个变量和static text绑定在一起,用于显示变化的最大值

afx_msg void OnBnClickedButton1();      //按钮的消息
afx_msg void OnClose();                            //关闭按钮的消息,用于结束循环

按钮消息的实现 OnBnClickedButton1()

while (!isClose)          //isClose用于判断是否结束
	{
		capture >> next;      //获取每一帧
		resize(next, next, Size(rect1.Width(), rect1.Height()));  //图片缩放为与控件同样大
		frameVar(frame, next);            //获取两帧图像灰度变化最大的差值
		next.copyTo(frame);                //frame代表上一帧,next下一帧
		m_diff.Format(_T("%d"), Max);          //将值输入static text 文本
		UpdateData(FALSE);                    //进行更新,将变量值传入控件
		imshow("src", frame);                 //显示图片至文本
		cvtColor(frame, frame, COLOR_RGB2GRAY);        //转为灰度图
		grayHist(frame);               //绘制灰度图,并显示到控件
		waitKey(30);                 //每30ms一帧
	}
关闭按钮消息的实现 OnClose()

                      isClose=TRUE;     //结束循环

灰度直方图的绘制 grayHist(Mat src)

	int arryNum = 1;
	const int channels[] = { 0 };
	int dims = 1;
	const int histSize = 256;
	float hranges[] = { 0,256 };
	const float *ranges[] = { hranges };
	Mat dstHist;
	calcHist(&src, arryNum, channels, Mat(), dstHist, dims, &histSize, ranges);
	double maxValue = 0;
	minMaxLoc(dstHist, NULL, &maxValue, 0, 0);
	Mat dstImage(Size(histSize+10, histSize), CV_8UC1, Scalar(255));
	for (int i = 0; i < histSize; ++i)
	{
		int realValue = saturate_cast<int>(dstHist.at<float>(i, 0)*0.9*histSize / maxValue);
		line(dstImage, Point(i * 1+5, histSize - 10), Point(i * 1+5, histSize - 10 - realValue), Scalar(88, 100, 52), 1, 4);
	}
	resize(dstImage, dstImage, Size(rect2.Width(), rect2.Height()));
	imshow("gray", dstImage); 
求差值frameVar(Mat src,Mat next)
	Max = 0;
	Mat diff = Mat(src.rows, src.cols, CV_8UC1);
	int width = src.cols;
	int height = src.rows;
	for (int i = 0; i < height; ++i)
	{
		uchar *data1 = src.ptr<uchar>(i);
		uchar *data2 = next.ptr<uchar>(i);
		uchar *data3 = diff.ptr<uchar>(i);
		for (int j = 0; j < width; ++j)
		{
			data3[j] = fabs(data1[j] -data2[j]);
		}
	}
	for (int i = 0; i < height; ++i)
	{
		uchar *data = diff.ptr<uchar>(i);
		for (int j = 0; j < width; ++j)
		{
			if ((int)data[j] > Max)
				Max = data[j];
		}
	}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值