C# 上位机之海康相机开发(SDK)

一 前言

发现工作中好多计算机视觉上位机项目都用海康相机,为了能够更好的学习和工作,我自己依据同事的源码和网上的一些总结编写本博客。通过本次学习,让我明白一点,无论学习什么技术都要学会自己看技术文档,而不是第一时间上网找源码。以工业相机SDK使用说明.chm为例,如何检索相机,打开相机,取流,抓取,保存图片,关闭相机,释放资源都有详细的介绍。

二 海康相机使用流程

以下部分图片引用自工业相机SDK使用手册 v2.4.1,仅作为学习使用,以下简称使用手册

这里要说明以下几点

1 这个接口流程是C接口流程,除了C接口流程以外还有C++接口流程,有朋友可能会问为什么标题是C#工业相机操作,这里却介绍C接口。实际上通过DoNet源码可以看出虽然方法名以_NET结尾,但是方法的实现引用了C接口,如下图所示

2 可能随着使用手册版本的更新导致变量名,方法名等发生小幅度改变,掌握方法是关键

3 由上述流程图可以看出使用相机的流程分为:查找子网内相机设备->创建管理相机的句柄->打开设备->获取数据包->数据包处理->关闭设备->释放资源

三 相机操作

3.1 检索网络设备

3.1.1 枚举相机类型

示例代码如下

using System;
using System.IO;
using MvCamCtrl.NET;

int nTransLayers = MyCamera.MV_CC_EnumerateTls_NET();
if ((nTransLayers & MyCamera.MV_GIGE_DEVICE) == MyCamera.MV_GIGE_DEVICE)
   {
      Console.WriteLine("MV_GIGE_DEVICE");
   }
3.1.2 枚举相机信息       

        大部分情况是不需要检索相机类型的,相机是你根据项目需求买的,你应该知道它是什么相机。而且相机通过网线与计算机联系,通过配置IP就可以知道是正在对哪台相机操作。所以正常情是直接从网络中枚举相机。也就是如下的方法

注意:此枚举方法的第二个参数类型是MV_CC_DEVICE_INFO_LIST 相机设备信息列表,以下分别是使用手册中的数据类型定义和VS中的数据类型定义。

       可以看到VS源码中多了一行代码[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)],这里的MarshalAs在VS里官方的注释是指示如何在托管代码与非托管代码之间封送数据,那么有牵扯了两个名词。通过百度百科得到以下总结

托管代码与非托管代码
名称释义与区别
托管代码托管代码 (managed code)同受管制的代码,由公共语言运行库环境(而不是直接由操作系统)执行的代码。托管代码应用程序可以获得公共语言运行库服务,例如自动垃圾回收、运行库类型检查和安全支持等。这些服务帮助提供独立于平台和语言的、统一的托管代码应用程序行为。
非托管代码公共语言运行库环境的外部,由操作系统直接执行的代码托管代码必须提供自己的垃圾回收、类型检查、安全支持等服务,它与托管代码不同,后者从公共语言运行库中获得这些服务,而非托管代码是在运行库之外运行的代码。例如COM 组件、ActiveX 接口和 Win32 API 函数都是非托管代码的示例。

        通过VS追踪MarshalAS可以看出其来自public sealed class MarshalAsAttribute : Attribute这个类中的方法。至于方法内部实现暂时不是我们需要考虑的,我们需要知道以下几点(引用自MarshalAs的简单总结-CSDN博客)

[MarshalAs(UnmanagedType unmanagedType, 命名参数)]

        实际上相当于构造一个MarshalAsAttribute类的对象

        常用的UnmanagedType枚举值:

        BStr   长度前缀为双字节的 Unicode 字符串;

        LPStr  单字节、空终止的 ANSI 字符串。;

        LPWStr  一个 2 字节、空终止的 Unicode 字符串;

        ByValArray 用于在结构中出现的内联定长字符数组,应始终使用MarshalAsAttribute的                    SizeConst字段来指示数组的大小。   

注意:

在用Marshal.SizeOf(),即获取对象的非托管大小时,获得的是自己定义的大小;

但在实际处理的时候,是按照实际的大小来获取的。

接下来介绍相关相机信息数据类型,注意这几个结构体在使用手册查找的时候要到索引中找

那么到底如何进行网络检索相机设备呢
/*虽然系统有专门对相机信息列表数据类型的定义,但是我们最好还是自定义一个相机信息数据类
为什么要专门定义一个类呢,原因如下
1 MV_CC_DEVICE_INFO通用结构体转化为专用的相机结构体中对于相机IP的并不是192.168.*.*的形式,需要们自行偏移获取
如MV_CC_DEVICE_INFO->MV_GIGE_DEVICE_INFO 
 MyCamera.MV_GIGE_DEVICE_INFO gigeInfo = (MyCamera.MV_GIGE_DEVICE_INFO)MyCamera.ByteToStruct(device.SpecialInfo.stGigEInfo, typeof(MyCamera.MV_GIGE_DEVICE_INFO));

UInt32 nNetIp1 = (gigeInfo.nNetExport & 0xFF000000) >> 24;
UInt32 nNetIp2 = (gigeInfo.nNetExport & 0x00FF0000) >> 16;
UInt32 nNetIp3 = (gigeInfo.nNetExport & 0x0000FF00) >> 8;
UInt32 nNetIp4 = (gigeInfo.nNetExport & 0x000000FF);

// ch:显示IP | en:Display IP
UInt32 nIp1 = (gigeInfo.nCurrentIp & 0xFF000000) >> 24;
UInt32 nIp2 = (gigeInfo.nCurrentIp & 0x00FF0000) >> 16;
UInt32 nIp3 = (gigeInfo.nCurrentIp & 0x0000FF00) >> 8;
UInt32 nIp4 = (gigeInfo.nCurrentIp & 0x000000FF);
*/




