2023年11月27日发(作者:)

VisionPro脚本(⼀⽂读懂VisionPro脚本原理与使⽤⽅法)

⼀、脚本简介

1.1 VisionPro项⽬组成简介

在介绍脚本之前先简单介绍⼀下VisionPro开发环境(QuickBuild)的项⽬结构,JobQuickBuild⼯程的基本组成单位,⼀个QucikBuild⼯程⾄少含有⼀个Job,

⼯程中所有的Job是并⾏结构,各个Job之间不会相互影响。每个Job中默认包含⼀个toolGroup,⽤户可以在默认的toolGroup中添加项⽬所需的⼯具和⼯具块。

⼯具块(toolBlock)与⼯具组(toolGroup)都是⼯具的**“容器”**,通过使⽤⼯具块与⼯具组可以将完成某⼀功能的⼯具进⾏封装,实现项⽬模块化,同时亦

可将某⼀特定功能的⼯具块或⼯具组导出实现重复使⽤,类似于编程语⾔中函数功能。⼯具块中亦可以包含⼯具块与⼯具组,两者之间的包含关系没有明确

层次关系。

1.2 VisionPro脚本简介

VisionPro⼯具封装了视觉算法与⽤户交互界⾯,toolGrouptoolBlock提供了组合⼯具的容器,但是并⾮所有的功能都能通过既定交互界⾯实现。为了让⽤户

实现客制化功能更加随⼼所欲,实现VisionPro本⾝⽆法实现的逻辑功能,VisionPro预留了脚本功能。脚本的类型、作⽤与⽀持语⾔如下图所⽰:

⼆、脚本类与⽅法

VisionPro通过多态技术实现脚本功能,VisionPro 的每⼀JobtoolGrouptoolBlock对象都含有⼀个接⼝对象,⽤户通过重写接⼝⽅法实现⾃定义拓展功

能。以toolGroup为例, ICogToolGroupScript接⼝中定义了⼦类中必须实现的函数,当toolGruoup执⾏到某⼀节点(⼯具准备运⾏、⼯具运⾏完成等)时会

调⽤相应的接⼝函数实现⽤户指定的功能。

如果你对接⼝、多态理解不够深⼊,你只需要明⽩脚本就是**“填空题”**VisionPro在适当的位置给你留下空⽩,在这个空⽩区域你可以在满⾜条件的情况

⾃由发挥,实现你想要实现的功能。

2.1 toolGroup脚本类

ToolGroup脚本为例展开,toolGroup 脚本是继承于CogToolGroupBaseScript,实现了ICogToolGroupScript接⼝,该接⼝有四个⽅法,详细介绍如下:

1 public class CogToolGroupBaseScript : ICogToolGroupScript

2 {

3 //

4 public virtual bool GroupRun(ref string message,ref lResultConstants result)

5 {

6 return true;

7 }

8

9 public virtual void ModifyCurrentRunRecord(ICogRecord currentRecord)

10 {}

11 public virtual void ModifyLastRunRecord(ICogRecord lastRecord)

12 {}

13 public virtual void Initialize(lGroup host)

14 {

15 toolGroup = host;

16 }

17 protected lGroup toolGroup=null;

18 }

Initialize() 顾名思义,该⽅法⽤于对toolGroup⼯具进⾏初始化,当退出脚本编辑⼯具时脚本会进⾏编译并进⾏初始化,此时该⽅法会被调⽤。此外,在对

group通过*.vpp⽂件进⾏加载时也会被⽴即调⽤。所以,所有的⼀次性的初始化⼯作都应该写在该⽅法中。

GroupRun()⽅法运⾏该Group中的⼯具,如果该⽅法返回值为true,所有的属于当前Group的视觉⼯具都将运⾏,如果返回值为false,⽤户可以⾃定义⼯

具的执⾏顺序,返回值为false为常见情况。

ModifyCurrentRunRecord() ⽅法⽤于修改CurrentRecord,toolGroupCurrentRecord被创建后调⽤。

ModifyLastRunRecord() ⽅法⽤于修改LastRunRecord,在toolGroupLastRunRecord被创建后调⽤,例如:在最终⽣成图像中添加标签、该表颜⾊、

⽤不同⼏何图像标记⽬标区域。

成员变量toolGroupCogToolGroup类型,该类的runTool⽅法⽤于运⾏指定视觉⼯具;Tools 属性为当前Group的⼯具集合,⼀般⽤于获取当前⼯具组

