VM是海康机器人自主研发的机器视觉软件,将一系列的图像算法、逻辑工具和通讯协议等封装成图形化模块,致力于帮助客户提供快速搭建视觉应用、解决视觉难题,能够满足视觉定位、尺寸测量、缺陷检测以及信息识别等机器视觉应用。


目录

  • 1 引言
  • 2 脚本模块
  • 2.1 接口介绍
  • 2.2 引用和调试
  • 2.3 VM4.2更新
  • 3 案例演示
  • 4 总结


1 引言

VM工具箱包含一百多个算法模块可供用户通过连线组合的方式来完成相应的视觉需求,但模块间数据处理逻辑是实际应用中不可或缺的。此时,使用脚本模块就可以灵活处理数据,提高方案的适用性。脚本使用的常用场景包括:日志打印、坐标排序、定位偏差计算、检测结果分类、图像格式转换、联合OpenCV开发等等。
脚本模块由三部分组成:输入变量、输出变量以及数据处理逻辑。脚本模块支持代码导入和导出功能,导出文件格式后缀为.cs;可编辑程序集来调用第三方库;可直接在脚本编辑页面编写代码、预编译和执行;也可导出当前脚本的工程,打开导出工程所在文件夹,再使用Visual Studio打开工程、附加到进程就可以进行脚本的实时调试,具体介绍见脚本模块章节。

2 脚本模块

双击打开脚本模块,界面如下所示,可以分为五个区域:变量输入区、变量输出区、菜单栏、C#编程区、提示区。

海康VM软件深度学习_计算机视觉

C#编程区的代码可分为三部分:命名空间、初始化函数、执行函数。Init()函数为初始化函数,Process()为执行函数。

海康VM软件深度学习_人工智能_02

2.1 接口介绍

使用脚本模块的目的,主要是为了处理数据,那么就需要获取脚本输入的数据以及通过设置数据将脚本某些结果进行输出,因此需要了解相应的获取和设置数据的接口函数。针对不同类型的数据有不同的接口函数,如:string、float、int、byte、image等数据类型的获取和设置接口大同小异。另外,还可以使用通信的发送数据接口,全局变量获取及设置接口,模块的结果获取和运行参数设置。

  1. 数据类型接口

功能

函数方法

参数说明

获取int型

GetIntValue(string paramName, ref int paramValue)

输入:变量名paramName;输出:变量值paramValue

获取float型

GetFloatValue (string paramName, ref float paramValue)

输入:变量名paramName;输出:变量值paramValue

获取string型

GetStringValue (string paramName, ref string paramValue)

输入:变量名paramName;输出:变量值paramValue

获取byte型

GetBytesValue (string paramName,ref byte[] paramValue)

输入:变量名paramName;输出:变量值paramValue

获取图像数据

GetIMAGEValue (string paramName, ref Image paramValue)

输入:变量名paramName;输出:变量值paramValue

获取int型数组

GetIntArrayValue(string paramName, ref int[] paramValue,out int arrayCount)

输入:变量名paramName;输出:变量值paramValue,数组个数arrayCount

获取float型数组

GetFloatArrayValue(string paramName, ref float[] paramValue,out int arrayCount)

输入:变量名paramName;输出:变量值paramValue,数组个数arrayCount

获取string型数组

GetStringArrayValue(string paramName, ref string[] paramValue,out int arrrayCount)

输入:变量名paramName;输出:变量值paramValue,数组个数arrayCount

设置int型

SetIntValue(string key, int value)

输入:变量名key,变量值value

设置float型

SetFloatValue (string key, float value)

输入:变量名key,变量值value

设置string型

SetStringValue (string key, string value)

输入:变量名key,变量值value

设置byte型

SetBytesValue (string key, byte[] value)

输入:变量名key,变量值value

设置图像数据

SetImageValue (string key, Image value)

输入:变量名key,变量值value

设置int型数组

SetIntValueByIndex(string key, int[] value, int index, int total)

输入:变量名key,变量值value,数组索引index,数组元素个数total

设置float型数组

SetFloatValueByIndex (string key, float[] value, int index, int total)

输入:变量名key,变量值value,数组索引index,数组元素个数total

设置string型数组

SetStringValueByIndex(string key, string[] value, int index, int total)

输入:变量名key,变量值value,数组索引index,数组元素个数total

  1. 其它接口

功能

函数方法

参数说明

设置全局变量

GlobalVariableModule.SetValue(string paramName,string paramValue)

输入:变量名paramName,变量值paramValue

获取全局变量

GlobalVariableModule.GetValue (string paramName)

输入:变量名paramName

获取模块结果数据

CurrentProcess.GetModule(string paramModuleName).GetValue(string paramValueName)

输入:模块名paramModuleName,结果名paramValueName

设置模块运行参数

CurrentProcess.GetModule(string paramModuleName).SetValue(string paramValueName,string paramValue)

输入:模块名paramModuleName,变量名paramValueName,变量值paramValue

PLC、Modbus发送数据

GlobalCommunicateModule.GetDevice(int deviceID).GetAddress(int addressID).SendData(string data,DataType dataType)

输入:设备deviceID,设备地址addressID,待发送数组data,待发送数据类型dataType

TCP、UDP、串口发送数据

GlobalCommunicateModule.GetDevice(int deviceID).SendData(string data)

输入:设备deviceID,待发送数据data

