概述:使用Halcon在VS中的控制項顯示一張圖片。要點:使用了圖像縮放和圖像顯示函數,以及滑鼠滾輪響應函數。1、創建WinForm項目參考上一篇:HSmartWindowControl之安裝篇 (Visual Studio 2013 & Halcon 18)https://www.cnblogs.c... ...
概述:使用Halcon在VS中的控制項顯示一張圖片。
要點:使用了圖像縮放和圖像顯示函數,以及滑鼠滾輪響應函數。
1、創建WinForm項目
首先在VS中添加Halcon所需的控制項HSmartWindowControl,參考上一篇:HSmartWindowControl之安裝篇 (Visual Studio 2013 & Halcon 18)https://www.cnblogs.com/oucsheep/p/9563876.html
然後創建新的winForm工程,並向窗體中拖入一個HSmartWindowControl控制項和兩個按鈕控制項。
拖入後不添加代碼,直接運行,可能會出現如下錯誤:
HalconDotNet.HHandleBase 的類型初始化值設定項引發異常
Halcon error #2381:License is for wrong edition of Halcon in Operator set_system
原因是halcon運行庫是64位的,vs的運行模式也需要設置為64位,預設的debug模式可能是any CPU,需要把這裡修改成x64。
或者從解決方案資源管理器(solution Explorer)中雙擊打開屬性(Property)頁面,把Build欄的Platform target 改為x64即可。
2、創建Halcon實時顯示代碼並導出
打開halcon,寫一句簡單的代碼
接著,選擇文件->導出,將HDevelop語言導出為C#語言。
3、halcon 導出的C#代碼分析
using System; using HalconDotNet; public partial class HDevelopExport { public HTuple hv_ExpDefaultWinHandle; // Main procedure private void action() { // Local iconic variables HObject ho_Image; // Local control variables HTuple hv_Width = new HTuple(), hv_Height = new HTuple(); // Initialize local and output iconic variables HOperatorSet.GenEmptyObj(out ho_Image); ho_Image.Dispose(); HOperatorSet.ReadImage(out ho_Image, "printer_chip/printer_chip_01"); hv_Width.Dispose();hv_Height.Dispose(); HOperatorSet.GetImageSize(ho_Image, out hv_Width, out hv_Height); ho_Image.Dispose(); hv_Width.Dispose(); hv_Height.Dispose(); } public void InitHalcon() { // Default settings used in HDevelop HOperatorSet.SetSystem("width", 512); HOperatorSet.SetSystem("height", 512); } public void RunHalcon(HTuple Window) { hv_ExpDefaultWinHandle = Window; action(); } }
實際有用的代碼就是action()內的代碼,首先聲明瞭圖像變數:HObject ho_Image;
需要註意的是,圖像類型需要先初始化再使用:HOperatorSet.GenEmptyObj(out ho_Image);
然後調用ReadImage函數讀入圖像文件,最後調用Dispose函數清空對象。但是沒有顯示圖像的代碼,需要自己添加。
4、向VS中插入代碼
打開Winform工程窗體關聯的cs文件Form1.cs,首先需要在文件頭部添加命名空間引用:
using HalconDotNet;
需要在類中定義全局的視窗變數,便於操作窗體:
private static HWindow hwindow; //全局視窗變數 public HTuple hv_ExpDefaultWinHandle; //導出的代碼定義的,其實沒用到
視窗的初始化函數中添加全局變數的初始化函數:
public Form1() { InitializeComponent(); hwindow = hSmartWindowControl1.HalconWindow;//初始化視窗變數 this.MouseWheel += new System.Windows.Forms.MouseEventHandler(this.my_MouseWheel); }
然後在按鈕的響應函數中添載入入圖像的及顯示的代碼:
private void button2_Click(object sender, EventArgs e) { #region 初始化變數 // Local iconic variables HObject ho_Image; // Local control variables HTuple hv_Width = new HTuple(), hv_Height = new HTuple(); // Initialize local and output iconic variables HOperatorSet.GenEmptyObj(out ho_Image); ho_Image.Dispose(); HOperatorSet.ReadImage(out ho_Image, "clip.png"); hv_Width.Dispose(); hv_Height.Dispose(); #endregion #region 縮放圖像,適應視窗 //獲取圖像大小及縱橫比 HOperatorSet.GetImageSize(ho_Image, out hv_Width, out hv_Height); int im_width = int.Parse(hv_Width.ToString()); int im_height = int.Parse(hv_Height.ToString()); double im_AspectRatio = (double)(im_width)/(double)(im_height); //獲取視窗大小及縱橫比 int w_width = hSmartWindowControl1.Size.Width; int w_height = hSmartWindowControl1.Size.Height; double w_AspectRatio = (double)(w_width)/(double)(w_height); HOperatorSet.SetSystem("int_zooming", "false");//圖像縮放之前最好將此參數設置為false. HTuple para = new HTuple("constant"); HObject ho_zoomImage; HOperatorSet.GenEmptyObj(out ho_zoomImage); ho_zoomImage.Dispose(); if(w_width<im_width && im_AspectRatio>w_AspectRatio) { //超寬圖像 HOperatorSet.ZoomImageSize(ho_Image, out ho_zoomImage, w_width, w_width / im_AspectRatio, para); } else if (w_height < im_height && im_AspectRatio < w_AspectRatio) { //超高圖像 HOperatorSet.ZoomImageSize(ho_Image, out ho_zoomImage, w_height * im_AspectRatio, w_height, para); } #endregion #region 顯示圖像 hwindow.SetPart(0, 0, -2, -2); hwindow.DispObj(ho_zoomImage); //HOperatorSet.GetImageSize(ho_zoomImage, out hv_Width, out hv_Height); //im_width = int.Parse(hv_Width.ToString()); //im_height = int.Parse(hv_Height.ToString()); //MessageBox.Show(hv_Width.ToString() + " " + hv_Height.ToString()); #endregion ho_Image.Dispose(); ho_zoomImage.Dispose(); hv_Width.Dispose(); hv_Height.Dispose(); }
5、圖像縮放和顯示
這裡我對導出的代碼做了修改,主要是增加了圖像縮放和顯示功能。
圖像縮放使用了ZoomImageSize函數,在幫助文檔中,這個函數有兩種用法:
static void HOperatorSet.ZoomImageSize(HObject image, out HObject imageZoom, HTuple width,HTuple height, HTuple interpolation) HImage HImage.ZoomImageSize(int width, int height, string interpolation)
上面的代碼中使用了第一種用法,所有的參數必須是Halcon的類型,但是實際使用時width 和height 可以用int類型,interpolation即差值演算法參數也可以直接傳入string類型,如“constant”。
第二種方法需要將使用HImage類型的變數來操作,所以需要將 HObject 類型定義的圖像變數轉換一下:
HImage img = new HImage(ho_Image); ho_zoomImage = img.ZoomImageSize(w_width, w_width, "constant");
圖像顯示功能:先調用SetPart函數確定要顯示圖像的區域,然後調用DispObj函數顯示圖像,DispObj也有三種用法:
static void HOperatorSet.DispObj(HObject objectVal, HTuple windowHandle) void HObject.DispObj(HWindow windowHandle) void HWindow.DispObj(HObject objectVal)
此處我用的第三種:通過Hwindow調用,參數為要顯示的圖像變數。
hwindow.SetPart(0, 0, -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
實際測試發現幫助文檔中的用法有一些問題,消息相應函數的註冊應該在整個窗體的初始化函數中,而不是SmartWindowControl的初始化函數中。
private void hSmartWindowControl1_Load(object sender, EventArgs e) { //這句話不起作用 this.MouseWheel += new System.Windows.Forms.MouseEventHandler(this.my_MouseWheel); }
public Form1() { InitializeComponent(); hwindow = hSmartWindowControl1.HalconWindow;//初始化視窗變數 // 滑鼠滾輪的響應函數註冊 this.MouseWheel += new System.Windows.Forms.MouseEventHandler(this.my_MouseWheel); }
這樣修改後,直接使用幫助文檔中提供的my_MouseWheel也有一個小bug,就是無論在窗體的任何位置滑動滾輪,圖片都會縮放,所以需要對滑鼠的位置做一下限制:
private void my_MouseWheel(object sender, MouseEventArgs e) { System.Drawing.Point pt = this.Location; int leftBorder = hSmartWindowControl1.Location.X; int rightBorder = hSmartWindowControl1.Location.X + hSmartWindowControl1.Size.Width; int topBorder = hSmartWindowControl1.Location.Y; int bottomBorder = hSmartWindowControl1.Location.Y + hSmartWindowControl1.Size.Height; if(e.X > leftBorder && e.X < rightBorder && e.Y > topBorder && e.Y < bottomBorder) { MouseEventArgs newe = new MouseEventArgs(e.Button, e.Clicks, e.X - pt.X, e.Y - pt.Y, e.Delta); hSmartWindowControl1.HSmartWindowControl_MouseWheel(sender, newe); } }