通用工业视觉软件设计之相机模块类库-ModuleCamera

通用工业视觉软件设计之相机模块类库-ModuleCamera

在这里插入图片描述

一 相机的基础类:CameraBase

using HalconDotNet;
using ModulePublicShare;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading;
using System.Threading.Tasks;


namespace ModuleCamera
{

    /// <summary>
    /// 相机的基础类
    /// </summary>
    [Serializable]
    public class CameraBase
    {

        public static int m_LastDeviceID = 0;//序列号ID

        /// <summary>
        /// 设备ID
        /// </summary>
        private string _DeviceID;

        public string m_DeviceID
        {
            get { return _DeviceID; }
            set { _DeviceID = value; }
        }

        /// <summary>
        /// 相机品牌
        /// </summary>
        private DeviceType _DeviceType;

        public DeviceType m_DeviceType
        {
            get { return _DeviceType; }
            set { _DeviceType = value; }
        }

        /// <summary>
        /// 标识符
        /// </summary>
        private string _UniqueLabe;

        public string m_UniqueLabe
        {
            get { return _UniqueLabe; }
            set { _UniqueLabe = value; }
        }

        /// <summary>
        /// 设备内部编号
        /// </summary>
        private string _SerialNO;

        public string m_SerialNO
        {
            set { _SerialNO = value; }
            get { return _SerialNO; }
        }

        /// <summary>
        /// SDK版本信息
        /// </summary>
        private string _ExtInfo;

        public string m_ExtInfo
        {
            get { return _ExtInfo; }
            set { _ExtInfo = value; }
        }

        /// <summary>
        /// 曝光
        /// </summary>
        private int _ExposeTime = 1360;

        public int m_ExposeTime
        {
            get { return _ExposeTime; }
            set { _ExposeTime = value; }
        }

        /// <summary>
        /// 增益
        /// </summary>
        private int _Gain = 1;

        public int m_Gain
        {
            get { return _Gain; }
            set { _Gain = value; }
        }

        /// <summary>
        /// 触发模式
        /// </summary>
        private TRIGGER_MODE _tRIGGER;

        public TRIGGER_MODE m_tRIGGER
        {
            get { return _tRIGGER; }
            set { _tRIGGER = value; }
        }


        /// <summary>
        /// 采集的图像
        /// </summary>
        [NonSerialized]
        private HImage _Image = new HImageExt();
        public HImage m_Image
        {
            get { return _Image; }
            set { _Image = value; }
        }

        /// <summary>
        /// 图像的宽度
        /// </summary>
        [NonSerialized]
        private int _ImgWidth;

        public int m_ImgWidth
        {
            get { return _ImgWidth; }
            set { _ImgWidth = value; }
        }

        /// <summary>
        /// 图像的高度
        /// </summary>
        [NonSerialized]
        private int _ImgHeight;

        public int m_ImgHeight
        {
            get { return _ImgHeight; }
            set { _ImgHeight = value; }
        }

        /// <summary>
        /// 设备连接状态
        /// </summary>
        private bool _bConnected = false;

        public bool m_bConnected
        {
            get { return _bConnected; }
            set { _bConnected = value; }
        }


        /// <summary>
        /// 是否开始采集图像
        /// </summary>
        private bool _isGrabbing = false;

        public bool m_isGrabbing
        {
            get { return _isGrabbing; }
            set { _isGrabbing = value; }
        }


        /// <summary>
        /// 是否为触发模式
        /// </summary>
        private bool _isTriggerMode = false;

        public bool m_isTriggerMode
        {
            get { return _isTriggerMode; }
            set { _isTriggerMode = value; }
        }



        /// <summary>
        /// 是不是最新采集的图像
        /// </summary>
        [NonSerialized]
        private bool _IsNewImage;

        public bool m_IsNewImage
        {
            get { return _IsNewImage; }
            set { _IsNewImage = value; }
        }

        /// <summary>
        /// X方向像素当量
        /// </summary>
        private double dScaleX = 1.0;
        public double ScaleX
        {
            get { return dScaleX; }
            set { dScaleX = value; }
        }

        /// <summary>
        /// Y方向像素当量
        /// </summary>
        private double dScaleY = 1.0;
        public double ScaleY
        {
            get { return dScaleY; }
            set { dScaleY = value; }
        }

        /// <summary>
        /// 采集信号
        /// </summary>
        [NonSerialized]
        public AutoResetEvent eventWait = new AutoResetEvent(false);

        /// <summary>
        /// 构造函数1
        /// </summary>
        public CameraBase()
        {

        }

        /// <summary>
        /// 构造函数2
        /// </summary>
        /// <param name="deviceType">初始化时指定设备类型</param>
        public CameraBase(DeviceType deviceType)
        {
            this._DeviceType = deviceType;
            m_LastDeviceID++;
            _DeviceID = "Dev" + m_LastDeviceID;
        }

        /// <summary>
        /// 建立设备连接
        /// </summary>
        public virtual void ConnectDev() { }

