当前位置: 移动技术网 > IT编程>开发语言>.net > HSmartWindowControl 之 摄像头实时显示( 使用 WPF )

HSmartWindowControl 之 摄像头实时显示( 使用 WPF )

2018年09月11日  | 移动技术网IT编程  | 我要评论

丁庆平,福建医科大学信息门户,数码照相机排行榜

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

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网