• Halcon HSmartWindowControl之显示图像


    概述:使用Halcon在VS中的控件显示一张图片。

    要点:使用了图像缩放和图像显示函数,以及鼠标滚轮响应函数。

    1、创建WinForm项目

    首先在VS中添加Halcon所需的控件HSmartWindowControl

    然后创建新的winForm工程,并向窗体中拖入一个HSmartWindowControl控件和两个按钮控件。

    image

    拖入后不添加代码,直接运行,可能会出现如下错误:

    HalconDotNet.HHandleBase 的类型初始化值设定项引发异常

    Snipaste_2018-08-30_18-31-30

    Halcon error #2381:License is for wrong edition of Halcon in Operator set_system

    Snipaste_2018-08-27_18-24-24

    原因是halcon运行库是64位的,vs的运行模式也需要设置为64位,默认的debug模式可能是any CPU,需要把这里修改成x64。

    image

    或者从解决方案资源管理器(solution Explorer)中双击打开属性(Property)页面,把Build栏的Platform target 改为x64即可。

    image

    2、创建Halcon实时显示代码并导出

    打开halcon,写一句简单的代码

    image

    接着,选择文件->导出,将HDevelop语言导出为C#语言。

    image

    3、halcon 导出的C#代码分析

     1 using System;
     2 using HalconDotNet;
     3 
     4 public partial class HDevelopExport
     5 {
     6   public HTuple hv_ExpDefaultWinHandle;
     7 
     8   // Main procedure 
     9   private void action()
    10   {
    11     // Local iconic variables 
    12     HObject ho_Image;
    13     // Local control variables 
    14     HTuple hv_Width = new HTuple(), hv_Height = new HTuple();
    15     // Initialize local and output iconic variables 
    16     HOperatorSet.GenEmptyObj(out ho_Image);
    17     ho_Image.Dispose();
    18     HOperatorSet.ReadImage(out ho_Image, "printer_chip/printer_chip_01");
    19     hv_Width.Dispose();hv_Height.Dispose();
    20     HOperatorSet.GetImageSize(ho_Image, out hv_Width, out hv_Height);
    21     ho_Image.Dispose();
    22 
    23     hv_Width.Dispose();
    24     hv_Height.Dispose();
    25   }
    26 
    27   public void InitHalcon()
    28   {
    29     // Default settings used in HDevelop 
    30     HOperatorSet.SetSystem("width", 512);
    31     HOperatorSet.SetSystem("height", 512);
    32   }
    33 
    34   public void RunHalcon(HTuple Window)
    35   {
    36     hv_ExpDefaultWinHandle = Window;
    37     action();
    38   }
    39 }

    实际有用的代码就是action()内的代码,首先声明了图像变量:HObject ho_Image;

    需要注意的是,图像类型需要先初始化再使用:HOperatorSet.GenEmptyObj(out ho_Image);

    然后调用ReadImage函数读入图像文件,最后调用Dispose函数清空对象。但是没有显示图像的代码,需要自己添加。

    4、向VS中插入代码

    打开Winform工程窗体关联的cs文件Form1.cs,首先需要在文件头部添加命名空间引用:

    using HalconDotNet;

    需要在类中定义全局的窗口变量,便于操作窗体:

    1 private static HWindow hwindow; //全局窗口变量
    2 public HTuple hv_ExpDefaultWinHandle; //导出的代码定义的,其实没用到

    窗口的初始化函数中添加全局变量的初始化函数:

    1 public Form1()
    2         {
    3             InitializeComponent();
    4             hwindow = hSmartWindowControl1.HalconWindow;//初始化窗口变量
    5             this.MouseWheel += new System.Windows.Forms.MouseEventHandler(this.my_MouseWheel);
    6         }

    然后在按钮的响应函数中添加载入图像的及显示的代码:

     1 private void button2_Click(object sender, EventArgs e)
     2         {
     3             #region 初始化变量
     4             // Local iconic variables 
     5             HObject ho_Image;
     6             // Local control variables 
     7             HTuple hv_Width = new HTuple(), hv_Height = new HTuple();
     8             // Initialize local and output iconic variables 
     9             HOperatorSet.GenEmptyObj(out ho_Image);
    10             ho_Image.Dispose();
    11             HOperatorSet.ReadImage(out ho_Image, "clip.png");
    12             hv_Width.Dispose(); hv_Height.Dispose();
    13             #endregion
    14 
    15             #region 缩放图像,适应窗口
    16             bool needResizeImage = true;
    17             //获取图像大小及纵横比
    18             HOperatorSet.GetImageSize(ho_Image, out hv_Width, out hv_Height);
    19             int im_width = int.Parse(hv_Width.ToString());
    20             int im_height = int.Parse(hv_Height.ToString());
    21             double im_AspectRatio = (double)(im_width)/(double)(im_height);
    22             //获取窗口大小及纵横比
    23             int w_width = hSmartWindowControl1.Size.Width;
    24             int w_height = hSmartWindowControl1.Size.Height;
    25             double w_AspectRatio = (double)(w_width)/(double)(w_height);
    26 
    27             HOperatorSet.SetSystem("int_zooming", "false");//图像缩放之前最好将此参数设置为false.
    28             HTuple para = new HTuple("constant");
    29             HObject ho_zoomImage;
    30             HOperatorSet.GenEmptyObj(out ho_zoomImage);
    31 
    32             ho_zoomImage.Dispose();
    33             if(w_width<im_width && im_AspectRatio>w_AspectRatio)
    34             {
    35                 //超宽图像               
    36                 HOperatorSet.ZoomImageSize(ho_Image, out ho_zoomImage, w_width, w_width / im_AspectRatio, para);            
    37             }
    38             else if (w_height < im_height && im_AspectRatio < w_AspectRatio)
    39             {
    40                 //超高图像                
    41                 HOperatorSet.ZoomImageSize(ho_Image, out ho_zoomImage, w_height * im_AspectRatio, w_height, para);
    42             }
    43             else
    44             {
    45                 needResizeImage = false;
    46             }
    47             #endregion
    48 
    49             #region 显示图像
    50             hwindow.SetPart(0, 0, -2, -2);         
    51             if (needResizeImage)
    52              {
    53                  hwindow.DispObj(ho_zoomImage);
    54              }
    55              else
    56              {
    57                  hwindow.DispObj(ho_Image);
    58              }
    59 
    60 
    61             //HOperatorSet.GetImageSize(ho_zoomImage, out hv_Width, out hv_Height);
    62             //im_width = int.Parse(hv_Width.ToString());
    63             //im_height = int.Parse(hv_Height.ToString());
    64             //MessageBox.Show(hv_Width.ToString() + "  " + hv_Height.ToString());
    65             
    66             #endregion
    67 
    68             ho_Image.Dispose();
    69             ho_zoomImage.Dispose();
    70             hv_Width.Dispose();
    71             hv_Height.Dispose();
    72         }

    5、图像缩放和显示

    这里我对导出的代码做了修改,主要是增加了图像缩放和显示功能。

    图像缩放使用了ZoomImageSize函数,在帮助文档中,这个函数有两种用法:

    1 static void HOperatorSet.ZoomImageSize(HObject image, out HObject imageZoom, HTuple width,HTuple height, HTuple interpolation)
    2 HImage HImage.ZoomImageSize(int width, int height, string interpolation)

    上面的代码中使用了第一种用法,所有的参数必须是Halcon的类型,但是实际使用时width 和height 可以用int类型,interpolation即差值算法参数也可以直接传入string类型,如“constant”。

    第二种方法需要将使用HImage类型的变量来操作,所以需要将 HObject 类型定义的图像变量转换一下:

    1 HImage img = new HImage(ho_Image);
    2 ho_zoomImage = img.ZoomImageSize(w_width, w_width, "constant");

    图像显示功能:先调用SetPart函数确定要显示图像的区域,然后调用DispObj函数显示图像,DispObj也有三种用法:

    1 static void HOperatorSet.DispObj(HObject objectVal, HTuple windowHandle)
    2 void HObject.DispObj(HWindow windowHandle)
    3 void HWindow.DispObj(HObject objectVal)

    此处我用的第三种:通过Hwindow调用,参数为要显示的图像变量。

    1 hwindow.SetPart(0, 0, -2, -2);
    2 hwindow.DispObj(ho_zoomImage);

    6、SmartWindowControl窗口交互

    前面实现了图像显示,SmartWindowControl最大的亮点其实是方便的交互功能。

    可以用鼠标拖动图像水平移动,利用鼠标滚轮实现图像放大缩小。

    另外,在winForm项目中,为了使用SmartWindowControl控件中图像的缩放,还需要添加鼠标滚轮响应的回调函数。

    详见:C:/Program Files/MVTec/HALCON-18.05-Progress/doc/html/manuals/programmers_guide/programmers_guide_0051.html

    image

    实际测试发现帮助文档中的用法有一些问题,消息相应函数的注册应该在整个窗体的初始化函数中,而不是SmartWindowControl的初始化函数中。

    1 private void hSmartWindowControl1_Load(object sender, EventArgs e)
    2         {
    3             //这句话不起作用
    4             this.MouseWheel += new System.Windows.Forms.MouseEventHandler(this.my_MouseWheel);
    5         }
    1 public Form1()
    2         {
    3             InitializeComponent();
    4             hwindow = hSmartWindowControl1.HalconWindow;//初始化窗口变量
    5             // 鼠标滚轮的响应函数注册
    6             this.MouseWheel += new System.Windows.Forms.MouseEventHandler(this.my_MouseWheel);
    7         }

    这样修改后,直接使用帮助文档中提供的my_MouseWheel也有一个小bug,就是无论在窗体的任何位置滑动滚轮,图片都会缩放,所以需要对鼠标的位置做一下限制:

     1 private void my_MouseWheel(object sender, MouseEventArgs e)
     2         {
     3             System.Drawing.Point pt = this.Location;
     4             int leftBorder = hSmartWindowControl1.Location.X;
     5             int rightBorder = hSmartWindowControl1.Location.X + hSmartWindowControl1.Size.Width;
     6             int topBorder = hSmartWindowControl1.Location.Y;
     7             int bottomBorder = hSmartWindowControl1.Location.Y + hSmartWindowControl1.Size.Height;
     8             if(e.X > leftBorder && e.X < rightBorder && e.Y > topBorder && e.Y < bottomBorder)
     9             {
    10                 MouseEventArgs newe = new MouseEventArgs(e.Button, e.Clicks,
    11                                                      e.X - pt.X, e.Y - pt.Y, e.Delta);
    12                 hSmartWindowControl1.HSmartWindowControl_MouseWheel(sender, newe);
    13             }           
    14         }
  • 相关阅读:
    Python subprocess- call、check_call、check_output
    Java Annotation认知(包括框架图、详细介绍、示例说明) (转)
    NVME SSD vs SATA SSD(转)
    scala中“_”的用法
    maven scope 'provided' 和 ‘compile’的区别
    scala tuple中的syntactic sugar
    Scala中的"null" 和“_”来初始化对象
    scala可变长度参数(转)
    Java中的Builder模式
    Scala中“=>”用法及含义
  • 原文地址:https://www.cnblogs.com/ybqjymy/p/12720985.html
Copyright © 2020-2023  润新知