一.学习资料

1.官网下载安装MVS软件。

2.文件资料路径:C:\Program Files (x86)\MVS\Development\Documentations

3.引用的DLL路径:C:\Program Files (x86)\Common Files\MVS\Runtime\Win64_x64\MvCameraControl.dll(实测是这个路径,而非官方推荐的C:\Program Files (x86)\MVS\Development\DotNet\win64\MvCamCtrl.Net.dll)

4.官方示例程序:C:\Program Files (x86)\MVS\Development\Samples\C#

二、相机程序流程

1.枚举图像采集卡;【可选操作】

2.打开图像采集卡;【可选操作】

3.设置采集卡参数;【可选操作】

4.枚举相机设备;

5.判断相机可访问性;

6.创建相机句柄;

7.打开设备;

8.获取/设置参数;

9.开始采集取流;

10.触发取像:(1)注册回调函数(CallBack)获取图像数据;(2)主动式获取图像数据(获取、释放);【两种方式只能使用一种】【相机取像在此环节循环操作】

11.停止采集取流;

12.关闭设备;

13.销毁句柄。

以上1,2,3为采集卡操作,如不涉及采集卡操作需要可忽略;10的取像方式两种只能使用其中一种,不支持复用,只要不是要关掉程序,软件即在此环节不断地循环并等待取像触发信号。

三、开发思路

1.将单个海康相机的信息和操作封装成一个类CCameraHik

2.创建一个含有CCameraHik类的实例列表的全局用的操作类CHikVision,主要用于统一管理程序上的所有相机。

3.在主程序里创建类CHikVision的实例供程序使用。

四、代码展示

1.单个相机类CCameraHik

打开相机:

/// <summary>
        /// 打开相机
        /// </summary>
        /// <returns></returns>
        public override bool Open()
        {
            if (m_Camera == null)
            {
                m_Camera = new MyCamera();
                if (m_Camera == null)
                {
                    ShowAlarm(string.Format("创建相机{0}资源失败", m_Name));
                    return false;
                }
            }

            //创建相机对象
            int nRet = m_Camera.MV_CC_CreateDevice_NET(ref m_CameraInfo);
            if (MyCamera.MV_OK != nRet)
            {
                ShowAlarm(string.Format("创建相机对象{0}失败,错误代码:{1}", m_Name, nRet));
                return false;
            }
            //打开相机对象
            nRet = m_Camera.MV_CC_OpenDevice_NET();
            if (MyCamera.MV_OK != nRet)
            {
                ShowAlarm(string.Format("打开相机{0}失败,错误代码:{1}", m_Name, nRet));
                return false;
            }
            else
            {
                //检测网络最佳包大小
                if (m_CameraInfo.nTLayerType == MyCamera.MV_GIGE_DEVICE)
                {
                    int nPacketSize = m_Camera.MV_CC_GetOptimalPacketSize_NET();
                    if (nPacketSize > 0)
                    {
                        nRet = m_Camera.MV_CC_SetIntValueEx_NET("GevSCPSPacketSize", nPacketSize);
                        if (nRet != MyCamera.MV_OK)
                        {
                            ShowAlarm(string.Format("设置相机{0}最佳数据包大小失败,错误代码:{1}", m_Name, nRet));
                        }
                    }
                    else
                    {
                        ShowAlarm(string.Format("获取相机{0}最佳数据包大小失败,错误代码:{1}", m_Name, nPacketSize));
                    }
                }

                //默认设置相机为触发模式
                SetTriggerMode(true);
                //默认设置相机为软触发
                SetSoftTrigger(true);
                //注册相机图像输出回调函数
               m_Camera.MV_CC_RegisterImageCallBackEx_NET(CHikVision.ImageOutputCallBack, (IntPtr)m_ID);

                return true;
            }
        }

        /// <summary>
        /// 设置触发模式
        /// </summary>
        /// <param name="isTrigger">触发模式:true;连续采集模式:false</param>
        public override void SetTriggerMode(bool isTrigger)
        {
            if (isTrigger)
            {
                m_Camera.MV_CC_SetEnumValue_NET("TriggerMode", (uint)MyCamera.MV_CAM_TRIGGER_MODE.MV_TRIGGER_MODE_ON);
            }
            else
            {
                m_Camera.MV_CC_SetEnumValue_NET("TriggerMode", (uint)MyCamera.MV_CAM_TRIGGER_MODE.MV_TRIGGER_MODE_OFF);
            }
        }

        /// <summary>
        /// 设置软触发
        /// </summary>
        /// <param name="trigBySoft"></param>
        public override void SetSoftTrigger(bool trigBySoft)
        {
            if (trigBySoft)
            {
                m_Camera.MV_CC_SetEnumValue_NET("TriggerSource", (uint)MyCamera.MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_SOFTWARE);
            }
            else
            {
                //外部触发源:Line0~Line3,默认用Line0
                m_Camera.MV_CC_SetEnumValue_NET("TriggerSource", (uint)MyCamera.MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_LINE0);
            }
        }