        /// <summary>
        /// 断开设备连接
        /// </summary>
        public virtual void DisConnectDev() { }

        /// <summary>
        /// 设置触发模式
        /// </summary>
        public virtual bool SetTrigger(TRIGGER_MODE tRIGGER_) { return true; }

        /// <summary>
        /// 设置曝光时间
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public virtual bool SetExposureTime(int value) { return true; }

        /// <summary>
        /// 设置增益
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public virtual bool SetGain(int value) { return true; }

        /// <summary>
        /// 获取参数
        /// </summary>
        public virtual void GetSetting() { }

        /// <summary>
        /// 设置参数
        /// </summary>
        public virtual void SetSetting() { }

        /// <summary>
        /// 取图
        /// </summary>
        /// <returns></returns>
        public virtual bool CaptureImage(bool byHand) { return true; }

        [OnDeserializing()]
        internal void OnDeSerializingMethod(StreamingContext context)
        {
            _Image = new HImage();
            eventWait = new AutoResetEvent(false);
        }
    }
}

二 相机类型:CameraType

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ModuleCamera
{

    /// <summary>
    /// 设备类型
    /// </summary>
    [Serializable]
    public enum DeviceType
    {
        None,
        海康相机,
        大华相机,
    }

    /// <summary>
    /// 触发模式
    /// </summary>
    [Serializable]
    public enum TRIGGER_MODE
    {
        软件触发,
        连续采集,
        硬件触发,
    }
}

三 CamInfo:相机信息类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ModuleCamera
{
    /// <summary>
    /// 相机信息
    /// </summary>
    public struct CamInfo
    {

        /// <summary>
        /// 相机品牌
        /// </summary>
        private DeviceType _DeviceType;

        public DeviceType m_DeviceType
        {
            get { return _DeviceType; }
            set { _DeviceType = value; }
        }


        /// <summary>
        /// 设备内部编号
        /// </summary>
        private string _SerialNO;

        public string m_SerialNO
        {
            set { _SerialNO = value; }
            get { return _SerialNO; }
        }


        /// <summary>
        /// 版本信息
        /// </summary>
        private string _ExtInfo;

        public string m_ExtInfo
        {
            get { return _ExtInfo; }
            set { _ExtInfo = value; }
        }

        /// <summary>
        /// 连接状态
        /// </summary>
        private bool _BConnected;

        public bool m_BConnected
        {
            get { return _BConnected; }
            set { _BConnected = value; }
        }

    }
}

四 海康相机实现

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MvCamCtrl.NET;
using ModuleLog;
using System.Runtime.InteropServices;
using System.IO;
using System.Runtime.Serialization;
using HalconDotNet;
using System.Drawing;
using System.Threading;
using System.Xml.Linq;
using System.Windows.Media.Media3D;

namespace ModuleCamera
{
    /// <summary>
    /// 委托
    /// </summary>
    /// <param name="image"></param>
    /// <param name="_user"></param>

    // 抓取图像委托
    public delegate void GrabImage(int width, int height, IntPtr Red, IntPtr Green, IntPtr Blue);
    public delegate void GrabGrayImage(int width, int height, IntPtr Gray);
    public delegate void DispImageCallback(HImage image, int _user);

    /// <summary>
    /// 海康威视
    /// </summary>
    [Serializable]
    public class DriveHKVision : CameraBase
    {
        /// <summary>
        /// 线程锁,保证多线程安全
        /// </summary>
        [NonSerialized]
        Mutex m_mutex = new Mutex();
        /// <summary>
        /// 委托变量
        /// </summary>
        // 抓取图像事件
        public event GrabImage GrabRGBImageEvent;
        public event GrabGrayImage GrabGrayImageEvent;

        [NonSerialized]
        public DispImageCallback dispImgCallback = null;
        /// <summary>
        /// 设备列表
        /// </summary>
        static MyCamera.MV_CC_DEVICE_INFO_LIST m_stDeviceList;

        /// <summary>
        /// 相机对象
        /// </summary>
        private MyCamera m_MyCamera = null;

        /// <summary>
        /// 取像线程
        /// </summary>
        Thread m_hReceiveThread = null;

        /// <summary>
        /// 帧信息
        /// </summary>
        MyCamera.MV_FRAME_OUT_INFO_EX m_stFrameInfo = new MyCamera.MV_FRAME_OUT_INFO_EX();

        /// <summary>
        /// 用于从驱动获取图像的缓存
        /// </summary>
        IntPtr m_BufForDriver;
        UInt32 m_nBufSizeForDriver = 0;
        byte[] m_pDataForRed = null;
        byte[] m_pDataForGreen = null;
        byte[] m_pDataForBlue = null;
        private Object BufForDriverLock = new Object();
        private Object BufForImageLock = new Object();  // 读写图像时锁定


