欢迎光临~湖南智能应用科技有限公司-hniat.com
语言选择: 中文版 ∷  英文版

基础知识

Halcon 机器视觉编程初探

在机器视觉领域,德国MVTec公司出品的视觉开发软件Halcon可谓无人不知,无人不晓,相比与其他轻量级的视觉开发包,Halcon提供了很多具有工业强度的图像识别算法,性能优越,是机器视觉开发首先。最新版为Halcon 12,提供C/C++,.Net等接口,可以非常方便用户将Halcon中的图像算法植入到自己的应用程序中来。

很早以前就打算深入研究一下Halcon机器视觉开发了,利用工作之余,捣鼓了一下,稍微试用了一下,立刻体会到,果真这个软件不是一般的牛逼,对于很多不是计算机图像专业出生的工程师来说,终于可以从晦涩难懂的高等代数与微积分,以及各种矩阵方程中解脱出来,让你不必了解图像处理理论,直接处理业务核心逻辑,极大的缩短了机器视觉的开发周期。本文以微软VS2010中使用MFC开发基于Halcon11的机器视觉应用为例,为很多像我一样的初学者做登堂入室的垫脚石。闲话少说,详见下文所述。

首先,在VS2010中使用MFC配置Halcon11,这一步虽然简单,但有很多初学者在迈出这第一步的时候就碰了一鼻子灰,无论怎么配置,程序就是编译通不过。不要着急,请仔细看好了。以基于对话框的MFC应用程序为例。

第一步,建立MFC应用程序,给工程取个名字叫HalconFirstStep,如下图所示:


第二步,选择基于对话框的应用程序,如下图所示:


第三步:在本例中,我们在对话框中,添加两个按钮,一个按钮用来加载图片,一个用来处理图片,如下所示:


第四步:我们在菜单栏找到”Project“ -> "HalconFirstStep Properties...",在弹出的对话中中,选择左边窗口选择VC++ Directories, 在右边窗口中选择Include Directories,添加Halcon的头文件路径,这个视Halcon的安装路径不同而不同,也许你电脑上的安装路径和下图中显示的有所出入。头文件路径包含两个路径,一个指定Halcon的Include文件夹位置,一个指定Include文件夹下CPP的位置。如下图所示:



第五步:还是在左边窗口选择VC++ Directories, 在右边窗口中选择Library Directories,添加Halcon的lib文件路径,如下图所示:


第六步:在左边窗口中选择C/C++, 在下拉树形列表中选择General,在窗口右边选择Additional Include Directories,配置Halcon头文件所在路径。如下图所示:


第七步:在窗口左边Linker下选择General,在窗口右边选择Addtional Library Directories,配置Halcon库文件所在路径,如下图所示:


第八步: 在左边窗口的Linker下选择Input,在右边窗口中选择Additional Dependencies 输入Halconcpp.lib。如下图所示:


在这一步需要注意的是,如果你安装的是Halcon的版本号是11.0.0.1的话,这里Additional Dependencies 输入的应该是halconcpp10.lib。这是因为11.0.0.1实际上仍然使用的是Halcon10所用的静态链接库。Halcon 11.0.0.1其实并不是真正意义的11.0版本。很多初学者,在安装了Halcon11.0.0.1版本后,参考网上的配置方法,程序编译时死活说找不到符号。多半都是卡在这里。笔者就被这个问题折磨了两天。

经过以上八步,恭喜你,VS 2010配置Halcon 11算是大功告成。接下来就是好戏上演的时刻了,我们要开始编代码来演示我们的例子了。

第九步:在HalconFirstStepDlg.h 文件开始处,添加代码:

[cpp] view plain copy
  1. #include "halconcpp.h"  
  2. using namespace Halcon;  
#include "halconcpp.h" using namespace Halcon;

注意,如果你安装的Halcon版本是11.0.0.1的话,实际上这个版本仍然和Halcon10一样,使用的是Halcon命名空间,而不是HalconCpp。

第十步:我们在HalconFirstStepDlg.cpp文件中,添加一个全局变量来存储打开的图片。

[cpp] view plain copy
  1. Hobject img;  
Hobject img;

第十一步:添加读取图片按钮的响应代码,我们双击对话框中的”加载图片“按钮,添加下面的代码:
[cpp] view plain copy
  1. void CHalconFisrtStepDlg::OnBnClickedButton1()  
  2. {  
  3.     //获取图像窗口父窗口句柄  
  4.     CRect rect;  
  5.     HWND hwnd = GetDlgItem(IDC_STATIC1)->m_hWnd;  
  6.     GetDlgItem(IDC_STATIC1)->GetWindowRect(&rect);  
  7.     //打开图像窗口  
  8.     Hlong windowId;  
  9.     open_window(0,0,rect.Width(),rect.Height(),(Hlong)hwnd,"visible","",&windowId);  
  10.     //将图像读入内存  
  11.     read_image(&img,"mreut");  
  12.     //获取图像大小  
  13.     HTuple width,height;  
  14.     get_image_size(img,&width,&height);  
  15.     //按照比例缩放到图像窗口  
  16.     set_part(windowId,0,0,width,height);  
  17.     //显示图像  
  18.     disp_obj(img,windowId);  
  19. }  
