1、新增Halcon控制元件,建立WPF專案
在VS2013中建立一個WPF工程,然後新增halcon的控制元件和工具包,參見:
HSmartWindowControl之安裝篇 (Visual Studio 2013 & Halcon 18)
在WPF工程中新增好HSmartWindowControlWPF控制元件後,將其拖入主窗體即可。
2、生成攝像頭實時顯示的halcon程式碼
使用Image Acquisition 連線筆記本自帶的攝像頭,然後生成實時顯示的程式碼即可:
* Image Acquisition 01: Code generated by Image Acquisition 01 open_framegrabber (`DirectShow`, 1, 1, 0, 0, 0, 0, `default`, 8, `rgb`, -1, `false`, `default`, `[0] Integrated Camera`, 0, -1, AcqHandle) grab_image_start (AcqHandle, -1) while (true) grab_image_async (Image, AcqHandle, -1) * Image Acquisition 01: Do something endwhile
3、匯出C#程式碼
這裡主要關注action函式:
// Main procedure private void action() { // Local iconic variables HObject ho_Image=null; // Local control variables HTuple hv_AcqHandle = new HTuple(); // Initialize local and output iconic variables HOperatorSet.GenEmptyObj(out ho_Image); //Image Acquisition 01: Code generated by Image Acquisition 01 //Image Acquisition 01: Attention: The initialization may fail in case parameters need to //Image Acquisition 01: be set in a specific order (e.g., image resolution vs. offset). hv_AcqHandle.Dispose(); HOperatorSet.OpenFramegrabber("DirectShow", 1, 1, 0, 0, 0, 0, "default", 8, "rgb", -1, "false", "default", "[0] Integrated Camera", 0, -1, out hv_AcqHandle); HOperatorSet.GrabImageStart(hv_AcqHandle, -1); while ((int)(1) != 0) { ho_Image.Dispose(); HOperatorSet.GrabImageAsync(out ho_Image, hv_AcqHandle, -1); //Image Acquisition 01: Do something } ho_Image.Dispose(); hv_AcqHandle.Dispose(); }
這段程式碼只是實現了採集影像,沒有在介面上顯示。
4、向VS專案新增halcon匯出的c#程式碼
向action()的程式碼中新增在視窗上顯示影像的程式碼,即使用DispObj函式。然後把action新增到按鈕響應中執行。
這樣點選按鈕之後就會進入死迴圈不停的GrabImage和DispObj,但是實際操作時介面會停止響應,而且影像並不會在視窗內重新整理。
5、新增實時顯示子執行緒
主執行緒中執行迴圈無法實時顯示,必須建立子執行緒。
這裡使用了工作者執行緒,點選按鈕後,啟動執行緒並執行一個迴圈顯示採集的影像;再次點選按鈕時,跳出迴圈結束worker執行緒。然後繼續點選按鈕又可以進入子執行緒開啟實時顯示,實現隨意啟停。
private void Button1_Click(object sender, RoutedEventArgs e) { if (isCameraOpened == false) { Button1.Content = "關閉實時顯示"; isCameraOpened = true; play_Thread = new Thread(action); play_Thread.Start(); } else { Button1.Content = "開啟實時顯示"; isCameraOpened = false; } }
注意呼叫執行緒需新增引用:
using System.Threading;//多執行緒
需要注意的是,為了防止在實時顯示過程中突然關閉窗體導致程式崩潰,在窗體的Un_load事件中加入強行停止子執行緒的程式碼。
private void Window_Unloaded(object sender, RoutedEventArgs e) { if(play_Thread.IsAlive) { play_Thread.Abort(); } }
6、調整影像尺寸以適應halconwindow視窗
(1)使用HSmartWindowControlWPF控制元件時,無需再新增滑鼠滾輪的響應函式便可使用滑鼠滾輪控制影像縮放。
(2)顯示單張影像時,可以直接向HSmartWindowControlWPF控制元件的HDisplayCurrentObject屬性賦HObject型別的影像即可自動調整影像尺寸來適應視窗大小。
hSmartWindowControl1.HDisplayCurrentObject = new HImage("girl.png");
但是這個方式不能適用於動態捕獲的影像,所以動態捕獲的影像還需要手動判斷來進行縮放。調整的方式比較簡單,就是獲取視窗尺寸和影像尺寸進行對比,根據影像過寬還是過高來縮放。
7、原始碼
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using HalconDotNet; using System.Threading;//多執行緒 namespace HalconWindowWPFDemo { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { #region 全域性變數 private static MainWindow mainWindow = new MainWindow(); private static HWindow hwindow; //全域性視窗變數 Thread play_Thread; //實時顯示執行緒 private static bool isCameraOpened; //是否正在實時顯示 private static double halconWindowHeight; //halcon視窗高度 private static double halconWindowWidth; ////halcon視窗寬度 #endregion #region 初始化 public MainWindow() { InitializeComponent(); } private void Window_Loaded(object sender, RoutedEventArgs e) { hwindow = hSmartWindowControl1.HalconWindow;//初始化視窗變數 isCameraOpened = false; //獲取halcon視窗大小 halconWindowHeight = mainWindow.hSmartWindowControl1.WindowSize.Width; halconWindowWidth = mainWindow.hSmartWindowControl1.WindowSize.Height; } #endregion #region 介面響應 /// <summary> /// 開啟和關閉實時顯示按鈕 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Button1_Click(object sender, RoutedEventArgs e) { if (isCameraOpened == false) { Button1.Content = "關閉實時顯示"; isCameraOpened = true; play_Thread = new Thread(action); play_Thread.Start(); } else { Button1.Content = "開啟實時顯示"; isCameraOpened = false; } } /// <summary> /// 顯示一張圖片 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Button2_Click(object sender, RoutedEventArgs e) { hSmartWindowControl1.HDisplayCurrentObject = new HImage("girl.png"); } #endregion #region 實時顯示用函式 /// <summary> /// 攝像頭實時顯示 /// </summary> private static void action() { // Local iconic variables HObject ho_Image = null; // Local control variables HTuple hv_AcqHandle = new HTuple(); // Initialize local and output iconic variables HOperatorSet.GenEmptyObj(out ho_Image); ho_Image.Dispose(); hv_AcqHandle.Dispose(); //Image Acquisition 01: Code generated by Image Acquisition 01 HOperatorSet.OpenFramegrabber("DirectShow", 1, 1, 0, 0, 0, 0, "default", 8, "rgb", -1, "false", "default", "[0] Integrated Camera", 0, -1, out hv_AcqHandle); HOperatorSet.GrabImageStart(hv_AcqHandle, -1); while (isCameraOpened) { HOperatorSet.GrabImageAsync(out ho_Image, hv_AcqHandle, -1); if (!mainWindow.ShowHalconImage(ho_Image)) break; } ho_Image.Dispose(); hv_AcqHandle.Dispose(); } /// <summary> /// 顯示影像 /// </summary> /// <param name="image"></param> /// <returns></returns> private bool ShowHalconImage(HObject ho_Image) { #region 縮放影像,適應視窗 //獲取影像大小及縱橫比 HTuple hv_Width = new HTuple(), hv_Height = new HTuple(); 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); //獲取視窗大小及縱橫比 double w_AspectRatio = halconWindowWidth / halconWindowHeight; HOperatorSet.SetSystem("int_zooming", "false");//影像縮放之前最好將此引數設定為false. HTuple para = new HTuple("constant"); HObject ho_zoomImage; HOperatorSet.GenEmptyObj(out ho_zoomImage); ho_zoomImage.Dispose(); if (halconWindowWidth < im_width && im_AspectRatio > w_AspectRatio) { //超寬影像 HOperatorSet.ZoomImageSize(ho_Image, out ho_zoomImage, halconWindowWidth, halconWindowWidth / im_AspectRatio, "constant"); } else if (halconWindowHeight < im_height && im_AspectRatio < w_AspectRatio) { //超高影像 HOperatorSet.ZoomImageSize(ho_Image, out ho_zoomImage, halconWindowHeight * im_AspectRatio, halconWindowHeight, para); } #endregion #region 顯示影像 try { hwindow.SetPart(0, 0, -2, -2); hwindow.DispObj(ho_zoomImage); } catch (Exception exp) { //MessageBox.Show(exp.ToString()); return false; } #endregion return true; } #endregion #region 解構函式 /// <summary> /// 關閉窗體時推出子執行緒,防止崩潰 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Window_Unloaded(object sender, RoutedEventArgs e) { if(play_Thread.IsAlive) { play_Thread.Abort(); } } #endregion } }