一、腳本簡介
1.1VisionPro項(xiàng)目組成簡介
在介紹腳本之前先簡單介紹一下VisionPro開發(fā)環(huán)境(QuickBuild)的項(xiàng)目結(jié)構(gòu),Job是QuickBuild工程的基本組成單位,一個(gè)QucikBuild工程至少含有一個(gè)Job,工程中所有的Job是并行結(jié)構(gòu),各個(gè)Job之間不會(huì)相互影響。每個(gè)Job中默認(rèn)包含一個(gè)toolGroup,用戶可以在默認(rèn)的toolGroup中添加項(xiàng)目所需的工具和工具塊。工具塊(toolBlock)與工具組(toolGroup)都是工具的**“容器”**,通過使用工具塊與工具組可以將完成某一功能的工具進(jìn)行封裝,實(shí)現(xiàn)項(xiàng)目模塊化,同時(shí)亦可將某一特定功能的工具塊或工具組導(dǎo)出實(shí)現(xiàn)重復(fù)使用,類似于編程語言中“函數(shù)”功能。工具塊中亦可以包含工具塊與工具組,兩者之間的包含關(guān)系沒有明確層次關(guān)系。
1.2VisionPro腳本簡介
VisionPro工具封裝了視覺算法與用戶交互界面,toolGroup與toolBlock提供了組合工具的容器,但是并非所有的功能都能通過既定交互界面實(shí)現(xiàn)。為了讓用戶實(shí)現(xiàn)客制化功能更加“隨心所欲”,實(shí)現(xiàn)VisionPro本身無法實(shí)現(xiàn)的邏輯功能,VisionPro預(yù)留了腳本功能。腳本的類型、作用與支持語言如下圖所示:
二、腳本類與方法
VisionPro通過”多態(tài)”技術(shù)實(shí)現(xiàn)腳本功能,VisionPro 的每一Job、toolGroup、toolBlock對象都含有一個(gè)接口對象,用戶通過重寫接口方法實(shí)現(xiàn)自定義拓展功能。以toolGroup為例, ICogToolGroupScript接口中定義了子類中必須實(shí)現(xiàn)的函數(shù),當(dāng)toolGruoup執(zhí)行到某一節(jié)點(diǎn)(工具準(zhǔn)備運(yùn)行、工具運(yùn)行完成等)時(shí)會(huì)調(diào)用相應(yīng)的接口函數(shù)實(shí)現(xiàn)用戶指定的功能。
如果你對接口、多態(tài)理解不夠深入,你只需要明白腳本就是**“填空題”**,VisionPro在適當(dāng)?shù)奈恢媒o你留下空白,在這個(gè)空白區(qū)域你可以在滿足條件的情況下“自由發(fā)揮”,實(shí)現(xiàn)你想要實(shí)現(xiàn)的功能。
2.1 toolGroup腳本類
以ToolGroup腳本為例展開,toolGroup 腳本是繼承于CogToolGroupBaseScript,實(shí)現(xiàn)了ICogToolGroupScript接口,該接口有四個(gè)方法,詳細(xì)介紹如下:
public class CogToolGroupBaseScript : ICogToolGroupScript{ // public virtual bool GroupRun(ref string message,ref Cognex.VisionPro.CogToolResultConstants result) { return true; } public virtual void ModifyCurrentRunRecord(ICogRecord currentRecord) {} public virtual void ModifyLastRunRecord(ICogRecord lastRecord) {} public virtual void Initialize(Cognex.VisionPro.ToolGroup.CogToolGroup host) { toolGroup = host; } protected Cognex.VisionPro.ToolGroup.CogToolGroup toolGroup=null;}
Initialize()顧名思義,該方法用于對toolGroup工具進(jìn)行初始化,當(dāng)退出腳本編輯工具時(shí)腳本會(huì)進(jìn)行編譯并進(jìn)行初始化,此時(shí)該方法會(huì)被調(diào)用。此外,在對該group通過*.vpp文件進(jìn)行加載時(shí)也會(huì)被立即調(diào)用。所以,所有的“一次性”的初始化工作都應(yīng)該寫在該方法中。
GroupRun()方法運(yùn)行該Group中的工具,如果該方法返回值為true,所有的屬于當(dāng)前Group的視覺工具都將運(yùn)行,如果返回值為false,用戶可以自定義工具的執(zhí)行順序,返回值為false為常見情況。
ModifyCurrentRunRecord()方法用于修改CurrentRecord,在toolGroup的CurrentRecord被創(chuàng)建后調(diào)用。
ModifyLastRunRecord()方法用于修改LastRunRecord,在toolGroup的LastRunRecord被創(chuàng)建后調(diào)用,例如:在最終生成圖像中添加標(biāo)簽、該表顏色、用不同幾何圖像標(biāo)記目標(biāo)區(qū)域。
成員變量toolGroup為CogToolGroup類型,該類的runTool方法用于運(yùn)行指定視覺工具;Tools 屬性為當(dāng)前Group的工具集合,一般用于獲取當(dāng)前工具組中某一工具的引用;DefineScriptTerminal、GetScriptTerminalData、SetScriptTerminalData 方法用于定義、獲取、設(shè)置輸入輸出終端。
//對于當(dāng)前Group存在的視覺工具的程序集與命名空間會(huì)自動(dòng)添加,如果用戶想要使用當(dāng)前Group不存在的工具或者添加自定義程序集可以手動(dòng)添加//詳細(xì)的操作步驟會(huì)在后續(xù)實(shí)例中進(jìn)行介紹using System;using Cognex.VisionPro;using Cognex.VisionPro3D;using Cognex.VisionPro.ToolGroup; public class UserScript : CogToolGroupBaseScript{ //默認(rèn)情況下遍歷group中所有的工具并運(yùn)行,用戶可以根據(jù)實(shí)際情況自定義運(yùn)行邏輯與順序 public override bool GroupRun(ref string message, ref CogToolResultConstants result) for (Int32 toolIdx = 0; toolIdx < toolGroup.Tools.Count; toolIdx++) toolGroup.RunTool(toolGroup.Tools[toolIdx], ref message, ref result); return false;//默認(rèn)情況下為false表示用戶可以控制工具的運(yùn)行順序,返回值為true則運(yùn)行當(dāng)前Group中所有工具。 } public override void ModifyCurrentRunRecord(Cognex.VisionPro.ICogRecord currentRecord) { //在此處添加用戶代碼實(shí)現(xiàn)自定義修改CurrentRunRecord的功能 } public override void ModifyLastRunRecord(Cognex.VisionPro.ICogRecord lastRecord) { //在此處添加用戶代碼用于所有工具運(yùn)行完成后根據(jù)用戶需求創(chuàng)建Record或者在既有Record中添加標(biāo)記等 } public override void Initialize(CogToolGroup host) { //調(diào)用父類初始化函數(shù),初始化toolGroup對象 base.Initialize(host); }}
2.2 toolBlcok腳本類
與toolGroup腳本類似,toolBlock的腳本父類CogToolBlockAdvancedScriptBase,該類實(shí)現(xiàn)的接口與toolGroup相同,都是ICogToolGroupScript,不同之處在于toolBlock與兩個(gè)腳本基類,CogToolBlockSimpleScript 與 CogToolBlockAdvancedScript 分別用于“簡單腳”與“復(fù)雜”腳本,兩者之間的區(qū)別在于復(fù)雜腳本能夠?qū)崿F(xiàn):①動(dòng)態(tài)定義toolBlock的輸入輸出終端,② 能夠訪問當(dāng)前工具塊所包含工具的所有屬性與方法,為保證與toolGroup腳本使用的統(tǒng)一性,推薦直接使用復(fù)雜腳本。
存在即合理,簡單腳本具有使用的便利性,在訪問工具塊的輸入輸出終端時(shí),兩者的具體訪問方式如下:
//使用簡單腳本為輸出賦值Outputs.Degrees = Inputs.Radians * 180 / Math.PI;//使用復(fù)雜腳本為輸出賦值this.mToolBlock.Outputs["Degrees"].Value = ((double) this.mToolBlock.Inputs["Radians"].Value) * 180 / Math.PI;
既然與toolGroup實(shí)現(xiàn)了相同的接口,toolBlock腳本基類的方法與toolGroup必然相同,功能基本無異,不再贅述。
2.3Job腳本類
Job腳本用于控制與圖像獲取相關(guān)的設(shè)備屬性與參數(shù),基類為CogJobBaseScript,實(shí)現(xiàn)ICogJobScript接口。
public class CogJobBaseScript : ICogJobScript { public virtual void Initialize(CogJob jobParam) { job = jobParam; } public virtual void AcqFifoConstruction(ICogAcqFifo fifo) {} public virtual void PreAcquisition() {} public virtual void PostAcquisition(ICogImage image) {} public virtual bool PostAcquisitionRef(ref ICogImage image) { PostAcquisition(image); return true; } public virtual bool PostAcquisitionRefInfo(ref ICogImage image, ICogAcqInfo info) { return PostAcquisitionRef(ref image); } protected CogJob job = null; }}
Initialize()初始化方法,獲取當(dāng)前job引用以及用戶需要的初始化數(shù)據(jù)。
PreAcquisition()在FIFO的StartAcquire()方法調(diào)用之前被調(diào)用,即在進(jìn)行圖像采集之前調(diào)用,如在圖像采集之前設(shè)置曝光、增益、對比度等圖像參數(shù)。
PostAcquisition()在圖像采集完成之后被調(diào)用。
PostAcquisitionRef()該方法與 PostAcquisition 類似,不同之處在于 image 是以引用的方式傳遞,如果這個(gè)方法返回 Ture , VisionPro 將處理這個(gè) image,如果這個(gè)方法返回 False ,這個(gè) image 將不會(huì)被立即進(jìn)行處理 ,而是采集下一幅圖像,這可以使你能夠在處理所取的多個(gè) image 之前將它們聯(lián)合在一起.(如果 PostAcquisition 和 PostAcquisitionRef 都被重寫,PostAcquisition 將被忽略)。例如你需要同一個(gè)相機(jī)采集多張不同曝光的圖像進(jìn)行合成,并不是每次采集后都立即進(jìn)行處理,而是采集到固定數(shù)量或者滿足某一條件時(shí)進(jìn)行處理。
PostAcquisitionRefInfo()與PostAcquisiitonRef相似,多了一個(gè)參數(shù),用戶可以通過ICogAcqInfo獲取圖像的時(shí)間戳,重寫該方法后 PostAcquisition 、PostAcquisitionRef、 PostAcquisitionRef會(huì)被忽略。
三、腳本使用案例
3.1 job本實(shí)用實(shí)例-----自動(dòng)調(diào)節(jié)曝光時(shí)間
setp1.新建Job,雙擊進(jìn)入job中。
step2配置->作業(yè)屬性->編輯腳本->C#腳本,進(jìn)入Job腳本編輯環(huán)境
using System;using Cognex.VisionPro;using Cognex.VisionPro.QuickBuild;using Cognex.VisionPro.ImageProcessing; public class UserScript : CogJobBaseScript{ double exposure = 10;#region "When an Acq Fifo Has Been Constructed and Assigned To The Job" // This function is called when a new fifo is assigned to the job. This usually // occurs when the "Initialize Acquisition" button is pressed on the image source // control. This function is where you would perform custom setup associated // with the fifo. public override void AcqFifoConstruction(Cognex.VisionPro.ICogAcqFifo fifo) { }#endregion #region "When an Acquisition is About To Be Started" // Called before an acquisition is started for manual and semi-automatic trigger // models. If "Number of Software Acquisitions Pre-queued" is set to 1 in the // job configuration, then no acquisitions should be in progress when this // function is called. public override void PreAcquisition() { // To let the execution stop in this script when a debugger is attached, uncomment the following lines. // #if DEBUG // if (System.Diagnostics.Debugger.IsAttached) System.Diagnostics.Debugger.Break(); // #endif ICogAcqExposure IExposure = job.AcqFifo.OwnedExposureParams; IExposure.Exposure = exposure; }#endregion #region "When an Acquisition Has Just Completed" // Called immediately after an acquisition has completed. // Return true if the image should be inspected. // Return false to skip the inspection and acquire another image. public override bool PostAcquisitionRefInfo(ref Cognex.VisionPro.ICogImage image, Cognex.VisionPro.ICogAcqInfo info) { // To let the execution stop in this script when a debugger is attached, uncomment the following lines. // #if DEBUG // if (System.Diagnostics.Debugger.IsAttached) System.Diagnostics.Debugger.Break(); // #endif CogHistogram curImageHist = new CogHistogram(); CogHistogramResult curHistResult = curImageHist.Execute(image,null); if(curHistResult.Mean>150) exposure *= 0.75; if(curHistResult.Mean < 50) exposure *= 1.5; if(exposure<0.1) exposure = 0.1; return true; }#endregion //Perform any initialization required by your script here. public override void Initialize(CogJob jobParam) { //DO NOT REMOVE - Call the base class implementation first - DO NOT REMOVE base.Initialize(jobParam); }#endregion }
3.2 toolBlock腳本使用實(shí)例-----顯示Blob區(qū)域的中心坐標(biāo)于當(dāng)前Blob區(qū)域
toolBlock腳本的應(yīng)用最為廣泛,用于控制工具的運(yùn)行邏輯,修改生成的record,拓展數(shù)據(jù)邏輯等。本例以最簡單的方式介紹toolBloc腳本使用方法,本例的具體應(yīng)用為在各個(gè)獨(dú)立的Blob區(qū)域顯示其中心坐標(biāo)值。
在進(jìn)行腳本編輯之前,根據(jù)用戶需要添加程序集以及命名空間,添加引用程序集的具體過程如下圖所示:
在編寫C#toolBlock腳本時(shí),其常規(guī)流程為:
step1.根據(jù)需求添加程序集以及命名空間
step2.聲明對應(yīng)toolBlock的相關(guān)變量以及用戶自定義變量
step3.在Initialize()函數(shù)中獲取toolBlock中工具的引用
step4.在GroupRun()方法中通過工具變量控制工具的執(zhí)行順序以及獲取所需用戶數(shù)據(jù)
step5.修改Record得到用戶所需效果
//==========================step1===================================#region namespace importsusing System;using System.Collections;using System.Collections.Generic;using System.Drawing;using System.IO;using System.Windows.Forms;using Cognex.VisionPro;using Cognex.VisionPro.ToolBlock;using Cognex.VisionPro3D;using Cognex.VisionPro.Blob;using Cognex.VisionPro.ResultsAnalysis;#endregion public class CogToolBlockAdvancedScript : CogToolBlockAdvancedScriptBase{//==========================step2=================================== #region Private Member Variables private Cognex.VisionPro.ToolBlock.CogToolBlock mToolBlock; private CogBlobTool mBlob; private List
效果圖為:
四、腳本進(jìn)階
4.1腳本是“插件”程序集
無論你是通過Job腳本、ToolGroup腳本還是ToolBlock腳本拓展QuickBuild程序功能時(shí),實(shí)際上是完善了繼承于某一接口的腳本類(繼承于CogToolGroupBaseScript、CogJobBaseScript或者CogToolBlockAdvancedScriptBase類),在退出腳本編輯環(huán)境時(shí)QuickBuild對你完善的子類進(jìn)行編譯,如果出現(xiàn)語法錯(cuò)誤會(huì)報(bào)錯(cuò)提示,在語法錯(cuò)誤改正前當(dāng)前腳本的所有內(nèi)容都不會(huì)被調(diào)用,因?yàn)闆]有通過編譯。如果出現(xiàn)邏輯錯(cuò)誤不會(huì)提示,需要在VS環(huán)境下進(jìn)行調(diào)試,調(diào)試方法后續(xù)會(huì)詳細(xì)介紹。QuickBuild程序運(yùn)行時(shí)通過接口實(shí)現(xiàn)對腳本子類成員函數(shù)的調(diào)用,從而將腳本函數(shù)的拓展功能進(jìn)行實(shí)現(xiàn)。
關(guān)于腳本,你還需要明白以下幾點(diǎn):
用戶在腳本中編寫的代碼會(huì)成為VisionPro程序的一部分,其中的bug也不可避免影響到VisionPro 的運(yùn)行。
用戶實(shí)現(xiàn)的腳本類會(huì)被編譯為程序集加載到內(nèi)存當(dāng)中,而且每次對腳本進(jìn)行編輯之后會(huì)重新編譯,但是舊版本的程序集會(huì)一致在內(nèi)存中直到你重新啟動(dòng)QuickBuild,因此頻繁修改腳本會(huì)增加一點(diǎn)點(diǎn)的內(nèi)存消耗。
腳本程序集被加載到內(nèi)存之后,VisionPro會(huì)創(chuàng)建一個(gè)該腳本類的接口對象。腳本重新編輯之后接口對象會(huì)釋放Dispose之前對象,運(yùn)行GC進(jìn)行垃圾回收,創(chuàng)建新腳本類的接口實(shí)例。
在進(jìn)行腳本編輯時(shí),如果腳本內(nèi)容比較多,最好經(jīng)常進(jìn)行保存,保存時(shí)需要退出腳本編輯環(huán)境對整個(gè)QuickBuild工程進(jìn)保存。補(bǔ)充一點(diǎn),在QuickBuild環(huán)境下進(jìn)行工具編輯時(shí)亦需要進(jìn)行隨手保存,工具Block誤刪除之后好像是無法恢復(fù)的只有退出QuickBuild時(shí)選擇不保存,前提是你誤刪除之前剛好保存過,慘痛的經(jīng)歷已不止一次。
4.2腳本實(shí)現(xiàn)事件與委托
事件響應(yīng)函數(shù)中要增加異常處理機(jī)制(Try …Catch),否則容易導(dǎo)致VisionPro運(yùn)行出現(xiàn)異常;
不要在事件處理函數(shù)中產(chǎn)生當(dāng)前的事件,否則會(huì)造成無限循環(huán);
重寫實(shí)現(xiàn)Dispose(),取消事件注冊。腳本每次修改退出后都會(huì)進(jìn)行編譯,運(yùn)行時(shí)重新注冊事件,如果沒有在Dispose總?cè)∠詴?huì)造成多次注冊;
當(dāng)前事件的響應(yīng)函數(shù)可能不止你在腳本中實(shí)現(xiàn),在VisionPro內(nèi)部機(jī)制中可能也有實(shí)現(xiàn),這些事件的響應(yīng)函數(shù)執(zhí)行順序是不確定的。
-
編程語言
+關(guān)注
關(guān)注
10文章
1939瀏覽量
34604 -
VisionPro
+關(guān)注
關(guān)注
6文章
19瀏覽量
15635 -
腳本
+關(guān)注
關(guān)注
1文章
387瀏覽量
14833
原文標(biāo)題:VisionPro之腳本(一文讀懂VisionPro腳本原理與使用方法)
文章出處:【微信號:vision263com,微信公眾號:新機(jī)器視覺】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論