//定义一个相机信息类 这个类定义的位置建议在一个全局模块中
public class CameraInfor
{
    public string userDefinedName { get; set; } //用户定义的名字
    public string serialNumber { get; set; }    //序列号
    public string deviceIPAdd { get; set; }     //设备IP地址
    public string manufacturerName { get; set; }//制造厂商名
    public string modelName { get; set; }       //型号名称
    public string deviceType { get; set; }      //型号名称
    public IntPtr pDeviceInfo;                  //相机句柄
    public float ExposureTime { get; set; }     //曝光时间
    public float Gain { get; set; }             //增益
    public float ResultingFrameRate { get; set; } //帧率
    public bool isOpenTriggerMode { get; set; }   //是否打开触发方式
}

//*********************************************************************
//相机模块部分
//创建一个全局的相机字典,IP为键,相机信息(CameraInfor)为值
 public static Dictionary<string, CameraInfor> mapOfGigeCameras = new Dictionary<string, CameraInfor>();
//创建一个全局的相机对象来保存当前正在使用的相机信息
private CameraInfor currentCameraInfor;
//根据相机枚举方法参数声明变量
MyCamera.MV_CC_DEVICE_INFO_LIST m_stDeviceList = new MyCamera.MV_CC_DEVICE_INFO_LIST();
//创建一个相机对象 注意只是创建了一个相机对象,并没有指定管理哪个相机
private MyCamera m_MyCamera = new MyCamera();
 //回调函数声明 用来处理拍照
 public delegate void Process(Mat src);
 public Process callback;
//抓图标志
public bool m_bGrabbing=false;
 Thread m_hReceiveThread = null;
 MyCamera.MV_FRAME_OUT_INFO_EX m_stFrameInfo = new MyCamera.MV_FRAME_OUT_INFO_EX();

 // ch:用于从驱动获取图像的缓存 
 UInt32 m_nBufSizeForDriver = 0;
 IntPtr m_BufForDriver = IntPtr.Zero;
 private static Object BufForDriverLock = new Object();


//封装枚举相机的方法
public void enumDevice()
{ 
 System.GC.Collect();//强制对所有代进行及时垃圾回收
 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)
 {
     return;
 }
mapOfGigeCameras.Clear(); //清空设备列表
CameraInfor cameraInfor ;
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));//获取第i个相机句柄的相机信息
    cameraInfor = new CameraInfor();
    cameraInfor.pDeviceInfo = m_stDeviceList.pDeviceInfo[i];//获取相机句柄
    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));//将通用相机信息结构体转化为Gige相机结构体

        UInt32 nNetIp1 = (gigeInfo.nNetExport & 0xFF000000) >> 24;
        UInt32 nNetIp2 = (gigeInfo.nNetExport & 0x00FF0000) >> 16;
        UInt32 nNetIp3 = (gigeInfo.nNetExport & 0x0000FF00) >> 8;
        UInt32 nNetIp4 = (gigeInfo.nNetExport & 0x000000FF);

        // ch:显示IP | en:Display IP
        UInt32 nIp1 = (gigeInfo.nCurrentIp & 0xFF000000) >> 24;
        UInt32 nIp2 = (gigeInfo.nCurrentIp & 0x00FF0000) >> 16;
        UInt32 nIp3 = (gigeInfo.nCurrentIp & 0x0000FF00) >> 8;
        UInt32 nIp4 = (gigeInfo.nCurrentIp & 0x000000FF);

        
        cameraInfor.serialNumber = gigeInfo.chSerialNumber;
        cameraInfor.userDefinedName = gigeInfo.chUserDefinedName;
        cameraInfor.manufacturerName = gigeInfo.chManufacturerName;
        cameraInfor.modelName = gigeInfo.chModelName;
        cameraInfor.deviceType = "GEV"; //千兆网工业相机技术之GigE Vision(GEV)
        cameraInfor.deviceIPAdd = nIp1.ToString() + "." + nIp2.ToString() + "." + nIp3.ToString() + "." + nIp4.ToString();
        mapOfGigeCameras.Add(cameraInfor.deviceIPAdd, cameraInfor);
    }
    else if (device.nTLayerType == MyCamera.MV_USB_DEVICE)
    {
        MyCamera.MV_USB3_DEVICE_INFO usbInfo = (MyCamera.MV_USB3_DEVICE_INFO)MyCamera.ByteToStruct(device.SpecialInfo.stUsb3VInfo, typeof(MyCamera.MV_USB3_DEVICE_INFO));
        //本文主要讲解Gige相机的使用,实际工作中可以根据需要编写此部分代码
    }
  }
}

3.2 打开相机

3.2.1 打开相机的流程:

        1  创建管理相机的句柄:通过创建句柄,指定我们之前创建的相机对象管理哪个相机

        2  打开相机对象

3.2.2 打开相机的相关方法

