c# winform 调用 海康威视工业相机(又全又细又简洁)

发布于:2025-08-07 ⋅ 阅读:(20) ⋅ 点赞:(0)

1.准备一个海康相机

从垃圾桶里翻出来一个USB口相机。

2.下载MVS 和SDK

海康机器人-机器视觉-下载中心

mvs:

sdk:

用MVS 调试一下,能连接就行。

海康威视相机,MVS连接成功,但无图像怎么办?-CSDN博客

3.打开VS,创建一个新项目

添加引用,点击浏览,找到  MvCameraControl.Net.dll。

MvCameraControl.Net.dll文件,在MVS的安装目录,路径:MVS\MVS\Development\DotNet

注意根据c#

选择win32 win64 还是anycpu。

在form1.cs中using MvCamCtrl.NET;

然后添加一些控件

定义枚举相机函数,把他放到 “寻找相机”事件中

然后,把枚举的相机 都写入 下拉框。

此阶段代码如下:

form1.cs

using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using MvCamCtrl.NET;


namespace test_HKCamera
{
    public partial class Form1 : Form
    {
        MyCamera device = new MyCamera();
        public static MyCamera.MV_CC_DEVICE_INFO_LIST stDevList = new MyCamera.MV_CC_DEVICE_INFO_LIST();
        
        public Form1()
        {
            InitializeComponent();
        }

        public List<string> ListDevices()//枚举相机
        {
            List<string> result = new List<string>();

            /**/
            if (MyCamera.MV_OK != MyCamera.MV_CC_EnumDevices_NET(MyCamera.MV_GIGE_DEVICE | MyCamera.MV_USB_DEVICE, ref stDevList))
            {
                MessageBox.Show("枚举设备失败");
                return null;
            }
            if (0 == stDevList.nDeviceNum)
            {
                //  MessageBox.Show("未找到设备");
                return null;
            }
            MyCamera.MV_CC_DEVICE_INFO stDevInfo;
            for (int i = 0; i < stDevList.nDeviceNum; i++)
            {

                stDevInfo = (MyCamera.MV_CC_DEVICE_INFO)Marshal.PtrToStructure(stDevList.pDeviceInfo[i], typeof(MyCamera.MV_CC_DEVICE_INFO));
                if (stDevInfo.nTLayerType == MyCamera.MV_GIGE_DEVICE)
                {
                    // 网口USB设备处理
                    IntPtr buffer = Marshal.UnsafeAddrOfPinnedArrayElement(stDevInfo.SpecialInfo.stGigEInfo, 0);
                    MyCamera.MV_GIGE_DEVICE_INFO gigeInfo = (MyCamera.MV_GIGE_DEVICE_INFO)Marshal.PtrToStructure(buffer, typeof(MyCamera.MV_GIGE_DEVICE_INFO));
                    result.Add(gigeInfo.chSerialNumber);
                }
                else if (stDevInfo.nTLayerType == MyCamera.MV_USB_DEVICE)
                {
                    // USB设备处理
                    IntPtr buffer = Marshal.UnsafeAddrOfPinnedArrayElement(stDevInfo.SpecialInfo.stUsb3VInfo, 0);
                    MyCamera.MV_USB3_DEVICE_INFO usbInfo = (MyCamera.MV_USB3_DEVICE_INFO)Marshal.PtrToStructure(
                        buffer,
                        typeof(MyCamera.MV_USB3_DEVICE_INFO)
                    );
                    result.Add(usbInfo.chSerialNumber);
                }


            }
            return result;
        }


        private void button_find_Click(object sender, EventArgs e)//寻找相机按钮
        {
            List<string> lstdevices = ListDevices();
            if (lstdevices == null)
            {
                MessageBox.Show("无相机");
            }
            else
            {
                MessageBox.Show("已找到设备");
                
                foreach (string device in lstdevices)
                {
                    comboBox1.Items.Add(device);//找到的设备写入下拉框

                }

            }

            
            comboBox1.Enabled = true;
        }

        private void button_takephoto_Click(object sender, EventArgs e)//拍照按钮
        {

        }
    }
}

form1.designer.cs

