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