(开源) C# MG.CamCtrl 工业相机库海康(HIK) 大恒(DHeng) 巴斯勒(Basler)

By admin at 2025-12-17 • 0人收藏 • 110人看过

开源地址: 

https://gitee.com/laomaogu/mgcamctrl

特色:

接口统一,底层采用回调+信号量模式封装 ,最大程度减小线程资源,提高采图效率。


目标平台设置: x64

如果需要其他平台,请将引用的所有相机dll更新为对应的平台.

需要安装对应相机得驱动, 这样不会提示缺少引用dll了/

image.png

image.png

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;
using MG.CamCtrl;

namespace MG.CamVisual
{
    public partial class MainWindow : Form
    {
        public MainWindow()
        {
            InitializeComponent();

            InitUI();
        }

        #region  相机操作
        private ICamera myCamera { get; set; }

        public bool isTriggerModel = false;

        public bool isConnected = false;


        private void Btn_SearchCam_Click(object sender, EventArgs e)
        {
            var cambrand = (CameraBrand)Enum.Parse(typeof(CameraBrand), BrandCombox.SelectedItem.ToString());

            List<string> listsn = CamFactory.GetDeviceEnum(cambrand);

            if (listsn.Count > 0)
            {
                SNCombox.Items.Clear();
                SNCombox.Items.AddRange(listsn.ToArray());
                SNCombox.SelectedIndex = 0;
                Log($"设备枚举成功");
            }
            else
            {
                Log("未查询到设备!");
                MessageBox.Show("未查询到设备!", "提示", MessageBoxButtons.OK);
                SNCombox.Items.Clear();
            }
        }

        private void Btn_CamInit_Click(object sender, EventArgs e)
        {
            if (isConnected)
            {
                myCamera.CloseDevice();
                myCamera = null;
            }
            var brand = (CameraBrand)Enum.Parse(typeof(CameraBrand), BrandCombox.SelectedItem.ToString());

            myCamera = CamFactory.CreatCamera(brand);
            bool res = myCamera.InitDevice(SNCombox.SelectedItem.ToString());

            if (!res)
            {
                Log($"[{SNCombox.SelectedItem}]初始化失败!");
                MessageBox.Show($"[{SNCombox.SelectedItem}]初始化失败!", "提示", MessageBoxButtons.OK);
                myCamera.CloseDevice();
                myCamera = null;
                isConnected = false;
            }
            Log($"[{SNCombox.SelectedItem}]相机初始化");
            GetCamconfig();
            isConnected = true;
            UpdateUI(isConnected, false);
            EnableParm(true);
            DisplayBox.Image = null;

        }


        private void Btn_Startup_Click(object sender, EventArgs e)
        {
            if (isTriggerModel)
            { //触发模式

                if (Rbtn_Trigger_Soft.Checked)
                { //软触发
                    isConnected = myCamera.StartWith_SoftTriggerModel();
                    Log($"软触发模 式启动");
                }
                else if (Rbtn_Trigger_SoftCallback.Checked)
                { //软触发+回调
                    Log($"软触发 + 回调模式 启动");
                    isConnected = myCamera.StartWith_SoftTriggerModel(CamCallBack);

                }
                else if (Rbtn_Trigger_Hard.Checked)
                { //硬触发
                    Log($"硬触发模式 启动");
                    TriggerSource linesource = (TriggerSource)Enum.Parse(typeof(TriggerSource), Combobox_HardSource.SelectedItem.ToString());
                    isConnected = myCamera.StartWith_HardTriggerModel(linesource);
                }
                else if (Rbtn_Trigger_HardCallback.Checked)
                { //硬触发 + 回调
                    Log($"硬触发 + 回调模式 启动");
                    TriggerSource linesource = (TriggerSource)Enum.Parse(typeof(TriggerSource), Combobox_HardSource.SelectedItem.ToString());
                    isConnected = myCamera.StartWith_HardTriggerModel(linesource, CamCallBack);
                }
            }
            else
            { //连续触发
                Log($"连续 + 回调模式 启动");
                isConnected = myCamera.StartWith_Continue(CamCallBack);
            }

            //更新UI
            UpdateUI(isConnected, true);

        }

        private void Btn_Destroy_Click(object sender, EventArgs e)
        {
            myCamera?.CloseDevice();
            myCamera = null;
            isConnected = false;

            //更新UI
            UpdateUI(isConnected, false);
            EnableParm(false);
            //DisplayBox.Image = null;

            Log($"[{SNCombox.SelectedItem}] 相机注销");
        }

