Halcon基本例程(二)

1、Halcon加载图片到MFC实际上,Halcon加载图片到MFC和直接加载图片到MFC有很大的区别。Halcon加载图片到MFC的实际流程是这样的:1.Halcon在MFC窗口上面打开一个Halcon窗口。Halcon生成的窗口依附在MFC上,看起来就像MFC窗口的一部分。open_window(10,10,1024,768,(Hlong)showwin,"visible","",&CPPExpDefaultWindow);
showwin是MFC窗口的handle.
2.在Halcon窗口上面显示图片。    disp_obj(Image CPPExpDefaultWindow);
看起来就像在MFC上显示一样。

2、Halcon摄像机标定流程

摄像机分两种,一种是面扫描摄像机(Area Scan Camera),一种是线扫描摄像机(Line Scan Camera)。准确来说,叫摄像机系统比较正确。两者的区别:面扫描摄像系统是指可以通过单纯曝光取得面积影像,而线扫描摄像机,必须利用运动速度才能取得影像。两种不同的摄像系统由于成像的过程有区别,所以标定的过程也有区别,这里仅讨论面扫描摄像系统。流程如下:

1、初始摄像机参数:startCamPar:=[f,k,Sx,Sy,Cx,Cy,NumCol,NumRow]
f:焦距;k:初始为0.0;Sx:两个相邻像素点的水平距离;Sy:两个相邻像素点的垂直距离;Cx、Cy:图像中心点的位置;NumCol NumRow:图像长和宽

2、caltab_points读取标定板描述文件里面描述的点到X[],Y[],z[],描述文件由gen_caltab生成。

3、fin_caltab找到标定板的位置4、find_marks_and_pose 输出标定点的位置和外参startpose5、camera_calibration输出内参和所有外部参数3、Halcon-Canny算法

Canny算子:使用累计直方图计算两个阀值。凡是大于高阀值的一定是边缘;凡是小于低阀值的一定不是边缘;如果检测结果大于低阀值但又小于高阀值,那就要看这个像素的邻接像素中有没有超过高阀值的边缘像素:如果有的话那么它就是边缘了,否则他就不是边缘;

Halcon里面:edges_sub_pix(Image:Edges:Filter,Alpha,Low,High:)提供了这个方法。alpha:参数指定值越小,平滑越强大,会减少边缘细节。(canny刚好相反,值越大,边缘细节越少)。Low:低阀值;High:高阀值。例如:read_image(Image,'test.bmp')edges_sub_pix(Image,Edges,'canny',0.5,20,40)

4、解决Halcon不支持的视频设备

一、使用ARFrameGrabber类读取数据,具体操作如下:

1、安装DirectX SDK,注意要下载directx 9.0b 版本。打开SDK安装目录(一般在C:\DXSDK\Samples\C++\DirectShow\BaseClasses),编译BaseClasses.dsw工程,将Debug中的strmbasd.lib文件和Release中的STRMBASE.lib文件拷到C:\DXSDK\Lib目录下; 在VC的工程中加入如下库文件和包含文件: 在vc.net下选择“工具”“选项”,在左边的目录下选择“项目”“VC++目录”在右上角的筐里选择“库文件”将C:\DXSDK\Lib加入库文件中;再选择“包含文件”,将

         C:\DXSDK\Include

         C:\DXSDK\Samples\C++\Common\Include

         C:\DXSDK\Samples\C++\DirectShow\BaseClasses

加入其中;注意:有必要将上述目录移到最上方,以免在编译时发生访问库的冲突!

项目设置添加Strmbasd.lib

2、安装并正确设置opencv,可参照opencv教程

3、复制ARFrameGrabber.h和ARFrameGrabber.cpp到工程目录下。

       工程包含ARFrameGrabber.h,在程序中定义ARFrameGrabber对象。注意这里定义的对象只能是静态的全局变量(static ARFrameGrabber frameGrabber)

核心代码如下:

frameGrabber.GrabByteFrame();//抓一帧

       BYTE *myBuffer = frameGrabber.GetByteBuffer();//取出图像缓存数据

       int width = frameGrabber.GetWidth();

       int height = frameGrabber.GetHeight(); //得出宽和高

       int stride = (width * sizeof( RGBTRIPLE ) + 3) & -4;

       cvInitImageHeader( &ds_frame, cvSize(width, height), 8, 3,IPL_ORIGIN_BL, 4 );

       ds_frame.widthStep = stride;

       cvSetData( &ds_frame, myBuffer, stride );

       frame = &ds_frame;

       cvSaveImage("f.bmp", frame);//把图像写入文件

//Halcon部分

       Hobject myImage;

       read_image(&myImage,"f.bmp");//读出文件

       HImage Image = HImage(myImage);//转换为HImage类型

       Image.Display(*m_pHWinFG);//在m_pHWinFG窗口显示

最终这个解决方案是放弃Halcon自带的FrameGrabber,利用SDK的ARFrameGrabber来采集图像,最后再和Halcon连接。一开始天真的我以为这样可以解决问题,又遇到更棘手的问题。SDK抓出来的BYTE送进去Halcon进行处理后的图像严重失真,估计是接口不一样。最后我走投无路了,想出了一个自认为卑鄙的办法。那就是再引入opencv,利用opencv把SDK抓的图保存为bmp文件(选用bmp主要是因为它格式简单,不用花太多的时间编码),再用Halcon读取bmp文件。最终才解决这个问题。但这个方案还是不好,毕竟它是通过读写硬盘文件来交换数据,如果需要高速运行的时候,会遇到速度瓶颈。但我只要50ms抓一帧图像,这方案还能适应这种速度。

你可能感兴趣的:(HALCON,应用,视觉,算法,HALCON)