【VisionMaster】二次开发之第三方库的使用
VisionMaster 支持使用第三方算法来丰富自身的功能。这里使用OpenCV
作为第三方库作为样例进行说明。
1. 生成算子框架
1.1 启动自定义模块生成工具
- 打开VisionMaster,并找到
菜单栏 >> 工具菜单 >> 自定义模板生成工具
- 打开`自定义模块生成工具
1.2 自定义模块生成工具参数说明
1.2.1 算法模块输入输出XML配置
VM版本
指定为哪一个版本的VisionMaster
开发自定义模块,当前支持VM3.X
与VM4.X
,根据需要进行选择模块名称
开发自定义模块的名称,尽量保证见词达意输入图像
自定义模块是否支持图像输入,即是否包含下图中的输入。位置修正信息
是否支持使用位置修正模块
对该模块进行ROI
的动态跟随。模块状态
只是模块的运行状态,运行成功为1
,运行失败为0
。
图像输出
指定该模块是否有输出图像。具有输出图像的模块,可在显示窗口的选择栏中进行选择显示
自定义输入输出
用于定义一些输入输出参数,该试用版本目前仅支持int
、float
与string
三种类型。输入参数
输入参数说明>
- 参数名称
代码中获取或设置该参数时使用的名称 - 显示名称
UI界面上显示的名称 - 参数类型
参数的类型,在代码中获取参数时,需要根据类型选择对应的函数 - 输入/输出
指定该参数是用于输入还是输出 - 输出参数
- 参数名称
结果显示
用于自定输出参数的显示,点击下图中的更新自定义输出
按钮会将自定义输出
进行同步
同步后,如下图:
如果仅仅完成这些操作,数据不会被输出到VisionMaster
的显示区域。为将数据显示到显示区域,需要选中
输出参数前的复选框。如下图:
- 当前结果
- 当前结果
- 历史结果
- 文本显示
1.2.2 算法模块界面XML配置
基本参数
输入图像源
不可更改,与算法模块输入输出XML配置
中的输入图像源
参数保持一致矩形ROI
多边形ROI
圆环ROI
圆卡尺ROI
直线卡尺ROI
屏蔽区
位置修正
不可更改,与算法模块输入输出XML配置
中的位置修正
参数保持一致
结果显示
- 文本显示
不可更改,受算法模块输入输出XML配置
中的文本显示
参数的影响。如果在算法模块输入输出XML配置
中的文本显示
处至少勾选了一个输出参数,则此处默认勾选。否则,反之。
- 文本显示
模板配置界面
- 模板配置
是否在配置中插入特征模板
选项卡。
- 模板配置
自定义运行参数
用于添加模块所使用的算法的参数。点击添加
按钮,增加如下一个参数:
在选择参数类型
,输入参数名称
与显示 名称
之后,点击编辑
列中对应项的单击编辑
按钮,弹出通用类型
对话框。
点击通用类型
对话框,中的确定
按钮后,关闭此对话框,并更新编辑状态
列中对应项的状态。
支持一下类型:- int
- float
- bool
- string
- enumeration
- intBetween
- floatBetween
命令按钮
- 生成XML
用于生成自定义模块
的相关配置 - 生成C++工程
用于生成自定义模块
的算法工程 - 生成C#工程
用于生成自定义模块
的UI工程
依次点击这个三个命令后,生成如下文件
- 生成XML
2. 编译工程
2.1 编译UI工程
- 使用
VS2013
及其以上版本打开CustomedModule_CsProj\CustomedModuleCs\CustomedModuleCs.sln
。注意,该工程需要.NET4.6.1
的支持 - 将编译类型切换为
Any CPU
+Release
- 编译
CustomedModuleCs
工程
- 将生成的
CustomedModuleCs.dll
拷贝到使用工具生成的CustomedModule
文件夹中
2.2 编译算法工程
- 使用
VS2013
及其以上版本打开CustomedModule_CProj\CustomedModule\CustomedModule.sln
。 - 属性页配置
Release
+x64
- 配置OpenCV头目录
- 配置OpenCV库目录
- 配置OpenCV依赖项
- 切换编译配置到
Release
+x64
,并生成工程。
- 打开源文件
AlgorithmModule.cpp
- 添加OpenCV头文件
#include <opencv2\opencv.hpp>using namespace cv;
- OpenCV::Mat与HKA_IMAGE互转
Mat HKAImageToMat(HKA_IMAGE hik_image)
{Mat mat;if (hik_image.format == HKA_IMG_MONO_08){mat = Mat(hik_image.height, hik_image.width, CV_8UC1, hik_image.data[0]);int a = mat.cols;}else if (hik_image.format == HKA_IMG_RGB_RGB24_C3){mat = Mat(hik_image.height, hik_image.width, CV_8UC3, hik_image.data[0]);}return mat;
}HKA_IMAGE MatToHKAImage(Mat mat)
{HKA_IMAGE image;if (mat.channels() == 1){image = { HKA_IMG_MONO_08, 0 };image.width = mat.cols;image.height = mat.rows;image.format = HKA_IMG_MONO_08;image.step[0] = mat.cols;image.data[0] = mat.data;}else if (mat.channels() == 3){image = { HKA_IMG_RGB_RGB24_C3, 0 };image.width = mat.cols;image.height = mat.rows;image.format = HKA_IMG_RGB_RGB24_C3;image.step[0] = 3 * mat.cols;image.data[0] = mat.data;}return image;
}
- 根据模块要求修改
CAlgorithmModule::Process
函数,这里仅演示二值化功能
int CAlgorithmModule::Process(IN void* hInput, IN void* hOutput, IN MVDSDK_BASE_MODU_INPUT* modu_input)
{OutputDebugStringA("###Call CAlgorithmModule::Proces -->begin\n");int nErrCode = 0;// 1.获取图像HKA_IMAGE struInputImg;HKA_S32 nRet = IMVS_EC_UNKNOWN;HKA_U32 nImageStatus = 0;do{nRet = VmModule_GetInputImageByName(hInput, "InImage", "InImageWidth", "InImageHeight", "InImagePixelFormat", &struInputImg, &nImageStatus);HKA_CHECK_BREAK(IMVS_EC_OK != nRet);} while (0);// 2. 图像转换Mat input_image = HKAImageToMat(struInputImg);// 3. 获取输入参数int count = -1;int inputInt = -1;nRet = VM_M_GetInt(hInput, "InputInt", 0, &inputInt, &count);float inputFloat = 0;nRet = VM_M_GetFloat(hInput, "InputFloat", 0, &inputFloat, &count);int inputString1Length = 100;char inputString1[100];nRet = VM_M_GetString(hInput, "InputString", 0, inputString1, 100, &inputString1Length, &count);// 4. 获取运行参数auto runParam1 = this->m_nRunInt;// 5. 算法处理OutputDebugStringA("###Call CAlgorithmModule::Proces --> do algorighm process\n");Mat binary;cv::threshold(input_image, binary, 128, 255, cv::THRESH_BINARY);// 6. 输出图像格式转换HKA_IMAGE output_image = MatToHKAImage(binary);// 7. 输出图像if (MVD_PIXEL_MONO_08 == modu_input->pImageInObj->GetPixelFormat()){VmModule_OutputImageByName_8u_C1R(hOutput, 1, "OutImage", "OutImageWidth", "OutImageHeight", "OutImagePixelFormat", &output_image);}else if (MVD_PIXEL_RGB_RGB24_C3 == modu_input->pImageInObj->GetPixelFormat()){VmModule_OutputImageByName_8u_C3R(hOutput, 1, "OutImage", "OutImageWidth", "OutImageHeight", "OutImagePixelFormat", &output_image);}// 8. 设置自定义输出参数VM_M_SetInt(hOutput, "OutputInt", 0, 77);VM_M_SetFloat(hOutput, "OutputFloat", 0, 3.1425f);VM_M_SetString(hOutput, "OutputString", 0, "OK");// 9. 设置模块运行状态VM_M_SetInt(hOutput, "ModuStatus", 0, nErrCode == 0 ? 1 : nErrCode);if (nErrCode != IMVS_EC_OK){return IMVS_EC_PARAM;}/************************************************///默认算法时间20ms,根据实际时间计算MODULE_RUNTIME_INFO struRunInfo = { 0 };struRunInfo.fAlgorithmTime = 20;VM_M_SetModuleRuntimeInfo(m_hModule, &struRunInfo);OutputDebugStringA("###Call CAlgorithmModule::Proces end\n");return IMVS_EC_OK;
}
编译生成算法工程
将生成的
CustomedModule.dll
与CustomedModule.pdb
文件拷贝到使用工具生成的CustomedModule
文件夹中
完整源码
#include "stdafx.h"
#include "AlgorithmModule.h"
#include <stdlib.h>
#include <fstream>
#include "ErrorCodeDefine.h"
#include "iMVS-6000PixelFormatDefine.h"#include <opencv2\opencv.hpp>using namespace cv;Mat HKAImageToMat(HKA_IMAGE hik_image)
{Mat mat;if (hik_image.format == HKA_IMG_MONO_08){mat = Mat(hik_image.height, hik_image.width, CV_8UC1, hik_image.data[0]);int a = mat.cols;}else if (hik_image.format == HKA_IMG_RGB_RGB24_C3){mat = Mat(hik_image.height, hik_image.width, CV_8UC3, hik_image.data[0]);}return mat;
}HKA_IMAGE MatToHKAImage(Mat mat)
{HKA_IMAGE image;if (mat.channels() == 1){image = { HKA_IMG_MONO_08, 0 };image.width = mat.cols;image.height = mat.rows;image.format = HKA_IMG_MONO_08;image.step[0] = mat.cols;image.data[0] = mat.data;}else if (mat.channels() == 3){image = { HKA_IMG_RGB_RGB24_C3, 0 };image.width = mat.cols;image.height = mat.rows;image.format = HKA_IMG_RGB_RGB24_C3;image.step[0] = 3 * mat.cols;image.data[0] = mat.data;}return image;
}int GetInputImage(IN void* hInput, HKA_IMAGE& struInputImg)
{HKA_S32 nRet = IMVS_EC_UNKNOWN;HKA_U32 nImageStatus = 0;do{nRet = VmModule_GetInputImageByName(hInput, "InImage", "InImageWidth", "InImageHeight", "InImagePixelFormat", &struInputImg, &nImageStatus);HKA_CHECK_BREAK(IMVS_EC_OK != nRet);} while (0);return nRet;
}CAlgorithmModule::CAlgorithmModule()
{m_nRunInt = 50;
}CAlgorithmModule::~CAlgorithmModule()
{}int CAlgorithmModule::Init()
{PARAM_VALUE_INFO_LIST stList = { 0 };int nRet = VM_M_GetDefaultConfigByFile(m_hModule, UNICODEtoUTF8(VmModule_GetXmlPath().GetBuffer()), &stList);if (nRet == IMVS_EC_OK){for (int i = 0; i < stList.nNum; i++){SetParam(stList.paramValueList[i].byParamName, stList.paramValueList[i].byParamValue, strlen(stList.paramValueList[i].byParamValue));}}return nRet;
}int CAlgorithmModule::Process(IN void* hInput, IN void* hOutput, IN MVDSDK_BASE_MODU_INPUT* modu_input)
{OutputDebugStringA("###Call CAlgorithmModule::Proces -->begin\n");int nErrCode = 0;// 1.获取图像HKA_IMAGE struInputImg;HKA_S32 nRet = IMVS_EC_UNKNOWN;HKA_U32 nImageStatus = 0;do{nRet = VmModule_GetInputImageByName(hInput, "InImage", "InImageWidth", "InImageHeight", "InImagePixelFormat", &struInputImg, &nImageStatus);HKA_CHECK_BREAK(IMVS_EC_OK != nRet);} while (0);// 2. 图像转换Mat input_image = HKAImageToMat(struInputImg);// 3. 获取输入参数int count = -1;int inputInt = -1;nRet = VM_M_GetInt(hInput, "InputInt", 0, &inputInt, &count);float inputFloat = 0;nRet = VM_M_GetFloat(hInput, "InputFloat", 0, &inputFloat, &count);int inputString1Length = 100;char inputString1[100];nRet = VM_M_GetString(hInput, "InputString", 0, inputString1, 100, &inputString1Length, &count);// 4. 获取运行参数auto runParam1 = this->m_nRunInt;// 5. 算法处理OutputDebugStringA("###Call CAlgorithmModule::Proces --> do algorighm process\n");Mat binary;cv::threshold(input_image, binary, 128, 255, cv::THRESH_BINARY);// 6. 输出图像格式转换HKA_IMAGE output_image = MatToHKAImage(binary);// 7. 输出图像if (MVD_PIXEL_MONO_08 == modu_input->pImageInObj->GetPixelFormat()){VmModule_OutputImageByName_8u_C1R(hOutput, 1, "OutImage", "OutImageWidth", "OutImageHeight", "OutImagePixelFormat", &output_image);}else if (MVD_PIXEL_RGB_RGB24_C3 == modu_input->pImageInObj->GetPixelFormat()){VmModule_OutputImageByName_8u_C3R(hOutput, 1, "OutImage", "OutImageWidth", "OutImageHeight", "OutImagePixelFormat", &output_image);}// 8. 设置自定义输出参数VM_M_SetInt(hOutput, "OutputInt", 0, 77);VM_M_SetFloat(hOutput, "OutputFloat", 0, 3.1425f);VM_M_SetString(hOutput, "OutputString", 0, "OK");// 9. 设置模块运行状态VM_M_SetInt(hOutput, "ModuStatus", 0, nErrCode == 0 ? 1 : nErrCode);if (nErrCode != IMVS_EC_OK){return IMVS_EC_PARAM;}/************************************************///默认算法时间20ms,根据实际时间计算MODULE_RUNTIME_INFO struRunInfo = { 0 };struRunInfo.fAlgorithmTime = 20;VM_M_SetModuleRuntimeInfo(m_hModule, &struRunInfo);OutputDebugStringA("###Call CAlgorithmModule::Proces end\n");return IMVS_EC_OK;
}int CAlgorithmModule::GetParam(IN const char* szParamName, OUT char* pBuff, IN int nBuffSize, OUT int* pDataLen)
{OutputDebugStringA("###Call CAlgorithmModule::GetParam");int nErrCode = IMVS_EC_OK;if (szParamName == NULL || strlen(szParamName) == 0 || pBuff == NULL || nBuffSize <= 0 || pDataLen == NULL){return IMVS_EC_PARAM;}//memset(pBuff, 0, nBuffSize);if (0 == strcmp("RunInt", szParamName)){sprintf_s(pBuff, nBuffSize, "%d", m_nRunInt);}else{return CVmAlgModuleBase::GetParam(szParamName, pBuff, nBuffSize, pDataLen);}return nErrCode;
}int CAlgorithmModule::SetParam(IN const char* szParamName, IN const char* pData, IN int nDataLen)
{OutputDebugStringA("###Call CAlgorithmModule::SetParam");int nErrCode = IMVS_EC_OK;if (szParamName == NULL || strlen(szParamName) == 0 || pData == NULL || nDataLen == 0){return IMVS_EC_PARAM;}if (0 == strcmp("RunInt", szParamName)){sscanf_s(pData, "%d", &m_nRunInt);}else{return CVmAlgModuleBase::SetParam(szParamName, pData, nDataLen);}return nErrCode;
}/模块须导出的接口(实现开始)//LINEMODULE_API CAbstractUserModule* __stdcall CreateModule(void* hModule)
{assert(hModule != NULL);// 创建用户模块,并记录实例。CAlgorithmModule* pUserModule = new(nothrow) CAlgorithmModule;if (pUserModule == NULL){return NULL;}pUserModule->m_hModule = hModule;int nRet = pUserModule->Init();if (IMVS_EC_OK != nRet){delete pUserModule;return NULL;}printf("[ LineModule ] CreateModule, hModule = 0x%x, pUserModule = 0x%x \n", hModule, pUserModule);OutputDebugStringA("###Call CreateModule");return pUserModule;
}LINEMODULE_API void __stdcall DestroyModule(void* hModule, CAbstractUserModule* pUserModule)
{assert(hModule != NULL);printf("\n[ LineModule ] DestroyModule, hModule = 0x%x\n", hModule);OutputDebugStringA("###Call DestroyModule");if (pUserModule != NULL){delete pUserModule;}
}
/模块须导出的接口(实现结束)//
3. 模块导入
- 将
CustomedModule
文件夹拷贝到C:\Program Files\VisionMaster4.0.0\Applications\Module(sp)\x64\UserTools
文件夹中
- 拷贝
opencv_world310.dll
到C:\Program Files\VisionMaster4.0.0\Applications\PublicFile\x64
。如果将自定义模块拖拽到流程图中提示找不到模块,需要重启电脑。
4. 模块测试
- 将自定义工具拖入流程图中
- 配置类似如下的方案
- 打开自定义模块,显示如下
- 配置自定义输入参数
- 点击运行按钮,查看结果
5. 调试自定义模块算法
配置好方案,并打开自定模块
用
VS2013
及其以上版本打开算法工程
选择
附件到进程
选择
VmModuleProxy.exe
在源代码的合适位置,打上
断点
运行自定义模块
查看是否进入断点调试中
【VisionMaster】二次开发之第三方库的使用相关推荐
- 不属于python开发用户界面第三方库的是-模拟试卷C【单项选择题】
原标题:模拟试卷C[单项选择题] 1. 按照"后进先出"原则组织数据的数据结构是____ 队列 栈 双向链表 二叉树 2. 以下选项的叙述中,正确的是 循环队列有队头和队尾两个指针 ...
- 2018年最全iOS开发之第三方库
最全iOS开发之第三方库 最新增加 EAIntroView 一个灵活的介绍界面,可以用作引导页 UI 下拉刷新 EGOTableViewPullRefresh– 最早的下拉刷新控件. SVPullTo ...
- 如何在LabVIEW中进行海康机器视觉算法平台VisionMaster二次开发
目录 1.导言 庞大的NI LabVIEW软件平台 LabVIEW 平台的特点 海康机器人的视觉算法平台VisionMaster特点 如何在LabVIEW中进行海康视觉算法平台二次开发 2.方法与步骤 ...
- 史上最全iOS开发之第三方库整理汇总
UI 下拉刷新 EGOTableViewPullRefresh – 最早的下拉刷新控件. SVPullToRefresh – 下拉刷新控件. MJRefresh – 仅需一行代码就可以为UITable ...
- iOS开发常用第三方库
UI 动画 网络相关 Model 其他 数据库 缓存处理 PDF 图像浏览及处理 摄像照相视频音频处理 响应式框架 消息相关 版本新API的Demo 代码安全与密码 测试及调试 AppleWatch ...
- python 的库如何开发_如何开发Python第三方库?
自己写过几个开源第三方库,说说具体流程吧. 1.明确项目需求.你的库必须要有实际作用,开发一些没有意义的库毫无意义.且你必须保证程序的稳定性和可持续性,为接下来的开发和更新做准备. 2.发布开源项目. ...
- python游戏开发的第三方库有哪些_Python 游戏开发方向的第三方库是
Python 游戏开发方向的第三方库是 答:Pygame 内分泌器官包括( ) 答:甲状腺 松果体 甲状旁腺 垂体 我国的社会保险制度体系主要包括.医疗保险.失业保险.工伤保险.生育保险等内容 答:养 ...
- iOS开发——导入第三方库引起的unknown type name 'NSString'
今天加入SVProgressHUD的第三方库的时候报了24个错误( too many errors emitted, stopping now),都是 expected identifier or ' ...
- 机器人开发常见第三方库、软件安装和使用
写在前面: 大多数情况下,没有人比官方更懂官方,所以编译安装.库配置及简单使用优先看官方github仓库README或者官网,当然不排除有些博文或者教程有更好的表达方式更详细的说明 cmake 编译三 ...
最新文章
- hdfs入门——常用命令
- 怎样玩儿转App手游自动化测试?
- javascript闭包学习
- rest framework 序列化
- 那些年我看过的前端书
- plsql developer无法识别32位oracle问题如何解决?
- 联合哈佛大学,Google 要用人工智能来预测地震余震
- 拖拽实例 对于设置监听setInterval 的理解
- spring3.1.0 jar包详解说明
- Oracle学习笔记(1)----忘记用户名的密码该如何找回
- 创新创业基础答案李家华金利杰
- html使table整体居中,如何让整个table表格居中?
- Segger和Micrium之间的区别和联系
- 关于英语单词记忆的总结
- 浅谈缓存-注解驱动的缓存 Spring cache介绍
- qq等级查询php源码,基于PHP的QQ等级计算器
- hdu 5442 (后缀数组)
- OpenDDS和RTI DDS内置数据类型的互联互通测试
- 清华大学2020年“姚班”“智班”报考指南及选拔方案发布!
- 从达沃斯世界经济论坛,看区块链和数字货币的三大发展趋势
热门文章
- 计算机考试word文档怎么画坐标,使用WORD画坐标系的方法
- 使用 Learner Lab - 使用 AWS Lambda 将图片写入 S3
- 视频格式那么多,MP4/RMVB/MKV/AVI 等,这些视频格式与编码压缩标准 mpeg4,H.264.H.265 等有什么关系?...
- 怎么压缩图片 ? 掌握这几种免费压缩图片的方法就够了
- STM32使用库函数点灯实验
- 新研究调查Masimo ORi™(氧储备指数)能否用作避免全麻期间高氧状态的指数
- LR之录制脚本修改完善
- 如何利用Simulink来设计一个AEB的算法,并通过SCANeR仿真来测试?
- Qt - 换肤功能实现
- 四十七、使用bootstrap中的选项卡制作产品特色页面