• VisionMaster自定义模块


    一、参考资料:

    1、教学视频

    2、VM服务管家

    【VM服务管家】VM4.x算法模块开发_4.3 联合Halcon开发-CSDN博客问题:有的用户在使用VisionMaster软件在开发视觉项目时,可能同时也使用HALCON,OpenCV等视觉算法库做一些图像的处理,并且希望能将HALCON等第三方算子集成到VM工具箱,能够在VM工具箱中拖拽出来,就像VisionMaster中的其他算法模块工具一样,可以通过弹出窗口配置运行参数,通过连线订阅其他模块传递的参数,设置ROI,通过图像窗口查看算法直接结果的渲染效果。实际上是可行的,VisionMaster是一个开放平台,可以接入第三方生态,这也是VisionMaster的一大亮点。https://blog.csdn.net/MVExpert/article/details/130413120

     3、二次开发之第三方库的使用

    【VisionMaster】二次开发之第三方库的使用_visionmaster二次开发-CSDN博客二次开发之第三方库的使用_visionmaster二次开发https://blog.csdn.net/zhy29563/article/details/124115483

    4、开发文档

    二、一些注意的点

    1、输出变量的定义

     2、多个ROI的实现

    本来是Single,说明只有一个ROI,我改成Mul之后,就可以多个ROI了

    3、设置halcon字符识别全局变量

    下图中,再Init函数种,放入那两个函数,还是有必要的,防止每次运行该模块,都会耗费时间create

    三、一些代码

    1、头文件

    1. #ifdef EXAMPLEMODULE_EXPORTS
    2. #define LINEMODULE_API __declspec(dllexport)
    3. #else
    4. #define LINEMODULE_API __declspec(dllimport)
    5. #endif
    6. #include "VmModuleBase.h"
    7. #include "VmAlgModuBase.h"
    8. #include "ErrorCodeDefine.h"
    9. #include "VmModuleSharedMemoryBase.h"
    10. #include "halconcpp.h"
    11. using namespace HalconCpp;
    12. // This class is exported from the LineModule.dll
    13. class LINEMODULE_API CAlgorithmModule : public CVmAlgModuleBase, public CModuleSharedMemoryBase
    14. {
    15. public:
    16. // 构造
    17. explicit CAlgorithmModule();
    18. // 析构
    19. virtual ~CAlgorithmModule();
    20. public:
    21. // 初始化
    22. int Init();
    23. // 进行算法
    24. int Process(IN void* hInput, IN void* hOutput, IN MVDSDK_BASE_MODU_INPUT* modu_input);
    25. // 获取算法参数
    26. int GetParam(IN const char* szParamName, OUT char* pBuff, IN int nBuffSize, OUT int* pDataLen);
    27. // 设置算法参数
    28. int SetParam(IN const char* szParamName, IN const char* pData, IN int nDataLen);
    29. //获取halcon格式图像,高恩阳的函数
    30. HObject GetHalconImage(MVDSDK_BASE_MODU_INPUT* modu_input);
    31. //我的DeepOCR
    32. string MyDeepOCR(IN HObject in);
    33. void set_suitable_device_in_ocr_handle(HTuple hv_DeepOcrHandle);
    34. public:
    35. //void* m_hModule; // 模块句柄 - 4.3 在基类中定义了
    36. private:
    37. int m_ntheta;
    38. HTuple hv_DeepOcrHandle;
    39. };
    40. /模块须导出的接口(实现开始)//
    41. #ifdef __cplusplus
    42. extern "C"
    43. {
    44. #endif
    45. // 采用__stdcall调用约定,且须在.def文件中增加接口描述。
    46. LINEMODULE_API CAbstractUserModule* __stdcall CreateModule(void* hModule);
    47. LINEMODULE_API void __stdcall DestroyModule(void* hModule, CAbstractUserModule* pUserModule);
    48. #ifdef __cplusplus
    49. };
    50. #endif
    51. /模块须导出的接口(实现结束)//

     2、cpp文件

    1. #include "stdafx.h"
    2. #include "AlgorithmModule.h"
    3. #include
    4. #include
    5. #include "ErrorCodeDefine.h"
    6. #include "iMVS-6000PixelFormatDefine.h"
    7. #include
    8. #include
    9. #include
    10. #include
    11. #include
    12. using namespace std;
    13. CAlgorithmModule::CAlgorithmModule()
    14. {
    15. m_ntheta = 128;
    16. }
    17. CAlgorithmModule::~CAlgorithmModule()
    18. {
    19. }
    20. int CAlgorithmModule::Init()
    21. {
    22. int nRet = VM_M_GetModuleId(m_hModule, &m_nModuleId);
    23. if (IMVS_EC_OK != nRet)
    24. {
    25. m_nModuleId = -1;
    26. return nRet;
    27. }
    28. nRet = ResetDefaultParam();
    29. if (nRet != IMVS_EC_OK)
    30. {
    31. OutputDebugStringA("###Call ResetDefaultParam failed.");
    32. }
    33. CreateDeepOcr(HTuple(), HTuple(), &hv_DeepOcrHandle);
    34. set_suitable_device_in_ocr_handle(hv_DeepOcrHandle);
    35. return nRet;
    36. }
    37. HObject CAlgorithmModule::GetHalconImage(MVDSDK_BASE_MODU_INPUT* modu_input)
    38. {
    39. HObject background_image1;
    40. GenEmptyObj(&background_image1);
    41. int width = modu_input->pImageInObj->GetWidth();
    42. int height = modu_input->pImageInObj->GetHeight();
    43. if (modu_input->pImageInObj->GetImageData(0)->pData != nullptr)
    44. {
    45. if (MVD_PIXEL_MONO_08 == modu_input->pImageInObj->GetPixelFormat())
    46. {
    47. GenImage1(&background_image1
    48. , "byte"
    49. , static_cast<int>(modu_input->pImageInObj->GetWidth())
    50. , static_cast<int>(modu_input->pImageInObj->GetHeight())
    51. , reinterpret_cast(modu_input->pImageInObj->GetImageData(0)->pData)
    52. );
    53. }
    54. if (MVD_PIXEL_RGB_RGB24_C3 == modu_input->pImageInObj->GetPixelFormat())
    55. {
    56. unsigned char* r = new unsigned char[width * height];
    57. unsigned char* g = new unsigned char[width * height];
    58. unsigned char* b = new unsigned char[width * height];
    59. for (size_t i = 0; i < width * height; i++)
    60. {
    61. r[i] = *((modu_input->pImageInObj->GetImageData(0)->pData) + i*3);
    62. g[i] = *((modu_input->pImageInObj->GetImageData(0)->pData) + i*3+1);
    63. b[i] = *((modu_input->pImageInObj->GetImageData(0)->pData) + i*3+2);
    64. }
    65. GenImage3(&background_image1
    66. , "byte"
    67. , static_cast<int>(modu_input->pImageInObj->GetWidth())
    68. , static_cast<int>(modu_input->pImageInObj->GetHeight())
    69. , reinterpret_cast(r)
    70. , reinterpret_cast(g)
    71. , reinterpret_cast(b)
    72. );
    73. }
    74. return ho_image;
    75. }
    76. string CAlgorithmModule::MyDeepOCR(IN HObject in)
    77. {
    78. HTuple hv_DeepOcrResult;
    79. HTuple hv_RecognizedWords,hv_RecognizedWord;
    80. ApplyDeepOcr(in, hv_DeepOcrHandle, "auto", &hv_DeepOcrResult);
    81. GetDictTuple(hv_DeepOcrResult, "words", &hv_RecognizedWords);
    82. GetDictTuple(hv_RecognizedWords, "word", &hv_RecognizedWord);
    83. int wordCount = hv_RecognizedWord.Length();
    84. string strBuff;
    85. for (size_t i = 0; i < wordCount; i++)
    86. {
    87. strBuff += hv_RecognizedWord[i].S();
    88. }
    89. return strBuff;
    90. }
    91. void CAlgorithmModule::set_suitable_device_in_ocr_handle(HTuple hv_DeepOcrHandle)
    92. {
    93. // Local control variables
    94. HTuple hv_DLDeviceHandles, hv_RecognitionImageWidthDefault;
    95. HTuple hv_Exception, hv_Index;
    96. //Determine deep learning device to work with (prefer GPU over CPU).
    97. QueryAvailableDlDevices((HTuple("runtime").Append("runtime")), (HTuple("gpu").Append("cpu")),
    98. &hv_DLDeviceHandles);
    99. if (0 != (int((hv_DLDeviceHandles.TupleLength()) == 0)))
    100. {
    101. throw HException("No supported device found to continue this example.");
    102. }
    103. //Set recognition_image_width larger for the example to work without memory problems.
    104. try
    105. {
    106. GetDeepOcrParam(hv_DeepOcrHandle, "recognition_image_width", &hv_RecognitionImageWidthDefault);
    107. SetDeepOcrParam(hv_DeepOcrHandle, "recognition_image_width", 250);
    108. }
    109. // catch (Exception)
    110. catch (HException& HDevExpDefaultException)
    111. {
    112. HDevExpDefaultException.ToHTuple(&hv_Exception);
    113. }
    114. //
    115. {
    116. HTuple end_val12 = (hv_DLDeviceHandles.TupleLength()) - 1;
    117. HTuple step_val12 = 1;
    118. for (hv_Index = 0; hv_Index.Continue(end_val12, step_val12); hv_Index += step_val12)
    119. {
    120. try
    121. {
    122. SetDeepOcrParam(hv_DeepOcrHandle, "device", HTuple(hv_DLDeviceHandles[hv_Index]));
    123. break;
    124. }
    125. // catch (Exception)
    126. catch (HException& HDevExpDefaultException)
    127. {
    128. HDevExpDefaultException.ToHTuple(&hv_Exception);
    129. if (0 != (int(hv_Index == ((hv_DLDeviceHandles.TupleLength()) - 1))))
    130. {
    131. throw HException("Could not set any of the supported devices to continue this example.");
    132. }
    133. }
    134. }
    135. }
    136. //Reset recognition_image_width to the default value.
    137. try
    138. {
    139. SetDeepOcrParam(hv_DeepOcrHandle, "recognition_image_width", hv_RecognitionImageWidthDefault);
    140. }
    141. // catch (Exception)
    142. catch (HException& HDevExpDefaultException)
    143. {
    144. HDevExpDefaultException.ToHTuple(&hv_Exception);
    145. }
    146. //
    147. return;
    148. }
    149. int CAlgorithmModule::Process(IN void* hInput, IN void* hOutput, IN MVDSDK_BASE_MODU_INPUT* modu_input)
    150. {
    151. OutputDebugStringA("###Call CAlgorithmModule::Proces -->begin\n");
    152. int nErrCode = 0;
    153. // 1.获取输入
    154. /************************************************/
    155. //ToDo Code...............
    156. HObject myImage=GetHalconImage(modu_input);
    157. int nsize = modu_input->vtFixRoiShapeObj.size();
    158. /************************************************/
    159. // 2.算法处理
    160. OutputDebugStringA("###Call CAlgorithmModule::Proces --> do algorighm process\n");
    161. /************************************************/
    162. for (size_t i = 0; i < nsize; i++)
    163. {
    164. IMvdRectangleF* rectangleRoi = dynamic_cast(modu_input->vtFixRoiShapeObj[i]);
    165. int width = rectangleRoi->GetWidth();
    166. int height = rectangleRoi->GetHeight();
    167. int centerX = rectangleRoi->GetCenterX();
    168. int centerY = rectangleRoi->GetCenterY();
    169. HObject rect,imageReduced,imageCroped;
    170. GenRectangle2(&rect, centerY, centerX, 0, width / 2, height / 2);
    171. HTuple Row1, Column1, Row2, Column2;
    172. SmallestRectangle1(rect, &Row1, &Column1, &Row2, &Column2);
    173. CropRectangle1(myImage, &imageCroped, Row1, Column1, Row2, Column2);
    174. ReduceDomain(myImage, rect, &imageReduced);
    175. //if (0 == i)
    176. //{
    177. // WriteImage(imageCroped, "bmp", 0, "D:\\gao\\ocr0");
    178. //}
    179. //if (1 == i)
    180. //{
    181. // WriteImage(imageCroped, "bmp", 0, "D:\\gao\\ocr1");
    182. //}
    183. //if (2 == i)
    184. //{
    185. // WriteImage(imageCroped, "bmp", 0, "D:\\gao\\ocr2");
    186. //}
    187. //if (3 == i)
    188. //{
    189. // WriteImage(imageCroped, "bmp", 0, "D:\\gao\\ocr3");
    190. //}
    191. //if (4 == i)
    192. //{
    193. // WriteImage(imageCroped, "bmp", 0, "D:\\gao\\ocr4");
    194. //}
    195. string ocrStr = MyDeepOCR(imageCroped);
    196. ofstream file1;
    197. //file1.open("D:\\gao\\car.txt", ios::app); // 所有输出附加在文件末尾,用追加的方式写入,
    198. // 写入追加的结果以换行的方式往下添加
    199. if (file1.is_open())
    200. {
    201. cout << "正确打开文件! " << endl;
    202. file1 << ocrStr << endl;
    203. }
    204. file1.close();
    205. const char* p = ocrStr.data();
    206. VM_M_SetString(hOutput, "mystring", i, p);
    207. }
    208. //ToDo Code...............
    209. /************************************************/
    210. // 3.输出结果
    211. /************************************************/
    212. //ToDo Code...............
    213. //输出图像(渲染控件只能显示共享内存中的图像数据)
    214. //char* pSharedName = NULL;
    215. //HKA_IMAGE stImage;
    216. //stImage.height = heightValue;
    217. //stImage.width = widthValue;
    218. //stImage.step[0] = widthValue;
    219. //int nRet = AllocateSharedMemory(m_nModuleId, stImage.height*stImage.width, (char**)(&stImage.data), &pSharedName);
    220. //if (nRet == IMVS_EC_OK && stImage.data != NULL)
    221. //{
    222. // memcpy_s(......);
    223. // VmModule_OutputImageByName_8u_C1R(hOutput,
    224. // status,
    225. // OUTIMAGE,
    226. // OUTIMAGEWIDTH,
    227. // OUTIMAGEHEIGHT,
    228. // OUTIMAGEPIXELFORMAT,
    229. // &stImage,
    230. // 0,
    231. // pSharedName);
    232. //}
    233. /************************************************/
    234. if (nErrCode != IMVS_EC_OK)
    235. {
    236. return IMVS_EC_PARAM;
    237. }
    238. /************************************************/
    239. //默认算法时间20ms,根据实际时间计算
    240. MODULE_RUNTIME_INFO struRunInfo = { 0 };
    241. struRunInfo.fAlgorithmTime = 20;
    242. VM_M_SetModuleRuntimeInfo(m_hModule, &struRunInfo);
    243. OutputDebugStringA("###Call CAlgorithmModule::Proces end\n");
    244. return IMVS_EC_OK;
    245. }
    246. int CAlgorithmModule::GetParam(IN const char* szParamName, OUT char* pBuff, IN int nBuffSize, OUT int* pDataLen)
    247. {
    248. OutputDebugStringA("###Call CAlgorithmModule::GetParam");
    249. int nMsgLen = 0;
    250. int nErrCode = IMVS_EC_OK;
    251. if (szParamName == NULL || strlen(szParamName) == 0 || pBuff == NULL || nBuffSize <= 0 || pDataLen == NULL)
    252. {
    253. return IMVS_EC_PARAM;
    254. }
    255. //memset(pBuff, 0, nBuffSize);
    256. if (0 == strcmp("theta", szParamName))
    257. {
    258. sprintf_s(pBuff, nBuffSize, "%d", m_ntheta);
    259. }
    260. else
    261. {
    262. return CVmAlgModuleBase::GetParam(szParamName, pBuff, nBuffSize, pDataLen);
    263. }
    264. //if(0 == strcmp(szParamName, "paramA"))
    265. //{
    266. // sprintf(pBuff, nBuffSize, "", ..);
    267. //}
    268. return nErrCode;
    269. }
    270. int CAlgorithmModule::SetParam(IN const char* szParamName, IN const char* pData, IN int nDataLen)
    271. {
    272. OutputDebugStringA("###Call CAlgorithmModule::SetParam");
    273. int nErrCode = IMVS_EC_OK;
    274. if (szParamName == NULL || strlen(szParamName) == 0 || pData == NULL || nDataLen == 0)
    275. {
    276. return IMVS_EC_PARAM;
    277. }
    278. if (0 == strcmp("theta", szParamName))
    279. {
    280. sscanf_s(pData, "%d", &m_ntheta);
    281. }
    282. else
    283. {
    284. return CVmAlgModuleBase::SetParam(szParamName, pData, nDataLen);
    285. }
    286. return nErrCode;
    287. }
    288. /模块须导出的接口(实现开始)//
    289. LINEMODULE_API CAbstractUserModule* __stdcall CreateModule(void* hModule)
    290. {
    291. assert(hModule != NULL);
    292. // 创建用户模块,并记录实例。
    293. CAlgorithmModule* pUserModule = new(nothrow) CAlgorithmModule;
    294. if (pUserModule == NULL)
    295. {
    296. return NULL;
    297. }
    298. pUserModule->m_hModule = hModule;
    299. int nRet = pUserModule->Init();
    300. if (IMVS_EC_OK != nRet)
    301. {
    302. delete pUserModule;
    303. return NULL;
    304. }
    305. OutputDebugStringA("###Call CreateModule");
    306. return pUserModule;
    307. }
    308. LINEMODULE_API void __stdcall DestroyModule(void* hModule, CAbstractUserModule* pUserModule)
    309. {
    310. assert(hModule != NULL);
    311. OutputDebugStringA("###Call DestroyModule");
    312. if (pUserModule != NULL)
    313. {
    314. delete pUserModule;
    315. }
    316. }
    317. /模块须导出的接口(实现结束)//

  • 相关阅读:
    基于ChatGPT打造安全脚本工具流程
    Sulfo-Cy3 NHS酯,Sulfo-Cy3 NHS ester,水溶性荧光染料Cy3标记琥珀酰亚胺活化酯
    【024】 快速上手mongoose web服务器
    MMSC BAPI
    什么是数字化?什么是数字化转型?为什么企业选择数字化转型?
    【内网穿透】公网远程访问本地硬盘文件
    数据结构<4>栈和队列——原理+实现
    <img>图片格式类型
    MATLAB初学者入门(17)—— 爬山算法
    MySQL_05:排序和分页
  • 原文地址:https://blog.csdn.net/gaoenyang760525/article/details/133782519