关闭相机:

/// <summary>
        /// 关闭相机
        /// </summary>
        /// <returns></returns>
        public override bool Close()
        {
            int nRet = m_Camera.MV_CC_CloseDevice_NET();
            if (nRet != MyCamera.MV_OK)
            {
                ShowAlarm(string.Format("关闭相机{0}失败,错误代码:{1}", m_Name, nRet));
                return false;
            }

            nRet = m_Camera.MV_CC_DestroyDevice_NET();
            if (nRet != MyCamera.MV_OK)
            {
                ShowAlarm(string.Format("销毁相机对象{0}失败,错误代码:{1}", m_Name, nRet));
                return false;
            }
            return true;
        }

 开始采集取流:

/// <summary>
        /// 开始采集
        /// </summary>
        public override void StartGrabbing()
        {
            int nRet;

            //开始采集前配置相机
            nRet = OperateBeforeGrab();
            if (MyCamera.MV_OK != nRet)
            {
                ShowAlarm(string.Format("相机{0}配置失败,错误代码:{1}", m_Name, nRet));
                return;
            }

            //取流之前先清除帧长度
            nFrames = 0;
            m_FrameInfo.nFrameLen = 0;
            m_FrameInfo.enPixelType = MyCamera.MvGvspPixelType.PixelType_Gvsp_Undefined;

            nRet = m_Camera.MV_CC_StartGrabbing_NET();
            if (MyCamera.MV_OK != nRet)
            {
                ShowAlarm(string.Format("相机{0}开始采集失败,错误代码:{1}", m_Name, nRet));
            }
        }

        /// <summary>
        /// 取图前的必要配置操作
        /// </summary>
        /// <returns></returns>
        private Int32 OperateBeforeGrab()
        {
            //取图像宽
            MyCamera.MVCC_INTVALUE_EX stWidth = new MyCamera.MVCC_INTVALUE_EX();
            int nRet = m_Camera.MV_CC_GetIntValueEx_NET("Width", ref stWidth);
            if (MyCamera.MV_OK != nRet)
            {
                //获取图像宽度失败
                return nRet;
            }
            //取图像高
            MyCamera.MVCC_INTVALUE_EX stHeight = new MyCamera.MVCC_INTVALUE_EX();
            nRet = m_Camera.MV_CC_GetIntValueEx_NET("Height", ref stHeight);
            if (MyCamera.MV_OK != nRet)
            {
                //获取图像高度失败
                return nRet;
            }
            //取像素格式
            MyCamera.MVCC_ENUMVALUE stPixelFormat = new MyCamera.MVCC_ENUMVALUE();
            nRet = m_Camera.MV_CC_GetEnumValue_NET("PixelFormat", ref stPixelFormat);
            if (MyCamera.MV_OK != nRet)
            {
                //获取像素格式失败
                return nRet;
            }

            //设置bitmap像素格式,申请相应大小内存
            if ((Int32)MyCamera.MvGvspPixelType.PixelType_Gvsp_Undefined == stPixelFormat.nCurValue)
            {
                //未知错误
                return MyCamera.MV_E_UNKNOW;
            }
            else if (IsMono(stPixelFormat.nCurValue))
            {
                m_BitmapPixelFormat = PixelFormat.Format8bppIndexed;

                if (IntPtr.Zero != m_pConvertDstBuf)
                {
                    Marshal.Release(m_pConvertDstBuf);
                    m_pConvertDstBuf = IntPtr.Zero;
                }

                // Mono8为单通道
                m_nConvertDstBufLen = (UInt32)(stWidth.nCurValue * stHeight.nCurValue);
                m_pConvertDstBuf = Marshal.AllocHGlobal((Int32)m_nConvertDstBufLen);
                if (IntPtr.Zero == m_pConvertDstBuf)
                {
                    //创建图像资源失败
                    return MyCamera.MV_E_RESOURCE;
                }
            }
            else
            {
                m_BitmapPixelFormat = PixelFormat.Format24bppRgb;

                if (IntPtr.Zero != m_pConvertDstBuf)
                {
                    Marshal.FreeHGlobal(m_pConvertDstBuf);
                    m_pConvertDstBuf = IntPtr.Zero;
                }

                // RGB为三通道
                m_nConvertDstBufLen = (UInt32)(3 * stWidth.nCurValue * stHeight.nCurValue);
                m_pConvertDstBuf = Marshal.AllocHGlobal((Int32)m_nConvertDstBufLen);
                if (IntPtr.Zero == m_pConvertDstBuf)
                {
                    //创建资源失败
                    return MyCamera.MV_E_RESOURCE;
                }
            }

            // 确保释放保存了旧图像数据的bitmap实例,用新图像宽高等信息new一个新的bitmap实例
            if (null != m_Bitmap)
            {
                m_Bitmap.Dispose();
                m_Bitmap = null;
            }
            m_Bitmap = new Bitmap((Int32)stWidth.nCurValue, (Int32)stHeight.nCurValue, m_BitmapPixelFormat);

            // ch:Mono8格式,设置为标准调色板 | en:Set Standard Palette in Mono8 Format
            if (PixelFormat.Format8bppIndexed == m_BitmapPixelFormat)
            {
                ColorPalette palette = m_Bitmap.Palette;
                for (int i = 0; i < palette.Entries.Length; i++)
                {
                    palette.Entries[i] = Color.FromArgb(i, i, i);
                }
                m_Bitmap.Palette = palette;
            }

            return MyCamera.MV_OK;
        }

