VisionMaster 支持使用第三方算法来丰富自身的功能。这里使用OpenCV作为第三方库作为样例进行说明。

1. 生成算子框架

1.1 启动自定义模块生成工具

  • 打开VisionMaster,并找到 菜单栏 >> 工具菜单 >> 自定义模板生成工具
  • 打开`自定义模块生成工具

1.2 自定义模块生成工具参数说明

1.2.1 算法模块输入输出XML配置

  • VM版本
    指定为哪一个版本的VisionMaster开发自定义模块,当前支持VM3.XVM4.X,根据需要进行选择

  • 模块名称
    开发自定义模块的名称,尽量保证见词达意

  • 输入图像
    自定义模块是否支持图像输入,即是否包含下图中的输入。

  • 位置修正信息
    是否支持使用位置修正模块对该模块进行ROI的动态跟随。

  • 模块状态
    只是模块的运行状态,运行成功为1,运行失败为0

  • 图像输出
    指定该模块是否有输出图像。具有输出图像的模块,可在显示窗口的选择栏中进行选择显示

  • 自定义输入输出
    用于定义一些输入输出参数,该试用版本目前仅支持intfloatstring三种类型。

  • 输入参数

  • 输入参数说明>

    • 参数名称
      代码中获取或设置该参数时使用的名称
    • 显示名称
      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工程

    依次点击这个三个命令后,生成如下文件

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.dllCustomedModule.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.dllC:\Program Files\VisionMaster4.0.0\Applications\PublicFile\x64。如果将自定义模块拖拽到流程图中提示找不到模块,需要重启电脑。

4. 模块测试

  • 将自定义工具拖入流程图中
  • 配置类似如下的方案
  • 打开自定义模块,显示如下
  • 配置自定义输入参数
  • 点击运行按钮,查看结果

5. 调试自定义模块算法

  • 配置好方案,并打开自定模块

  • VS2013及其以上版本打开算法工程

  • 选择附件到进程

  • 选择VmModuleProxy.exe

  • 在源代码的合适位置,打上断点

  • 运行自定义模块

  • 查看是否进入断点调试中

【VisionMaster】二次开发之第三方库的使用相关推荐

  1. 不属于python开发用户界面第三方库的是-模拟试卷C【单项选择题】

    原标题:模拟试卷C[单项选择题] 1. 按照"后进先出"原则组织数据的数据结构是____ 队列 栈 双向链表 二叉树 2. 以下选项的叙述中,正确的是 循环队列有队头和队尾两个指针 ...

  2. 2018年最全iOS开发之第三方库

    最全iOS开发之第三方库 最新增加 EAIntroView 一个灵活的介绍界面,可以用作引导页 UI 下拉刷新 EGOTableViewPullRefresh– 最早的下拉刷新控件. SVPullTo ...

  3. 如何在LabVIEW中进行海康机器视觉算法平台VisionMaster二次开发

    目录 1.导言 庞大的NI LabVIEW软件平台 LabVIEW 平台的特点 海康机器人的视觉算法平台VisionMaster特点 如何在LabVIEW中进行海康视觉算法平台二次开发 2.方法与步骤 ...

  4. 史上最全iOS开发之第三方库整理汇总

    UI 下拉刷新 EGOTableViewPullRefresh – 最早的下拉刷新控件. SVPullToRefresh – 下拉刷新控件. MJRefresh – 仅需一行代码就可以为UITable ...

  5. iOS开发常用第三方库

    UI 动画 网络相关 Model 其他 数据库 缓存处理 PDF 图像浏览及处理 摄像照相视频音频处理 响应式框架 消息相关 版本新API的Demo 代码安全与密码 测试及调试 AppleWatch ...

  6. python 的库如何开发_如何开发Python第三方库?

    自己写过几个开源第三方库,说说具体流程吧. 1.明确项目需求.你的库必须要有实际作用,开发一些没有意义的库毫无意义.且你必须保证程序的稳定性和可持续性,为接下来的开发和更新做准备. 2.发布开源项目. ...

  7. python游戏开发的第三方库有哪些_Python 游戏开发方向的第三方库是

    Python 游戏开发方向的第三方库是 答:Pygame 内分泌器官包括( ) 答:甲状腺 松果体 甲状旁腺 垂体 我国的社会保险制度体系主要包括.医疗保险.失业保险.工伤保险.生育保险等内容 答:养 ...

  8. iOS开发——导入第三方库引起的unknown type name 'NSString'

    今天加入SVProgressHUD的第三方库的时候报了24个错误( too many errors emitted, stopping now),都是 expected identifier or ' ...

  9. 机器人开发常见第三方库、软件安装和使用

    写在前面: 大多数情况下,没有人比官方更懂官方,所以编译安装.库配置及简单使用优先看官方github仓库README或者官网,当然不排除有些博文或者教程有更好的表达方式更详细的说明 cmake 编译三 ...

最新文章

  1. hdfs入门——常用命令
  2. 怎样玩儿转App手游自动化测试?
  3. javascript闭包学习
  4. rest framework 序列化
  5. 那些年我看过的前端书
  6. plsql developer无法识别32位oracle问题如何解决?
  7. 联合哈佛大学,Google 要用人工智能来预测地震余震
  8. 拖拽实例 对于设置监听setInterval 的理解
  9. spring3.1.0 jar包详解说明
  10. Oracle学习笔记(1)----忘记用户名的密码该如何找回
  11. 创新创业基础答案李家华金利杰
  12. html使table整体居中,如何让整个table表格居中?
  13. Segger和Micrium之间的区别和联系
  14. 关于英语单词记忆的总结
  15. 浅谈缓存-注解驱动的缓存 Spring cache介绍
  16. qq等级查询php源码,基于PHP的QQ等级计算器
  17. hdu 5442 (后缀数组)
  18. OpenDDS和RTI DDS内置数据类型的互联互通测试
  19. 清华大学2020年“姚班”“智班”报考指南及选拔方案发布!
  20. 从达沃斯世界经济论坛,看区块链和数字货币的三大发展趋势

热门文章

  1. 计算机考试word文档怎么画坐标,使用WORD画坐标系的方法
  2. 使用 Learner Lab - 使用 AWS Lambda 将图片写入 S3
  3. 视频格式那么多,MP4/RMVB/MKV/AVI 等,这些视频格式与编码压缩标准 mpeg4,H.264.H.265 等有什么关系?...
  4. 怎么压缩图片 ? 掌握这几种免费压缩图片的方法就够了
  5. STM32使用库函数点灯实验
  6. 新研究调查Masimo ORi™(氧储备指数)能否用作避免全麻期间高氧状态的指数
  7. LR之录制脚本修改完善
  8. 如何利用Simulink来设计一个AEB的算法,并通过SCANeR仿真来测试?
  9. Qt - 换肤功能实现
  10. 四十七、使用bootstrap中的选项卡制作产品特色页面