void CHalconFisrtStepDlg::OnBnClickedButton1()
{ //获取图像窗口父窗口句柄 CRect rect;
	HWND hwnd = GetDlgItem(IDC_STATIC1)->m_hWnd;
	GetDlgItem(IDC_STATIC1)->GetWindowRect(&rect); //打开图像窗口 Hlong windowId;
	open_window(0,0,rect.Width(),rect.Height(),(Hlong)hwnd,"visible","",&windowId); //将图像读入内存 read_image(&img,"mreut"); //获取图像大小 HTuple width,height;
	get_image_size(img,&width,&height); //按照比例缩放到图像窗口 set_part(windowId,0,0,width,height); //显示图像 disp_obj(img,windowId);
}

上面的代码中读取的图片,是怎样一副图片呢,如下图所示:


在这幅卫星图片中,我们的目的是,找出公路所在区域,并把它用红色标记出来。从这幅图片的特征我们不难看出,公路与周围草坪的颜色反差很大,草坪和公路颜色泾渭分明,所以,我们对图像进行二值化处理,区域灰度在阈值以下的全部变黑,区域灰度在阈值以上的全部变白,只留下阈值范围内的区域。然后联通所有存在的区域,并选择其中最大的区域。有了这样的思路,我们就可以给按钮“图像处理”单击事件添加下面的代码:

[cpp] view plain copy
  1. void CHalconFisrtStepDlg::OnBnClickedButton2()  
  2. {  
  3.     //获取图像窗口父窗口句柄  
  4.     CRect rect;  
  5.     HWND hwnd = GetDlgItem(IDC_STATIC2)->m_hWnd;  
  6.     GetDlgItem(IDC_STATIC2)->GetWindowRect(&rect);  
  7.     //打开图像窗口  
  8.     Hlong windowId;  
  9.     open_window(0,0,rect.Width(),rect.Height(),(Hlong)hwnd,"visible","",&windowId);  
  10.     //获取图像大小  
  11.     HTuple width,height;  
  12.     get_image_size(img,&width,&height);  
  13.     //按照比例缩放到图像窗口  
  14.     set_part(windowId,0,0,width,height);  
  15.     //显示图像  
  16.     disp_obj(img,windowId);  
  17.     Hobject BrightRegion,ConnectedRegion,SelectedRegion;  
  18.     //将图像二值化,设定阈值下限为180,上限为255  
  19.     threshold(img,&BrightRegion,188,255);  
  20.     //连通阈值范围内明亮区域  
  21.     connection(BrightRegion,&ConnectedRegion);  
  22.     //选择连通区域内面积最大的区域  
  23.     select_shape_std(ConnectedRegion,&SelectedRegion,"max_area",0);  
  24.     //设定选择区域的颜色为红色  
  25.     set_color(windowId,"red");  
  26.     //显示选择区域  
  27.     disp_obj(SelectedRegion,windowId);    
  28. }  
void CHalconFisrtStepDlg::OnBnClickedButton2()
{ //获取图像窗口父窗口句柄 CRect rect;
	HWND hwnd = GetDlgItem(IDC_STATIC2)->m_hWnd;
	GetDlgItem(IDC_STATIC2)->GetWindowRect(&rect); //打开图像窗口 Hlong windowId;
	open_window(0,0,rect.Width(),rect.Height(),(Hlong)hwnd,"visible","",&windowId); //获取图像大小 HTuple width,height;
	get_image_size(img,&width,&height); //按照比例缩放到图像窗口 set_part(windowId,0,0,width,height); //显示图像 disp_obj(img,windowId);
	Hobject BrightRegion,ConnectedRegion,SelectedRegion; //将图像二值化,设定阈值下限为180,上限为255 threshold(img,&BrightRegion,188,255); //连通阈值范围内明亮区域 connection(BrightRegion,&ConnectedRegion); //选择连通区域内面积最大的区域 select_shape_std(ConnectedRegion,&SelectedRegion,"max_area",0); //设定选择区域的颜色为红色 set_color(windowId,"red"); //显示选择区域 disp_obj(SelectedRegion,windowId);	
}

好了,完整的程序代码到这里就全部结束了,我们来检验一下程序的运行效果,我们调试运行一下,先点击“载入图片”,然后点击“处理图片”按钮。果然程序按照我们预想的那样工作了。怎么样,是不是很惊喜呀。我们惊喜的同时,要感谢那些为Halcon编写算法的那些算法工程师和数学家,感谢他们为我们提供了一个这么智能的视觉开发包。下图是程序运行效果。


要转载本文,请注明出处,尊重知识产权。

关闭
用手机扫描二维码关闭
二维码