停止采集取流:

/// <summary>
        /// 停止采集
        /// </summary>
        public override void StopGrabbing()
        {
            int nRet = m_Camera.MV_CC_StopGrabbing_NET();
            if (nRet != MyCamera.MV_OK)
            {
                ShowAlarm(string.Format("相机{0}结束采集失败,错误代码:{1}", m_Name, nRet));
            }
        }

软件触发取像:

/// <summary>
        /// 拍摄图像
        /// </summary>
        /// <returns></returns>
        public override GrabImage()
        {
            lock (this)
            {
                grabSuccess = false;
                int nRet = m_Camera.MV_CC_SetCommandValue_NET("TriggerSoftware");
                if (MyCamera.MV_OK != nRet)
                {
                    ShowAlarm(string.Format("相机{0}获取图像失败,错误代码:{1}", m_Name, nRet));
                }
            }
        }

设置曝光值:

/// <summary>
        /// 设置相机曝光
        /// </summary>
        /// <param name="value"></param>
        public override void SetExposure(float value)
        {
            m_Camera.MV_CC_SetEnumValue_NET("ExposureAuto", 0);

            int nRet = m_Camera.MV_CC_SetFloatValue_NET("ExposureTime", value);
            if (nRet != MyCamera.MV_OK)
            {
                ShowAlarm(string.Format("相机{0}设置曝光值失败,错误代码:{1}", m_Name, nRet));
            }
        }

设置增益值:

/// <summary>
        /// 设置相机增益
        /// </summary>
        /// <param name="value"></param>
        public override void SetGainValue(float value)
        {
            m_Camera.MV_CC_SetEnumValue_NET("GainAuto", 0);
            int nRet = m_Camera.MV_CC_SetFloatValue_NET("Gain", value);
            if (nRet != MyCamera.MV_OK)
            {
                ShowAlarm(string.Format("相机{0}设置增益值失败,错误代码:{1}", m_Name, nRet));
            }
        }