中某⼀⼯具的引⽤;DefineScriptTerminalGetScriptTerminalDataSetScriptTerminalData ⽅法⽤于定义、获取、设置输⼊输出终端。

1 //对于当前Group存在的视觉⼯具的程序集与命名空间会⾃动添加,如果⽤户想要使⽤当前Group不存在的⼯具或者添加⾃定义程序集可以⼿动添加

2 //详细的操作步骤会在后续实例中进⾏介绍

3 using System;

4 using Pro;

5 using Pro3D;

6 using oup;

7

8 public class UserScript : CogToolGroupBaseScript

9 {

10 //默认情况下遍历group中所有的⼯具并运⾏,⽤户可以根据实际情况⾃定义运⾏逻辑与顺序

11 public override bool GroupRun(ref string message, ref CogToolResultConstants result)

12 for (Int32 toolIdx = 0; toolIdx < ; toolIdx++)

13 l([toolIdx], ref message, ref result);

14 return false;//默认情况下为false表⽰⽤户可以控制⼯具的运⾏顺序,返回值为true则运⾏当前Group中所有⼯具。

15 }

16 public override void ModifyCurrentRunRecord(cord currentRecord)

17 {

18 //在此处添加⽤户代码实现⾃定义修改CurrentRunRecord的功能

19 }

20 public override void ModifyLastRunRecord(cord lastRecord)

21 {

22 //在此处添加⽤户代码⽤于所有⼯具运⾏完成后根据⽤户需求创建Record或者在既有Record中添加标记等

23 }

24 public override void Initialize(CogToolGroup host)

25 {

26 //调⽤⽗类初始化函数,初始化toolGroup对象

27 base.Initialize(host);

28 }

29 }

2.2 toolBlcok脚本类

toolGroup脚本类似,toolBlock的脚本⽗类CogToolBlockAdvancedScriptBase,该类实现的接⼝与toolGroup相同,都是ICogToolGroupScript,不同之处在

toolBlock与两个脚本基类,CogToolBlockSimpleScript CogToolBlockAdvancedScript 分别⽤于简单脚复杂脚本,两者之间的区别在于复杂脚本能

够实现:动态定义toolBlock的输⼊输出终端, 能够访问当前⼯具块所包含⼯具的所有属性与⽅法 ,为保证与toolGroup脚本使⽤的统⼀性,推荐直接使⽤

复杂脚本。

存在即合理,简单脚本具有使⽤的便利性,在访问⼯具块的输⼊输出终端时,两者的具体访问⽅式如下:

1 //使⽤简单脚本为输出赋值

2 s = s * 180 / ;

3 //使⽤复杂脚本为输出赋值

4 this.s["Degrees"].Value = ((double) this.["Radians"].Value) * 180 / ;

既然与toolGroup实现了相同的接⼝,toolBlock脚本基类的⽅法与toolGroup必然相同,功能基本⽆异,不再赘述。

2.3Job脚本类

Job脚本⽤于控制与图像获取相关的设备属性与参数,基类为CogJobBaseScript,实现ICogJobScript接⼝。

1 public class CogJobBaseScript : ICogJobScript

2 {

3 public virtual void Initialize(CogJob jobParam)

4 {

5 job = jobParam;

6 }

7 public virtual void AcqFifoConstruction(ICogAcqFifo fifo)

8 {}

9 public virtual void PreAcquisition()

10 {}

11 public virtual void PostAcquisition(ICogImage image)

12 {}

13 public virtual bool PostAcquisitionRef(ref ICogImage image)

14 {

15 PostAcquisition(image);

16 return true;

17 }

18 public virtual bool PostAcquisitionRefInfo(ref ICogImage image, ICogAcqInfo info)

19 {

20 return PostAcquisitionRef(ref image);

21 }

22 protected CogJob job = null;

23 }

24 }

Initialize() 初始化⽅法,获取当前job引⽤以及⽤户需要的初始化数据。

PreAcquisition() FIFOStartAcquire()⽅法调⽤之前被调⽤,即在进⾏图像采集之前调⽤,如在图像采集之前设置曝光、增益、对⽐度等图像参数。

PostAcquisition() 在图像采集完成之后被调⽤。

PostAcquisitionRef() 该⽅法与 PostAcquisition 类似,不同之处在于 image 是以引⽤的⽅式传递,如果这个⽅法返回 Ture VisionPro 将处理这个