        [NonSerialized]
        Bitmap m_pcBitmap = null;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="_DeviceType"></param>
        public DriveHKVision(DeviceType _DeviceType) : base(_DeviceType)
        {

        }

        /// <summary>
        /// 查询相机,添加到相机列表中
        /// </summary>
        /// <param name="m_CamInfoList"></param>
        public static void SearchCameras(out List<CamInfo> m_CamInfoList)
        {
            m_CamInfoList = new List<CamInfo>();

            // ch:创建设备列表 | en:Create Device List

            // 枚举设备列表
            m_stDeviceList.nDeviceNum = 0;
            // 核心1:查找GIGE和USB接口的相机
            int nRet = MyCamera.MV_CC_EnumDevices_NET(MyCamera.MV_GIGE_DEVICE | MyCamera.MV_USB_DEVICE, ref m_stDeviceList);


            if (0 != nRet)
            {
                System.Windows.Forms.MessageBox.Show("查找设备失败!");
                Log.Error("查找设备失败!");
                return;
            }

            // ch:打印设备信息 en:Print device info

            for (int i = 0; i < m_stDeviceList.nDeviceNum; i++)
            {
                CamInfo _camInfo = new CamInfo();
                MyCamera.MV_CC_DEVICE_INFO device = (MyCamera.MV_CC_DEVICE_INFO)Marshal.PtrToStructure(m_stDeviceList.pDeviceInfo[i], typeof(MyCamera.MV_CC_DEVICE_INFO));
                if (device.nTLayerType == MyCamera.MV_USB_DEVICE)
                {
                    MyCamera.MV_USB3_DEVICE_INFO usb3Info = (MyCamera.MV_USB3_DEVICE_INFO)MyCamera.ByteToStruct(device.SpecialInfo.stUsb3VInfo, typeof(MyCamera.MV_USB3_DEVICE_INFO));

                    _camInfo.m_SerialNO = usb3Info.chSerialNumber;
                    _camInfo.m_DeviceType = DeviceType.海康相机;
                }
                else if (device.nTLayerType == MyCamera.MV_GIGE_DEVICE)
                {
                    MyCamera.MV_GIGE_DEVICE_INFO gigeInfo = (MyCamera.MV_GIGE_DEVICE_INFO)MyCamera.ByteToStruct(device.SpecialInfo.stGigEInfo, typeof(MyCamera.MV_GIGE_DEVICE_INFO));
                    _camInfo.m_SerialNO = gigeInfo.chSerialNumber;
                    _camInfo.m_DeviceType = DeviceType.海康相机;
                }

                // 核心2:添加相机信息
                m_CamInfoList.Add(_camInfo);
            }


        }

        /// <summary>
        /// 获取相机对应的枚举索引
        /// </summary>
        /// <param name="CameraID"></param>
        /// <returns></returns>
        private int GetDeviceIndex(string CameraID)
        {
            for (int i = 0; i < m_stDeviceList.nDeviceNum; i++)
            {
                MyCamera.MV_CC_DEVICE_INFO device = (MyCamera.MV_CC_DEVICE_INFO)Marshal.PtrToStructure(m_stDeviceList.pDeviceInfo[i], typeof(MyCamera.MV_CC_DEVICE_INFO));
                if (device.nTLayerType == MyCamera.MV_GIGE_DEVICE)
                {
                    MyCamera.MV_GIGE_DEVICE_INFO gigeInfo = (MyCamera.MV_GIGE_DEVICE_INFO)MyCamera.ByteToStruct(device.SpecialInfo.stGigEInfo, typeof(MyCamera.MV_GIGE_DEVICE_INFO));
                    if (gigeInfo.chSerialNumber == CameraID)
                        return i;
                }
                else if (device.nTLayerType == MyCamera.MV_USB_DEVICE)
                {
                    MyCamera.MV_USB3_DEVICE_INFO usb3Info = (MyCamera.MV_USB3_DEVICE_INFO)MyCamera.ByteToStruct(device.SpecialInfo.stUsb3VInfo, typeof(MyCamera.MV_USB3_DEVICE_INFO));
                    if (usb3Info.chSerialNumber == CameraID)
                        return i;
                }
            }

            return -1;
        }