3.2.3 打开相机操作
public void OpenDeviceByIP(string deviceIp)
{
    if (m_stDeviceList.nDeviceNum == 0 || deviceIp=="")//枚举设备个数为0或者传入IP为空
    {
        return;
    }
    currentCameraInfor = mapOfGigeCameras[deviceIp];//之前创建的全局当前相机信息用于获取指定IP的相机
    MyCamera.MV_CC_DEVICE_INFO device =(MyCamera.MV_CC_DEVICE_INFO)Marshal.PtrToStructure(mapOfGigeCameras[deviceIp].pDeviceInfo,typeof(MyCamera.MV_CC_DEVICE_INFO));//IP索引到指定相机句柄的信息

    if (null == m_MyCamera) //判断之前创建的全局相机对象是否创建成功
    {
        m_MyCamera = new MyCamera();
        if (null == m_MyCamera)
        {
            return;
        }
    }

    int nRet = m_MyCamera.MV_CC_CreateDevice_NET(ref device);//指定对象管理哪一个相机
    if (MyCamera.MV_OK != nRet)
    {
        return;
    }

    nRet = m_MyCamera.MV_CC_OpenDevice_NET();//打开对象管理的相机
    if (MyCamera.MV_OK != nRet)
    {
        m_MyCamera.MV_CC_DestroyDevice_NET();
        return;
    }

    // ch:探测网络最佳包大小(只对GigE相机有效) 
    /*这里介绍一下相关方法 当我们要获取或者设置相机对象参数的时候注意查看使用手册中对应的参数信息 
       1  目标参数是什么数据类型
       2  调用对应的获取整形,浮点型的方法通过参数名获取
       后面详细介绍
      
     
     */
    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)
            {
            }
        }
        else
        {
        }
    }
   
    // ch:设置采集连续模式 
    m_MyCamera.MV_CC_SetEnumValue_NET("AcquisitionMode", (uint)MyCamera.MV_CAM_ACQUISITION_MODE.MV_ACQ_MODE_CONTINUOUS);//采集模式:单帧,多帧,连续

    m_MyCamera.MV_CC_SetEnumValue_NET("TriggerMode", (uint)MyCamera.MV_CAM_TRIGGER_MODE.MV_TRIGGER_MODE_OFF);//触发模式 0-关 1-开

    // ch:获取参数 
    MyCamera.MVCC_FLOATVALUE stParam = new MyCamera.MVCC_FLOATVALUE();
    nRet = m_MyCamera.MV_CC_GetFloatValue_NET("ExposureTime", ref stParam);//获取曝光时间
    if (MyCamera.MV_OK == nRet)
    {
       mapOfGigeCameras[deviceIp].ExposureTime = stParam.fCurValue;
    }

    nRet = m_MyCamera.MV_CC_GetFloatValue_NET("Gain", ref stParam);//获取相机增益
    if (MyCamera.MV_OK == nRet)
    {
        mapOfGigeCameras[deviceIp].Gain = stParam.fCurValue;
    }

    nRet = m_MyCamera.MV_CC_GetFloatValue_NET("ResultingFrameRate", ref stParam);//采集帧率
    if (MyCamera.MV_OK == nRet)
    {
        mapOfGigeCameras[deviceIp].ResultingFrameRate = stParam.fCurValue;
    }
    
}

3.3. 拍照

3.3.1 拍照流程

          1 采集图像

          2 取流抓图

          3 保存图片

          4 释放流数据

3.3.2 相关方法与数据类型

MV_FRAME_OUT在使用手册中并没有找到但是在VS中反编译中有源码,其中pBufAddr是帧输出结果在内存中的地址

3.3.3 相关操作
public void CaptureFile(Process proc) //Process为委托数据类型 之前在全局代码中生命
{
    this.callback = proc;
    m_bGrabbing = true;

    m_hReceiveThread = new Thread(ReceiveThreadProcess);
    m_hReceiveThread.Start();

    m_stFrameInfo.nFrameLen = 0;//取流之前先清除帧长度
    m_stFrameInfo.enPixelType = MyCamera.MvGvspPixelType.PixelType_Gvsp_Undefined;
    // ch:开始采集 
    int nRet = m_MyCamera.MV_CC_StartGrabbing_NET();
    if (MyCamera.MV_OK != nRet)
    {
        m_bGrabbing = false;
        m_hReceiveThread.Join();

        return;
    }
}
public void ReceiveThreadProcess()
{
    MyCamera.MV_FRAME_OUT stFrameInfo = new MyCamera.MV_FRAME_OUT();//定义输出的帧信息结构体
    MyCamera.MV_DISPLAY_FRAME_INFO stDisplayInfo = new MyCamera.MV_DISPLAY_FRAME_INFO();
    int nRet = MyCamera.MV_OK;
    while (m_bGrabbing)
    {
        nRet = m_MyCamera.MV_CC_GetImageBuffer_NET(ref stFrameInfo, 1000);//获取一帧图片 并将图片信息保留在stFrameInfo中,超时时间设置为1秒 加的这一秒就是等待上一个线程采集完毕
        if (nRet == MyCamera.MV_OK)
        {
            lock (BufForDriverLock) //同步互斥操作
            {
                if (m_BufForDriver == IntPtr.Zero || stFrameInfo.stFrameInfo.nFrameLen > m_nBufSizeForDriver) //帧长度大于0
                {
                    if (m_BufForDriver != IntPtr.Zero)
                    {
                        Marshal.Release(m_BufForDriver);
                        m_BufForDriver = IntPtr.Zero;
                    }

                    m_BufForDriver = Marshal.AllocHGlobal((Int32)stFrameInfo.stFrameInfo.nFrameLen);//申请数据流大小的内存
                    if (m_BufForDriver == IntPtr.Zero)//申请失败
                    {
                        return;
                    }
                    m_nBufSizeForDriver = stFrameInfo.stFrameInfo.nFrameLen;//帧长度赋值
                }

                m_stFrameInfo = stFrameInfo.stFrameInfo;//帧信息
                CopyMemory(m_BufForDriver, stFrameInfo.pBufAddr, stFrameInfo.stFrameInfo.nFrameLen);//到内存指定的地址去获取帧数据
            }

            if (RemoveCustomPixelFormats(stFrameInfo.stFrameInfo.enPixelType))
            {
                m_MyCamera.MV_CC_FreeImageBuffer_NET(ref stFrameInfo);
                continue;
            }
            stDisplayInfo.hWnd = hWnd_pictureBox;
            stDisplayInfo.pData = stFrameInfo.pBufAddr;
            stDisplayInfo.nDataLen = stFrameInfo.stFrameInfo.nFrameLen;
            stDisplayInfo.nWidth = stFrameInfo.stFrameInfo.nWidth;
            stDisplayInfo.nHeight = stFrameInfo.stFrameInfo.nHeight;
            stDisplayInfo.enPixelType = stFrameInfo.stFrameInfo.enPixelType;//像素格式
            if (isDisplayOnPictureBox)//初始化完成之后
            {
                m_MyCamera.MV_CC_DisplayOneFrame_NET(ref stDisplayInfo);//显示一帧图像 将这帧图像的信息保存在变量中
            }                 

            Mat dst1 = new Mat(stDisplayInfo.nHeight, stDisplayInfo.nWidth,MatType.CV_8UC3, m_BufForDriver);
            callback(dst1);  //回调函数对图像进行相应的处理操作
           
            m_MyCamera.MV_CC_FreeImageBuffer_NET(ref stFrameInfo);
        }
        else
        {
            if (currentCameraInfor.isOpenTriggerMode)
            {
                Thread.Sleep(5);
            }
        }
    }
}
//去除自定义的像素格式
private bool RemoveCustomPixelFormats(MyCamera.MvGvspPixelType enPixelFormat)
{
    Int32 nResult = ((int)enPixelFormat) & (unchecked((Int32)0x80000000));
    if (0x80000000 == nResult) //错误或者无效句柄
    {
        return true;
    }
    else
    {
        return false;
    }
}

