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、头文件

#ifdef EXAMPLEMODULE_EXPORTS
#define LINEMODULE_API __declspec(dllexport)
#else
#define LINEMODULE_API __declspec(dllimport)
#endif
#include "VmModuleBase.h"
#include "VmAlgModuBase.h"
#include "ErrorCodeDefine.h"
#include "VmModuleSharedMemoryBase.h"

#include "halconcpp.h"
using namespace HalconCpp;

// This class is exported from the LineModule.dll
class LINEMODULE_API CAlgorithmModule : public CVmAlgModuleBase, public CModuleSharedMemoryBase
{
public:
	// 构造
	explicit CAlgorithmModule();
	
	// 析构
	virtual ~CAlgorithmModule();

public:

	// 初始化
	int Init();

	// 进行算法
	int Process(IN void* hInput, IN void* hOutput, IN MVDSDK_BASE_MODU_INPUT* modu_input);

	// 获取算法参数
	int GetParam(IN const char* szParamName, OUT char* pBuff, IN int nBuffSize, OUT int* pDataLen);

	// 设置算法参数
	int SetParam(IN const char* szParamName, IN const char* pData, IN int nDataLen);

	//获取halcon格式图像,高恩阳的函数
	HObject GetHalconImage(MVDSDK_BASE_MODU_INPUT* modu_input);

	//我的DeepOCR
	string MyDeepOCR(IN HObject in);

	void set_suitable_device_in_ocr_handle(HTuple hv_DeepOcrHandle);

public:
	//void* m_hModule;   // 模块句柄 - 4.3 在基类中定义了


private:

	int m_ntheta;
	HTuple  hv_DeepOcrHandle;

};


/模块须导出的接口(实现开始)//
#ifdef __cplusplus
extern "C"
{
#endif
    
    // 采用__stdcall调用约定,且须在.def文件中增加接口描述。
	LINEMODULE_API CAbstractUserModule* __stdcall CreateModule(void* hModule);
	LINEMODULE_API void __stdcall DestroyModule(void* hModule, CAbstractUserModule* pUserModule);

#ifdef __cplusplus
};
#endif
/模块须导出的接口(实现结束)//

 2、cpp文件

#include "stdafx.h"
#include "AlgorithmModule.h"
#include <stdlib.h>
#include <fstream>
#include "ErrorCodeDefine.h"
#include "iMVS-6000PixelFormatDefine.h"


#include<iostream>
#include<fstream>
#include<ctime>
#include<string>
#include<sstream>
using namespace std;



CAlgorithmModule::CAlgorithmModule()
{
	m_ntheta = 128;
}

CAlgorithmModule::~CAlgorithmModule()
{

}

int CAlgorithmModule::Init()
{

	int nRet = VM_M_GetModuleId(m_hModule, &m_nModuleId);
	if (IMVS_EC_OK != nRet)
	{
		m_nModuleId = -1;
		return nRet;
	}

	nRet = ResetDefaultParam();
	if (nRet != IMVS_EC_OK)
	{
		OutputDebugStringA("###Call ResetDefaultParam failed.");
	}

	CreateDeepOcr(HTuple(), HTuple(), &hv_DeepOcrHandle);
	set_suitable_device_in_ocr_handle(hv_DeepOcrHandle);


	return nRet;
}

