前言
我们在Halcon上可以很容易的实现连接相机与实时采集图片的操作,利用电脑自带的“DirectShow”相机执行文件可以实现实时显示相机的采集效果与拍照,现在我们利用halcon的内部算子在MFC中写一个,相机实时采集与保存采集图片的demo。
搭建好MFC与halcon的联合环境MFC+halcon联合环境配置
1、Halcon中实现效果
以下为简单的在Halcon中实现相机的实时采集算法
//打开相机,此处相机为同步采集
open_framegrabber ('DirectShow', 1, 1, 0, 0, 0, 0, 'default', 8, 'rgb', -1, 'false', 'default', '[0] ', 0, -1, AcqHandle)
//使用循环实现实时采集效果
while (true)
//采集图片
grab_image (Image, AcqHandle)
endwhile
//关闭相机
close_framegrabber (AcqHandle)
按照C++的编码方式导出算法
void action()
{
HObject ho_Image; //定义图像
HTuple hv_AcqHandle; //定义相机句柄
//打开相机
OpenFramegrabber("DirectShow", 1, 1, 0, 0, 0, 0, "default", 8, "rgb", -1, "false",
"default", "[0] ", 0, -1, &hv_AcqHandle);
while (0 != 1)
{
GrabImage(&ho_Image, hv_AcqHandle); //采集图片
}
CloseFramegrabber(hv_AcqHandle); //关闭相机
}
2、MFC项目的搭建
新建–>项目–>MFC应用程序–>命名项目名称(此处我的项目名是Camera);
此处有用到halcon内部的DirectShow.dll,需要将其添加在可执行项目目录下
接着在资源视图–>diadlg中设置需要利用的控件
点击静态文本框设置ID为:IDC_STATIC_SHOW_WND;右键文本框添加变量,类别为Control,变量类型CStatic,变量名:可以自己设置(这里是m_ctlShowWnd)
在头文件中定义公共类型的变量
public:
HObject ho_Image; //采集的图片
HTuple hv_AcqHandle, hWndID; //窗口句柄
HTuple hW, hH; //图片的宽高
CStatic m_ctlShowWnd; //静态类对象
添加两个按钮一个用来关闭相机一个用于保存采集的图片,并在头文件声明
控件ID分别为 关闭按钮:IDCANCEL,保存按钮:IDC_BUTTON_SAVE
public:
HObject ho_Image; //采集的图片
HTuple hv_AcqHandle, hWndID; //窗口句柄
HTuple hW, hH; //图片的宽高
CStatic m_ctlShowWnd; //静态类对象
afx_msg void OnBnClickedCancel(); //关闭按钮
afx_msg void OnBnClickedButtonSave(); //保存按钮
添加一个选取盒控件中文显示为实时,控件的ID:IDC_CHECK_CONTINUE_GRAB
右键添加变量,类别为:Value,变量类型Bool,变量名:m_fContinueGrab(可以自定义)
接着声明变量
HObject ho_Image; //采集的图片
HTuple hv_AcqHandle, hWndID; //窗口句柄
HTuple hW, hH; //图片的宽高
CStatic m_ctlShowWnd; //静态类对象
afx_msg void OnBnClickedCancel(); //关闭按钮
afx_msg void OnBnClickedButtonSave(); //保存按钮
afx_msg void OnBnClickedCheckContinueGrab(); //实时选择按钮
BOOL m_fContinueGrab; //判断是否选择打开实时按钮
然后我们在cpp文件中初始化位置打开相机与开窗口
// TODO: 在此添加额外的初始化代码
//打开相机
OpenFramegrabber("DirectShow", 1, 1, 0, 0, 0, 0, "default", 8, "rgb", -1, "false","default", "[0] ", 0, -1, &hv_AcqHandle);
//开窗口
CRect rct;
m_ctlShowWnd.GetClientRect(rct); //获取静态框矩形
long IWindowID = 0; //定义静态框句柄
long m_PicWidth = rct.Width(); //定义静态框宽度
long m_PicHeight = rct.Height(); //定义静态框高度
IWindowID = (long)m_ctlShowWnd.GetSafeHwnd(); //获取静态框的句柄
OpenWindow(0,0,(Hlong)m_PicWidth,(Hlong)m_PicHeight, IWindowID,"visible","",&hWndID); //调用halcon打开窗口函数
//采图
GrabImage(&ho_Image, hv_AcqHandle);
//显示
GetImageSize(ho_Image,&hW,&hH); //获取图片大小
SetPart(hWndID, 0, 0, hH, hW); //设置显示的范围
DispObj(ho_Image, hWndID); //显示图片
接着对关闭相机的按钮编写具体实现
void CCameraDlg::OnBnClickedCancel()
{
// TODO: 在此添加控件通知处理程序代码
CloseFramegrabber(hv_AcqHandle);
CDialog::OnCancel();
}
保存图片具体实现
void CCameraDlg::OnBnClickedButtonSave()
{
// TODO: 在此添加控件通知处理程序代码
if (m_fContinueGrab)
{
AfxMessageBox(_T("请先关闭实时"));
return;
}
else
{
WriteImage(ho_Image,"bmp",0,"C:/Users/xinyuanchai/Desktop/20210722");
}
}
选择是否选择实时按钮具体实现我们需要开辟一个新的线程在头文件中声明一个私有类的静态方法
private:
static UINT ContinueGrabThread(LPVOID p); //开辟线程
然后实现选择点击了实时框后就可以实现实时采图的功能
UINT CCameraDlg::ContinueGrabThread(LPVOID p)
{
CCameraDlg *pThis = (CCameraDlg*)p;
while (WaitForSingleObject(exitGrabThread.m_hObject,2)!=WAIT_OBJECT_0)
{
GrabImage(&pThis->ho_Image, pThis->hv_AcqHandle);
DispObj(pThis->ho_Image, pThis->hWndID);
}
return 0;
}
是否点击实时选择框具体实现
void CCameraDlg::OnBnClickedCheckContinueGrab()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);
if (m_fContinueGrab)
{
AfxBeginThread(ContinueGrabThread,this);
}
else
{
exitGrabThread.SetEvent();
}
}
其中ContinueGrabThread为新开的线程;exitGrabThread在头文件前面声明
CEvent exitGrabThread;
最后
运行看看效果