        /// <summary>
        /// 枚举所有设备
        /// </summary>
        public void EnumDevices()
        {
            // 枚举设备列表
            m_stDeviceList.nDeviceNum = 0;
            // 核心:
            int nRet = MyCamera.MV_CC_EnumDevices_NET(MyCamera.MV_GIGE_DEVICE | MyCamera.MV_USB_DEVICE, ref m_stDeviceList);
            if (0 != nRet)
            {
                Log.Error("枚举HIK相机设备失败!");
                return;
            }
        }
        /// <summary>
        /// 连接相机
        /// </summary>
        public override void ConnectDev()
        {
            try
            {
                // 如果设备已经连接先断开
                DisConnectDev();

                // 枚举并搜索指定ID的相机是否存在
                EnumDevices();

                // ch:获取选择的设备信息 | en:Get selected device information
                //CCameraInfo device = m_ltDeviceList.Find(item => ((CGigECameraInfo)item).chSerialNumber == m_SerialNO);
                int camIdx = GetDeviceIndex(m_SerialNO);
                if (camIdx == -1)
                {
                    Log.Error("找不到该ID的相机!");
                }
                MyCamera.MV_CC_DEVICE_INFO device = (MyCamera.MV_CC_DEVICE_INFO)Marshal.PtrToStructure(m_stDeviceList.pDeviceInfo[camIdx],
                                                                  typeof(MyCamera.MV_CC_DEVICE_INFO));




                // 建立设备对象
                if (null == m_MyCamera)
                {
                    m_MyCamera = new MyCamera();
                    if (null == m_MyCamera)
                    {
                        Log.Error("初始化相机对象失败");

                    }
                }

                // 创建设备
                int nRet = m_MyCamera.MV_CC_CreateDevice_NET(ref device);
                if (MyCamera.MV_OK != nRet)
                {
                    Log.Error($"创建设备失败,失败代码:{nRet}");
                }


                // 尝试打开设备
                nRet = m_MyCamera.MV_CC_OpenDevice_NET();
                if (MyCamera.MV_OK != nRet)
                {
                    m_MyCamera.MV_CC_DestroyDevice_NET();

                    Log.Error($"设备打开失败,失败代码:{nRet}");
                }

                // 探测网络最佳包大小(只对GigE相机有效)
                if (device.nTLayerType == MyCamera.MV_GIGE_DEVICE)
                {
                    int nPacketSize = m_MyCamera.MV_CC_GetOptimalPacketSize_NET();
                    if (nPacketSize > 0)
                    {
                        nRet = m_MyCamera.MV_CC_SetIntValue_NET("GevSCPSPacketSize", (uint)nPacketSize);
                        if (nRet != MyCamera.MV_OK)
                        {
                            Log.Warn($"设置包大小失败,失败代码:{nRet}");
                        }
                    }
                    else
                    {
                        Log.Warn($"获取包大小失败,返回的包大小为:{nPacketSize}");
                    }
                }

                // ch:设置触发模式为off || en:set trigger mode as off
                m_MyCamera.MV_CC_SetEnumValue_NET("TriggerMode", (uint)MyCamera.MV_CAM_TRIGGER_MODE.MV_TRIGGER_MODE_OFF);
                m_MyCamera.MV_CC_SetEnumValue_NET("AcquisitionMode", (uint)MyCamera.MV_CAM_ACQUISITION_MODE.MV_ACQ_MODE_CONTINUOUS);

                //获取相机参数
                GetSetting();

                //设置相机参数
                SetSetting();

                // ch:注册回调函数 | en:Register image callback,把图像数据传出去
                GrabGrayImageEvent += GrayImageCallbackFunc;
                GrabRGBImageEvent += RGBImageCallbackFunc;



                // 标志位置位true
                m_isGrabbing = true;
                // 核心:取图线程
                m_hReceiveThread = new Thread(ReceiveThreadProcess);
                m_hReceiveThread.Start();

                // 取流之前先清除帧长度
                m_stFrameInfo.nFrameLen = 0;
                m_stFrameInfo.enPixelType = MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerBG8;

                // 开始采集
                nRet = m_MyCamera.MV_CC_StartGrabbing_NET();
                if (MyCamera.MV_OK != nRet)
                {
                    m_isGrabbing = false;
                    m_hReceiveThread.Join();

                    Log.Error($"连续采集失败,失败代码:{nRet}");
                }

                m_bConnected = true;
            }
            catch (Exception ex)
            {
                m_bConnected = false;
            }
        }


        /// <summary>
        /// 断开相机连接
        /// </summary>
        public override void DisConnectDev()
        {
            try
            {
                if (m_MyCamera == null)
                {
                    return;
                }

                if (m_MyCamera != null)
                {
                    // 关闭设备
                    m_MyCamera.MV_CC_CloseDevice_NET();
                    m_MyCamera.MV_CC_DestroyDevice_NET();
                }

                m_bConnected = false;

            }
            catch (Exception)
            {
                throw;
            }
        }


        /// <summary>
        /// 设置曝光时间
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public override bool SetExposureTime(int value)
        {
            m_ExposeTime = value;
            try
            {
                if (m_MyCamera != null && m_bConnected)
                {
                    // 关闭自动曝光
                    m_MyCamera.MV_CC_SetEnumValue_NET("ExposureAuto", 0);

                    int nRet = m_MyCamera.MV_CC_SetFloatValue_NET("ExposureTime", value);

                    if (nRet != MyCamera.MV_OK)
                    {
                        System.Windows.Forms.MessageBox.Show("Set Exposure Time Fail!");
                        return false;
                    }
                    else
                    {
                        return true;
                    }
                }
                return false;
            }
            catch (Exception)
            {
                return false;
            }
        }