image,如果这个⽅法返回 False ,这个 image 将不会被⽴即进⾏处理 ,⽽是采集下⼀幅图像,这可以使你能够在处理所取的多个 image 之前将它们联

合在⼀起.(如果 PostAcquisition PostAcquisitionRef 都被重写,PostAcquisition 将被忽略)。例如你需要同⼀个相机采集多张不同曝光的图像进⾏合成,

并不是每次采集后都⽴即进⾏处理,⽽是采集到固定数量或者满⾜某⼀条件时进⾏处理。

PostAcquisitionRefInfo() PostAcquisiitonRef相似,多了⼀个参数,⽤户可以通过ICogAcqInfo获取图像的时间戳,重写该⽅法后 PostAcquisition

PostAcquisitionRef PostAcquisitionRef会被忽略。

三、脚本使⽤案例

3.1 job本实⽤实例-----⾃动调节曝光时间

setp1.新建Job,双击进⼊job中。

step2 配置->作业属性->编辑脚本->C#脚本,进⼊Job脚本编辑环境

1 using System;

2 using Pro;

3 using uild;

4 using rocessing;

5

6 public class UserScript : CogJobBaseScript

7 {

8 double exposure = 10;

9 #region "When an Acq Fifo Has Been Constructed and Assigned To The Job"

10 // This function is called when a new fifo is assigned to the job. This usually

11 // occurs when the "Initialize Acquisition" button is pressed on the image source

12 // control. This function is where you would perform custom setup associated

13 // with the fifo.

14 public override void AcqFifoConstruction(qFifo fifo)

15 {

16 }

17 #endregion

18

19 #region "When an Acquisition is About To Be Started"

20 // Called before an acquisition is started for manual and semi-automatic trigger

21 // models. If "Number of Software Acquisitions Pre-queued" is set to 1 in the

22 // job configuration, then no acquisitions should be in progress when this

23 // function is called.

24 public override void PreAcquisition()

25 {

26 // To let the execution stop in this script when a debugger is attached, uncomment the following lines.

27 // #if DEBUG

28 // if (ched) ();

29 // #endif

30 ICogAcqExposure IExposure = xposureParams;

31 re = exposure;

32 }

33 #endregion

34

35 #region "When an Acquisition Has Just Completed"

36 // Called immediately after an acquisition has completed.

37 // Return true if the image should be inspected.

38 // Return false to skip the inspection and acquire another image.

39 public override bool PostAcquisitionRefInfo(ref age image,

40 qInfo info)

41 {

42 // To let the execution stop in this script when a debugger is attached, uncomment the following lines.

43 // #if DEBUG

44 // if (ched) ();

45 // #endif

46 CogHistogram curImageHist = new CogHistogram();

47 CogHistogramResult curHistResult = e(image,null);

48 if(>150)

49 exposure *= 0.75;

50 if( < 50)

51 exposure *= 1.5;

52 if(exposure<0.1)

53 exposure = 0.1;

54 return true;

55 }

56 #endregion

57

58 //Perform any initialization required by your script here.

59 public override void Initialize(CogJob jobParam)

60 {

61 //DO NOT REMOVE - Call the base class implementation first - DO NOT REMOVE

62 base.Initialize(jobParam);

63 }

64 #endregion

65

66 }

3.2 toolBlock脚本使⽤实例-----显⽰Blob区域的中⼼坐标于当前Blob区域

toolBlock脚本的应⽤最为⼴泛,⽤于控制⼯具的运⾏逻辑,修改⽣成的record,拓展数据逻辑等。本例以最简单的⽅式介绍toolBloc脚本使⽤⽅法,本例的具体

应⽤为在各个独⽴的Blob区域显⽰其中⼼坐标值。

10 using ock;

11 using Pro3D;

12 using ;

13 using sAnalysis;

14 #endregion

15

16 public class CogToolBlockAdvancedScript : CogToolBlockAdvancedScriptBase