HObject CAlgorithmModule::GetHalconImage(MVDSDK_BASE_MODU_INPUT* modu_input)
{
	HObject background_image1;
	GenEmptyObj(&background_image1);

		int width = modu_input->pImageInObj->GetWidth();
	int height = modu_input->pImageInObj->GetHeight();


	if (modu_input->pImageInObj->GetImageData(0)->pData != nullptr)
	{
		if (MVD_PIXEL_MONO_08 == modu_input->pImageInObj->GetPixelFormat())
		{
			GenImage1(&background_image1
				, "byte"
				, static_cast<int>(modu_input->pImageInObj->GetWidth())
				, static_cast<int>(modu_input->pImageInObj->GetHeight())
				, reinterpret_cast<Hlong>(modu_input->pImageInObj->GetImageData(0)->pData)
			);
		}

		if (MVD_PIXEL_RGB_RGB24_C3 == modu_input->pImageInObj->GetPixelFormat())
		{

			unsigned char* r = new unsigned char[width * height];
			unsigned char* g = new unsigned char[width * height];
			unsigned char* b = new unsigned char[width * height];

			for (size_t i = 0; i < width * height; i++)
			{
				r[i] = *((modu_input->pImageInObj->GetImageData(0)->pData)  + i*3);
				g[i] = *((modu_input->pImageInObj->GetImageData(0)->pData)  + i*3+1);
				b[i] = *((modu_input->pImageInObj->GetImageData(0)->pData)  + i*3+2);

			}

			GenImage3(&background_image1
				, "byte"
				, static_cast<int>(modu_input->pImageInObj->GetWidth())
				, static_cast<int>(modu_input->pImageInObj->GetHeight())
				, reinterpret_cast<Hlong>(r)
				, reinterpret_cast<Hlong>(g)
				, reinterpret_cast<Hlong>(b)
			);
		}


	return ho_image;
	
}

string CAlgorithmModule::MyDeepOCR(IN HObject in)
{

	HTuple  hv_DeepOcrResult;
	HTuple  hv_RecognizedWords,hv_RecognizedWord;

	ApplyDeepOcr(in, hv_DeepOcrHandle, "auto", &hv_DeepOcrResult);
	GetDictTuple(hv_DeepOcrResult, "words", &hv_RecognizedWords);
	GetDictTuple(hv_RecognizedWords, "word", &hv_RecognizedWord);
	int wordCount = hv_RecognizedWord.Length(); 
	string strBuff;
	for (size_t i = 0; i < wordCount; i++)
	{
		strBuff += hv_RecognizedWord[i].S();
	}

	return strBuff;
}

void CAlgorithmModule::set_suitable_device_in_ocr_handle(HTuple hv_DeepOcrHandle)
{

	// Local control variables
	HTuple  hv_DLDeviceHandles, hv_RecognitionImageWidthDefault;
	HTuple  hv_Exception, hv_Index;

	//Determine deep learning device to work with (prefer GPU over CPU).
	QueryAvailableDlDevices((HTuple("runtime").Append("runtime")), (HTuple("gpu").Append("cpu")),
		&hv_DLDeviceHandles);
	if (0 != (int((hv_DLDeviceHandles.TupleLength()) == 0)))
	{
		throw HException("No supported device found to continue this example.");
	}
	//Set recognition_image_width larger for the example to work without memory problems.
	try
	{
		GetDeepOcrParam(hv_DeepOcrHandle, "recognition_image_width", &hv_RecognitionImageWidthDefault);
		SetDeepOcrParam(hv_DeepOcrHandle, "recognition_image_width", 250);
	}
	// catch (Exception) 
	catch (HException& HDevExpDefaultException)
	{
		HDevExpDefaultException.ToHTuple(&hv_Exception);
	}
	//
	{
		HTuple end_val12 = (hv_DLDeviceHandles.TupleLength()) - 1;
		HTuple step_val12 = 1;
		for (hv_Index = 0; hv_Index.Continue(end_val12, step_val12); hv_Index += step_val12)
		{
			try
			{
				SetDeepOcrParam(hv_DeepOcrHandle, "device", HTuple(hv_DLDeviceHandles[hv_Index]));
				break;
			}
			// catch (Exception) 
			catch (HException& HDevExpDefaultException)
			{
				HDevExpDefaultException.ToHTuple(&hv_Exception);
				if (0 != (int(hv_Index == ((hv_DLDeviceHandles.TupleLength()) - 1))))
				{
					throw HException("Could not set any of the supported devices to continue this example.");
				}
			}
		}
	}
	//Reset recognition_image_width to the default value.
	try
	{
		SetDeepOcrParam(hv_DeepOcrHandle, "recognition_image_width", hv_RecognitionImageWidthDefault);
	}
	// catch (Exception) 
	catch (HException& HDevExpDefaultException)
	{
		HDevExpDefaultException.ToHTuple(&hv_Exception);
	}
	//
	return;
}

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.获取输入
	
	/************************************************/

	//ToDo Code...............
	HObject myImage=GetHalconImage(modu_input);
    int nsize = modu_input->vtFixRoiShapeObj.size();

	/************************************************/

// 2.算法处理
	OutputDebugStringA("###Call CAlgorithmModule::Proces --> do algorighm process\n");

	/************************************************/
	for (size_t i = 0; i < nsize; i++)
	{
		IMvdRectangleF* rectangleRoi = dynamic_cast<IMvdRectangleF*>(modu_input->vtFixRoiShapeObj[i]);
		int width = rectangleRoi->GetWidth();
		int height = rectangleRoi->GetHeight();
		int centerX = rectangleRoi->GetCenterX();
		int centerY = rectangleRoi->GetCenterY();
		HObject rect,imageReduced,imageCroped;
		GenRectangle2(&rect, centerY, centerX, 0, width / 2, height / 2);
		HTuple Row1, Column1, Row2, Column2;
		SmallestRectangle1(rect, &Row1, &Column1, &Row2, &Column2);
		CropRectangle1(myImage, &imageCroped, Row1, Column1, Row2, Column2);
		ReduceDomain(myImage, rect, &imageReduced);
		//if (0 == i)
		//{
		//	WriteImage(imageCroped, "bmp", 0, "D:\\gao\\ocr0");
		//}
		//if (1 == i)
		//{
		//	WriteImage(imageCroped, "bmp", 0, "D:\\gao\\ocr1");
		//}
		//if (2 == i)
		//{
		//	WriteImage(imageCroped, "bmp", 0, "D:\\gao\\ocr2");
		//}
		//if (3 == i)
		//{
		//	WriteImage(imageCroped, "bmp", 0, "D:\\gao\\ocr3");
		//}
		//if (4 == i)
		//{
		//	WriteImage(imageCroped, "bmp", 0, "D:\\gao\\ocr4");
		//}

		

		string ocrStr = MyDeepOCR(imageCroped);

		ofstream file1;
		//file1.open("D:\\gao\\car.txt", ios::app);      //   所有输出附加在文件末尾,用追加的方式写入,
		//   写入追加的结果以换行的方式往下添加
		if (file1.is_open())
		{
			cout << "正确打开文件! " << endl;
			file1 << ocrStr << endl;

		}
		file1.close();


		const char* p = ocrStr.data();
		VM_M_SetString(hOutput, "mystring", i, p);
	}
	//ToDo Code...............

	/************************************************/


// 3.输出结果
	
	/************************************************/

	//ToDo Code...............

    //输出图像(渲染控件只能显示共享内存中的图像数据)
        //char* pSharedName = NULL;
        //HKA_IMAGE stImage;
        //stImage.height = heightValue;
        //stImage.width = widthValue;
        //stImage.step[0] = widthValue;
        //int nRet = AllocateSharedMemory(m_nModuleId, stImage.height*stImage.width, (char**)(&stImage.data), &pSharedName);
        //if (nRet == IMVS_EC_OK && stImage.data != NULL)
        //{
        //    memcpy_s(......);
        //    VmModule_OutputImageByName_8u_C1R(hOutput, 
		//		  status, 
		//		  OUTIMAGE, 
		//		  OUTIMAGEWIDTH, 
		//		  OUTIMAGEHEIGHT, 
		//		  OUTIMAGEPIXELFORMAT, 
		//		  &stImage, 
		//		  0, 
		//		  pSharedName);
        //}


	/************************************************/

	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 nMsgLen = 0;
	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("theta", szParamName))
	{
		sprintf_s(pBuff, nBuffSize, "%d", m_ntheta);
	}
	else
	{
		return CVmAlgModuleBase::GetParam(szParamName, pBuff, nBuffSize, pDataLen);
	}
	//if(0 == strcmp(szParamName, "paramA"))
	//{
	//	  sprintf(pBuff, nBuffSize, "", ..);
	//}
	
	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("theta", szParamName))
	{
		sscanf_s(pData, "%d", &m_ntheta);
	}
	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;
	}

	OutputDebugStringA("###Call CreateModule");

	return pUserModule;
}