        /// <summary>
        /// 设置增益
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public override bool SetGain(int value)
        {
            m_Gain = value;
            try
            {
                if (m_MyCamera != null && m_bConnected)
                {
                    m_MyCamera.MV_CC_SetEnumValue_NET("GainAuto", 0);
                    int nRet = m_MyCamera.MV_CC_SetFloatValue_NET("Gain", (float)value);
                    if (nRet != MyCamera.MV_OK)
                    {
                        System.Windows.Forms.MessageBox.Show("Set Gain Fail!");
                        return false;
                    }
                    else
                    {
                        return true;
                    }
                }
                return false;
            }
            catch (Exception)
            {
                return false;
            }
        }

        /// <summary>
        /// 设置触发模式
        /// </summary>
        /// <param name="tRIGGER_"></param>
        /// <returns></returns>
        public override bool SetTrigger(TRIGGER_MODE tRIGGER_)
        {
            try
            {
                if (m_MyCamera != null && m_bConnected)
                {
                    switch (tRIGGER_)
                    {
                        case TRIGGER_MODE.软件触发:
                            int nRet = m_MyCamera.MV_CC_SetEnumValue_NET("TriggerMode", (uint)MyCamera.MV_CAM_TRIGGER_MODE.MV_TRIGGER_MODE_ON);
                            m_MyCamera.MV_CC_SetEnumValue_NET("TriggerSource", (uint)MyCamera.MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_SOFTWARE);
                            m_isTriggerMode = true;
                            break;
                        case TRIGGER_MODE.连续采集:
                            //m_pMyCamera.SetEnumValue("TriggerMode", (uint)MV_CAM_TRIGGER_MODE.MV_TRIGGER_MODE_OFF);
                            int nRet2 = m_MyCamera.MV_CC_SetEnumValue_NET("TriggerMode", (uint)MyCamera.MV_CAM_TRIGGER_MODE.MV_TRIGGER_MODE_OFF);
                            m_isTriggerMode = false;

                            break;
                        case TRIGGER_MODE.硬件触发:
                            int nRet3 = m_MyCamera.MV_CC_SetEnumValue_NET("TriggerMode", (uint)MyCamera.MV_CAM_TRIGGER_MODE.MV_TRIGGER_MODE_ON);

                            // Line0触发
                            m_MyCamera.MV_CC_SetEnumValue_NET("TriggerSource", (uint)MyCamera.MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_LINE0);

                            // 采用上升沿触发
                            m_MyCamera.MV_CC_SetEnumValue_NET("TriggerActivation", 0);

                            // 线路防抖 250us
                            m_MyCamera.MV_CC_SetIntValue_NET("LineDebouncerTime", 250);
                            m_isTriggerMode = true;
                            break;
                        default:
                            break;
                    }
                    return true;
                }
                else
                {
                    return false;
                }
            }
            catch (Exception)
            {
                return false;
            }
        }