namespace test_HKCamera
{
    partial class Form1
    {
        /// <summary>
        ///  Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        ///  Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        ///  Required method for Designer support - do not modify
        ///  the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            button_find = new Button();
            comboBox1 = new ComboBox();
            button_takephoto = new Button();
            pictureBox1 = new PictureBox();
            ((System.ComponentModel.ISupportInitialize)pictureBox1).BeginInit();
            SuspendLayout();
            // 
            // button_find
            // 
            button_find.Location = new Point(248, 178);
            button_find.Name = "button_find";
            button_find.Size = new Size(227, 98);
            button_find.TabIndex = 0;
            button_find.Text = "寻找相机";
            button_find.UseVisualStyleBackColor = true;
            button_find.Click += button_find_Click;
            // 
            // comboBox1
            // 
            comboBox1.FormattingEnabled = true;
            comboBox1.Location = new Point(169, 437);
            comboBox1.Name = "comboBox1";
            comboBox1.Size = new Size(400, 32);
            comboBox1.TabIndex = 1;
            // 
            // button_takephoto
            // 
            button_takephoto.Location = new Point(235, 668);
            button_takephoto.Name = "button_takephoto";
            button_takephoto.Size = new Size(240, 92);
            button_takephoto.TabIndex = 2;
            button_takephoto.Text = "拍照";
            button_takephoto.UseVisualStyleBackColor = true;
            button_takephoto.Click += button_takephoto_Click;
            // 
            // pictureBox1
            // 
            pictureBox1.Location = new Point(698, 141);
            pictureBox1.Name = "pictureBox1";
            pictureBox1.Size = new Size(800, 600);
            pictureBox1.TabIndex = 3;
            pictureBox1.TabStop = false;
            // 
            // Form1
            // 
            AutoScaleDimensions = new SizeF(11F, 24F);
            AutoScaleMode = AutoScaleMode.Font;
            ClientSize = new Size(1597, 918);
            Controls.Add(pictureBox1);
            Controls.Add(button_takephoto);
            Controls.Add(comboBox1);
            Controls.Add(button_find);
            Name = "Form1";
            Text = "Form1";
            ((System.ComponentModel.ISupportInitialize)pictureBox1).EndInit();
            ResumeLayout(false);
        }

        #endregion

        private Button button_find;
        private ComboBox comboBox1;
        private Button button_takephoto;
        private PictureBox pictureBox1;
    }
}

运行

接下来完善拍照功能。

修改button_find_Click