public void SaveJPG(string path)
{
MyCamera.MV_SAVE_IMG_TO_FILE_PARAM stSaveFileParam = new MyCamera.MV_SAVE_IMG_TO_FILE_PARAM();

    if (m_stFrameInfo.nFrameLen == 0)
    {
        return;
    }
    stSaveFileParam.enImageType = MyCamera.MV_SAVE_IAMGE_TYPE.MV_Image_Jpeg;
    stSaveFileParam.enPixelType = m_stFrameInfo.enPixelType;
    stSaveFileParam.pData = m_BufForDriver;
    stSaveFileParam.nDataLen = m_stFrameInfo.nFrameLen;
    stSaveFileParam.nHeight = m_stFrameInfo.nHeight;
    stSaveFileParam.nWidth = m_stFrameInfo.nWidth;
    stSaveFileParam.nQuality = 80;
    stSaveFileParam.iMethodValue = 2;
    if (string.IsNullOrEmpty(path))
        stSaveFileParam.pImagePath = System.Environment.CurrentDirectory + "\\Image\\" + picSavePath + "Image_w" + stSaveFileParam.nWidth.ToString() + "_h" + stSaveFileParam.nHeight.ToString() + "_fn" + m_stFrameInfo.nFrameNum.ToString() + ".jpg";
    else
    {
        stSaveFileParam.pImagePath = path;
    }
    int nRet = m_MyCamera.MV_CC_SaveImageToFile_NET(ref stSaveFileParam);

    //Mat dst1 = new Mat(stSaveFileParam.nHeight, stSaveFileParam.nWidth,MatType.CV_8UC3, m_BufForDriver);
    //dst1.SaveImage("D:\\111.jpg");

    if (MyCamera.MV_OK != nRet)
    {
        return;
    }
}

4 关闭相机

public void CloseDevice()
{
    // ch:取流标志位清零 
   

    if (m_BufForDriver != IntPtr.Zero) //如果用于存储流数据的内存不为空则清空
    {
        Marshal.Release(m_BufForDriver);
    }
    // ch:关闭设备 
    m_MyCamera.MV_CC_CloseDevice_NET();
    m_MyCamera.MV_CC_DestroyDevice_NET();
}

5 完整相机模块 里面还有其他模块的数据类型声明但是本博客不在扩展

using System;
using System.Collections.Generic;

using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using MvCamCtrl;
using MvCamCtrl.NET;
using OpenCvSharp;

namespace GH
{
    public class HKCameraHelper
    {
        [DllImport("kernel32.dll", EntryPoint = "CopyMemory", SetLastError = false)] //非重叠区域的拷贝CopyMemory 完全拷贝MoveMemory
        public static extern void CopyMemory(IntPtr dest, IntPtr src, uint count); //复制内存块的目的地址,复制内存块的源地址 复制大小(单位字节)
        /// <summary>
        /// 枚举出来的子网信息,都在相机结构体 MV_CC_DEVICE_INFO_LIST 里面
        /// </summary>
        MyCamera.MV_CC_DEVICE_INFO_LIST m_stDeviceList = new MyCamera.MV_CC_DEVICE_INFO_LIST();
        private MyCamera m_MyCamera = new MyCamera();
        bool m_bGrabbing = false;
        Thread m_hReceiveThread = null;
        MyCamera.MV_FRAME_OUT_INFO_EX m_stFrameInfo = new MyCamera.MV_FRAME_OUT_INFO_EX();

        // ch:用于从驱动获取图像的缓存 | en:Buffer for getting image from driver
        UInt32 m_nBufSizeForDriver = 0;
        IntPtr m_BufForDriver = IntPtr.Zero;
        private static Object BufForDriverLock = new Object();
        //枚举所有相机设备列表
        public static Dictionary<string, CameraInfor> mapOfCameraDevice = new Dictionary<string, CameraInfor>();
        //保存获取的当前相机
        private CameraInfor currentCameraInfor;
        public string picSavePath { get; set; }
        public IntPtr hWnd_pictureBox { get; set; }
        public ASCameraParamInfor aSCameraParamInfor { get; set; }   //相机参数
        //回调函数声明
        public delegate void ProcessBussess(Mat src);
        public ProcessBussess callback;

