HSmartWindowControl 之 攝像頭實時顯示( 使用 WPF )

不鏽鋼老鼠發表於2018-09-11

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
    }
}

相關文章