一个工业相机通用类解决大部分业内流行相机的访问(基于大华相机的动态链接库开发的通用相机类)C#版

 

其实工业相机里面大部分不同的知名厂家的相机完全可以通过一个共用类来访问,这一点有在使用halcon小助手连接相机上体现。比如说常用的GigE接口的相机几乎都适应于halcon提供的GigE接口类。

以下分享一个我使用大华相机动态链接库开发的一个共用相机类。

环境:

大华相机的dll:

共用类:

public class CamCommon
    {
        #region 属性相关
        //搜索到的设备集合
        static List<IDeviceInfo> li = Enumerator.EnumerateDevices();

        List<IGrabbedRawData> m_frameList = new List<IGrabbedRawData>();        /* 图像缓存列表 */
        Thread renderThread = null;         /* 显示线程  */
        bool m_bShowLoop = true;            /* 线程控制变量 */
        Mutex m_mutex = new Mutex();        /* 锁,保证多线程安全 */
        private Graphics _g = null;
        bool m_bShowByGDI;                  /* 是否使用GDI绘图 */

        const int DEFAULT_INTERVAL = 40;
        Stopwatch m_stopWatch = new Stopwatch();    /* 时间统计器 */

        /* 设备对象 大华官方SDK */
        private ThridLibray.IDevice m_dev;
        /// <summary>
        /// 相机ID
        /// </summary>
        public string userID;
        #endregion

        #region 委托事件相关
        /// <summary>
        /// 给需要显示图像的地方绑定,图像回调委托
        /// </summary>
        /// <param name="image"></param>
        public delegate void DaHuaImageShow(HObject image);

        /// <summary>
        /// 图像回调显示函数
        /// </summary>
        public event DaHuaImageShow evetAsynchImage;
        #endregion

        #region 构造相关
        /// <summary>
        /// 根据UserID 名称自动对应创建实例化 并
        /// </summary>
        /// <param name="userID"></param>
        public CamCommon(string userID){

            this.userID = userID;
            if (li.Count > 0)
            {
                for (int i = 0; i < li.Count; i++)
                {/// 如果要获取该相机设置名称, 可以用li[i].Key  返回的就是设置名
                    if (li[i].Name == userID) { // 表示找到了该相机就打开连接

                        /* 获取搜索到的第一个设备  连接到相机实例化 */
                        m_dev = Enumerator.GetDeviceByIndex(i);

                    }
                }
            }
        }
        #endregion

        #region 一般方法相关
        /// <summary>
        /// 获取连接到的设备名
        /// </summary>
        /// <returns>返回设备集合</returns>
        public static List<string> DeviceNames() {
            List<string> DeviceNameList = new List<string>();
            if (li.Count > 0)
            {
                for (int i = 0; i < li.Count; i++)
                {
                    DeviceNameList.Add(li[i].Name);
                }
            }
            return DeviceNameList;
        }
        /// <summary>
        /// 图像采集函数 ,线程
        /// </summary>
        private void ShowThread()
        {
            while (m_bShowLoop)
            {
                if (m_frameList.Count == 0)
                {
                    Thread.Sleep(10);
                    continue;
                }

                /* 图像队列取最新帧 */
                m_mutex.WaitOne();
                IGrabbedRawData frame = m_frameList.ElementAt(m_frameList.Count - 1);
                m_frameList.Clear();
                m_mutex.ReleaseMutex();

                /* 主动调用回收垃圾 */
                GC.Collect();

                /* 控制显示最高帧率为25FPS */
                if (false == isTimeToDisplay())
                {
                    continue;
                }

                try
                {
                    /* 图像转码成bitmap图像 */
                    var bitmap = frame.ToBitmap(false);
                    Bitmap bitmap1 = null;
                    m_bShowByGDI = true;
                    if (m_bShowByGDI)
                    {

                        /// 事件触发,通过委托进行窗口间转换
                        HObject image = BitmapToHImage(bitmap);


                        /// 添加事件通过绑定事件的方式进行图像传播
                        if (evetAsynchImage!=null) { /// 避免没有接受事件者触发
                            evetAsynchImage(image);
                        }
                        image.Dispose();

                        bitmap.Dispose();
                    }
                }
                catch (Exception exception)
                {
                    Catcher.Show(exception);
                }
            }
        }
        /* 判断是否应该做显示操作 */
        private bool isTimeToDisplay()
        {
            m_stopWatch.Stop();
            long m_lDisplayInterval = m_stopWatch.ElapsedMilliseconds;
            if (m_lDisplayInterval <= DEFAULT_INTERVAL)
            {
                m_stopWatch.Start();
                return false;
            }
            else
            {
                m_stopWatch.Reset();
                m_stopWatch.Start();
                return true;
            }
        }
        /// <summary>
        /// 打开相机
        /// </summary>
        /// <returns></returns>
        public bool openCam() {
            try
            {
                /* 注册链接事件 */
                m_dev.ConnectionLost += OnConnectLoss;

                /* 打开设备 */
                while (!m_dev.Open())
                {
                    MessageBox.Show("连接相机失败");
                    Thread.Sleep(5000);
                    return false;
                }
                ///* 设置图像格式 */
                //using (IEnumParameter p = m_dev.ParameterCollection[ParametrizeNameSet.ImagePixelFormat])
                //{
                //    p.SetValue("Mono8");
                //}

                ///* 设置曝光 */
                ///*using (IFloatParameter p = m_dev.ParameterCollection[ParametrizeNameSet.ExposureTime])
                //{
                //    p.SetValue(20000);
                //}*/

                ///* 设置增益 */
                //using (IFloatParameter p = m_dev.ParameterCollection[ParametrizeNameSet.GainRaw])
                //{
                //    p.SetValue(1.0);
                //}
                /// 开启图像采集函数线程
                renderThread = new Thread(new ThreadStart(ShowThread));
                renderThread.IsBackground = true;
                renderThread.Start();
                /* 设置缓存个数为8(默认值为16) */
                m_dev.StreamGrabber.SetBufferCount(8);

                /* 注册码流回调事件 图像回调函数 */
                m_dev.StreamGrabber.ImageGrabbed += OnImageGrabbed;
            }
            catch {
                MessageBox.Show("连接相机失败");
                return false;
            }
            return true;
        }
        /// <summary>
        /// 开始连续采集
        /// </summary>
        public void openConsecutive() {
            try
            {
                if (m_dev != null) {
                    /* 开启码流 */
                    if (!m_dev.GrabUsingGrabLoopThread())
                    {
                        MessageBox.Show(@"开启码流失败");
                        return;
                    }
                }
            }
            catch { }
        }
        /// <summary>
        /// 关闭连续采集
        /// </summary>
        public void closeConsecutive() {
            try
            {
                if (m_dev != null)
                {
                    m_dev.ShutdownGrab();                                       /* 停止码流 */
                }
            }
            catch { }
        }
        /// <summary>
        /// 关闭相机
        /// </summary>
        public void closeCam() {
            try
            {
                if (m_dev == null)
                {
                    throw new InvalidOperationException("Device is invalid");
                }
                m_dev.StreamGrabber.ImageGrabbed -= OnImageGrabbed;         /* 反注册回调 */
                m_dev.ShutdownGrab();                                       /* 停止码流 */
                m_dev.Close();                                              /* 关闭相机 */
            }
            catch {
                MessageBox.Show("关闭失败!","Error");
            }
        }
        /// <summary>
        /// 码流数据回调
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnImageGrabbed(Object sender, GrabbedEventArgs e)
        {
            m_mutex.WaitOne();
            m_frameList.Add(e.GrabResult.Clone());
            m_mutex.ReleaseMutex();
        }
        /// <summary>
        /// 相机掉线重连函数
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnConnectLoss(object sender, EventArgs e)
        {
            /// 先关闭所有信息
            m_dev.ShutdownGrab();
            m_dev.Dispose();
            m_dev = null;

            ///重新创建实例绑定时间 开始连接

            /* 设备搜索 */
            List<IDeviceInfo> li = Enumerator.EnumerateDevices();
            if (li.Count > 0)
            {
                for (int i = 0; i < li.Count; i++)
                {
                    if (li[i].Name == userID)
                    { // 表示找到了该相机就打开连接
                        /* 获取搜索到的第一个设备  连接到相机实例化 */
                        m_dev = Enumerator.GetDeviceByIndex(i);

                        // 实例化之后打开相机并开启实时采集
                        /* 打开设备  只尝试打开3次 如果打开3次失败则关闭 */
                        int ii = 0;
                        while (!m_dev.Open())
                        {
                            ii += 1;
                            Thread.Sleep(200);
                            if (ii >= 3) {
                                return;
                            }
                        }
                        / 开启实时采集
                        /* 设置缓存个数为8(默认值为16) */
                        m_dev.StreamGrabber.SetBufferCount(8);
                        /* 注册码流回调事件 */
                        m_dev.StreamGrabber.ImageGrabbed += OnImageGrabbed;
                        /* 开启码流  or  开启实时采集*/
                        m_dev.GrabUsingGrabLoopThread();
                    }
                }


            }
            else {
                MessageBox.Show("未找到"+userID+ "的相机,请检查相机接口!");
            }
        }
        /// <summary>
        /// 图像转换
        /// </summary>
        /// <param name="SrcImage"></param>
        /// <returns></returns>
        public static HObject BitmapToHImage(Bitmap SrcImage)
        {
            HObject Hobj;
            HOperatorSet.GenEmptyObj(out Hobj);
            Point po = new Point(0, 0);
            Size so = new Size(SrcImage.Width, SrcImage.Height);
            //template.Width, template.Height        
            Rectangle ro = new Rectangle(po, so);
            Bitmap DstImage = new Bitmap(SrcImage.Width, SrcImage.Height, PixelFormat.Format8bppIndexed);
            DstImage = SrcImage.Clone(ro, PixelFormat.Format8bppIndexed);
            int width = DstImage.Width;
            int height = DstImage.Height;
            Rectangle rect = new Rectangle(0, 0, width, height);
            System.Drawing.Imaging.BitmapData dstBmpData = DstImage.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
            //pImage.PixelFormat     
            int PixelSize = Bitmap.GetPixelFormatSize(dstBmpData.PixelFormat) / 8;
            int stride = dstBmpData.Stride;
            //重点在此       
            unsafe
            {
                int count = height * width;
                byte[] data = new byte[count];
                byte* bptr = (byte*)dstBmpData.Scan0;
                fixed (byte* pData = data)
                {
                    for (int i = 0; i < height; i++)
                        for (int j = 0; j < width; j++)
                        {
                            data[i * width + j] = bptr[i * stride + j];
                        }
                    HOperatorSet.GenImage1(out Hobj, "byte", width, height, new IntPtr(pData));
                }
            }
            DstImage.UnlockBits(dstBmpData);
            return Hobj;
        }
        /// <summary>
        /// 开启硬件触发,其实触发模式设置为on既可以硬触发也可以软触发
        /// </summary>
        /// <returns></returns>
        public bool openTriggerLinel()
        {
            return m_dev.TriggerSet.Open(TriggerSourceEnum.Line1);
        }
        /// <summary>
        /// 开启软件触发
        /// </summary>
        /// <returns></returns>
        public bool openSoftwareTrigger() {
            return m_dev.TriggerSet.Open(TriggerSourceEnum.Software);
        }
        /// <summary>
        /// 触发模式或软触发模式触发一次相机采集
        /// </summary>
        public void SoftwareTrigger() {
            if (m_dev == null)
            {
                throw new InvalidOperationException("Device is invalid");
            }
            try
            {
                m_dev.ExecuteSoftwareTrigger();
            }
            catch (Exception exception)
            {
                Catcher.Show(exception);
            }
        }

        #endregion

        #region 相机参数相关
        //定义一般参数; 格式:中文名,大华相机官方参数keys,类型
        static string[,] prms = 
            {   {  "设备型号", "DeviceModelName", "string"  } ,
                { "图像格式","PixelFormat","Enumeration"  },
                { "帧数","AcquisitionFrameCount","Integer"  },
                { "曝光时间","ExposureTimeAbs","Float"  },
                { "增益","GainRaw","Float"  },
                { "灰度系数","Gamma","Float"  },
                { "长","Width","Integer"  },
                { "宽","Height","Integer"  },
                { "触发模式","TriggerMode","Enumeration"  }
            };

        /// <summary>
        /// 获取一般参数的键
        /// </summary>
        /// <returns></returns>
        public static string[] getPrmKeys()
        {
            int len = prms.GetLength(0);
            string[] keys = new string[len];
            for (int i = 0; i < len; i++)
            {
                keys[i] = prms[i,0];
            }
            return keys;
        }
        /// <summary>
        /// 获取相机参数值
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public  string[] getValue(string key)
        {
            string type = null;
            string prmKey = null; 
            for (int i = 0; i < prms.GetLength(0); i++)
            {
                if (prms[i,0] == key)
                {
                    type = prms[i,2];
                    prmKey = prms[i, 1];
                    break;
                }
            }
            if (type == null)
            {
                return null;
            }
            return getPrmValue(prmKey, type);
        }
        /// <summary>
        /// 可以通过传入通用参数key值和类型来获取参数
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public string[] getPrmValue(string key,  string type) {
            //获取相机参数值
            if ("string" == type)
            {
                using (IStringParameter p = m_dev.ParameterCollection[new StringName(key)])
                {
                    string[] values = { p.GetValue() };
                    return values;
                }
            }
            if ("Enumeration" == type)
            {
                using (IEnumParameter p = m_dev.ParameterCollection[new EnumName(key)])
                {
                    List<string> list = new List<string>();
                    list = p.GetAllValues();
                    string[] values = new string[list.Count];
                    list.CopyTo(values, 0);
                    return values;
                }
            }
            if ("Integer" == type)
            {
                using (IIntegraParameter p = m_dev.ParameterCollection[new IntegerName(key)])
                {
                    string[] values = { p.GetValue().ToString() };
                    return values;
                }
            }
            if ("Float" == type)
            {
                using (IFloatParameter p = m_dev.ParameterCollection[new FloatName(key)])
                {
                    string[] values = { p.GetValue().ToString("f2") };
                    return values;
                }
            }
            if ("Bool" == type)
            {
                using (IBooleanParameter p = m_dev.ParameterCollection[new BooleanName(key)])
                {
                    string strText;
                    if (true == p.GetValue())
                    {
                        strText = "True";
                    }
                    else
                    {
                        strText = "False";
                    }
                    string[] values = { strText };
                    return values;
                }
            }
            return null;
        }
        /// <summary>
        /// 设置相机参数值
        /// </summary>
        /// <param name="key"></param>
        public bool setValue(string key ,string value) {
            string type = null;
            string prmKey = null;
            for (int i = 0; i < prms.GetLength(0); i++)
            {
                if (prms[i, 0] == key)
                {
                    type = prms[i, 2];
                    prmKey = prms[i, 1];
                    break;
                }
            }
            if (type == null)
            {
                return false;
            }
            return setPrmValue(prmKey, value,type);
        }
        /// <summary>
        /// 可以通过传入通用参数key值和类型来设置参数
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public bool setPrmValue(string key ,string value, string type) {
            try
            {
                //设置相机参数值
                if ("string" == type)
                {
                    using (IStringParameter p = m_dev.ParameterCollection[new StringName(key)])
                    {
                        return p.SetValue(value);
                    }
                }
                if ("Enumeration" == type)
                {
                    using (IEnumParameter p = m_dev.ParameterCollection[new EnumName(key)])
                    {
                        return p.SetValue(value);
                    }
                }
                if ("Integer" == type)
                {
                    using (IIntegraParameter p = m_dev.ParameterCollection[new IntegerName(key)])
                    {
                        return p.SetValue(int.Parse(value));
                    }
                }
                if ("Float" == type)
                {
                    using (IFloatParameter p = m_dev.ParameterCollection[new FloatName(key)])
                    {
                        return p.SetValue(float.Parse(value));
                    }
                }
                if ("Bool" == type)
                {
                    using (IBooleanParameter p = m_dev.ParameterCollection[new BooleanName(key)])
                    {
                        return p.SetValue(bool.Parse(value));
                    }
                }
            }
            catch (Exception)
            {
                MessageBox.Show("设置参数异常!");
            }
            return false;
        }
        #endregion
    }