源海康帧数据转换成.NET的bitmap和Halcon的HImage:

/// <summary>
        /// 转化像素为Bit图像
        /// </summary>
        /// <param name="pData"></param>
        /// <param name="pFrameInfo"></param>
        public void ConvertToBitmap()
        {
            //创建转换变量
            MyCamera.MV_PIXEL_CONVERT_PARAM stConvertInfo = new MyCamera.MV_PIXEL_CONVERT_PARAM();
            //设置图像宽度、高度
            stConvertInfo.nWidth = m_FrameInfo.nWidth;
            stConvertInfo.nHeight = m_FrameInfo.nHeight;
            //源数据地址、数据包大小、像素类型
            stConvertInfo.pSrcData = pSaveImageBuf;
            stConvertInfo.nSrcDataLen = nSaveImageBufSize;
            stConvertInfo.enSrcPixelType = m_FrameInfo.enPixelType;
            //转换后的数据地址、数据包大小、像素类型
            stConvertInfo.pDstBuffer = m_pConvertDstBuf;
            stConvertInfo.nDstBufferSize = m_nConvertDstBufLen;
            if (m_Bitmap.PixelFormat == PixelFormat.Format8bppIndexed)
            {
                stConvertInfo.enDstPixelType = MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8;
                m_Camera.MV_CC_ConvertPixelType_NET(ref stConvertInfo);
            }
            else
            {
                stConvertInfo.enDstPixelType = MyCamera.MvGvspPixelType.PixelType_Gvsp_BGR8_Packed;
                m_Camera.MV_CC_ConvertPixelType_NET(ref stConvertInfo);
            }

            //保存Bitmap数据
            BitmapData bitmapData = m_Bitmap.LockBits(new Rectangle(0, 0, stConvertInfo.nWidth, stConvertInfo.nHeight), ImageLockMode.ReadWrite, m_Bitmap.PixelFormat);
            CopyMemory(bitmapData.Scan0, stConvertInfo.pDstBuffer, (UInt32)(bitmapData.Stride * m_Bitmap.Height));
            m_Bitmap.UnlockBits(bitmapData);
        }

        /// <summary>
        /// 将帧数据转成Halcon图像
        /// </summary>
        /// <param name="pData"></param>
        /// <param name="pFrameInfo"></param>
        public HImage ConvertToHImage()
        {
            HImage hImage = new HImage();

            //创建转换变量
            MyCamera.MV_PIXEL_CONVERT_PARAM stConvertInfo = new MyCamera.MV_PIXEL_CONVERT_PARAM();
            //设置图像宽度、高度
            stConvertInfo.nWidth = m_FrameInfo.nWidth;
            stConvertInfo.nHeight = m_FrameInfo.nHeight;
            //源数据地址、数据包大小、像素类型
            stConvertInfo.pSrcData = pSaveImageBuf;
            stConvertInfo.nSrcDataLen = nSaveImageBufSize;
            stConvertInfo.enSrcPixelType = m_FrameInfo.enPixelType;
            //转换后的数据地址、数据包大小、像素类型
            stConvertInfo.pDstBuffer = m_pConvertDstBuf;
            stConvertInfo.nDstBufferSize = m_nConvertDstBufLen;
            if (m_Bitmap.PixelFormat == PixelFormat.Format8bppIndexed)
            {
                stConvertInfo.enDstPixelType = MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8;
                m_Camera.MV_CC_ConvertPixelType_NET(ref stConvertInfo);
            }
            else
            {
                stConvertInfo.enDstPixelType = MyCamera.MvGvspPixelType.PixelType_Gvsp_BGR8_Packed;
                m_Camera.MV_CC_ConvertPixelType_NET(ref stConvertInfo);
            }

            //彩色图像转换
            if (IsColorPixelFormat(stConvertInfo.enDstPixelType))
            {
                try
                {
                    hImage.GenImageInterleaved((HTuple)stConvertInfo.pDstBuffer, (HTuple)"rgb", (HTuple)stConvertInfo.nWidth, (HTuple)stConvertInfo.nHeight, -1, "byte", 0, 0, 0, 0, -1, 0);
                }
                catch (Exception ex)
                {
                    SDKKernal.ShowAlarm("4100", string.Format("相机{0}帧数据转彩色图像失败:{1}", m_Name, ex.Message));
                    return null;
                }
            }
            //黑白图像转换
            else if (IsMonoPixelFormat(stConvertInfo.enDstPixelType))
            {
                try
                {
                    hImage.GenImage1Extern("byte", stConvertInfo.nWidth , stConvertInfo.nHeight, stConvertInfo.pDstBuffer, IntPtr.Zero);
                }
                catch (Exception ex)
                {
                    SDKKernal.ShowAlarm("4100", string.Format("相机{0}帧数据转黑白图像失败:{1}", m_Name, ex.Message));
                    return null;
                }
            }

            return hImage;
        }

        private bool IsMonoPixelFormat(MyCamera.MvGvspPixelType enType)
        {
            switch (enType)
            {
                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;
            }
        }

        private bool IsColorPixelFormat(MyCamera.MvGvspPixelType enType)
        {
            switch (enType)
            {
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_RGB8_Packed:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BGR8_Packed:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_RGBA8_Packed:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BGRA8_Packed:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_YUV422_Packed:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_YUV422_YUYV_Packed:
                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_BayerGB10:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGB10_Packed:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerBG10:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerBG10_Packed:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerRG10:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerRG10_Packed:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGR10:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGR10_Packed:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGB12:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGB12_Packed:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerBG12:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerBG12_Packed:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerRG12:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerRG12_Packed:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGR12:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGR12_Packed:
                    return true;
                default:
                    return false;
            }
        }