17 {

18 //==========================step2===================================

19 #region Private Member Variables

20 private lBlock mToolBlock;

21 private CogBlobTool mBlob;

22 private List mLabels;

23

24 #endregion

25 ///

26 /// Called when the parent tool is run.

27 /// Add code here to customize or replace the normal run behavior.

28 ///

29 /// Sets the Message in the tool's RunStatus.

30 /// Sets the Result in the tool's RunStatus

31 /// True if the tool should run normally,

32 /// False if GroupRun customizes run behavior

33 public override bool GroupRun(ref string message, ref CogToolResultConstants result)

34 {

35 // To let the execution stop in this script when a debugger is attached, uncomment the following lines.

36 // #if DEBUG

37 // if (ched) ();

38 // #endif

39 //==========================step4===================================

40 ();

41 // Run each tool using the RunTool function

42 //foreach(ICogTool tool in )

43 //l(tool, ref message, ref result);

44 l(mBlob, ref message, ref result);

45 CogBlobResultCollection blobs = bs();

46 foreach(CogBlobResult blob in blobs)

47 {

48 CogGraphicLabel tempLabel = new CogGraphicLabel();

49 ent = neCenter;

50 ext(OfMassX, OfMassY, ng(OfMassX)+","+ng(OfMassY));

51 = ;

52 (tempLabel);

53 }

54 return false;

55 }

56

57 #region When the Current Run Record is Created

58 ///

59 /// Called when the current record may have changed and is being reconstructed

60 ///

61 ///

62 /// The new currentRecord is available to be initialized or customized.

63 public override void ModifyCurrentRunRecord(cord currentRecord)

64 {

65 }

87 ///

88 /// The host tool

89 public override void Initialize(lGroup host)

90 {

91 // DO NOT REMOVE - Call the base class implementation first - DO NOT REMOVE

92 base.Initialize(host);

93 // Store a local copy of the script host

94 //==========================step3===================================

95 this.mToolBlock = ((lBlock)(host));

96 mBlob = this.["CogBlobTool1"] as CogBlobTool;

97 mLabels = new List();

98 }

99 #endregion

100 }

效果图为:

四、脚本进阶

4.1 脚本是插件程序集

⽆论你是通过Job脚本、ToolGroup脚本还是ToolBlock脚本拓展QuickBuild程序功能时,实际上是完善了继承于某⼀接⼝的脚本类(继承于

CogToolGroupBaseScriptCogJobBaseScript或者CogToolBlockAdvancedScriptBase类),在退出脚本编辑环境时QuickBuild对你完善的⼦类进⾏编译,

如果出现语法错误会报错提⽰,在语法错误改正前当前脚本的所有内容都不会被调⽤,因为没有通过编译。如果出现逻辑错误不会提⽰,需要在VS环境下进

⾏调试,调试⽅法后续会详细介绍。QuickBuild程序运⾏时通过接⼝实现对脚本⼦类成员函数的调⽤,从⽽将脚本函数的拓展功能进⾏实现。

关于脚本,你还需要明⽩以下⼏点:

⽤户在脚本中编写的代码会成为VisionPro程序的⼀部分,其中的bug也不可避免影响到VisionPro 的运⾏。

⽤户实现的脚本类会被编译为程序集加载到内存当中,⽽且每次对脚本进⾏编辑之后会重新编译,但是旧版本的程序集会⼀致在内存中直到你重新

启动QuickBuild,因此频繁修改脚本会增加⼀点点的内存消耗。

脚本程序集被加载到内存之后,VisionPro会创建⼀个该脚本类的接⼝对象。脚本重新编辑之后接⼝对象会释放Dispose之前对象,运⾏GC进⾏垃圾

回收,创建新脚本类的接⼝实例。

在进⾏脚本编辑时,如果脚本内容⽐较多,最好经常进⾏保存,保存时需要退出脚本编辑环境对整个QuickBuild⼯程进保存。补充⼀点,在

QuickBuild环境下进⾏⼯具编辑时亦需要进⾏随⼿保存,⼯具Block误删除之后好像是⽆法恢复的只有退出QuickBuild时选择不保存,前提是你误删

除之前刚好保存过,惨痛的经历已不⽌⼀次。

4.2 脚本实现事件与委托

事件响应函数中要增加异常处理机制(Try …Catch,否则容易导致VisionPro运⾏出现异常;

不要在事件处理函数中产⽣当前的事件,否则会造成⽆限循环

重写实现Dispose(),取消事件注册。脚本每次修改退出后都会进⾏编译,运⾏时重新注册事件,如果没有在Dispose总取消注册会造成多次注册。

当前事件的响应函数可能不⽌你在脚本中实现,在VisionPro内部机制中可能也有实现,这些事件的响应函数执⾏顺序是不确定的。