        public bool isDisplayOnPictureBox { get; set; }
        //获取相机设备列表
        public void DeviceListAcq()
        {
            // ch:创建设备列表 | en:Create Device List
            System.GC.Collect();
            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)
            {
                return;
            }
            mapOfCameraDevice.Clear(); //清空设备列表
            CameraInfor cameraInfor ;
            // ch:在窗体列表中显示设备名 | en:Display device name in the form list
            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));
                cameraInfor = new CameraInfor();
                cameraInfor.pDeviceInfo = m_stDeviceList.pDeviceInfo[i];
                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));

                    UInt32 nNetIp1 = (gigeInfo.nNetExport & 0xFF000000) >> 24;
                    UInt32 nNetIp2 = (gigeInfo.nNetExport & 0x00FF0000) >> 16;
                    UInt32 nNetIp3 = (gigeInfo.nNetExport & 0x0000FF00) >> 8;
                    UInt32 nNetIp4 = (gigeInfo.nNetExport & 0x000000FF);

                    // ch:显示IP | en:Display IP
                    UInt32 nIp1 = (gigeInfo.nCurrentIp & 0xFF000000) >> 24;
                    UInt32 nIp2 = (gigeInfo.nCurrentIp & 0x00FF0000) >> 16;
                    UInt32 nIp3 = (gigeInfo.nCurrentIp & 0x0000FF00) >> 8;
                    UInt32 nIp4 = (gigeInfo.nCurrentIp & 0x000000FF);

                    
                    cameraInfor.serialNumber = gigeInfo.chSerialNumber;
                    cameraInfor.userDefinedName = gigeInfo.chUserDefinedName;
                    cameraInfor.manufacturerName = gigeInfo.chManufacturerName;
                    cameraInfor.modelName = gigeInfo.chModelName;
                    cameraInfor.deviceType = "GEV"; //千兆网工业相机技术之GigE Vision(GEV)
                    cameraInfor.deviceIPAdd = nIp1.ToString() + "." + nIp2.ToString() + "." + nIp3.ToString() + "." + nIp4.ToString();
                    mapOfCameraDevice.Add(cameraInfor.deviceIPAdd, cameraInfor);
                }
                else if (device.nTLayerType == MyCamera.MV_USB_DEVICE)
                {
                    MyCamera.MV_USB3_DEVICE_INFO usbInfo = (MyCamera.MV_USB3_DEVICE_INFO)MyCamera.ByteToStruct(device.SpecialInfo.stUsb3VInfo, typeof(MyCamera.MV_USB3_DEVICE_INFO));
                    cameraInfor.serialNumber = usbInfo.chSerialNumber;
                    cameraInfor.userDefinedName = usbInfo.chUserDefinedName;
                    cameraInfor.manufacturerName = usbInfo.chManufacturerName;
                    cameraInfor.modelName = usbInfo.chModelName;
                    cameraInfor.deviceType = "U3V";
                    mapOfCameraDevice.Add(cameraInfor.deviceIPAdd, cameraInfor);
                }
            }
        }
        //打开相机
        public void OpenDeviceByIPAdd(string deviceIpAdd)
        {
            if (m_stDeviceList.nDeviceNum == 0 || deviceIpAdd=="")
            {
                return;
            }
            currentCameraInfor = mapOfCameraDevice[deviceIpAdd];
            // ch:获取选择的设备信息 | en:Get selected device information
            MyCamera.MV_CC_DEVICE_INFO device =(MyCamera.MV_CC_DEVICE_INFO)Marshal.PtrToStructure(mapOfCameraDevice[deviceIpAdd].pDeviceInfo,
                                                              typeof(MyCamera.MV_CC_DEVICE_INFO));

            // ch:打开设备 | en:Open device
            if (null == m_MyCamera)
            {
                m_MyCamera = new MyCamera();
                if (null == m_MyCamera)
                {
                    return;
                }
            }

            int nRet = m_MyCamera.MV_CC_CreateDevice_NET(ref device);
            if (MyCamera.MV_OK != nRet)
            {
                return;
            }

            nRet = m_MyCamera.MV_CC_OpenDevice_NET();
            if (MyCamera.MV_OK != nRet)
            {
                m_MyCamera.MV_CC_DestroyDevice_NET();
                return;
            }

            // ch:探测网络最佳包大小(只对GigE相机有效) | en:Detection network optimal package size(It only works for the GigE camera)
            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)
                    {
                    }
                }
                else
                {
                }
            }
            // ch:设置采集连续模式 | en:Set Continues Aquisition Mode
            m_MyCamera.MV_CC_SetEnumValue_NET("AcquisitionMode", (uint)MyCamera.MV_CAM_ACQUISITION_MODE.MV_ACQ_MODE_CONTINUOUS);
            m_MyCamera.MV_CC_SetEnumValue_NET("TriggerMode", (uint)MyCamera.MV_CAM_TRIGGER_MODE.MV_TRIGGER_MODE_OFF);

            // ch:获取参数 | en:Get parameters
            MyCamera.MVCC_FLOATVALUE stParam = new MyCamera.MVCC_FLOATVALUE();
            nRet = m_MyCamera.MV_CC_GetFloatValue_NET("ExposureTime", ref stParam);
            if (MyCamera.MV_OK == nRet)
            {
                mapOfCameraDevice[deviceIpAdd].ExposureTime = stParam.fCurValue;
            }

            nRet = m_MyCamera.MV_CC_GetFloatValue_NET("Gain", ref stParam);
            if (MyCamera.MV_OK == nRet)
            {
                mapOfCameraDevice[deviceIpAdd].Gain = stParam.fCurValue;
            }

            nRet = m_MyCamera.MV_CC_GetFloatValue_NET("ResultingFrameRate", ref stParam);
            if (MyCamera.MV_OK == nRet)
            {
                mapOfCameraDevice[deviceIpAdd].ResultingFrameRate = stParam.fCurValue;
            }
            // ch:控件操作 | en:Control operation
        }
        //关闭设备
        public void CloseDevice()
        {
            // ch:取流标志位清零 | en:Reset flow flag bit
            if (m_bGrabbing == true)
            {
                m_bGrabbing = false;
                m_hReceiveThread.Join();
            }

            if (m_BufForDriver != IntPtr.Zero)
            {
                Marshal.Release(m_BufForDriver);
            }
            // ch:关闭设备 | en:Close Device
            m_MyCamera.MV_CC_CloseDevice_NET();
            m_MyCamera.MV_CC_DestroyDevice_NET();
        }
        //设置为连续模式,关闭触发方式
        public void SetContinuesMode()
        {
            m_MyCamera.MV_CC_SetEnumValue_NET("TriggerMode", (uint)MyCamera.MV_CAM_TRIGGER_MODE.MV_TRIGGER_MODE_OFF);
            currentCameraInfor.isOpenTriggerMode = false;
        }
        public void OpenTiggerMode()
        {
            m_MyCamera.MV_CC_SetEnumValue_NET("TriggerMode", (uint)MyCamera.MV_CAM_TRIGGER_MODE.MV_TRIGGER_MODE_ON);
            currentCameraInfor.isOpenTriggerMode = true;
        }

        public void SetTiggerMode(int tiggerMode)
        {
            m_MyCamera.MV_CC_SetEnumValue_NET("TriggerMode", (uint)MyCamera.MV_CAM_TRIGGER_MODE.MV_TRIGGER_MODE_ON);
            currentCameraInfor.isOpenTriggerMode = true;
            // ch:触发源选择:0 - Line0; | en:Trigger source select:0 - Line0;
            //           1 - Line1;
            //           2 - Line2;
            //           3 - Line3;
            //           4 - Counter;
            //           7 - Software;
            m_MyCamera.MV_CC_SetEnumValue_NET("TriggerSource",(uint) tiggerMode);
        }

        public void CaptureFile(ProcessBussess proc)
        {
            this.callback = proc;
            m_bGrabbing = true;

            m_hReceiveThread = new Thread(ReceiveThreadProcess);
            m_hReceiveThread.Start();

            m_stFrameInfo.nFrameLen = 0;//取流之前先清除帧长度
            m_stFrameInfo.enPixelType = MyCamera.MvGvspPixelType.PixelType_Gvsp_Undefined;
            // ch:开始采集 | en:Start Grabbing
            int nRet = m_MyCamera.MV_CC_StartGrabbing_NET();
            if (MyCamera.MV_OK != nRet)
            {
                m_bGrabbing = false;
                m_hReceiveThread.Join();

                return;
            }
        }
        
        public void ReceiveThreadProcess()
        {
            MyCamera.MV_FRAME_OUT stFrameInfo = new MyCamera.MV_FRAME_OUT();
            MyCamera.MV_DISPLAY_FRAME_INFO stDisplayInfo = new MyCamera.MV_DISPLAY_FRAME_INFO();
            int nRet = MyCamera.MV_OK;
            while (m_bGrabbing)
            {
                nRet = m_MyCamera.MV_CC_GetImageBuffer_NET(ref stFrameInfo, 1000);//获取一帧图片 并将图片信息保留在stFrameInfo中,超时时间设置为1秒 加的这一秒就是等待上一个线程抓取完毕
                if (nRet == MyCamera.MV_OK)
                {
                    lock (BufForDriverLock) //同步互斥操作
                    {
                        if (m_BufForDriver == IntPtr.Zero || stFrameInfo.stFrameInfo.nFrameLen > m_nBufSizeForDriver) //帧长度大于0
                        {
                            if (m_BufForDriver != IntPtr.Zero)
                            {
                                Marshal.Release(m_BufForDriver);
                                m_BufForDriver = IntPtr.Zero;
                            }

                            m_BufForDriver = Marshal.AllocHGlobal((Int32)stFrameInfo.stFrameInfo.nFrameLen);
                            if (m_BufForDriver == IntPtr.Zero)
                            {
                                return;
                            }
                            m_nBufSizeForDriver = stFrameInfo.stFrameInfo.nFrameLen;
                        }

                        m_stFrameInfo = stFrameInfo.stFrameInfo;
                        CopyMemory(m_BufForDriver, stFrameInfo.pBufAddr, stFrameInfo.stFrameInfo.nFrameLen);
                    }

                    if (RemoveCustomPixelFormats(stFrameInfo.stFrameInfo.enPixelType))
                    {
                        m_MyCamera.MV_CC_FreeImageBuffer_NET(ref stFrameInfo);
                        continue;
                    }
                    stDisplayInfo.hWnd = hWnd_pictureBox;
                    stDisplayInfo.pData = stFrameInfo.pBufAddr;
                    stDisplayInfo.nDataLen = stFrameInfo.stFrameInfo.nFrameLen;
                    stDisplayInfo.nWidth = stFrameInfo.stFrameInfo.nWidth;
                    stDisplayInfo.nHeight = stFrameInfo.stFrameInfo.nHeight;
                    stDisplayInfo.enPixelType = stFrameInfo.stFrameInfo.enPixelType;//像素格式
                    if (isDisplayOnPictureBox)//初始化完成之后
                    {
                        m_MyCamera.MV_CC_DisplayOneFrame_NET(ref stDisplayInfo);//显示一帧图像 将这帧图像的信息保存在变量中
                    }                 

                    Mat dst1 = new Mat(stDisplayInfo.nHeight, stDisplayInfo.nWidth,MatType.CV_8UC3, m_BufForDriver);
                    callback(dst1);  //回调函数 识别
                    /*Rect rectangle = new Rect(20, 20, 300, 300);
                    Cv2.Rectangle(dst1, rectangle, new Scalar(0, 0, 255), 2, LineTypes.AntiAlias);
                    //dst1.SaveImage("D:\\333.jpg");
                    */
                    m_MyCamera.MV_CC_FreeImageBuffer_NET(ref stFrameInfo);
                }
                else
                {
                    if (currentCameraInfor.isOpenTriggerMode)
                    {
                        Thread.Sleep(5);
                    }
                }
            }
        }
        // ch:去除自定义的像素格式 | en:Remove custom pixel formats
        private bool RemoveCustomPixelFormats(MyCamera.MvGvspPixelType enPixelFormat)
        {
            Int32 nResult = ((int)enPixelFormat) & (unchecked((Int32)0x80000000));
            if (0x80000000 == nResult)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        public bool SetCameraParam()
        {
            m_MyCamera.MV_CC_SetEnumValue_NET("ExposureAuto", 0);
            int nRet = m_MyCamera.MV_CC_SetFloatValue_NET("ExposureTime", aSCameraParamInfor.ExposureTime);
            if (nRet != MyCamera.MV_OK)
            {
                return false;
            }

            m_MyCamera.MV_CC_SetEnumValue_NET("GainAuto", 0);
            nRet = m_MyCamera.MV_CC_SetFloatValue_NET("Gain", aSCameraParamInfor.Gain);
            if (nRet != MyCamera.MV_OK)
            {
                return false;
            }

            nRet = m_MyCamera.MV_CC_SetFloatValue_NET("AcquisitionFrameRate", aSCameraParamInfor.FrameRate);
            if (nRet != MyCamera.MV_OK)
            {
                return false;
            }
            return true;
        }

        public void SavePNG()
        {
            if (false == m_bGrabbing)
            {
                return;
            }

            if (RemoveCustomPixelFormats(m_stFrameInfo.enPixelType))
            {
                return;
            }

            MyCamera.MV_SAVE_IMG_TO_FILE_PARAM stSaveFileParam = new MyCamera.MV_SAVE_IMG_TO_FILE_PARAM();
            lock (BufForDriverLock)
            {
                if (m_stFrameInfo.nFrameLen == 0)
                {
                    return;
                }
                stSaveFileParam.enImageType = MyCamera.MV_SAVE_IAMGE_TYPE.MV_Image_Png;
                stSaveFileParam.enPixelType = m_stFrameInfo.enPixelType;
                stSaveFileParam.pData = m_BufForDriver;
                stSaveFileParam.nDataLen = m_stFrameInfo.nFrameLen;
                stSaveFileParam.nHeight = m_stFrameInfo.nHeight;
                stSaveFileParam.nWidth = m_stFrameInfo.nWidth;
                stSaveFileParam.nQuality = 8;
                stSaveFileParam.iMethodValue = 2;
                if (picSavePath == "")
                {
                    picSavePath = System.Environment.CurrentDirectory + "\\Image\\";
                }
                stSaveFileParam.pImagePath = picSavePath  + "Image_w" + stSaveFileParam.nWidth.ToString() + "_h" + stSaveFileParam.nHeight.ToString() + "_fn" + m_stFrameInfo.nFrameNum.ToString() + ".png";
                int nRet = m_MyCamera.MV_CC_SaveImageToFile_NET(ref stSaveFileParam);
                if (MyCamera.MV_OK != nRet)
                {
                    return;
                }
            }
        }

        public void SaveTiff()
        {
            if (false == m_bGrabbing)
            {
                return;
            }

            if (RemoveCustomPixelFormats(m_stFrameInfo.enPixelType))
            {
                return;
            }

            MyCamera.MV_SAVE_IMG_TO_FILE_PARAM stSaveFileParam = new MyCamera.MV_SAVE_IMG_TO_FILE_PARAM();

            lock (BufForDriverLock)
            {
                if (m_stFrameInfo.nFrameLen == 0)
                {
                    return;
                }
                stSaveFileParam.enImageType = MyCamera.MV_SAVE_IAMGE_TYPE.MV_Image_Tif;
                stSaveFileParam.enPixelType = m_stFrameInfo.enPixelType;
                stSaveFileParam.pData = m_BufForDriver;
                stSaveFileParam.nDataLen = m_stFrameInfo.nFrameLen;
                stSaveFileParam.nHeight = m_stFrameInfo.nHeight;
                stSaveFileParam.nWidth = m_stFrameInfo.nWidth;
                stSaveFileParam.iMethodValue = 2;
                if (picSavePath == "")
                {
                    picSavePath = System.Environment.CurrentDirectory + "\\Image\\";
                }
                stSaveFileParam.pImagePath = picSavePath + "Image_w" + stSaveFileParam.nWidth.ToString() + "_h" + stSaveFileParam.nHeight.ToString() + "_fn" + m_stFrameInfo.nFrameNum.ToString() + ".tif";
                int nRet = m_MyCamera.MV_CC_SaveImageToFile_NET(ref stSaveFileParam);
                if (MyCamera.MV_OK != nRet)
                {
                    return;
                }
            }
        }

        public void SaveBMP()
        {
            if (false == m_bGrabbing)
            {
                return;
            }

            if (RemoveCustomPixelFormats(m_stFrameInfo.enPixelType))
            {
                return;
            }

            MyCamera.MV_SAVE_IMG_TO_FILE_PARAM stSaveFileParam = new MyCamera.MV_SAVE_IMG_TO_FILE_PARAM();

            lock (BufForDriverLock)
            {
                if (m_stFrameInfo.nFrameLen == 0)
                {
                    return;
                }
                stSaveFileParam.enImageType = MyCamera.MV_SAVE_IAMGE_TYPE.MV_Image_Bmp;
                stSaveFileParam.enPixelType = m_stFrameInfo.enPixelType;
                stSaveFileParam.pData = m_BufForDriver;
                stSaveFileParam.nDataLen = m_stFrameInfo.nFrameLen;
                stSaveFileParam.nHeight = m_stFrameInfo.nHeight;
                stSaveFileParam.nWidth = m_stFrameInfo.nWidth;
                stSaveFileParam.iMethodValue = 2;
                if (picSavePath == "")
                {
                    picSavePath = System.Environment.CurrentDirectory + "\\Image\\";
                }
                stSaveFileParam.pImagePath = picSavePath + "Image_w" + stSaveFileParam.nWidth.ToString() + "_h" + stSaveFileParam.nHeight.ToString() + "_fn" + m_stFrameInfo.nFrameNum.ToString() + ".bmp";
                int nRet = m_MyCamera.MV_CC_SaveImageToFile_NET(ref stSaveFileParam);
                if (MyCamera.MV_OK != nRet)
                {
                    return;
                }
            }
        }
        public void SaveJPG(string path)
        {
            //if (false == m_bGrabbing)
            //{
            //    return;
            //}
            //if (RemoveCustomPixelFormats(m_stFrameInfo.enPixelType))
            //{
            //    return;
            //}
            //MyCamera.MV_SAVE_IMG_TO_FILE_PARAM stSaveFileParam = new MyCamera.MV_SAVE_IMG_TO_FILE_PARAM();
            //lock (BufForDriverLock)
            //{
            //    if (m_stFrameInfo.nFrameLen == 0)
            //    {
            //        return;
            //    }
            //    stSaveFileParam.enImageType = MyCamera.MV_SAVE_IAMGE_TYPE.MV_Image_Jpeg;
            //    stSaveFileParam.enPixelType = m_stFrameInfo.enPixelType;
            //    stSaveFileParam.pData = m_BufForDriver;
            //    stSaveFileParam.nDataLen = m_stFrameInfo.nFrameLen;
            //    stSaveFileParam.nHeight = m_stFrameInfo.nHeight;
            //    stSaveFileParam.nWidth = m_stFrameInfo.nWidth;
            //    stSaveFileParam.nQuality = 80;
            //    stSaveFileParam.iMethodValue = 2;
            //    if (picSavePath == "" || picSavePath==null)
            //    {
            //        picSavePath = System.Environment.CurrentDirectory + "\\Image\\";
            //    }
            //    stSaveFileParam.pImagePath = picSavePath + "Image_w" + stSaveFileParam.nWidth.ToString() + "_h" + stSaveFileParam.nHeight.ToString() + "_fn" + m_stFrameInfo.nFrameNum.ToString() + ".jpg";
            //    int nRet = m_MyCamera.MV_CC_SaveImageToFile_NET(ref stSaveFileParam);

            //    //Mat dst1 = new Mat(stSaveFileParam.nHeight, stSaveFileParam.nWidth,MatType.CV_8UC3, m_BufForDriver);
            //    //dst1.SaveImage("D:\\111.jpg");

            //    if (MyCamera.MV_OK != nRet)
            //    {
            //        return;
            //    }
            //}


            if (false == m_bGrabbing)
            {
                return;
            }
            if (RemoveCustomPixelFormats(m_stFrameInfo.enPixelType))
            {
                return;
            }
            MyCamera.MV_SAVE_IMG_TO_FILE_PARAM stSaveFileParam = new MyCamera.MV_SAVE_IMG_TO_FILE_PARAM();
            lock (BufForDriverLock)
            {
                if (m_stFrameInfo.nFrameLen == 0)
                {
                    return;
                }
                stSaveFileParam.enImageType = MyCamera.MV_SAVE_IAMGE_TYPE.MV_Image_Jpeg;
                stSaveFileParam.enPixelType = m_stFrameInfo.enPixelType;
                stSaveFileParam.pData = m_BufForDriver;
                stSaveFileParam.nDataLen = m_stFrameInfo.nFrameLen;
                stSaveFileParam.nHeight = m_stFrameInfo.nHeight;
                stSaveFileParam.nWidth = m_stFrameInfo.nWidth;
                stSaveFileParam.nQuality = 80;
                stSaveFileParam.iMethodValue = 2;
                if (string.IsNullOrEmpty(path))
                    stSaveFileParam.pImagePath = System.Environment.CurrentDirectory + "\\Image\\" + picSavePath + "Image_w" + stSaveFileParam.nWidth.ToString() + "_h" + stSaveFileParam.nHeight.ToString() + "_fn" + m_stFrameInfo.nFrameNum.ToString() + ".jpg";
                else
                {
                    stSaveFileParam.pImagePath = path;
                }
                int nRet = m_MyCamera.MV_CC_SaveImageToFile_NET(ref stSaveFileParam);

                //Mat dst1 = new Mat(stSaveFileParam.nHeight, stSaveFileParam.nWidth,MatType.CV_8UC3, m_BufForDriver);
                //dst1.SaveImage("D:\\111.jpg");

                if (MyCamera.MV_OK != nRet)
                {
                    return;
                }
            }
        }
        static 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;
            }
        }
    }
}

  • 24
    点赞
  • 63
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在 C# 中使用海康相机 SDK 取图,您需要先安装海康相机 SDK 并在 C# 项目中添加对 SDK 的引用。然后,您可以使用 SDK 中的函数来初始化相机、设置相机参数、取图等操作。 以下是一个示例代码,演示如何使用海康相机 SDKC# 中取图: ```csharp using System; using System.Drawing; using System.Windows.Forms; using HCNetSDK; namespace CameraDemo { public partial class Form1 : Form { private CHCNetSDK.NET_DVR_DEVICEINFO_V30 m_deviceInfo; // 设备信息 private int m_cameraHandle; // 相机句柄 private CHCNetSDK.NET_DVR_IPPARACFG_V40 m_ipParaCfg; // IP参数配置 public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { // 初始化 SDK CHCNetSDK.NET_DVR_Init(); // 登录设备 m_deviceInfo = new CHCNetSDK.NET_DVR_DEVICEINFO_V30(); m_cameraHandle = CHCNetSDK.NET_DVR_Login_V30("192.168.1.100", 8000, "admin", "password", ref m_deviceInfo); // 设置 IP 参数 m_ipParaCfg = new CHCNetSDK.NET_DVR_IPPARACFG_V40(); uint dwBytesReturned = 0; IntPtr lpInBuffer = IntPtr.Zero; uint dwInBufferSize = 0; bool bSuccess = CHCNetSDK.NET_DVR_GetDVRConfig(m_cameraHandle, CHCNetSDK.NET_DVR_GET_IPPARACFG_V40, -1, lpInBuffer, dwInBufferSize, out dwBytesReturned); if (bSuccess) { lpInBuffer = Marshal.AllocHGlobal((Int32)dwBytesReturned); dwInBufferSize = dwBytesReturned; bSuccess = CHCNetSDK.NET_DVR_GetDVRConfig(m_cameraHandle, CHCNetSDK.NET_DVR_GET_IPPARACFG_V40, -1, lpInBuffer, dwInBufferSize, out dwBytesReturned); if (bSuccess) { m_ipParaCfg = (CHCNetSDK.NET_DVR_IPPARACFG_V40)Marshal.PtrToStructure(lpInBuffer, typeof(CHCNetSDK.NET_DVR_IPPARACFG_V40)); } Marshal.FreeHGlobal(lpInBuffer); } } private void Form1_FormClosing(object sender, FormClosingEventArgs e) { // 注销登录 CHCNetSDK.NET_DVR_Logout(m_cameraHandle); // 释放 SDK 资源 CHCNetSDK.NET_DVR_Cleanup(); } private void btnCapture_Click(object sender, EventArgs e) { // 设置为抓图模式 CHCNetSDK.NET_DVR_SetCapturePictureMode(0); // 抓图并保存到文件 string fileName = "capture.jpg"; bool bSuccess = CHCNetSDK.NET_DVR_CapturePicture(m_cameraHandle, fileName); if (bSuccess) { // 加载图像并显示 Image image = Image.FromFile(fileName); pictureBox1.Image = image; } } } } ``` 在这个示例中,我们在 `Form1_Load` 事件中初始化了 SDK,并登录了设备。然后,我们使用 `NET_DVR_GetDVRConfig` 函数获取了设备的 IP 参数配置。在 `btnCapture_Click` 事件中,我们设置了抓图模式,并使用 `NET_DVR_CapturePicture` 函数抓取图像并保存到文件。最后,我们加载图像并显示在 `pictureBox1` 控件中。 请注意,这只是一个简单的示例代码,实际情况可能更加复杂。在实际开发中,您可能需要根据具体需求配置相机参数、处理图像等操作。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值