halcon引擎学习笔记(七)在在HDevEngine/C#中使用实时编译器JIT

勇哥这套halcon引擎的学习笔记贴子共七篇,它是在官方指导文档《http://47.98.154.65/?id=1343》的基础上学习编写而成的笔记。只是有一篇讲解怎么调用向量变量的没有加入,因为勇哥实在不知道这个向量变量有啥子用。以后如果搞明白了再加入吧。


2020/7/3勇哥注:

原来halcon中的向量就是个容器,跟c++标准模板库中的那个向量是一致的。第八篇加上来吧

halcon引擎学习笔记(八)使用向量变量


halcon引擎学习笔记(七)在在HDevEngine/C#中使用实时编译器JIT 

halcon引擎学习笔记(六)多线程并发执行外部函数,多窗口显示  

halcon引擎学习笔记(五)多线程并发执行外部函数  

halcon引擎学习笔记(四)调用时的错误处理   

halcon引擎学习笔记(三)执行本地或者外部程序   

halcon引擎学习笔记(二)执行Procedure程序,扩展名为hdvp的halcon函数   

halcon引擎学习笔记(一)执行hdev程序   

演示程序勇哥用的是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)

可以打开设置窗口。

image.png

高级用户选项下面就可以看到JIT的开关。

image.png

或者在用halcon引擎运行函数的时候可以使用下面指令打开JIT开关。

Engine.SetEngineAttribute("execute_procedures_jit_compiled",
   mode == CompileMode.eNoCompile ? "false" : "true");


JIT实时编译有一些限制,详细见下图:

image.png


本篇的演示程序功能是计算:

不编译、显式编译、隐式编译三种方式的执行时间。

image.png


同时可以演示程序中学习到下面的内容:

  • 演示如何控制HDevelop的编译

  • 使用集成实时编译器hdev和hdvp的过程。

  • 可以全局控制是否应该在执行之前编译过程。

  • 此外,还可以控制在什么时间点执行编译。




在主程序中,调用了三个不同的本地函数进行测试。包括:

1)fib,一些HDevelop过程的递归调用。

2)mean_sp_real,使用大量循环的过滤器的实现。

3)process,部分HALCON算子的顺序调用。


三个本地函数的代码与参数如下:


fib本地函数的参数

image.png

源码:

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的参数

image.png

源码:

* 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的参数

image.png

源码:

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

版权声明:本文为博主原创文章,转载请附上博文链接!



本文出自勇哥的网站《少有人走的路》wwww.skcircle.com,转载请注明出处!讨论可扫码加群:
本帖最后由 勇哥,很想停止 于 2020-06-26 16:37:37 编辑
  • 评论列表:
  •  访客
     发布于 2020-12-17 23:56:12  回复该评论
  • HDevEngine 类有个UnloadProcedure方法,将你加载的程序名称移除了,可以修改halcon代码而不用重启程序即可执行;(小黄鱼 qq:3243223774)
  •  xiongqing
     发布于 2023-08-02 11:22:55  回复该评论
  • 这篇文章halcon代码写的厉害, 比halcon的demo更丰富

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

会员中心
搜索
«    2025年4月    »
123456
78910111213
14151617181920
21222324252627
282930
网站分类
标签列表
最新留言
    热门文章 | 热评文章 | 随机文章
文章归档
友情链接
  • 订阅本站的 RSS 2.0 新闻聚合
  • 扫描加本站机器视觉QQ群,验证答案为:halcon勇哥的机器视觉
  • 点击查阅微信群二维码
  • 扫描加勇哥的非标自动化群,验证答案:C#/C++/VB勇哥的非标自动化群
  • 扫描加站长微信:站长微信:abc496103864
  • 扫描加站长QQ:
  • 扫描赞赏本站:
  • 留言板:

Powered By Z-BlogPHP 1.7.2

Copyright Your skcircle.com Rights Reserved.

鄂ICP备18008319号


站长QQ:496103864 微信:abc496103864