HSmartWindowControl 之 攝像頭實時顯示( 使用 WPF )
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 privatevoid 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 } }
HSmartWindowControl 之 攝像頭實時顯示( 使用 WPF )