2.全局操作类HikVision

获取相机列表:

/// <summary>
        /// 获取相机列表
        /// </summary>
        public AcquireCameraList()
        {
            //强制回收即时垃圾
            GC.Collect();

            //枚举相机设备
            m_CamList.nDeviceNum = 0;
            int nRet = MyCamera.MV_CC_EnumDevices_NET(MyCamera.MV_GIGE_DEVICE, ref m_CamList);
            //获取失败则退出程序
            if (nRet != 0)
            {
                ShowAlarm("获取海康相机列表失败!");
                return;
            }

            hikCameras = new CCameraHik[m_CamList.nDeviceNum];
            strCameraName = new string[m_CamList.nDeviceNum];

            //创建相机列表
            for (int i = 0; i < m_CamList.nDeviceNum; i++)
            {
                MyCamera.MV_CC_DEVICE_INFO cam = (MyCamera.MV_CC_DEVICE_INFO)Marshal.PtrToStructure(m_CamList.pDeviceInfo[i],
                                                    typeof(MyCamera.MV_CC_DEVICE_INFO));
                if (cam.nTLayerType == MyCamera.MV_GIGE_DEVICE)
                {
                    MyCamera.MV_GIGE_DEVICE_INFO gigeInfo = (MyCamera.MV_GIGE_DEVICE_INFO)MyCamera.ByteToStruct(cam.SpecialInfo.stGigEInfo,
                                                                typeof(MyCamera.MV_GIGE_DEVICE_INFO));
                    hikCameras[i] = new CCameraHik();
                    hikCameras[i].ID = i;
                    hikCameras[i].SerialNumber = gigeInfo.chSerialNumber;

                    if (gigeInfo.chUserDefinedName != "")
                        hikCameras[i].Name = gigeInfo.chUserDefinedName;
                    else
                        hikCameras[i].Name = gigeInfo.chManufacturerName;

                    hikCameras[i].CameraInfo = cam;
                    
                }
            }
        }

全局操作:

