勇哥这套halcon引擎的学习笔记贴子共七篇,它是在官方指导文档《http://www.skcircle.com/?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
版权声明:本文为博主原创文章,转载请附上博文链接!