遍历SDK返回的原始设备列表,保存设备信息到 _deviceList

                for (int i = 0; i < stDevList.nDeviceNum; i++)
                {
                    var devInfo = (MyCamera.MV_CC_DEVICE_INFO)Marshal.PtrToStructure(
                        stDevList.pDeviceInfo[i],
                        typeof(MyCamera.MV_CC_DEVICE_INFO)
                    );
                    _deviceList.Add(devInfo);     

增加 oneshot功能:

创建设备对象:实例化MyCamera对象,用于后续操作。

创建设备句柄:调用MV_CC_CreateDevice_NET,传入选中的设备信息,创建设备句柄。

打开设备:使用MV_CC_OpenDevice_NET以独占模式打开设备。

开始采集图像:调用MV_CC_StartGrabbing_NET启动图像采集。

获取图像参数:通过MV_CC_GetIntValue_NET获取PayloadSize,即图像数据的大小。

分配缓冲区:使用Marshal.AllocHGlobal分配非托管内存,用于存储图像数据。

获取单帧图像:调用MV_CC_GetOneFrameTimeout_NET,设置超时时间为1000毫秒,尝试获取一帧图像。

显示图像:如果成功获取图像数据,填充MV_DISPLAY_FRAME_INFO结构体,并调用MV_CC_DisplayOneFrame_NET显示图像。

释放资源:释放之前分配的非托管内存缓冲区。

finally块:确保在方法执行完毕后,无论是否发生异常,都会停止采集、关闭设备并销毁设备句柄

        public void OneShot(PictureBox pictureBox, MyCamera.MV_CC_DEVICE_INFO selectedDevice)
        {
            MyCamera device = new MyCamera();
            int nRet = MyCamera.MV_OK;

            try
            {
                // 直接使用传入的设备信息
                nRet = device.MV_CC_CreateDevice_NET(ref selectedDevice);
                if (nRet != MyCamera.MV_OK)
                {
                    MessageBox.Show($"创建设备失败: 0x{nRet:X8}");
                    return;
                }

                nRet = device.MV_CC_OpenDevice_NET(MyCamera.MV_ACCESS_Exclusive, 0);
                if (nRet != MyCamera.MV_OK)
                {
                    MessageBox.Show($"打开设备失败: 0x{nRet:X8}");
                    return;
                }

                nRet = device.MV_CC_StartGrabbing_NET();
                if (nRet != MyCamera.MV_OK)
                {
                    MessageBox.Show($"开始采集失败: 0x{nRet:X8}");
                    return;
                }

                // 获取图像参数
                MyCamera.MVCC_INTVALUE stParam = new MyCamera.MVCC_INTVALUE();
                nRet = device.MV_CC_GetIntValue_NET("PayloadSize", ref stParam);
                if (nRet != MyCamera.MV_OK)
                {
                    MessageBox.Show($"获取图像大小失败: 0x{nRet:X8}");
                    return;
                }

                // 分配缓冲区
                IntPtr pBuf = Marshal.AllocHGlobal((int)stParam.nCurValue);
                MyCamera.MV_FRAME_OUT_INFO_EX frameInfo = new MyCamera.MV_FRAME_OUT_INFO_EX();

                // 获取单帧图像
                nRet = device.MV_CC_GetOneFrameTimeout_NET(pBuf, stParam.nCurValue, ref frameInfo, 1000);
                if (nRet == MyCamera.MV_OK)
                {
                    // 显示图像
                    MyCamera.MV_DISPLAY_FRAME_INFO displayInfo = new MyCamera.MV_DISPLAY_FRAME_INFO
                    {
                        hWnd = pictureBox.Handle,
                        pData = pBuf,
                        nDataLen = frameInfo.nFrameLen,
                        nWidth = frameInfo.nWidth,
                        nHeight = frameInfo.nHeight,
                        enPixelType = frameInfo.enPixelType
                    };
                    device.MV_CC_DisplayOneFrame_NET(ref displayInfo);
                }
                else
                {
                    MessageBox.Show($"获取图像超时: 0x{nRet:X8}");
                }

                // 释放资源
                Marshal.FreeHGlobal(pBuf);
            }
            finally
            {
                // 确保资源释放
                if (device != null)
                {
                    device.MV_CC_StopGrabbing_NET();
                    device.MV_CC_CloseDevice_NET();
                    device.MV_CC_DestroyDevice_NET();
                }
            }
        }

在“拍照事件”中,传入

        private void button_takephoto_Click(object sender, EventArgs e)//拍照按钮
        {
            try {
                _selectedDeviceInfo = _deviceList[comboBox1.SelectedIndex];
            } catch {
                MessageBox.Show("请选择相机");
            }
            
            OneShot(pictureBox1, _selectedDeviceInfo); // 传递设备信息
            

        }

运行后:

图像很黑,设置一下曝光

nRet = device.MV_CC_SetFloatValue_NET("ExposureTime", 15000);//设置曝光时间

运行后:

完整代码

using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using MvCamCtrl.NET;


namespace test_HKCamera
{
    public partial class Form1 : Form
    {
        //用于临时存储通过海康SDK枚举到的原始设备列表
        public static MyCamera.MV_CC_DEVICE_INFO_LIST stDevList = new MyCamera.MV_CC_DEVICE_INFO_LIST();
        //从下拉框 comboBox1 中选择的设备信息
        private MyCamera.MV_CC_DEVICE_INFO _selectedDeviceInfo;
        //保存当前枚举到的所有设备信息||下拉框 comboBox1 的选项
        List<MyCamera.MV_CC_DEVICE_INFO> _deviceList = new List<MyCamera.MV_CC_DEVICE_INFO>();

        public Form1()
        {
            InitializeComponent();
        }

        public List<string> ListDevices()//枚举相机
        {
            List<string> result = new List<string>();

            /**/
            if (MyCamera.MV_OK != MyCamera.MV_CC_EnumDevices_NET(MyCamera.MV_GIGE_DEVICE | MyCamera.MV_USB_DEVICE, ref stDevList))
            {
                MessageBox.Show("枚举设备失败");
                return null;
            }
            if (0 == stDevList.nDeviceNum)
            {
                //  MessageBox.Show("未找到设备");
                return null;
            }
            MyCamera.MV_CC_DEVICE_INFO stDevInfo;
            for (int i = 0; i < stDevList.nDeviceNum; i++)
            {

                stDevInfo = (MyCamera.MV_CC_DEVICE_INFO)Marshal.PtrToStructure(stDevList.pDeviceInfo[i], typeof(MyCamera.MV_CC_DEVICE_INFO));
                if (stDevInfo.nTLayerType == MyCamera.MV_GIGE_DEVICE)
                {
                    // 网口USB设备处理
                    IntPtr buffer = Marshal.UnsafeAddrOfPinnedArrayElement(stDevInfo.SpecialInfo.stGigEInfo, 0);
                    MyCamera.MV_GIGE_DEVICE_INFO gigeInfo = (MyCamera.MV_GIGE_DEVICE_INFO)Marshal.PtrToStructure(buffer, typeof(MyCamera.MV_GIGE_DEVICE_INFO));
                    result.Add(gigeInfo.chSerialNumber);
                }
                else if (stDevInfo.nTLayerType == MyCamera.MV_USB_DEVICE)
                {
                    // USB设备处理
                    IntPtr buffer = Marshal.UnsafeAddrOfPinnedArrayElement(stDevInfo.SpecialInfo.stUsb3VInfo, 0);
                    MyCamera.MV_USB3_DEVICE_INFO usbInfo = (MyCamera.MV_USB3_DEVICE_INFO)Marshal.PtrToStructure(
                        buffer,
                        typeof(MyCamera.MV_USB3_DEVICE_INFO)
                    );
                    result.Add(usbInfo.chSerialNumber);
                }


            }
            return result;
        }


        public void OneShot(PictureBox pictureBox, MyCamera.MV_CC_DEVICE_INFO selectedDevice)
        {
            MyCamera device = new MyCamera();
            int nRet = MyCamera.MV_OK;

            try
            {
                // 直接使用传入的设备信息
                nRet = device.MV_CC_CreateDevice_NET(ref selectedDevice);
                if (nRet != MyCamera.MV_OK)
                {
                    MessageBox.Show($"创建设备失败: 0x{nRet:X8}");
                    return;
                }

                nRet = device.MV_CC_OpenDevice_NET(MyCamera.MV_ACCESS_Exclusive, 0);
                if (nRet != MyCamera.MV_OK)
                {
                    MessageBox.Show($"打开设备失败: 0x{nRet:X8}");
                    return;
                }

                nRet = device.MV_CC_StartGrabbing_NET();
                if (nRet != MyCamera.MV_OK)
                {
                    MessageBox.Show($"开始采集失败: 0x{nRet:X8}");
                    return;
                }

                //nRet = device.MV_CC_SetFloatValue_NET("ExposureTime", 15000);//设置曝光时间


                // 获取图像参数
                MyCamera.MVCC_INTVALUE stParam = new MyCamera.MVCC_INTVALUE();
                nRet = device.MV_CC_GetIntValue_NET("PayloadSize", ref stParam);
                if (nRet != MyCamera.MV_OK)
                {
                    MessageBox.Show($"获取图像大小失败: 0x{nRet:X8}");
                    return;
                }

                // 分配缓冲区
                IntPtr pBuf = Marshal.AllocHGlobal((int)stParam.nCurValue);
                MyCamera.MV_FRAME_OUT_INFO_EX frameInfo = new MyCamera.MV_FRAME_OUT_INFO_EX();

                // 获取单帧图像
                nRet = device.MV_CC_GetOneFrameTimeout_NET(pBuf, stParam.nCurValue, ref frameInfo, 1000);
                if (nRet == MyCamera.MV_OK)
                {
                    // 显示图像
                    MyCamera.MV_DISPLAY_FRAME_INFO displayInfo = new MyCamera.MV_DISPLAY_FRAME_INFO
                    {
                        hWnd = pictureBox.Handle,
                        pData = pBuf,
                        nDataLen = frameInfo.nFrameLen,
                        nWidth = frameInfo.nWidth,
                        nHeight = frameInfo.nHeight,
                        enPixelType = frameInfo.enPixelType
                    };
                    device.MV_CC_DisplayOneFrame_NET(ref displayInfo);
                }
                else
                {
                    MessageBox.Show($"获取图像超时: 0x{nRet:X8}");
                }

                // 释放资源
                Marshal.FreeHGlobal(pBuf);
            }
            finally
            {
                // 确保资源释放
                if (device != null)
                {
                    device.MV_CC_StopGrabbing_NET();
                    device.MV_CC_CloseDevice_NET();
                    device.MV_CC_DestroyDevice_NET();
                }
            }
        }



        private void button_find_Click(object sender, EventArgs e)//寻找相机按钮
        {
            List<string> lstdevices = ListDevices();
            if (lstdevices == null)
            {
                MessageBox.Show("无相机");
            }
            else
            {
                MessageBox.Show("已找到设备");
                
                foreach (string device in lstdevices)
                {
                    comboBox1.Items.Add(device);//找到的设备写入下拉框

                }
                for (int i = 0; i < stDevList.nDeviceNum; i++)
                {
                    var devInfo = (MyCamera.MV_CC_DEVICE_INFO)Marshal.PtrToStructure(
                        stDevList.pDeviceInfo[i],
                        typeof(MyCamera.MV_CC_DEVICE_INFO)
                    );
                    _deviceList.Add(devInfo);                    
                }




            }

            
            comboBox1.Enabled = true;
        }

        private void button_takephoto_Click(object sender, EventArgs e)//拍照按钮
        {
            try {
                _selectedDeviceInfo = _deviceList[comboBox1.SelectedIndex];
            } catch {
                MessageBox.Show("请选择相机");
            }
            
            OneShot(pictureBox1, _selectedDeviceInfo); // 传递设备信息
            

        }
    }
}


网站公告

今日签到

点亮在社区的每一天
去签到