Demo演示:

窗体设计:

代码:

 public partial class Form1 : Form
    {
        //当前的相机设备
        CamCommon cam;
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            //加载参数列表
            string[] prm = CamCommon.getPrmKeys();
            this.comboBox1.Items.AddRange(prm);
            //加载设备
            List<string> DeviceNames = CamCommon.DeviceNames();
            if (DeviceNames.Count ==0)
            {
                MessageBox.Show("未找到设备!");
                return;
            }
            foreach (string name in DeviceNames)
            {
                comboBox_DevList.Items.Add(name);
            }
            comboBox_DevList.Text = DeviceNames[0];

            //设置只读控件
            this.comboBox_DevList.DropDownStyle = ComboBoxStyle.DropDownList;
            this.comboBox1.DropDownStyle = ComboBoxStyle.DropDownList;
            //控件绑定事件
            this.btnOpen.Click += btnOpen_Click;
            this.button1.Click += button1_Click;
            this.button2.Click += button2_Click;
            this.button3.Click += button3_Click;
            this.button4.Click += button4_Click;
            this.comboBox1.TextChanged += comboBox1_TextChanged;
            this.comboBox2.Validated += comboBox2_Validated;

        }
        #region 控件事件
        //打开设备
        private void btnOpen_Click(object sender, EventArgs e)
        {
            string CamID = comboBox_DevList.Text;
            try
            {
                cam = new CamCommon(CamID);
                for (int i = 0; !cam.openCam(); i++) { Thread.Sleep(500); }/// 绑定回调函数事件
                cam.evetAsynchImage += ShowImage; /// 图像显示函数
                MessageBox.Show("当前设备连接成功!");
                EnaledTrue();
            }
            catch (Exception)
            {

                MessageBox.Show("当前设备连接失败!");
            }
        }
        //开始采集
        private void button1_Click(object sender, EventArgs e)
        {
            if (cam == null)
            {
                return;
            }
            cam.openConsecutive();
            this.button1.Enabled = false;
            this.button2.Enabled = true;

        }
        //停止采集
        private void button2_Click(object sender, EventArgs e)
        {
            if (cam == null)
            {
                return;
            }
            cam.closeConsecutive();
            this.button1.Enabled = true;
            this.button2.Enabled = false;
        }
        //软触发,这里将触发模式参数设为on即可,也可以直接调用CamCommon类中提供的方法打开软触发
        private void button4_Click(object sender, EventArgs e)
        {
            if (cam == null)
            {
                return;
            }
            cam.openSoftwareTrigger();
            cam.SoftwareTrigger();
        }
        //关闭相机
        private void button3_Click(object sender, EventArgs e)
        {
            if (cam == null)
            {
                return;
            }
            cam.closeCam();
            cam = null;
            EnaledTrue();
            this.comboBox2.Items.Clear();
            this.comboBox2.Text = "";
        }
        //获取参数
        private void comboBox1_TextChanged(object sender, EventArgs e)
        {
            string key = this.comboBox1.Text;
            if (cam == null)
            {
                return;
            }
            string[] values = cam.getValue(key);
            this.comboBox2.Items.AddRange(values);
            this.comboBox2.Text = values[0];
        }

        private void comboBox2_Validated(object sender, EventArgs e)
        {
            if (cam == null)
            {
                return;
            }
            string key = this.comboBox1.Text;
            string value = this.comboBox2.Text;
            if (cam.setValue(key, value))
            {
                MessageBox.Show("设置成功!");
            }
            else
            {
                MessageBox.Show("设置失败!");
            }
        }
        #endregion
        #region 通用方法相关
        //打开控件状态
        public void EnaledTrue() {
            this.button1.Enabled = true;
            this.button2.Enabled = true;
        }
        public void ShowImage(HObject img) {
            HTuple hv_WidthCam = null, hv_HeightCam = null;
            //判断来图
            if (img == null)
            {
                return;
            }

            HOperatorSet.GetImageSize(img, out hv_WidthCam, out hv_HeightCam);
            HOperatorSet.SetPart(hWindowControl1.HalconWindow, 0, 0, hv_HeightCam, hv_WidthCam);
            HOperatorSet.DispObj(img, hWindowControl1.HalconWindow);
            img.Dispose();
        }
        #endregion
    }

 

  • 7
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
大华相机通用SDK开发手册提供了开发者使用大华相机进行软件开发的指南。该手册详细介绍了如何通过SDK与大华相机进行交互,并完成常见的操作,如图像采集、图像处理和设备管理等。 首先,该手册提供了SDK的安装指南,包括系统环境的需求和安装步骤。开发者可以根据手册中的指引,轻松安装并配置SDK环境。 接下来,手册介绍了SDK的基本概念和架构,让开发者对SDK的工作原理有一个全面的了解。开发者可以了解SDK提供的功能和接口,并根据自身需求选择合适的接口进行开发。 在开发过程中,开发者可以通过手册中的示例代码快速上手开发。手册提供了丰富的代码示例,包括图像采集、图像处理、设备控制等方面的示例。开发者可以对照示例代码,更好地理解SDK的使用。 此外,手册还介绍了SDK中常用的函数和数据结构,为开发者提供了方便的参考。开发者可以根据手册提供的API文档,了解每个函数的用途和参数,并根据需求进行调用。 最后,手册也包含了常见问题的解答和技术支持的联系方式。开发者可以通过手册解答常见问题,提高开发效率。同时,如果遇到更复杂的问题,开发者可以通过联系技术支持获取进一步的帮助。 总的来说,大华相机通用SDK开发手册提供了一个全面且易于理解的指南,帮助开发者快速掌握SDK的使用,实现与大华相机的高效交互,并开发出符合自身需求的软件应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值