        private void Rbtn_ModelChanged(object sender, EventArgs e)
        {
            if (Rbtn_ContinueModel.Checked)
            {//选择连续模式
                isTriggerModel = false;
                EnableTriggerItem(false);
                Log($"切换为连续模式");
            }
            else if (Rbtn_TriggerModel.Checked)
            {//选择触发模式 
                isTriggerModel = true;
                EnableTriggerItem(true);
                Rbtn_Trigger_Soft.Checked = true;
                Log($"切换为触发模式");
            }
        }

        private void Rbtn_TriggerStyleChanged(object sender, EventArgs e)
        {
            Btn_SoftTrigger.Enabled = Rbtn_Trigger_Soft.Checked;
            Btn_SoftTrigger_Callback.Enabled = Rbtn_Trigger_SoftCallback.Checked;
            Combobox_HardSource.Enabled = Rbtn_Trigger_Hard.Checked;
            Combobox_HardSource_Callback.Enabled = Rbtn_Trigger_HardCallback.Checked;

        }

        private void Btn_SoftTrigger_Click(object sender, EventArgs e)
        {
            if (isConnected)
            {
                Log($"软触发取图");
                myCamera.GetImageWithSoftTrigger(out Bitmap res, 5000);
                DisplayBox.Image = res.Clone() as Bitmap;
                res?.Dispose();

            }
        }

        private void Btn_SoftTrigger_Callback_Click(object sender, EventArgs e)
        {
            if (isConnected)
            {
                Log($"软触发");
                myCamera?.SoftTrigger();
            }
        }

        /// <summary>
        /// 回调函数
        /// </summary>
        /// <param name="img"></param>
        private void CamCallBack(Bitmap data)
        {
            Bitmap buff = data.Clone() as Bitmap;
            this.BeginInvoke(new Action(() =>
            {
                if (isConnected)
                {

                    DisplayBox.Image = buff;

                    // img?.Dispose();
                }
            }));


            if (EnableSave)
            {

                data.Save(SaveDir);

            }

        }


        readonly Object obj = new object();
        #endregion

        #region 获取参数

        private void GetCamconfig()
        {
            CamConfig camcfg = null;
            if (myCamera != null)
            {
                myCamera?.GetCamConfig(out camcfg);
                Tbox_ExpouseTime.Text = camcfg.ExpouseTime.ToString();
                Tbox_Gain.Text = camcfg.Gain.ToString();
                Tbox_TriggerFliter.Text = camcfg.TriggerFilter.ToString();
                string dav = camcfg.triggerPolarity.ToString();
                cmbox_TriggerPolarity.SelectedIndex = cmbox_TriggerPolarity.Items.IndexOf(dav);
            }
        }

        #endregion

        #region 参数设置
        private void Tbox_ExpouseTime_TextChanged(object sender, EventArgs e)
        {
            bool res = ushort.TryParse(Tbox_ExpouseTime.Text, out ushort value);
            if (!res) return;
            if (isConnected && myCamera != null)
            {
                myCamera?.SetExpouseTime(value);
                Log($"设置曝光时长[{value}]");
            }
        }

        private void Tbox_Gain_TextChanged(object sender, EventArgs e)
        {
            bool res = short.TryParse(Tbox_Gain.Text, out short value);
            if (!res) return;
            if (isConnected && myCamera != null)
            {
                myCamera?.SetGain(value);
                Log($"设置增益[{value}]");
            }
        }

        private void Btn_AutoWhiteBlance_Click(object sender, EventArgs e)
        {
            if (isConnected && myCamera != null)
            {
                myCamera?.AutoBalanceWhite();
                Log($"自动白平衡");
            }
        }

        private void Tbox_TriggerFliter_TextChanged(object sender, EventArgs e)
        {
            bool res = ushort.TryParse(Tbox_TriggerFliter.Text, out ushort value);
            if (!res) return;
            if (isConnected && myCamera != null)
            {
                myCamera?.SetTriggerFliter(value);
                Log($"设置触发滤波[{value}]");
            }
        }
        #endregion

        #region 读写图片
        private void Btn_ReadImage_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.Filter = "图片(*.bmp)|*.bmp;*.png;*.jpg;*.jpeg| (*.png)|*.png;*.PNG| (*.jpg)|*.jpg;*.JPG| (*.jpeg)|*.jpeg;*.JPEG";
            openFileDialog.Multiselect = false;
            openFileDialog.CheckFileExists = true;
            openFileDialog.AddExtension = true;
            openFileDialog.RestoreDirectory = true;
            ;