        /// <summary>
        /// 采集图像
        /// </summary>
        /// <param name="byHand">是否手动采集图像</param>
        /// <returns></returns>
        public override bool CaptureImage(bool byHand)
        {
            try
            {
                if (m_MyCamera == null)
                {
                    m_bConnected = false;
                    return false;
                }

                // ch:触发命令 | en:Trigger command
                int nRet = m_MyCamera.MV_CC_SetCommandValue_NET("TriggerSoftware");
                if (MyCamera.MV_OK != nRet)
                {
                    System.Windows.Forms.MessageBox.Show("Open camera failed!");
                    Log.Error("打开相机失败!");
                    m_bConnected = false;
                    return false;
                }
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        /// <summary>
        /// 设置参数
        /// </summary>
        public override void SetSetting()
        {
            if (m_MyCamera == null && !m_bConnected)
                return;

            //设置曝光
            SetExposureTime(m_ExposeTime);
            //设置增益 
            SetGain(m_Gain);
            // 设置缓存个数为8(默认值为16) 
            //m_dev.StreamGrabber.SetBufferCount(8);
            //设置触发模式
            SetTrigger(m_tRIGGER);

        }

        /// <summary>
        /// 获取参数
        /// </summary>
        public override void GetSetting()
        {
            if (m_MyCamera == null && !m_bConnected)
                return;
            // 获取曝光时间
            MyCamera.MVCC_FLOATVALUE stParam = new MyCamera.MVCC_FLOATVALUE();
            int nRet = m_MyCamera.MV_CC_GetFloatValue_NET("ExposureTime", ref stParam);
            if (MyCamera.MV_OK == nRet)
            {
                m_ExposeTime = Convert.ToInt32(stParam.fCurValue);
            }

            //获取增益参数        
            stParam = new MyCamera.MVCC_FLOATVALUE();
            nRet = m_MyCamera.MV_CC_GetFloatValue_NET("Gain", ref stParam);
            if (MyCamera.MV_OK == nRet)
            {
                m_Gain = Convert.ToInt32(stParam.fCurValue);
            }

        }

        /// <summary>
        /// 取像线程(核心)
        /// </summary>
        private void ReceiveThreadProcess()
        {
            MyCamera.MVCC_INTVALUE stParam = new MyCamera.MVCC_INTVALUE();
            int nRet = m_MyCamera.MV_CC_GetIntValue_NET("PayloadSize", ref stParam);
            if (MyCamera.MV_OK != nRet)
            {
                Log.Error($"读取PayloadSize失败,失败代码:{nRet}");
                return;
            }
            UInt32 nPayloadSize = stParam.nCurValue;

            // 获取图像高
            nRet = m_MyCamera.MV_CC_GetIntValue_NET("Height", ref stParam);
            if (MyCamera.MV_OK != nRet)
            {
                Log.Error($"获取图像高失败,失败代码:{nRet}");
                return;
            }
            uint nHeight = stParam.nCurValue;

            // 获取图像宽
            nRet = m_MyCamera.MV_CC_GetIntValue_NET("Width", ref stParam);
            if (MyCamera.MV_OK != nRet)
            {
                Log.Error($"获取图像宽失败,失败代码:{nRet}");
                return;
            }
            uint nWidth = stParam.nCurValue;

            // 根据图像大小设置图像缓存
            m_pDataForRed = new byte[nWidth * nHeight];
            m_pDataForGreen = new byte[nWidth * nHeight];
            m_pDataForBlue = new byte[nWidth * nHeight];
            if (3 * nPayloadSize > m_nBufSizeForDriver)
            {
                if (m_BufForDriver != IntPtr.Zero)
                {
                    Marshal.Release(m_BufForDriver);
                }
                m_nBufSizeForDriver = 3 * nPayloadSize;
                m_BufForDriver = Marshal.AllocHGlobal((Int32)m_nBufSizeForDriver);
            }
            if (m_BufForDriver == IntPtr.Zero)
            {
                return;
            }

            IntPtr pImageBuffer = Marshal.AllocHGlobal((int)nPayloadSize * 3);
            if (pImageBuffer == IntPtr.Zero)
            {
                Log.Error($"申请图像缓存区失败!");
                return;
            }

            MyCamera.MV_FRAME_OUT_INFO_EX stFrameInfo = new MyCamera.MV_FRAME_OUT_INFO_EX();
            IntPtr RedPtr = IntPtr.Zero;
            IntPtr GreenPtr = IntPtr.Zero;
            IntPtr BluePtr = IntPtr.Zero;
            IntPtr pTemp = IntPtr.Zero;
            while (m_isGrabbing)
            {
                lock (BufForDriverLock)
                {
                    nRet = m_MyCamera.MV_CC_GetOneFrameTimeout_NET(m_BufForDriver, m_nBufSizeForDriver, ref stFrameInfo, 1000);
                    if (nRet == MyCamera.MV_OK)
                    {
                        Log.Debug("相机取图完成,开始处理...");
                        m_stFrameInfo = stFrameInfo;
                    }
                }
                HImage hImage = new HImage();

                if (nRet == MyCamera.MV_OK)
                {
                    // 彩色相机
                    if (IsColorData(stFrameInfo.enPixelType))
                    {
                        if (stFrameInfo.enPixelType == MyCamera.MvGvspPixelType.PixelType_Gvsp_RGB8_Packed)
                        {
                            pTemp = m_BufForDriver;
                        }
                        else
                        {
                            nRet = ConvertToRGB(m_MyCamera, m_BufForDriver, stFrameInfo.nHeight, stFrameInfo.nWidth, stFrameInfo.enPixelType, pImageBuffer);
                            if (MyCamera.MV_OK != nRet)
                            {
                                return;
                            }
                            pTemp = pImageBuffer;
                        }
                        //hImage.GenImageInterleaved(pTemp, "rgb", (int)stFrameInfo.nWidth, (int)stFrameInfo.nHeight, 0, "byte", (int)stFrameInfo.nWidth, (int)stFrameInfo.nHeight, 0, 0, -1, 0);
                        //HOperatorSet.WriteImage(hImage, "jpg", 255, "D://1");
                        unsafe
                        {
                            byte* pBufForSaveImage = (byte*)pTemp;

                            UInt32 nSupWidth = (stFrameInfo.nWidth + (UInt32)3) & 0xfffffffc;//5120

                            for (int nRow = 0; nRow < stFrameInfo.nHeight; nRow++)
                            {
                                for (int col = 0; col < stFrameInfo.nWidth; col++)
                                {
                                    m_pDataForRed[nRow * nSupWidth + col] = pBufForSaveImage[nRow * stFrameInfo.nWidth * 3 + (3 * col)];
                                    m_pDataForGreen[nRow * nSupWidth + col] = pBufForSaveImage[nRow * stFrameInfo.nWidth * 3 + (3 * col + 1)];
                                    m_pDataForBlue[nRow * nSupWidth + col] = pBufForSaveImage[nRow * stFrameInfo.nWidth * 3 + (3 * col + 2)];
                                }
                            }
                        }

                        RedPtr = Marshal.UnsafeAddrOfPinnedArrayElement(m_pDataForRed, 0);
                        GreenPtr = Marshal.UnsafeAddrOfPinnedArrayElement(m_pDataForGreen, 0);
                        BluePtr = Marshal.UnsafeAddrOfPinnedArrayElement(m_pDataForBlue, 0);
                        //try
                        //{

                        //    HOperatorSet.GenImage3Extern(out HObject Hobj, (HTuple)"byte", stFrameInfo.nWidth, stFrameInfo.nHeight,
                        //                        (new HTuple(RedPtr)), (new HTuple(GreenPtr)), (new HTuple(BluePtr)), IntPtr.Zero);
                        //    HOperatorSet.WriteImage(Hobj, "jpg", 255, "D://1");
                        //}
                        //catch (System.Exception ex)
                        //{
                        //    MessageBox.Show(ex.ToString());
                        //}
                        lock (BufForImageLock)
                        {
                            Log.Debug("相机触发事件...");
                            if (GrabRGBImageEvent != null)
                                GrabRGBImageEvent(stFrameInfo.nWidth, stFrameInfo.nHeight, RedPtr, GreenPtr, BluePtr);
                        }
                    }
                    else if (IsMonoData(stFrameInfo.enPixelType))                     // 黑白图像
                    {
                        if (stFrameInfo.enPixelType == MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8)
                        {
                            pTemp = m_BufForDriver;
                        }
                        else
                        {
                            nRet = ConvertToMono8(m_MyCamera, m_BufForDriver, pImageBuffer, stFrameInfo.nHeight, stFrameInfo.nWidth, stFrameInfo.enPixelType);
                            if (MyCamera.MV_OK != nRet)
                            {
                                return;
                            }
                            pTemp = pImageBuffer;
                        }

                        // 通过事件传递图像数据
                        lock (BufForImageLock)
                        {
                            if (GrabGrayImageEvent != null)
                                GrabGrayImageEvent(stFrameInfo.nWidth, stFrameInfo.nHeight, pTemp);
                        }
                    }
                    else
                    {
                        continue;
                    }
                }
                else
                {
                    if (m_isTriggerMode)
                    {
                        Thread.Sleep(5);
                    }
                }
            }
        }



        /// <summary>
        /// 回传灰色图像
        /// </summary>
        /// <param name="pData"></param>
        /// <param name="pFrameInfo"></param>
        /// <param name="pUser"></param>
        public void GrayImageCallbackFunc(int width, int height, IntPtr ImageData)
        {
            try
            {
                // 获取图像队列最新帧 
                m_mutex.WaitOne();
                m_mutex.ReleaseMutex();

                // 灰度图
                HImage hImg = new HImage();
                hImg.GenImage1("byte", width, height, ImageData);
                // 核心:复制父类图像变量,可用于传递图像
                m_Image = new HalconDotNet.HImage(hImg);

                eventWait.Set();
                // 显示图像委托变量
                if (dispImgCallback != null)
                {
                    // 核心:传递图像
                    dispImgCallback(m_Image, 0);
                }

      
            }
            catch (Exception)
            {
                eventWait.Set();
            }
        }

        /// <summary>
        /// 回传彩色halcon图像
        /// </summary>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="Red"></param>
        /// <param name="Green"></param>
        /// <param name="Blue"></param>

        public void RGBImageCallbackFunc(int width, int height, IntPtr Red, IntPtr Green, IntPtr Blue)
        {
            try
            {
                // 获取图像队列最新帧 
                m_mutex.WaitOne();
                m_mutex.ReleaseMutex();

                HImage hImg = new HImage();
                hImg.GenImage3Extern("byte", width, height, Red, Green, Blue, IntPtr.Zero);
                // 核心:复制父类图像变量,可用于传递图像
                m_Image = new HalconDotNet.HImage(hImg);

                eventWait.Set();
                // 显示图像委托变量
                if (dispImgCallback != null)
                {
                    // 核心:传递图像
                    dispImgCallback(m_Image, 0);
                }

        
            }
            catch (Exception)
            {
                eventWait.Set();
            }
        }

        /// <summary>
        /// 判断是否为黑白图像
        /// </summary>
        /// <param name="enGvspPixelType"></param>
        /// <returns></returns>
        private Boolean IsMonoData(MyCamera.MvGvspPixelType enGvspPixelType)
        {
            switch (enGvspPixelType)
            {
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono10:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono10_Packed:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono12:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono12_Packed:
                    return true;

                default:
                    return false;
            }
        }

        /// <summary>
        /// 判断是否为彩色图像
        /// </summary>
        /// <param name="enGvspPixelType"></param>
        /// <returns></returns>
        private Boolean IsColorData(MyCamera.MvGvspPixelType enGvspPixelType)
        {
            switch (enGvspPixelType)
            {
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGR8:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerRG8:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGB8:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerBG8:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGR10:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerRG10:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGB10:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerBG10:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGR12:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerRG12:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGB12:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerBG12:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGR10_Packed:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerRG10_Packed:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGB10_Packed:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerBG10_Packed:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGR12_Packed:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerRG12_Packed:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGB12_Packed:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerBG12_Packed:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_RGB8_Packed:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_YUV422_Packed:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_YUV422_YUYV_Packed:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_YCBCR411_8_CBYYCRYY:
                    return true;
                default:
                    return false;
            }
        }

        /// <summary>
        /// 转换为RGB格式
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="pSrc"></param>
        /// <param name="nHeight"></param>
        /// <param name="nWidth"></param>
        /// <param name="nPixelType"></param>
        /// <param name="pDst"></param>
        /// <returns></returns>
        private Int32 ConvertToRGB(object obj, IntPtr pSrc, ushort nHeight, ushort nWidth, MyCamera.MvGvspPixelType nPixelType, IntPtr pDst)
        {
            if (IntPtr.Zero == pSrc || IntPtr.Zero == pDst)
            {
                return MyCamera.MV_E_PARAMETER;
            }

            int nRet = MyCamera.MV_OK;
            MyCamera device = obj as MyCamera;
            MyCamera.MV_PIXEL_CONVERT_PARAM stPixelConvertParam = new MyCamera.MV_PIXEL_CONVERT_PARAM();

            stPixelConvertParam.pSrcData = pSrc;//源数据
            if (IntPtr.Zero == stPixelConvertParam.pSrcData)
            {
                return -1;
            }

            stPixelConvertParam.nWidth = nWidth;//图像宽度
            stPixelConvertParam.nHeight = nHeight;//图像高度
            stPixelConvertParam.enSrcPixelType = nPixelType;//源数据的格式
            stPixelConvertParam.nSrcDataLen = (uint)(nWidth * nHeight * ((((uint)nPixelType) >> 16) & 0x00ff) >> 3);

            stPixelConvertParam.nDstBufferSize = (uint)(nWidth * nHeight * ((((uint)MyCamera.MvGvspPixelType.PixelType_Gvsp_RGB8_Packed) >> 16) & 0x00ff) >> 3);
            stPixelConvertParam.pDstBuffer = pDst;//转换后的数据
            stPixelConvertParam.enDstPixelType = MyCamera.MvGvspPixelType.PixelType_Gvsp_RGB8_Packed;
            stPixelConvertParam.nDstBufferSize = (uint)nWidth * nHeight * 3;

            nRet = device.MV_CC_ConvertPixelType_NET(ref stPixelConvertParam);//格式转换
            if (MyCamera.MV_OK != nRet)
            {
                return -1;
            }

            return MyCamera.MV_OK;
        }

        /// <summary>
        ///  转换为Mono8格式
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="pInData"></param>
        /// <param name="pOutData"></param>
        /// <param name="nHeight"></param>
        /// <param name="nWidth"></param>
        /// <param name="nPixelType"></param>
        /// <returns></returns>
        private Int32 ConvertToMono8(object obj, IntPtr pInData, IntPtr pOutData, ushort nHeight, ushort nWidth, MyCamera.MvGvspPixelType nPixelType)
        {
            if (IntPtr.Zero == pInData || IntPtr.Zero == pOutData)
            {
                return MyCamera.MV_E_PARAMETER;
            }

            int nRet = MyCamera.MV_OK;
            MyCamera device = obj as MyCamera;
            MyCamera.MV_PIXEL_CONVERT_PARAM stPixelConvertParam = new MyCamera.MV_PIXEL_CONVERT_PARAM();

            stPixelConvertParam.pSrcData = pInData;//源数据
            if (IntPtr.Zero == stPixelConvertParam.pSrcData)
            {
                return -1;
            }

            stPixelConvertParam.nWidth = nWidth;//图像宽度
            stPixelConvertParam.nHeight = nHeight;//图像高度
            stPixelConvertParam.enSrcPixelType = nPixelType;//源数据的格式
            stPixelConvertParam.nSrcDataLen = (uint)(nWidth * nHeight * ((((uint)nPixelType) >> 16) & 0x00ff) >> 3);

            stPixelConvertParam.nDstBufferSize = (uint)(nWidth * nHeight * ((((uint)MyCamera.MvGvspPixelType.PixelType_Gvsp_RGB8_Packed) >> 16) & 0x00ff) >> 3);
            stPixelConvertParam.pDstBuffer = pOutData;//转换后的数据
            stPixelConvertParam.enDstPixelType = MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8;
            stPixelConvertParam.nDstBufferSize = (uint)(nWidth * nHeight * 3);

            nRet = device.MV_CC_ConvertPixelType_NET(ref stPixelConvertParam);//格式转换
            if (MyCamera.MV_OK != nRet)
            {
                return -1;
            }

            return nRet;
        }






    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值