/// <summary>
        /// 打开所有相机
        /// </summary>
        public void OpenAllCamera()
        {
            if (m_CamList.nDeviceNum == 0)
            {
                ShowAlarm( "相机列表为空,打开相机失败!");
            }

            //遍历所有相机
            for (int i = 0; i < m_CamList.nDeviceNum; i++)
            {
                if (hikCameras[i].Open())
                    m_ConnectedCamNum++;
            }

            //判断连接相机是否与设备设计相等
            if (m_ConnectedCamNum != m_CamCount)
            {
                ShowAlarm("已连接的相机数量与设备预设数量不同!");
            }
        }


        /// <summary>
        /// 开始所有相机采集
        /// </summary>
        public void StartAllGrabbing()
        {
            //开始采集
            for (int i = 0; i < m_ConnectedCamNum; i++)
            {
                hikCameras[i].StartGrabbing();
            }

            //打开帧数监控标志位
            bFrameTimerFlag = true;

            //开始采集标志位
            m_bGrabbing = true;
        }

        /// <summary>
        /// 停止所有相机采集
        /// </summary>
        public void StopAllGrabbing()
        {
            for (int i = 0; i < m_ConnectedCamNum; ++i)
            {
                hikCameras[i].StopGrabbing();
            }

            //停止采集标志位
            m_bGrabbing = false;

            //关闭帧数监控标志位
            bFrameTimerFlag = false;
        }

        /// <summary>
        /// 关闭所有相机
        /// </summary>
        public void CloseAllCamera()
        {
            for (int i = 0; i < m_ConnectedCamNum; ++i)
            {
                hikCameras[i].Close();
            }

            //停止采集标志位
            m_bGrabbing = false;

            //重置成员变量
            Initialize();
        }

相机取像回调函数:

/// <summary>
        /// 取流回调函数
        /// </summary>
        /// <param name="pData">数据源指针</param>
        /// <param name="pFrameInfo">单帧图像信息源</param>
        /// <param name="pUser">相机ID</param>
        public void ImageCallBack(IntPtr pData, ref MyCamera.MV_FRAME_OUT_INFO_EX pFrameInfo, IntPtr pUser)
        {
            int nIndex = (int)pUser;

            //抓取的帧数
            ++hikCameras[nIndex].nFrames;

            //按指针操作驱动数据时,进行锁保护
            lock (hikCameras[nIndex].objForSaveImageLock)
            {
                //修改相机的图像缓存地址和尺寸
                if (hikCameras[nIndex].pSaveImageBuf == IntPtr.Zero || pFrameInfo.nFrameLen > hikCameras[nIndex].nSaveImageBufSize)
                {
                    if (hikCameras[nIndex].pSaveImageBuf != IntPtr.Zero)
                    {
                        Marshal.Release(hikCameras[nIndex].pSaveImageBuf);
                        hikCameras[nIndex].pSaveImageBuf = IntPtr.Zero;
                    }

                    hikCameras[nIndex].pSaveImageBuf = Marshal.AllocHGlobal((Int32)pFrameInfo.nFrameLen);
                    if (hikCameras[nIndex].pSaveImageBuf == IntPtr.Zero)
                    {
                        return;
                    }
                    hikCameras[nIndex].nSaveImageBufSize = pFrameInfo.nFrameLen;
                }
                //复制缓存图像
                hikCameras[nIndex].FrameInfo = pFrameInfo;
                CopyMemory(hikCameras[nIndex].pSaveImageBuf, pData, pFrameInfo.nFrameLen);

                hikCameras[nIndex].grabSuccess = true;
            }
        }

五、使用示例

private void btnFindCameras_Click(object sender, EventArgs e)
        {
            cameraList = hikVision.AcquireCameraList();
            if (cameraList != null)
            {
                this.textCamName.Text = cameraList[0];
            }
            else
            {
                ShowAlarm("未找到相机");
            }
        }

        private void btnOpenCamera_Click(object sender, EventArgs e)
        {
            hikVision.OpenAllCamera();
        }

        private void btnCloseCamera_Click(object sender, EventArgs e)
        {
            hikVision.CloseAllCamera();
        }

        private void btnStartGrab_Click(object sender, EventArgs e)
        {
            hikVision.StartAllGrabbing();
        }

        private void btnStopGrab_Click(object sender, EventArgs e)
        {
            hikVision.StopAllGrabbing();
        }

        private void btnTrigger_Click(object sender, EventArgs e)
        {
            hikVision.hikCameras[0].GrabImage();
        }

相互学习,共同富裕。