            if (openFileDialog.ShowDialog(this) == DialogResult.OK)
            {
                if (!File.Exists(openFileDialog.FileName)) return;
                DisplayBox.Image = new Bitmap(openFileDialog.FileName);
            }
        }

        private void Btn_SaveImage_Click(object sender, EventArgs e)
        {
            try
            {
                SaveFileDialog saveFileDialog = new SaveFileDialog();
                saveFileDialog.Filter = "图片(*.bmp)|*.bmp;*.png;*.jpg;*.jpeg| (*.png)|*.png;*.PNG| (*.jpg)|*.jpg;*.JPG| (*.jpeg)|*.jpeg;*.JPEG";
                saveFileDialog.CheckFileExists = false;
                saveFileDialog.AddExtension = true;
                saveFileDialog.RestoreDirectory = true;
                saveFileDialog.FileName = DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss-ffff");

                if (saveFileDialog.ShowDialog(this) == DialogResult.OK)
                {
                    DisplayBox.Image.Save(saveFileDialog.FileName);
                }
            }
            catch (Exception)
            {
                throw;
            }
        }
        #endregion

        #region 图片缩放

        private bool IsMove = false;
        private int ZoomStep = 50;
        private Point MouseDownPoint;

        private void DisplayBox_MouseWheel(object sender, MouseEventArgs e)
        {
            if (DisplayBox.Image == null) return;

            PictureBox pbox = DisplayBox;
            int x = e.Location.X;
            int y = e.Location.Y;
            int ow = pbox.Width;
            int oh = pbox.Height;
            int VX, VY;  //因缩放产生的位移矢量
            if (e.Delta > 0) //放大
            {
                //第1步
                pbox.Width += ZoomStep;
                pbox.Height += ZoomStep;
                //第2步
                PropertyInfo pInfo = pbox.GetType().GetProperty("ImageRectangle", BindingFlags.Instance | BindingFlags.NonPublic);
                Rectangle rect = (Rectangle)pInfo.GetValue(pbox, null);
                //第3步
                pbox.Width = rect.Width;
                pbox.Height = rect.Height;

                //Console.WriteLine(string.Format("宽:{0},高:{1}",pbox.Width,pbox.Height));
            }
            if (e.Delta < 0) //缩小
            {
                //防止一直缩成负值
                if (pbox.Width < 300)
                    return;

                pbox.Width -= ZoomStep;
                pbox.Height -= ZoomStep;
                PropertyInfo pInfo = pbox.GetType().GetProperty("ImageRectangle", BindingFlags.Instance |
                 BindingFlags.NonPublic);
                Rectangle rect = (Rectangle)pInfo.GetValue(pbox, null);
                pbox.Width = rect.Width;
                pbox.Height = rect.Height;
            }

            //第4步,求因缩放产生的位移,进行补偿,实现锚点缩放的效果
            VX = (int)((double)x * (ow - pbox.Width) / ow);
            VY = (int)((double)y * (oh - pbox.Height) / oh);
            pbox.Location = new Point(pbox.Location.X + VX, pbox.Location.Y + VY);


        }

        private void DisplayBox_MouseMove(object sender, MouseEventArgs e)
        {
            if (DisplayBox.Image == null) return;
            DisplayBox.Focus(); //鼠标在picturebox上时才有焦点,此时可以缩放
            if (IsMove)
            {
                int x, y;   //新的DisplayBox.Location(x,y)
                int moveX, moveY; //X方向,Y方向移动大小。
                moveX = Cursor.Position.X - MouseDownPoint.X;
                moveY = Cursor.Position.Y - MouseDownPoint.Y;
                x = DisplayBox.Location.X + moveX;
                y = DisplayBox.Location.Y + moveY;
                DisplayBox.Location = new Point(x, y);
                MouseDownPoint.X = Cursor.Position.X;
                MouseDownPoint.Y = Cursor.Position.Y;
            }
        }

