最近在用Halcon生成的C++代码,配合MFC做上层显示,在显示点云和图片拉伸上遇到了一些问题,现将解决方法写在下面:
1. 图片显示基础
不管Halcon想在MFC里面显示什么,本质上都是在MFC的Picture Control控件作为父类的基础上,打开新的窗口,然后使用新的窗口的句柄进行显示。准备代码如下:
CRect rtWindow;// 定义一个矩形对象
HWND hImgWnd = GetDlgItem(IDC_DISPLAY_STATIC)->m_hWnd;// 获取Picture Control控件的句柄
GetDlgItem(IDC_DISPLAY_STATIC)->GetClientRect(&rtWindow);// 获取Picture Control控件的实际大小
OpenWindow(rtWindow.left, rtWindow.top, rtWindow.Width(), rtWindow.Height(), (Hlong)hImgWnd, "visible", "", &hv_WindowHandle);//建立和Picture Control控件大小相同的窗口
HDevWindowStack::Push(hv_WindowHandle);//将新建的窗口句柄推入队列中
这其中IDC_DISPLAY_STATIC
是Picture Control控件的ID
2. 点云显示
点云显示和halcon中一样,使用visualize_object_model_3d
函数(不过要使用这个函数,大量的前置函数是必不可少的,不过都是halcon自动生成的,这里就不赘述了)
visualize_object_model_3d(hv_WindowHandle, hv_PipeJointPileOM3DID, hv_CamParam0,hv_Pose0, (HTuple("color").Append("point_size")), (HTuple("yellow").Append(1)),HTuple(), HTuple(), HTuple(), &hv_PoseOut);
其中hv_WindowHandle
就是第1部分中用OpenWindow打开的窗口句柄。值得注意的是,在这个函数里它在使用句柄hv_WindowHandle
时,代码有一段如下:
HDevWindowStack::SetActive(hv_WindowHandle);
if (HDevWindowStack::IsOpen())
DispObj(ho_ImageDump, HDevWindowStack::GetActive());
它使用了HDevWindowStack
类里的SetActive
和IsOpen
方法,但是它并没有使用Push
方法将窗口句柄推入堆栈中,这就是为什么要在第1部分的最后使用如下代码了,如果不加这个是会报错的。
HDevWindowStack::Push(hv_WindowHandle);
PS:halcon在C++中的点云,也就是这个变量hv_PipeJointPileOM3DID
,仍然是使用和halcon中一致的object_model_3d类型,所以不要妄想手动向其中写入输入,还是要用ReadObjectModel3d
函数读取模型文件,当然也有可能是我水平不足没有发现写入方法(也不排除这个可能性)。
3. 图片拉伸
有时在显示图片时可能会出现如下情况:
图片全部集中在窗口的上半部分了,这是因为没有使用SetPart
函数设置使用这个窗口的多大部分显示图片,只要在显示之前加入如下代码:
SetPart(hv_WindowHandle, 0, 0, hv_Height, hv_Width);
其中hv_Height
和hv_Width
是图片的高和宽,可以用GetImageSize
函数从图片中获取,或者直接手动输入也可以。加入上面的代码后,显示正常:
4. 其他
关于HDevWindowStack类,在halcon中使用dev_display
函数,转化为C++代码时需要使用到的类,转化后的代码如下:
if (HDevWindowStack::IsOpen())
DispObj(ho_Image, HDevWindowStack::GetActive());
这里面也是没有HDevWindowStack::Push
函数的,所以如果要使用halcon中的dev_display
时,前面也要加Push函数。当然还有第2部分中提到的显示点云之前也要使用这个Push函数。