LINEMODULE_API void __stdcall DestroyModule(void* hModule, CAbstractUserModule* pUserModule)
{
	assert(hModule != NULL);
	OutputDebugStringA("###Call DestroyModule");

	if (pUserModule != NULL)
	{
		delete pUserModule;
	}
}
/模块须导出的接口(实现结束)//

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
VisionMaster分支模块是在现有的VisionMaster控制系统基础上开发的一种可扩展模块,旨在满足更多复杂的处理场景需求。在工业自动化控制系统中,VisionMaster分支模块可以协同工业机器视觉技术,通过高速采集和处理图像数据,实时获取生产线上的图像信息,保障生产线的高效、准确、稳定运行。 VisionMaster分支模块所提供的功能包括图像采集、图像处理、特征提取、图像识别等。其优秀的性能和稳定性,不仅可以应用于工业领域,也可以用于医疗、交通、安防等领域。比如,在医疗领域可以用于病灶的检测、医学影像的处理等方面,在交通领域可以用于交通监测、车辆识别等方面,在安防领域可以用于人脸识别、车辆识别等方面,具有广泛的应用前景和市场空间。 VisionMaster分支模块采用现代化的算法和技术,可以实现高精度的图像识别,解决了传统图像处理技术中易受光照、角度、噪声等因素影响的问题。同时,VisionMaster分支模块的可扩展性和灵活性也为工业控制系统的升级提供了更多选择和空间,使加工精度更高、运行效率更快、产品质量更可靠。 总的来说,VisionMaster分支模块是一种高性能的工业控制系统模块,它的可靠性和性能能够满足各种生产场景下的需求。VisionMaster分支模块为各行各业的生产线提高了运行效率和产品质量的保证,是工业智能化发展的重要组成部分之一。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值