        private void DisplayBox_MouseDown(object sender, MouseEventArgs e)
        {
            if (DisplayBox.Image == null) return;

            if (e.Button == MouseButtons.Left)
            {
                MouseDownPoint.X = Cursor.Position.X; //记录鼠标左键按下时位置
                MouseDownPoint.Y = Cursor.Position.Y;
                IsMove = true;
                DisplayBox.Focus(); //鼠标滚轮事件(缩放时)需要picturebox有焦点
            }
        }
        private void DisplayBox_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                IsMove = false;
            }
        }

        private void DisplayBox_MouseDoubleClick(object sender, MouseEventArgs e)
        {

            DisplayBox.Location = new Point(0, 0);
            DisplayBox.Width = mWidth;
            DisplayBox.Height = mHeight;
        }
        #endregion

        #region other  
        int mWidth { get; set; }
        int mHeight { get; set; }
        private void InitUI()
        {
            DisplayBox.MouseWheel += DisplayBox_MouseWheel;
            mWidth = DisplayBox.Width;
            mHeight = DisplayBox.Height;
            Btn_Startup.Enabled = false;
            Btn_Destroy.Enabled = false;

            Combobox_HardSource.SelectedIndex = 0;
            Combobox_HardSource_Callback.SelectedIndex = 0;
            BrandCombox.SelectedIndex = 0;
            cmbox_TriggerPolarity.SelectedIndex = 0;


            EnableTriggerItem(isTriggerModel);
            EnableParm(false);
        }

        private void UpdateUI(bool camisConnected, bool isstarted)
        {
            Btn_CamInit.Enabled = !camisConnected;

            Btn_Startup.Enabled = isstarted ? false : isConnected;
            Btn_Destroy.Enabled = camisConnected;

            //EnableTriggerItem(!camisConnected);
        }

        private void EnableTriggerItem(bool flag)
        {
            Rbtn_Trigger_Soft.Enabled = flag;
            Rbtn_Trigger_Hard.Enabled = flag;
            Rbtn_Trigger_SoftCallback.Enabled = flag;
            Rbtn_Trigger_HardCallback.Enabled = flag;
            Btn_SoftTrigger.Enabled = flag;
            Btn_SoftTrigger_Callback.Enabled = flag;

            if (!flag)
            {
                Btn_SoftTrigger.Enabled = false;
                Btn_SoftTrigger_Callback.Enabled = false;
                Combobox_HardSource.Enabled = false;
                Combobox_HardSource_Callback.Enabled = false;
            }
        }

        private void EnableParm(bool flag)
        {
            Tbox_ExpouseTime.Enabled = flag;
            Tbox_Gain.Enabled = flag;
            Btn_AutoWhiteBlance.Enabled = flag;
            cmbox_TriggerPolarity.Enabled = flag;
            Tbox_TriggerFliter.Enabled = flag;
        }

        private void Log(string message)
        {
            this.Invoke(new Action(() =>
            {
                if (Tbox_Log.Lines.Count() > 500)
                {
                    Tbox_Log.Clear();
                }

                Tbox_Log.AppendText($"\r\n[{DateTime.Now.ToString("HH:mm:ss:ff")}]:{message}");
            }));

        }

        private void menubtn_about_Click(object sender, EventArgs e)
        {
            About about = new About();
            about.Show();
        }

        private void MainWindow_FormClosing(object sender, FormClosingEventArgs e)
        {
            this.Invoke(new Action(() =>
            {
                CamFactory.DestroyAll();
                isConnected = false;

            }));
        }
        #endregion

        private void Btn_StopSave(object sender, EventArgs e)
        {
            StopSaveImg();
        }

        private void Btn_StartSave(object sender, EventArgs e)
        {
            StartSaveImg();
        }


        ConcurrentQueue<Bitmap> queue_datapool = new ConcurrentQueue<Bitmap>();
        ConcurrentQueue<string> queue_date = new ConcurrentQueue<string>();

        bool EnableSave = false;


        protected string SaveDir { get; set; } = "./ImgRecord/";

        public void StartSaveImg() { EnableSave = true; }
        public void StartSaveImgWithTiming() { EnableSave = true; }
        public void StopSaveImg()
        {
            EnableSave = false;
        }



    }
}



登录后方可回帖

登 录
信息栏
本站域名

ChengXu.XYZ

投诉联系:  popdes@126.com



快速上位机开发学习,本站主要记录了学习过程中遇到的问题和解决办法及上位机代码分享

这里主要专注于学习交流和经验分享.
纯私人站,当笔记本用的,学到哪写到哪.
如果侵权,联系 Popdes@126.com

友情链接
Aardio官方
Aardio资源网


才仁机械


网站地图SiteMap

Loading...