勇哥这套halcon引擎的学习笔记贴子共七篇,它是在官方指导文档《http://47.98.154.65/?id=1343》的基础上学习编写而成的笔记。只是有一篇讲解怎么调用向量变量的没有加入,因为勇哥实在不知道这个向量变量有啥子用。以后如果搞明白了再加入吧。
2020/7/3勇哥注:
原来halcon中的向量就是个容器,跟c++标准模板库中的那个向量是一致的。第八篇加上来吧
halcon引擎学习笔记(七)在在HDevEngine/C#中使用实时编译器JIT
halcon引擎学习笔记(六)多线程并发执行外部函数,多窗口显示
halcon引擎学习笔记(二)执行Procedure程序,扩展名为hdvp的halcon函数
演示程序勇哥用的是halcon19.11,C#使用的是vs2013版本。
全部测试代码勇哥已经打包,请点击《下载》
如果你要调用的程序是一个hdev主程序,且当中没有外部函数或者自定义函数,则可以看(一)
如果你要调用的程序是一个hdev主程序,且当中有若干的外部函数或者自定义函数,则可以看(三)
如果你要调用的程序只是一个hdvp的外部函数,则可以看(二)
如果你需要多线程调用外部函数,则可以看(六)(七)
如果你的程序中用到向量变量,则可以看(八)
2020/10/15勇哥注:
勇哥最近寻遍halcon引擎类的功能,发现无法实现修改halcon程序并保存后,C#这边能实时运行修改后的halcon程序。
必须要退出C#程序后,再次执行才是跑的修改后的代码。
这真是个遗憾,因为机器正在做货时,重启C#程序是相当不方便的一件事。
如果有人知道怎么实现,麻烦告诉勇哥,非常感谢!
2020/12/18勇哥注:
由网友“小黄鱼”指出,HDevEngine 类有个UnloadProcedure方法调用后,可以实现不需要重启C#程序即可执行更新后的外部函数。
经我测试后,发现是有效的!
在这里非常感谢他的指点!!!
正文部分
========================
之前勇哥对halcon的向量变量不了解。后来对这方面的知识进行了一点补充,见下面的贴子:
了解了之后,就补上这系列教程的第8篇吧。
演示源码:
// HDevEngine/.NET (C#) example for executing HDevelop programs // //?2007-2019 MVTec Software GmbH // // Purpose: // This example program shows how vector variables are supported by the // classes HDevEngine, HDevProgram, HDevProgramCall, HDevProcedure, and // HDevProcedureCall. // The program uses two vectors: an object vector containing the input // images and a tuple vector containing scaling factors for the processing. // In the HDevelop code the gray values of the input images are scaled // by the factors provided in the input tuples. Afterwards the factors // are transformed into string values. In case of the program call the // two global variables are used for input and output, the unaltered // input values are stored in the two program variables. // When you click the button Load, the HDevelop program and procedure are // loaded, when you click Execute they are executed. using System; using System.Drawing; using System.Collections; using System.ComponentModel; using System.Windows.Forms; using System.Data; using HalconDotNet; namespace UseVectorVariables { /// <summary> /// Summary description for Form1. /// </summary> public class UseVectorVariablesForm : System.Windows.Forms.Form { internal System.Windows.Forms.Button LoadBtn; internal System.Windows.Forms.Button ExecuteBtn; /// <summary> /// Required designer variable. /// </summary> private System.ComponentModel.Container components = null; // HDevEngine // Instance of the engine private HDevEngine MyEngine = new HDevEngine(); // Instance of the program call private HDevProgram Program; private HDevProgramCall ProgramCall; // Instance of the procedure call private HDevProcedure Procedure; private HDevProcedureCall ProcCall; // Path of HDevelop program String ProgramPathString; private HSmartWindowControl WindowControl; // HALCON window private HWindow Window; public UseVectorVariablesForm() { // // Required for Windows Form Designer support // InitializeComponent(); // // TODO: Add any constructor code after InitializeComponent call // } /// <summary> /// Clean up any resources being used. /// </summary> protected override void Dispose( bool disposing ) { if( disposing ) { if (components != null) { components.Dispose(); } } base.Dispose( disposing ); } #region Windows Form Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { this.LoadBtn = new System.Windows.Forms.Button(); this.ExecuteBtn = new System.Windows.Forms.Button(); this.WindowControl = new HalconDotNet.HSmartWindowControl(); this.SuspendLayout(); // // LoadBtn // this.LoadBtn.Location = new System.Drawing.Point(678, 11); this.LoadBtn.Name = "LoadBtn"; this.LoadBtn.Size = new System.Drawing.Size(192, 55); this.LoadBtn.TabIndex = 3; this.LoadBtn.Text = "Load Program"; this.LoadBtn.Click += new System.EventHandler(this.LoadBtn_Click); // // ExecuteBtn // this.ExecuteBtn.Location = new System.Drawing.Point(678, 89); this.ExecuteBtn.Name = "ExecuteBtn"; this.ExecuteBtn.Size = new System.Drawing.Size(192, 55); this.ExecuteBtn.TabIndex = 6; this.ExecuteBtn.Text = "Execute Program"; this.ExecuteBtn.Click += new System.EventHandler(this.ExecuteBtn_Click); // // WindowControl // this.WindowControl.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; this.WindowControl.AutoValidate = System.Windows.Forms.AutoValidate.EnableAllowFocusChange; this.WindowControl.HDoubleClickToFitContent = true; this.WindowControl.HDrawingObjectsModifier = HalconDotNet.HSmartWindowControl.DrawingObjectsModifier.None; this.WindowControl.HImagePart = new System.Drawing.Rectangle(0, 0, 768, 576); this.WindowControl.HKeepAspectRatio = true; this.WindowControl.HMoveContent = true; this.WindowControl.HZoomContent = HalconDotNet.HSmartWindowControl.ZoomContent.WheelForwardZoomsIn; this.WindowControl.Location = new System.Drawing.Point(26, 11); this.WindowControl.Margin = new System.Windows.Forms.Padding(2); this.WindowControl.Name = "WindowControl"; this.WindowControl.Size = new System.Drawing.Size(614, 399); this.WindowControl.TabIndex = 7; this.WindowControl.WindowSize = new System.Drawing.Size(614, 399); this.WindowControl.Load += new System.EventHandler(this.WindowControl_Load); // // UseVectorVariablesForm // this.AutoScaleBaseSize = new System.Drawing.Size(8, 18); this.ClientSize = new System.Drawing.Size(890, 434); this.Controls.Add(this.WindowControl); this.Controls.Add(this.ExecuteBtn); this.Controls.Add(this.LoadBtn); this.Name = "UseVectorVariablesForm"; this.Text = "Use Vector Variables in an HDevelop Program via HDevEngine"; this.Load += new System.EventHandler(this.UseVectorVariablesForm_Load); this.ResumeLayout(false); } #endregion /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main() { Application.Run(new UseVectorVariablesForm()); } private void UseVectorVariablesForm_Load(object sender, System.EventArgs e) { // path of external procedures string halconExamples = HSystem.GetSystem("example_dir"); string ProcedurePath = halconExamples + @"\hdevengine\procedures"; ProgramPathString = halconExamples + @"\hdevengine\hdevelop\use_vector_variables.hdev"; if (!HalconAPI.isWindows) { // Unix-based systems (Mono) ProcedurePath = ProcedurePath.Replace('\\', '/'); ProgramPathString = ProgramPathString.Replace('\\', '/'); } MyEngine.SetProcedurePath(ProcedurePath); // disable Execute button ExecuteBtn.Enabled = false; } private void WindowControl_Load(object sender, System.EventArgs e) { Window = WindowControl.HalconWindow; // Warning: Convenience implementation for rerouting display // operators is not thread-safe, use it only to execute programs // in the main thread. MyEngine.SetHDevOperators(new HDevOpMultiWindowImpl(Window)); } private void LoadBtn_Click(object sender, System.EventArgs e) { try { Program = new HDevProgram(ProgramPathString); ProgramCall = new HDevProgramCall(Program); Procedure = new HDevProcedure("use_vector_variables"); ProcCall = new HDevProcedureCall(Procedure); } catch (HDevEngineException Ex) { MessageBox.Show(Ex.Message, "HDevEngine Exception"); return; } // Enable Execute button ExecuteBtn.Enabled = true; } private void ExecuteBtn_Click(object sender, System.EventArgs e) { try { // // HDevEngine/global variables // // Set global variables int dim = 1; // The actual dimension of global vector variables can be // inquired from the HDevEngine class. dim = MyEngine.GetGlobalIconicVarDimension("GObjectVector"); HObjectVector gObjectVector = new HObjectVector(dim); HImage image = new HImage(); image.ReadImage("datacode/qrcode/qr_workpiece_09"); gObjectVector[1].O = image; image.ReadImage("datacode/qrcode/qr_workpiece_02"); gObjectVector[0].O = image; dim = MyEngine.GetGlobalCtrlVarDimension("GTupleVector"); HTupleVector gTupleVector = new HTupleVector(dim); gTupleVector[1][0].T = 3.0; gTupleVector[0][0].T = 0.3; MyEngine.SetGlobalIconicVarVector("GObjectVector", gObjectVector); MyEngine.SetGlobalCtrlVarVector("GTupleVector",gTupleVector); // Execute program ProgramCall.Execute(); // Get global variables gObjectVector = MyEngine.GetGlobalIconicVarVector("GObjectVector"); gTupleVector = MyEngine.GetGlobalCtrlVarVector("GTupleVector"); // // HDevProgram and HDevProgramCall // // The actual dimension of program variables can be inquired // from the HDevProgram class. Either as a tuple with the // dimensions of all iconic or control variables... HTuple ctrlDimensions = new HTuple(); ctrlDimensions = Program.GetCtrlVarDimensions(); HTuple iconicDimensions = new HTuple(); iconicDimensions = Program.GetIconicVarDimensions(); // Get program variables for (int i = 1; i <= Program.GetIconicVarCount(); i++) if (Program.GetIconicVarName(i) == "ObjectVector") { // ... or for each variable separately. dim = Program.GetIconicVarDimension(i); break; } HObjectVector objectVector = new HObjectVector(dim); objectVector = ProgramCall.GetIconicVarVector("ObjectVector"); for (int i = 1; i <= Program.GetCtrlVarCount(); i++) if (Program.GetCtrlVarName(i) == "TupleVector") { dim = Program.GetCtrlVarDimension(i); break; } HTupleVector tupleVector = new HTupleVector(dim); tupleVector = ProgramCall.GetCtrlVarVector("TupleVector"); // Display result Window.ClearWindow(); Window.SetTposition(5, 5); Window.WriteString("Program execution"); Window.SetTposition(60, 5); Window.WriteString("Scaling factors"); Window.SetTposition(110, 5); Window.WriteString("Input (control): "); Window.WriteString(tupleVector.ToString()); Window.SetTposition(150, 5); Window.WriteString("Output (control): "); Window.WriteString(gTupleVector.ToString()); HSystem.WaitSeconds(3.0); for (int i = 0; i < objectVector.Length; i++) { Window.ClearWindow(); Window.DispObj(objectVector[i].O); Window.SetTposition(480, 5); Window.WriteString("Program execution: input image"); HSystem.WaitSeconds(1.5); Window.ClearWindow(); Window.DispObj(gObjectVector[i].O); Window.SetTposition(480, 5); Window.WriteString("Program execution: scaled output image"); HSystem.WaitSeconds(1.5); } // // HDevProcedure and HDevProcedureCall // // Set input parameters // The actual dimension of procedure parameters can be inquired // from the HDevProcedure class. HTuple dims = Procedure.GetInputCtrlParamDimensions(); dims = Procedure.GetInputIconicParamDimensions(); dim = Procedure.GetInputIconicParamDimension(1); HObjectVector inObjectVector = new HObjectVector(dim); image = new HImage(); image.ReadImage("datacode/ecc200/ecc200_cpu_016"); inObjectVector[1].O = image; image.ReadImage("datacode/ecc200/ecc200_cpu_017"); inObjectVector[0].O = image; dim = Procedure.GetOutputCtrlParamDimension(1); HTupleVector inTupleVector = new HTupleVector(dim); inTupleVector[1][0].T = 2.0; inTupleVector[0][0].T = 0.5; // Parameters can be accessed via the parameter name... ProcCall.SetInputIconicParamVector("InputObjectVector", inObjectVector); ProcCall.SetInputCtrlParamVector("InputTupleVector", inTupleVector); // ...or the parameter index. ProcCall.SetInputIconicParamVector(1, inObjectVector); ProcCall.SetInputCtrlParamVector(1, inTupleVector); ProcCall.Execute(); // Get output parameters dims = Procedure.GetOutputCtrlParamDimensions(); dims = Procedure.GetOutputIconicParamDimensions(); dim = Procedure.GetOutputIconicParamDimension(1); HObjectVector outObjectVector = new HObjectVector(dim); dim = Procedure.GetOutputCtrlParamDimension(1); HTupleVector outTupleVector = new HTupleVector(dim); outObjectVector = ProcCall.GetOutputIconicParamVector("OutputObjectVector"); outTupleVector = ProcCall.GetOutputCtrlParamVector("OutputTupleVector"); outObjectVector = ProcCall.GetOutputIconicParamVector(1); outTupleVector = ProcCall.GetOutputCtrlParamVector(1); // Display result Window.ClearWindow(); Window.SetTposition(5, 5); Window.WriteString("Procedure execution"); Window.NewLine(); Window.NewLine(); Window.SetTposition(60, 5); Window.WriteString("Scaling factors"); Window.SetTposition(110, 5); Window.WriteString("Input (control): "); Window.WriteString(inTupleVector.ToString()); Window.SetTposition(150, 5); Window.WriteString("Output (control): "); Window.WriteString(outTupleVector.ToString()); HSystem.WaitSeconds(3.0); for (int i = 0; i < inObjectVector.Length; i++) { Window.ClearWindow(); Window.DispObj(inObjectVector[i].O); Window.SetTposition(480, 5); Window.WriteString("Procedure execution: input image"); HSystem.WaitSeconds(1.5); Window.ClearWindow(); Window.DispObj(outObjectVector[i].O); Window.SetTposition(480, 5); Window.WriteString("Procedure execution: scaled output image"); HSystem.WaitSeconds(1.5); } } catch (HDevEngineException Ex) { MessageBox.Show(Ex.Message, "HDevEngine Exception"); return; } catch (HOperatorException) { // Window Handle cleared during execution ...? // --> do nothing else. } } } }
主程序use_vector_variables.hdev 源码:
global object vector(1) GObjectVector global tuple vector(2) GTupleVector * * save the original values of the global variables in program variables for I := 0 to GObjectVector.length() - 1 by 1 ObjectVector.at(I) := GObjectVector.at(I) TupleVector.at(I) := GTupleVector.at(I) endfor * * process the global variables use_vector_variables (GObjectVector, GObjectVector, GTupleVector, GTupleVector) *
注意: 这个主程序,居然不能直接跑起来,会报GObjectVector没有初始化的值。
但是我们C#调用的时候,因为提前设置了这个对象的值,就可以正常跑起来。
use_vector_variables.hdvp的参数
源码:
if (InputObjectVector.length() != InputTupleVector.length()) throw (30000) endif for I := 0 to InputObjectVector.length() - 1 by 1 Image := InputObjectVector.at(I) scale_image (Image, OutputObjectVector.at(I), InputTupleVector.at(I).at(0), 0) OutputTupleVector.at(I).at(0) := InputTupleVector.at(I).at(0)$'10.2f' endfor return ()
程序中的重点知识点:
(1) 注意点击执行按钮后,程序前面一部分代码调用执行的代码是use_vector_variables.hdev,而并不是use_vector_variables.hdvp
而在后面一部分代码,则调用的是use_vector_variables.hdvp。
(2) dim = MyEngine.GetGlobalIconicVarDimension("GObjectVector"); 这句读取了全局变量GObjectVector,它是个向量变量。
(3) 保存图片的向量在C#中是HObjectVector对象
而保存HTuple向量在C#中是HTupleVector对象
ImageVector[I].O=image 其中的字母O指的是HObject对象的意思,就像HTuple.D指的是double。
注意是大写的O,不是零。
这里执行完gObjectVector[1].O = image; 后,是复制图片一份,而不是传地址。
HObjectVector gObjectVector = new HObjectVector(dim); HImage image = new HImage(); image.ReadImage("datacode/qrcode/qr_workpiece_09"); gObjectVector[1].O = image; image.ReadImage("datacode/qrcode/qr_workpiece_02"); gObjectVector[0].O = image;
(4) 这个是读取全局向量变量(元素为HTuple的向量)
然后声明一个HTupleVector向量,进行赋值。
gTupleVector[1][0].T 这其中的T,指的是HTuple的意思。而且这还是一个二维向量。
dim = MyEngine.GetGlobalCtrlVarDimension("GTupleVector"); HTupleVector gTupleVector = new HTupleVector(dim); gTupleVector[1][0].T = 3.0; gTupleVector[0][0].T = 0.3;
以上可见,在HDevProgram中容易使用的数据类型Vector,在C#中封装成对象后,使用起来就复杂些,增加了许多对象与其对应的方法。
难怪官方要特意花篇幅讲解如何用halcon引擎调用向量变量。
---------------------
作者:hackpig
来源:www.skcircle.com
版权声明:本文为博主原创文章,转载请附上博文链接!

