当前位置: 首页 > news >正文

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

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);}#endregionprivate 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); // 传递设备信息}}
}

http://www.dtcms.com/a/317967.html

相关文章:

  • 字典树trie
  • 技术博客:从HTML提取到PDF生成的完整解决方案
  • 奔图P2500NW打印机手机无线连接方法
  • 强化应急通信生命线:遨游三防平板、卫星电话破局极端灾害救援
  • 2.6 sync
  • 2024年测绘程序设计比赛--空间探索性分析(数据为2025年第三次模拟数据)
  • 第二十六天(数据结构:树(补充版程序请看下一篇))
  • 【数据结构与算法】刷题篇——环形链表的约瑟夫问题
  • tmux.conf配置-简易版
  • Java技术栈/面试题合集(15)-RabbitMQ篇
  • 202506 电子学会青少年等级考试机器人四级实际操作真题
  • vue3 vite 使用vitest 单元测试 组件测试
  • Python数据可视化:从基础到高级实战指南
  • 【代码随想录day 12】 力扣 144.145.94.前序遍历中序遍历后序遍历
  • 【数据可视化-82】中国城市幸福指数可视化分析:Python + PyEcharts 打造炫酷城市幸福指数可视化大屏
  • 架构层防护在高并发场景下的实践
  • Linux系统之Docker命令与镜像、容器管理
  • Spring Cloud系列—Eureka服务注册/发现
  • ElasticSearch~DSL常用语法
  • Unity 调节 Rigidbody2D 响应速度的解决方案【资料】
  • CS课程项目设计8:基于Canvas支持AI人机对战的五子棋游戏
  • Lesson 35 Stop thief!
  • MATLAB实现的改进遗传算法用于有约束优化问题
  • Java 工具类的“活化石”:Apache Commons 核心用法、性能陷阱与现代替代方案
  • 03-mysql/redis/apache安装记录
  • 从《中国开源年度报告》看中国开源力量的十年变迁中,Apache SeaTunnel 的跃迁
  • SmartMediaKit 模块化音视频框架实战指南:场景链路 + 能力矩阵全解析
  • LinkedList 深度解析:核心原理与实践
  • uniapp开发中 解决App端 点击input输入框 整体上移
  • DocBench:面向大模型文档阅读系统的评估基准与数据集分析