一.引言
1.设计目的
基于海康机器人第一届“启智杯”机器视觉设计大赛参赛手册第2.3.2节所描述的需求,旨在使用海康算子库等开发一款模板匹配建模与识别的图像控件。具体实现功能如下:
- ①图像加载与显示
- ②图像信息与像素信息显示
- ③鼠标滚轮缩放图像
- ④在图像上添加ROI或MASK图形(矩形、扇环、多边形)
- ⑤橡皮擦(擦除匹配轮廓点)
- ⑥清空图形
- ⑦全屏显示
- ⑧撤销重做
- ⑨训练导出模型
- ⑩载入匹配模型
2.编译环境
- 程序设计语言:C++;标准:C++14。
- 应用程序框架:MFC;版本:14.29.30133.0。
- 位图、图形绘制:GDI;
- 开发工具集:Microsoft Visual Studio Community 2019;版本:16.11.21。
- 硬件环境:
- 处理器:Intel® Core™ i5-7300HQ CPU @ 2.50GHz;
- 机带RAM:16.0GB。
二.功能实现思路
1.图像显示功能
1.1图像加载与显示
使用海康算子库的IMvdImage类,调用IMvdImage类的InitImage函数实现图像加载,再将IMvdImage对象转换为用于GDI绘图的CBitmap对象,具体转换见文章IMvdImage类型转换为MFC的CBitmap类型。
大致实现步骤
(Ⅰ)实例化IMvdImage对象m_pOtherImage;
(Ⅱ)调用IMvdImage类的接口函数m_pOtherImage->InitImage(strPath.c_str()),将选中的图像路径传入。
实现效果
1.2图像信息及像素信息显示
使用IMvdImage类的GetWidth()、GetHeight()函数获取图像宽高信息,使用GDI的DrawText()函数进行渲染。
大致实现步骤
(Ⅰ)调用GetWidth()函数、GetHeight()函数获取图像宽高;
(Ⅱ)实例化CString对象m_renderStr,调用CString类的内置函数Format将图像宽高数据输入;
(Ⅲ)使用MFC的CDC类封装的DrawText()函数将m_renderStr绘制在显示界面的右上角。
实现效果
1.3鼠标滚轮缩放图像
大致实现步骤
(Ⅰ)判断当前传入鼠标位置是否在PICTURE CONTROL控件的图像区域内;
(Ⅱ)若在,则以该点作为图像缩放点;反之,则求距离该点最近的图像区域内点作为图像缩放点;
(Ⅲ)以缩小图像为例,如图2-8所示,可得图像矩形的新左上角点坐标及新宽高信息,计算后存入结构体m_image2Device中,重新渲染一帧。
实现原理
实现效果
1.4添加图形
大致实现步骤
(Ⅰ)判断当前鼠标区域是否在PICTURE CONTROL控件的图像区域内;
(Ⅱ)若在,以绘制矩形为例,当产生鼠标左键按下消息时,响应void startDrawRect(CPoint* currentPoint)函数,即开始绘制矩形;当鼠标左键按下并拖动时,响应void perfectRect (CPoint* currentPoint)函数,即完善矩形信息;当产生鼠标左键松开消息时,响应void endDrawRect()函数和void finishChangeRect ()函数,即完成该矩形的绘制,除后续Resize和Move该矩形外,该矩形信息不再变化。
实现效果
1.5橡皮擦
大致实现步骤
(Ⅰ)判断当前传入鼠标位置是否在PICTURE CONTROL控件的图像区域内;
(Ⅱ)若在,则将该点及其左、上、右、下点存入Vector中;
(Ⅲ)调用CDC类的SetPixel()函数设置鼠标当前位置及其左、上、右、下点的RGB值。
实现效果
1.6清空图形
由于添加的图形均存于三条双向链表内,故实现该功能只需要清空三条双向链表即可。
1.7全屏显示
大致实现步骤
(Ⅰ)隐藏除PICTURE CONTROL控件外的其他控件;
(Ⅱ)去除对话框标题和边框,并最大化对话框;
(Ⅲ)画布DC选入与屏幕大小相同的Cbitmap对象,修改相关参数;
(Ⅳ)记录PICTURE CONTROL控件的原始位置,最大化PICTURE CONTROL控件。
实现效果
1.8撤销重做
使用海康算子库的IMvdImage类,调用IMvdImage类的InitImage函数实现图像加载,再将IMvdImage对象转换为用于GDI绘图的CBitmap对象,具体转换见文章IMvdImage类型转换为MFC的CBitmap类型。
大致实现步骤
(Ⅰ)从remake事件栈中弹出最后一个事件n1,并将n1压入redo事件栈;
(Ⅱ)判断n1的事件类型,若为RESIZE_XXX,则再从remake事件栈中获取最后一个与该事件指向同一图形的事件n2,并设置n2所指向的图形的值为n2所指向的数据
1.9训练导出模型
使用海康算子库的IHPFeaturePattern类。
大致实现步骤
(Ⅰ)实例化IHPFeaturePattern*对象m_pHPFeaturePatternObj;
(Ⅱ)调用IHPFeaturePattern类的函数InitImage传入训练图片;
(Ⅲ)设置ROI和MASK;
(Ⅳ)调用IHPFeaturePattern类的函数Train()完成训练;
(Ⅴ)在内存DC上将匹配点修改为绿色;
(Ⅵ)调用IHPFeaturePattern类的函数ExportPattern()导出模型。
实现效果
1.10载入匹配模型
使用海康算子库的IHPFeaturePatMatchTool类和IHPFeaturePattern类。
大致实现步骤
(Ⅰ)实例化IHPFeaturePattern对象m_pHPFeaturePatternObj;
(Ⅱ)调用IHPFeaturePattern类的函数ImportPattern()载入模型;
(Ⅲ)实例化IHPFeaturePatMatchTool对象m_pHPFeaturePatMatchToolObj;
(Ⅳ)传入ROI、MASK、模板、图片等信息,调用IHPFeaturePatMatchTool类的函数Run ()完成模型匹配;
(Ⅴ)在内存DC上将匹配点修改为绿色。
实现效果
2.图形交互功能
2.1选中图形
大致实现步骤
(Ⅰ)判断鼠标所处区域;
(Ⅱ)若鼠标处于矩形区,取矩形链表,计算鼠标位于矩形链表的哪一个节点,设置该节点的isHover为1;
(Ⅲ)为画布DC选入红笔,绘制红色矩形,并在矩形的四个角点绘制4个小矩形,绘制完选回蓝笔;
实现效果
2.2移动图形
大致实现步骤
(Ⅰ)判断鼠标所处区域;
(Ⅱ)若鼠标处于矩形区,取矩形链表,计算鼠标位于矩形链表的哪一个节点;
(Ⅲ)计算鼠标当前坐标与按下鼠标时坐标的差值,修改该链表节点;
实现效果
2.3删除选中图形
大致实现步骤
(Ⅰ)判断鼠标所处区域;
(Ⅱ)若鼠标处于矩形区,取矩形链表,计算鼠标位于矩形链表的哪一个节点;
(Ⅲ)在矩形链表中删除该节点;
实现效果
3.图像保存功能
默认保存的图像为带有图形的图像,设置isSource为1则保存原始图像。
大致实现步骤
(Ⅰ)创建临时CDC对象和临时CBitmap对象;
(Ⅱ)将加载入内存DC的Cbitmap对象复制到临时CBitmap对象;
(Ⅲ)在临时CDC对象上绘制链表中的图形;
(Ⅳ)使用MFC的CImage类保存图像;
实现效果
4.用户开发功能
4.1添加、调整、删除图形回调事件
#回调函数定义
void (*rectEventCallback)(MYFIGUREEVENTTYPE rectEventType, S_RECTINFO* rect)
void rectEvent(MYFIGUREEVENTTYPE rectEventType, S_RECTINFO* rect) {
switch (rectEventType)
{
case ADD_RECT: {
std::cout << "event: ADD_RECT\n";
break;
}
case RESIZE_RECT: {
std::cout << "event: RESIZE_RECT\n";
break;
}
case DELETE_RECT: {
std::cout << "event: DELETE_RECT\n";
break;
}
default:
break;
}
std::cout << "rect->data->left" << rect->data->left << "\n";
std::cout << "rect->data->top" << rect->data->top << "\n";
std::cout << "rect->data->right" << rect->data->right << "\n";
std::cout << "rect->data->bottom" << rect->data->bottom << "\n";
}
实现效果
4.2其他接口函数
加载图像接口。
保存原始图和渲染图(带图形的图像)接口。
添加、删除图形,获取选中图形的位置、类型信息接口。
更改控件背景色接口。该接口的实现使用了GDI的CDC类的FillSolidRect()函
使用步骤如下:
(Ⅰ)实例化MyRenderClass对象m_render;
(Ⅱ)m_render->setBkColor(RGB(255, 255, 255))即可设置渲染背景色。
实现效果
三.控件结构设计
1.系统总体结构
2.系统组织设计
主要模块为:模板载入与匹配模块、模板训练与导出模块;其下包含的组件为:基本图像渲染组件、日志组件、图像图形渲染组件、链表节点管理组件、位图按钮管理组件。
模板载入与匹配模块为主模块,点击“创建模板”按钮即启动模板训练与导出模块。
在模板载入与匹配模块中,其核心组件为基本图像渲染组件,该组件完成了模块的核心交互功能:图像交互、匹配结果显示功能。
在模板训练与导出模块中,其核心组件为图像渲染组件,该组件完成了模块的核心交互功能:图像交互、图形绘制、模板中心设置、模型生成、区域擦除、撤销重做、放大缩小、一比一显示图像、全屏显示图像、图形删除、导出模型等功能。
3.核心组件——图像渲染组件
3.1组件逻辑
在VisionMaster 4.2.0的高精度匹配模块中,点击“选择其他图像”并加载图像,当鼠标处于该模块的图像显示部分且不移动、鼠标不在该模块上且胡乱操作时,VisionMaster的CPU占用率为0%;当鼠标处于该模块的图像显示部分且只移动鼠标时,VisionMaster的CPU占用率为7-8%;当鼠标处于该模块的图像显示部分且鼠标同时按下加移动时,VisionMaster的CPU占用率为44-46%。
由此可见,该模块的渲染图像逻辑与事件类型有关:当不产生事件或事件与VisionMaster不相关时,不做任何重新渲染操作;当产生与VisionMaster相关的事件时,首先判断消息类型,若事件满足特定条件(如在图像区域按下并移动),则重新渲染图像,此时CPU占用率变高,否则只做一些其他不占CPU的事件。
因此,借鉴VisionMaster 4.2.0的高精度匹配模块,本控件也采用类似操作逻辑。当不产生事件或事件与本控件不相关时,不做任何操作;当事件与本控件相关时,首先判断事件是否满足重新渲染图像的要求,再选择性重新渲染一帧图像。
组件逻辑图如图所示
3.2组件实现效果
4.模板载入与匹配模块
在本模块中,除了图像匹配结果显示界面,其余大部分均从海康算子的例子HPFeaturePatMatchCppDemo项目中复制而来。
交互界面如图所示
5.模板训练与导出模块
交互界面如图所示
四.设计总结
相较于VisionMaster 4.2.0的高精度匹配模块,本软件具有的优势为:
(Ⅰ)全屏显示界面可以进行非全屏界面的所有交互事件。
本软件存在的不足之处在于:
(Ⅰ)矩形不可旋转;
(Ⅱ)所有图形均只存在边界,而没有图形包围部分的半透明蓝色掩膜;
(Ⅲ)撤销重做仅支持resize图形,不支持add和delete图形事件;
(Ⅳ)日志记录等级仅info和error两级;
(Ⅴ)存在少量不影响功能的bug…….