勇哥这套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#程序即可执行更新后的外部函数。
经我测试后,发现是有效的!
在这里非常感谢他的指点!!!
正文部分
========================
使用JIT实时编译器的目的是加快程序的运行速度。
通过算子 dev_open_tool ('preferences', 10, 10, 400, 200, 'page', 'general_options/experienced_users', ToolId)
可以打开设置窗口。
高级用户选项下面就可以看到JIT的开关。
或者在用halcon引擎运行函数的时候可以使用下面指令打开JIT开关。
Engine.SetEngineAttribute("execute_procedures_jit_compiled", mode == CompileMode.eNoCompile ? "false" : "true");
JIT实时编译有一些限制,详细见下图:
本篇的演示程序功能是计算:
不编译、显式编译、隐式编译三种方式的执行时间。
同时可以演示程序中学习到下面的内容:
演示如何控制HDevelop的编译
使用集成实时编译器hdev和hdvp的过程。
可以全局控制是否应该在执行之前编译过程。
此外,还可以控制在什么时间点执行编译。
在主程序中,调用了三个不同的本地函数进行测试。包括:
1)fib,一些HDevelop过程的递归调用。
2)mean_sp_real,使用大量循环的过滤器的实现。
3)process,部分HALCON算子的顺序调用。
三个本地函数的代码与参数如下:
fib本地函数的参数
源码:
if (N <= 0) Fib := 0 elseif (N == 1 or N == 2) Fib := 1 else fib (N - 1, A) fib (N - 2, B) Fib := A + B endif * return ()
本地函数mean_sp_real的参数
源码:
* see IM 2104 * MW := (MaskWidth - 1) / 2 MH := (MaskHeight - 1) / 2 * get_image_size (Image, Width, Height) get_image_type (Image, Type) * * * Decompose region into border and inner region gen_rectangle1 (RectangleInner, MH, MW, Height - 1 - MH, Width - 1 - MW) difference (Image, RectangleInner, RegionBorder) intersection (Image, RectangleInner, RegionInner) get_region_points (RegionBorder, RowsBorder, ColumnsBorder) get_region_points (RegionInner, RowsInner, ColumnsInner) * * gen_rectangle1 (Rectangle, 0, 0, Height - 1, Width - 1) get_region_points (Rectangle, RowsRect, ColumnsRect) get_grayval (Image, RowsRect, ColumnsRect, C) * * Generate a new tuple of same type as Image COut := C * * Border processing for idx := 0 to |RowsBorder| - 1 by 1 * Get all neighboring pixels X0 := max2(0,ColumnsBorder[idx] - MW) Y0 := max2(0,RowsBorder[idx] - MH) X1 := min2(Width - 1,ColumnsBorder[idx] + MW) Y1 := min2(Height - 1,RowsBorder[idx] + MH) * Threshold values NN := (X1 - X0 + 1) * (Y1 - Y0 + 1) if (NN > 0) NeighX := [X0:X1][[0:NN - 1] % (X1 - X0 + 1)] NeighY := [Y0:Y1][[0:NN - 1] / (X1 - X0 + 1)] NeighOffs := NeighY * Width + NeighX NeighVal := C[NeighOffs] NeighGoodMask := (NeighVal [>=] MinThresh) and (NeighVal [<=] MaxThresh) NeighGoodNum := sum(NeighGoodMask) if (NeighGoodNum > 0) SumGood := sum(NeighVal * NeighGoodMask) COut[RowsBorder[idx] * Width + ColumnsBorder[idx]] := SumGood / NeighGoodNum endif endif endfor * * Inner image region NN := (2 * MW + 1) * (2 * MH + 1) NeighXBase := [-MW:MW][[0:NN - 1] % (2 * MW + 1)] NeighYBase := [-MH:MH][[0:NN - 1] / (2 * MW + 1)] NeighOffsBase := NeighYBase * Width + NeighXBase * for idx := 0 to |RowsInner| - 1 by 1 x := ColumnsInner[idx] y := RowsInner[idx] NeighVal := C[NeighOffsBase + y * Width + x] NeighGoodMask := (NeighVal [>=] MinThresh) and (NeighVal [<=] MaxThresh) NeighGoodNum := sum(NeighGoodMask) if (NeighGoodNum > 0) SumGood := sum(NeighVal * NeighGoodMask) COut[y * Width + x] := SumGood / NeighGoodNum endif endfor * gen_image_const (ImageSPMean, Type, Width, Height) change_domain (ImageSPMean, Image, ImageSPMean) set_grayval (ImageSPMean, RowsRect, ColumnsRect, COut) * return ()
本地函数process的参数
源码:
mean_image (Image, ImageOut, 13, 13) threshold (ImageOut, Region, 128, 255) overpaint_region (ImageOut, Region, 128, 'fill') median_image (ImageOut, ImageOut, 'circle', 30, 'mirrored') return ()
主程序test_jit_speedup.hdev源码:
dev_update_off () * * for TestIdx := 0 to 1 by 1 dev_open_tool ('preferences', 10, 10, 400, 200, 'page', 'general_options/experienced_users', ToolId) stop () * *********************************************************** * if TestIdx is 0 uncheck in the Preferences dialog the * preference 'Execute procedures JIT-compiled' * else (TestIdx is 1) check it * *********************************************************** * * *********************************************************** * 1st test: * FIB: Many recursive calls * -> measure speedup of HDevelop Procedure Calls * *********************************************************** * * test runtime (first call in compiled mode calls the compiler) T := [] for Index := 0 to 9 by 1 count_seconds (T1) fib (20, F20) count_seconds (T2) T[Index] := 1000.0 * (T2 - T1) * select best measuring T_fib[TestIdx] := min(T) endfor * * * *********************************************************** * 2nd test: * LOOP: Many loops with computations * -> measure speedup of loops * *********************************************************** read_image (Image, 'fabrik') convert_image_type (Image, Image, 'uint2') * * test runtime (first call in compiled mode calls the compiler) T := [] for Index := 0 to 3 by 1 count_seconds (T1) mean_sp_real (Image, ImageSPMean, 3, 3, 10, 250) count_seconds (T2) T[Index] := 1000.0 * (T2 - T1) * select best measuring T_loop[TestIdx] := min(T) endfor * * * *********************************************************** * 3rd test: * OPS: Many HLib operator calls * -> There is little or no speedup, because most of the * time is spent in the operators * *********************************************************** * * test runtime (first call in compiled mode calls the compiler) T := [] for Index := 0 to 3 by 1 count_seconds (T1) process (Image, ImageOut) count_seconds (T2) T[Index] := 1000.0 * (T2 - T1) * select best measuring T_ops[TestIdx] := min(T) endfor endfor * * calculate the speedup for the 3 test cases SpeedUp_fib := T_fib[0] / T_fib[1] SpeedUp_loop := T_loop[0] / T_loop[1] SpeedUp_ops := T_ops[0] / T_ops[1] dev_inspect_ctrl ([SpeedUp_fib,SpeedUp_loop,SpeedUp_ops]) *
本篇C#测试程序的源码如下:
//下面的演示程序的目的: //演示如何控制HDevelop的编译 //使用集成实时编译器hdev和hdvp的过程。 //可以全局控制是否应该在执行之前编译过程。 //此外,还可以控制在什么时间点执行编译。 using System; using System.Drawing; using System.Collections; using System.ComponentModel; using System.Windows.Forms; using System.Data; using HalconDotNet; namespace UseJitCompiler { /// <summary> /// Summary description for Form1. /// </summary> public class UseJitCompilerForm : System.Windows.Forms.Form { internal System.Windows.Forms.Button NoCompileBtn; internal System.Windows.Forms.Button ExplicitBtn; internal System.Windows.Forms.Button ImplicitBtn; /// <summary> /// Required designer variable. /// </summary> private System.ComponentModel.Container components = null; // path of HDevelop program String ProgramPathString; // procedure calls private DataGridView resultGrid; enum CompileMode { eNoCompile, eExplicit, eImplicit }; public UseJitCompilerForm() { InitializeComponent(); } 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.NoCompileBtn = new System.Windows.Forms.Button(); this.ExplicitBtn = new System.Windows.Forms.Button(); this.ImplicitBtn = new System.Windows.Forms.Button(); this.resultGrid = new System.Windows.Forms.DataGridView(); ((System.ComponentModel.ISupportInitialize)(this.resultGrid)).BeginInit(); this.SuspendLayout(); // // NoCompileBtn // this.NoCompileBtn.Location = new System.Drawing.Point(19, 68); this.NoCompileBtn.Name = "NoCompileBtn"; this.NoCompileBtn.Size = new System.Drawing.Size(192, 55); this.NoCompileBtn.TabIndex = 4; this.NoCompileBtn.Text = "No compile"; this.NoCompileBtn.Click += new System.EventHandler(this.NoCompileBtn_Click); // // ExplicitBtn // this.ExplicitBtn.Location = new System.Drawing.Point(19, 145); this.ExplicitBtn.Name = "ExplicitBtn"; this.ExplicitBtn.Size = new System.Drawing.Size(192, 56); this.ExplicitBtn.TabIndex = 7; this.ExplicitBtn.Text = "Explicit Compile"; this.ExplicitBtn.Click += new System.EventHandler(this.ExplicitBtn_Click); // // ImplicitBtn // this.ImplicitBtn.Location = new System.Drawing.Point(19, 223); this.ImplicitBtn.Name = "ImplicitBtn"; this.ImplicitBtn.Size = new System.Drawing.Size(192, 55); this.ImplicitBtn.TabIndex = 8; this.ImplicitBtn.Text = "Implicit Compile"; this.ImplicitBtn.Click += new System.EventHandler(this.ImplicitBtn_Click); // // resultGrid // this.resultGrid.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; this.resultGrid.Location = new System.Drawing.Point(217, 15); this.resultGrid.Name = "resultGrid"; this.resultGrid.Size = new System.Drawing.Size(983, 278); this.resultGrid.TabIndex = 9; // // UseJitCompilerForm // this.AutoScaleBaseSize = new System.Drawing.Size(8, 18); this.ClientSize = new System.Drawing.Size(1220, 305); this.Controls.Add(this.resultGrid); this.Controls.Add(this.ImplicitBtn); this.Controls.Add(this.ExplicitBtn); this.Controls.Add(this.NoCompileBtn); this.Name = "UseJitCompilerForm"; this.Text = "Execute procedure with and without JIT compilation"; this.Load += new System.EventHandler(this.UseJitCompilerForm_Load); ((System.ComponentModel.ISupportInitialize)(this.resultGrid)).EndInit(); this.ResumeLayout(false); } #endregion [STAThread] static void Main() { Application.Run(new UseJitCompilerForm()); } private void UseJitCompilerForm_Load(object sender, System.EventArgs e) { string halconExamples = HSystem.GetSystem("example_dir"); ProgramPathString = halconExamples + @"\hdevengine\hdevelop\test_jit_speedup.hdev"; if (!HalconAPI.isWindows) { ProgramPathString = ProgramPathString.Replace('\\', '/'); } resultGrid.ColumnCount = 9; resultGrid.RowCount = HalconAPI.isWindows ? 3 : 4; resultGrid.RowHeadersVisible = false; resultGrid.Columns[0].Name = "Compile Fibonacci"; resultGrid.Columns[1].Name = "Prepare Fibonacci"; resultGrid.Columns[2].Name = "Execute Fibonacci"; resultGrid.Columns[3].Name = "Compile Mean"; resultGrid.Columns[4].Name = "Prepare Mean"; resultGrid.Columns[5].Name = "Execute Mean"; resultGrid.Columns[6].Name = "Compile Process"; resultGrid.Columns[7].Name = "Prepare Process"; resultGrid.Columns[8].Name = "Execute Process"; resultGrid.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight; resultGrid.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill; resultGrid.AutoResizeColumns(); int height = ExplicitBtn.Top - NoCompileBtn.Top; resultGrid.Rows[0].Height = height; resultGrid.Rows[1].Height = height; resultGrid.Rows[2].Height = height; resultGrid.CurrentCell.Selected = false; resultGrid.ReadOnly = true; for (int i = 0; i < resultGrid.Columns.Count; i++) { resultGrid.Columns[i].SortMode = DataGridViewColumnSortMode.Programmatic; } } delegate void ProcInputParamSetter(HDevProcedureCall call); private void ShowTime(int row, int col, double seconds) { resultGrid[col, row].Value = String.Format("{0,7:F1} ms",1000*seconds); resultGrid.Update(); } private void ClearTime(int row) { for (int i = 0; i < resultGrid.Columns.Count; i++) { resultGrid[i, row].Value = ""; } resultGrid.Update(); } private void RunProc(string name, CompileMode mode, int rowIndex, int columnOffset, ProcInputParamSetter setter) { HDevEngine Engine = null; HDevProgram Program = null; HDevProcedure Proc = null; HDevProcedureCall Call = null; try { Engine = new HDevEngine(); // 启用或禁用编译过程的执行,即JIT的开关 Engine.SetEngineAttribute("execute_procedures_jit_compiled", mode == CompileMode.eNoCompile ? "false" : "true"); Program = new HDevProgram(ProgramPathString); //载入主程序test_jit_speedup.hdev Proc = new HDevProcedure(Program, name); double T1 = HSystem.CountSeconds(); // 模式为预编译方式的处理 if (mode == CompileMode.eExplicit) Proc.CompileUsedProcedures(); double T2 = HSystem.CountSeconds(); ShowTime(rowIndex, columnOffset, T2 - T1); // 创建调用函数并设置参数 Call = new HDevProcedureCall(Proc); setter(Call); double T3 = HSystem.CountSeconds(); ShowTime(rowIndex, columnOffset + 1, T3 - T2); // 执行调用函数 Call.Execute(); double T4 = HSystem.CountSeconds(); ShowTime(rowIndex, columnOffset + 2, T4 - T3); } catch (HDevEngineException Ex) { MessageBox.Show(Ex.Message, "HDevEngine Exception"); } finally { // Cleanup if (Call != null) Call.Dispose(); if (Proc != null) Proc.Dispose(); if (Program != null) Program.Dispose(); if (Engine != null) Engine.Dispose(); } } private void RunProcs(CompileMode mode) { Cursor = Cursors.WaitCursor; int rowIndex = mode == CompileMode.eNoCompile ? 0 : mode == CompileMode.eExplicit ? 1 : 2; ClearTime(rowIndex); HImage image = new HImage("fabrik"); HImage imageUInt2 = image.ConvertImageType("uint2"); RunProc("fib", mode, rowIndex, 0, (ProcInputParamSetter) delegate(HDevProcedureCall call) { call.SetInputCtrlParamTuple(1,20); }); RunProc("mean_sp_real", mode, rowIndex, 3, (ProcInputParamSetter)delegate(HDevProcedureCall call) { call.SetInputIconicParamObject(1, imageUInt2); call.SetInputCtrlParamTuple(1, 3); call.SetInputCtrlParamTuple(2, 3); call.SetInputCtrlParamTuple(3, 10); call.SetInputCtrlParamTuple(4, 250); }); RunProc("process", mode, rowIndex, 6, (ProcInputParamSetter)delegate(HDevProcedureCall call) { call.SetInputIconicParamObject(1, imageUInt2); }); imageUInt2.Dispose(); image.Dispose(); Cursor = Cursors.Default; } private void NoCompileBtn_Click(object sender, System.EventArgs e) { RunProcs(CompileMode.eNoCompile); } private void ExplicitBtn_Click(object sender, System.EventArgs e) { RunProcs(CompileMode.eExplicit); } private void ImplicitBtn_Click(object sender, System.EventArgs e) { RunProcs(CompileMode.eImplicit); } } }
---------------------
作者:hackpig
来源:www.skcircle.com
版权声明:本文为博主原创文章,转载请附上博文链接!

