MFC&Halcon之实时视频监控
上一篇实现了在MFC的窗体内显示图片,本篇介绍如何在MFC窗体内实时显示摄像头的影像。
要实现的功能是点击一个“开始”按钮,可以显示影像,再点击“停止”按钮,可以停止显示。
因为实时显示影像需要在一个循环里执行,为了在显示影像的同时还可以干别的(比如,点击“停止”按钮),这里需要用到多线程,即显示影像的代码放到子线程中,与主线程并发执行。
重点已经说清楚了,下面是开发步骤:
1、先把Halcon中实时显示的程序搞定
2、Halcon代码导出为C++代码
3、建立MFC工程
4、在MFC中添加Halcon代码
下面说细节:
1、打开Halcon,点击助手,选择打开新的Acquisition
从资源选项卡可以看到检测到的接口为DirectShow,这是微软开发的视频设备驱动。
从连接选项卡能看到检测到相机,是笔记本自带的摄像头。点击上方的摄像机图标,Halcon的图形窗口就开始实时显示摄像头的画面了,很方便。
下面点击“代码生成”选项卡,点击“插入代码”按钮,就把实时显示的代码插入到代码窗口中了。
注意这里的采集模式是异步采集,在循环中采集图像的意思就是实时显示。
生成的Halcon代码如下:
* Image Acquisition 01: Code generated by Image Acquisition 01
open_framegrabber ('DirectShow', 1, 1, 0, 0, 0, 0, 'default', 8, 'rgb', -1, 'false', 'default', '[0] Integrated Camera', 0, -1, AcqHandle)
grab_image_start (AcqHandle, -1)
while (true)
grab_image_async (Image, AcqHandle, -1)
* Image Acquisition 01: Do something
endwhile
close_framegrabber (AcqHandle)
2、导出Halcon代码
导出的C++代码中Action函数如下:
void action()
{
// Local iconic variables
HObject ho_Image;
// Local control variables
HTuple hv_AcqHandle;
//Image Acquisition 01: Code generated by Image Acquisition 01
OpenFramegrabber("DirectShow", 1, 1, 0, 0, 0, 0, "default", 8, "rgb", -1, "false",
"default", "[0] Integrated Camera", 0, -1, &hv_AcqHandle);
GrabImageStart(hv_AcqHandle, -1);
while (0 != 1)
{
GrabImageAsync(&ho_Image, hv_AcqHandle, -1);
//Image Acquisition 01: Do something
}
CloseFramegrabber(hv_AcqHandle);
}
这就是我们需要添加到MFC的代码,需要注意到while循环中只是获取了图像,并没有显示图像,所以我们还要添加显示图像的代码。
3、建立MFC工程
与上一篇类似,新建基于对话框的MFC项目,添加Picture Control 和两个按钮。
4、添加C++代码
首先打开对话框类的头文件HalconCameraDlg.h,需要做下面四件事:
1、在文件开头添加Halcon头文件以及命名空间
#include "halconcpp.h"
using namespace HalconCpp;
2、在类外添加线程函数的声明
//线程函数的声明应在类CMultiThread1Dlg的外部
void ThreadFunc(LPVOID lpParam);
3、在类内添加Halcon变量为对话框类的Public成员
HObject ho_Image;
HTuple hv_AcqHandle;
HTuple m_HWindowID;
HTuple m_FGHandle,m_ImageWidth,m_ImageHeight;
4、添加线程函数的变量为对话框类的Protected成员
HANDLE hThread;
DWORD ThreadID;
然后在HalconCameraDlg.cpp中添加代码:
1、首先添加Halcon头文件和命名空间,并定义全局变量
volatile BOOL m_bRun;
volatile BOOL m_bShowFlag;
Volatile关键词告诉编译器不对此变量进行优化,使该值可被多个线程修改,对于多线程意义重大。
2、为开始按钮添加单机响应函数
CWnd * pWnd = AfxGetApp()->GetMainWnd();
if(m_bShowFlag){
m_bRun=TRUE;
}else{
hThread = CreateThread(NULL,
0,
(LPTHREAD_START_ROUTINE) ThreadFunc, //
this, //传入主窗口指针
0,
&ThreadID );
}
为了能随时停止和开始实时监控,我设置了m_bShowFlag这个变量,第一次点击“开始”按钮时,m_bShowFlag为FALSE,执行CreateThread函数启动子线程,在子线程中m_bShowFlag被置为TRUE,所以下次点击“开始”按钮时不会再次开启子线程,而只是修改线程中的标志位来启动实时监控。
3、子线程函数的实现代码
void ThreadFunc(LPVOID pParam)
{
CHalconCameraDlg * pMainWindow;
pMainWindow=(CHalconCameraDlg * ) pParam; //强制转化为主窗口指针
HTuple HWindowID;
CRect Rect;
CWnd * pWnd = pMainWindow->GetDlgItem( IDC_STATIC);
HWindowID = (Hlong)pWnd->m_hWnd;
pWnd->GetWindowRect(&Rect);
OpenWindow(0,0,Rect.Width(),Rect.Height(),HWindowID,"visible","",&(pMainWindow->m_HWindowID) );
//显示相机捕捉的图像
OpenFramegrabber("DirectShow", 1, 1, 0, 0, 0, 0, "default", 8, "rgb", -1, "false",
"default", "[0] Integrated Camera", 0, -1, &(pMainWindow->hv_AcqHandle) );
GrabImageStart(pMainWindow->hv_AcqHandle, -1);
ClearWindow(pMainWindow->m_HWindowID);
GrabImage(&(pMainWindow->ho_Image), pMainWindow->hv_AcqHandle);
GetImagePointer1((pMainWindow->ho_Image),NULL,NULL,&(pMainWindow->m_ImageWidth),&(pMainWindow->m_ImageHeight) );
SetPart(pMainWindow->m_HWindowID,0,0,pMainWindow->m_ImageHeight-1,pMainWindow->m_ImageWidth-1);
m_bShowFlag=TRUE;//设置运行状态
m_bRun=TRUE;
while (m_bShowFlag){
if(m_bRun){
GrabImageAsync(&(pMainWindow->ho_Image), pMainWindow->hv_AcqHandle, -1);
DispObj(pMainWindow->ho_Image, pMainWindow->m_HWindowID);
Sleep(50);
}
}
ClearWindow(pMainWindow->m_HWindowID);
CloseFramegrabber(pMainWindow->hv_AcqHandle);
CloseWindow(pMainWindow->m_HWindowID);
ExitThread(0);
} while循环之前的代码与上一篇类似,循环中当m_bRun为TRUE时执行获取与显示图像的语句,因此当全局变量m_bRun被置为FALSE时显示会停止,实现了前述的功能(注意,此时线程并不退出)。
4、停止按钮的响应函数
只需要一句话就够了。因为m_bRun被声明为volatile变量,在子线程外部可以更改它,修改为FALSE之后子线程中实时显示的语句就无法执行,表现出来就是图像静止,不再更新。
m_bRun=FALSE;
遇到的问题:
在这个程序中,子线程一直没有退出,即m_bShowFlag没有被置为FLASE。
之前我试过在停止按钮里把m_bShowFlag置为FALSE,即让线程退出,然后再次点击开始按钮时重新启动线程,但是在关闭窗口时会出现下面的错误。
触发了一个断点。其原因可能是堆被损坏。原因也可能是用户在HalconCamera.exe具有焦点时按下了F12。
这个错误可能是退出线程时没有把空间释放干净所致,在多次的开启与关闭子线程(即多次点击开始和停止按钮)后,就会出现问题。
所以只能改为现在的线程不退出方案,让子线程一直执行,通过修改其中的标志位来启动和停止显示。
MFC&Halcon之实时视频监控的更多相关文章
- MFC&Halcon之图片显示
上一篇介绍了MFC调用Halcon功能的简单例子,在这个例子中,点击按钮会弹出一个窗口显示图片,但是这样显示并不美观,而且...于是我决定把显示窗口做在MFC的窗体内部. 具体的方案是:使用一个Pic ...
- 【嵌入式开发】树莓派h264实时视频监控
FishXX之前用VLC串流输出视频,在电脑上需要VLC播放器.试了一下,感觉还是有点延时. 今天发现一个更加流畅,也不需要VLC播放器的树莓派远程视频监控方法,直接在浏览器中打开即可. 地址:htt ...
- linux下motion摄像头监控编译与配置
利用linxu下的开源的motion搭建嵌入式视频动态监控系统 所谓移动图像监测,简单来说就是利用摄像头定点监测某个区域,当有移动物体经过时,摄像头便自动抓拍(要监测多大物体.按拍照速率都是可调的), ...
- c# 远程监控(1) 大纲
此篇文章主要讲了如何使用C# Winform程序模拟一个远程监控系统,并使用RTP实时传输协议传输数据. 应用场景:远程监控.局域网视频会议.客户端流式缓冲播放 这方面的资料还是有一些,但是都需要整合 ...
- Raspberry Pi + 3个USB摄像头 + Motion(简易监控设备配置记录1——介绍以及安装) 分类: Raspberry Pi 服务器搭建 2015-04-12 19:21 226人阅读 评论(0) 收藏
参考: Debian官网链接 Motion官网链接 首先,参见Debian官网链接对Motion的介绍,网页中包含了所有相关依赖包,请首先确保这些依赖包的安装. Motion介绍 摘出对Motion的 ...
- 13行代码实现:Python实时视频采集(附源码)
一.前言 本文是<人脸识别完整项目实战>系列博文第3部分:程序设计篇(Python版),第1节<Python实时视频采集程序设计>,本章内容系统介绍:基于Python+open ...
- 基于Spring4+SpringMVC4+Mybatis3+Hibernate4+Junit4框架构建高性能企业级的部标1077视频监控平台
开发企业级的部标GPS监控平台,投入的开发力量很大,开发周期也很长,选择主流的开发语言以及成熟的开源技术框架来构建基础平台,是最恰当不过的事情,在设计之初就避免掉了技术选型的风险,避免以后在开发过程中 ...
- 基于C#和Asp.NET MVC开发GPS部标视频监控平台
基于C#和Asp.NET MVC开发GPS部标监控平台 目前整理了基于.NET技术的部标平台开发文章,可以参考: 1.部标Jt808协议模拟终端的设计和开发 2.C#版的808GPS服务器开发-> ...
- GIS和视频监控的集成
本文讨论了使用增强现实(AR)技术的三维(3D)地理信息系统(GIS)和视频监视系统的集成.进行这种集成的动机是要克服常规视频监视系统面临的问题.关于哪个摄像机当前监视此类系统中哪个区域的明确信息:因 ...
随机推荐
- Asp.net Boilerplate源码中NotNullAttribute的用处
看Asp.net Boilerplate 1.1.3.0源码时发现有一个NotNullAttribute的定义和27处的引用,就是不知道它的作用,当然顾名思义是可以的,就是不知道它是怎么判断的,在哪里 ...
- iOS可视化动态绘制八种排序过程
前面几篇博客都是关于排序的,在之前陆陆续续发布的博客中,我们先后介绍了冒泡排序.选择排序.插入排序.希尔排序.堆排序.归并排序以及快速排序.俗话说的好,做事儿要善始善终,本篇博客就算是对之前那几篇博客 ...
- favicon.ioc使用以及注意事项
1.效果 2.使用引入方法 2.1 注意事项:(把图标命名为favicon.ico,并且放在根目录下,同时使用Link标签,多重保险) 浏览器默认使用根目录下的favicon.ico 图标(如果你并没 ...
- SQL Server-聚焦NOT IN VS NOT EXISTS VS LEFT JOIN...IS NULL性能分析(十八)
前言 本节我们来综合比较NOT IN VS NOT EXISTS VS LEFT JOIN...IS NULL的性能,简短的内容,深入的理解,Always to review the basics. ...
- iOS架构一个中型普通App的一些经验总结
这一版比较完善的的App终于提交审核了.有时间写写自己的一些经验的总结了.自己主导的从0到比较成型的app到目前来说也只有两个,但是其中的很多东西都是大同小异.基本上是想到了什么就写什么,感觉写的不到 ...
- 代码的坏味道(18)——依恋情结(Feature Envy)
坏味道--依恋情结(Feature Envy) 特征 一个函数访问其它对象的数据比访问自己的数据更多. 问题原因 这种气味可能发生在字段移动到数据类之后.如果是这种情况,你可能想将数据类的操作移动到这 ...
- angular2之前端篇—1(node服务器分支)
上一篇.net core和angular2之前端篇-1 使用的是dotnet模板.之所以用它,因为想用他写webapi,但是写道下一篇的时候遇到点问题,所以先写个分支测试一下.这次是用Node作为服务 ...
- iOS之判断手机号码、邮箱格式是否正确
//判断手机号码格式是否正确 + (BOOL)valiMobile:(NSString *)mobile{ mobile = [mobile stringByReplacingOccurren ...
- Android中实现APP文本内容的分享发送与接收方法简述
谨记(指定选择器Intent.createChooser()) 开始今天的内容前,先闲聊一下: (1)突然有一天头脑风暴,对很多问题有了新的看法和见解,迫不及待的想要分享给大家,文档已经写好了,我需要 ...
- IOS开发基础知识--碎片51
1:https关闭证书跟域名的验证 AFSecurityPolicy *securityPolicy = [AFSecurityPolicy defaultPolicy]; securityPolic ...