2.2 引用和调试

  1. 添加引用
    在脚本界面点击【编辑程序集】进入程序集界面,点击【添加】根据需求进行程序集动态库的添加,仅支持C#程序集添加,到需要的第三方程序集路径下找到想要添加的.dll点击打开即可添加,添加完成后在脚本中调用即可。
  2. 海康VM软件深度学习_图像处理_03

  3. 调试步骤
    在脚本界面点击【导出工程】,选择.sln文件使用VS打开,设置断点并且重新生成,然后点击【调试】中的【附加到进程】,VM4.2版本是选择VmModuleProxy.exe(VM4.0版本是附加ShellMouleManager.exe)附加,最后在VM中单次执行方案或者单次执行流程或者脚本模块来查看是否能进入断点。小小提示:断点调试时,每次修改代码都需要重新编译,VS每次重新编译后,只有第一次运行会进入初始化函数Init()。
  4. 海康VM软件深度学习_c#_04

2.3 VM4.2更新

  1. VM4.2脚本模块在保留VM4.0的一系列接口函数的同时,还提供一套更简便的编程规则,用户无需调用接口函数,只用在脚本中使用赋值运算符(=),就能获取输入变量的值或是给输出变量赋值。
  2. 相比VM4.0,VM4.2脚本模块调试附加的进程由ShellMouleManager.exe变为VmModuleProxy.exe。这是因为当一个方案中包含多个脚本时,我们对每个脚本进行调试附加进程,附加进程名都是ShellMouleManager.exe,此时需要打开任务管理器,在进程中来查看每个脚本对应的PID,然后通过ID编号来确定当前脚本调试需要附加的是哪个ShellMouleManager.exe。这种调试方法步骤繁琐,因此新版本更新为附加到VmModuleProxy.exe,无论用户对哪个脚本模块进行调试,都只需要附加这个进程即可。

3 案例演示

需求:获取下图中条码信息和二维码信息,然后通过编写脚本打印日志到本地。

海康VM软件深度学习_海康VM软件深度学习_05

海康VM软件深度学习_c#_06


根据案例需求,步骤如下:

  1. 使用条码识别模块和二维码识别模块获取识别信息;
  2. 用GetStringValue函数分别获取条码和二维码信息;
  3. 通过FileStream类操作流写入信息到本地;
  4. 并通过SetstringValue函数输出打印日志的状态信息给到下一个模块。

效果如下所示,确定输入输出变量,然后编写代码,执行之后将输出相应得结果。

海康VM软件深度学习_c#_07


完整代码如下所示:

using System;
using System.Text;
using System.Windows.Forms;
using System.IO;
using Script.Methods;
public partial class UserScript:ScriptMethods,IProcessMethods
{
   //********输入变量**********   
    string Barcode; 				//条码 
	string TwoD_Code;				//二维码	    
    //*******输出变量**********    
    string writeSucceedOrFailed; 	//日志写入状态;
    
    /// <summary>
    /// 预编译时变量初始化
    /// </summary>
    public void Init()
    {
		//变量初始化,其余变量可在该函数中添加      
    }

    /// <summary>
    /// Enter the process function when running code once
	/// 流程执行一次进入Process函数
    /// </summary>
    /// <returns></returns>
    public bool Process()
    {
        //每次执行将进入该函数,此处添加所需的逻辑流程处理           
        GetStringValue("barcode",ref Barcode);				//获取条码信息
        GetStringValue("twoD_Code", ref TwoD_Code);			//获取二维码信息        
        try
       {
       	   using(FileStream fsWrite = new FileStream(@"E:\\Log.txt",FileMode.Append,FileAccess.Write) )
           {
       		  string str= "条码信息:"+ Barcode + "\r\n" + "二维码信息:" + TwoD_Code;
       		  byte[] buffer=Encoding.Default.GetBytes(str+"\r\n");		
       		  fsWrite.Write(buffer,0,buffer.Length); 		
           }
           writeSucceedOrFailed="写入OKAY";    
       }
         catch
       {
			writeSucceedOrFailed="写入失败";
       }
       SetStringValue("stateOutput",writeSucceedOrFailed);	  //输出日志打印状态
        
        return true;
    }
}

由于我们可以直接使用赋值运算符(=)进行赋值,不需要使用不同类型的接口函数获取变量(GetxxxxValue)和赋值变量(SetxxxxValue),上述Process()函数中的代码也可以用如下方式实现。

public bool Process()
{
    //每次执行将进入该函数,此处添加所需的逻辑流程处理           
    Barcode=barcode;//获取条码信息
    TwoD_Code=twoD_Code;//获取二维码信息
        
    try
    {
       	using(FileStream fsWrite = new FileStream(@"E:\\Log.txt",FileMode.Append,FileAccess.Write) )
        {
       		string str= "条码信息:"+ Barcode + "\r\n" + "二维码信息:" + TwoD_Code;
       		byte[] buffer=Encoding.Default.GetBytes(str+"\r\n");		
       		fsWrite.Write(buffer,0,buffer.Length); 		
        }
        writeSucceedOrFailed="写入OKAY";    
    }
    catch
    {
		writeSucceedOrFailed="写入失败";
    }
    //输出日志打印状态
    stateOutput=writeSucceedOrFailed; 
    return true;
}

4 总结

作为VM中的逻辑模块之一,脚本模块能够灵活的按照需求处理数据,只要简单的模仿写过一遍,就能掌握其中规则,随后就能在实际项目中拓展使用。最后,根据小编多年工程经验,有以下两点需要注意:

  1. 无法命中断点位置。建议调试过程中,导出工程后关闭脚本模块编辑界面,只使用Visual Studio修改代码和编译,然后附加到进程。
  2. 全局变量与局部变量的差异,在函数外定义的是全局变量,在process函数定义的是局部变量。
  3. 建议变量初始化放在Process()函数中。