网站首页 > 技术文章 正文
转自: DotNet技术匠
本文只做学术分享,如有侵权,联系删文
前言
在工业自动化视觉检测领域,海康威视工业相机以其高性价比和完善的SDK支持被广泛应用。
本文将基于C#语言,结合海康威视官方SDK,详细介绍工业相机的对接开发流程、关键技术实现及常见问题解决方案。通过实际代码示例,帮助大家快速掌握海康相机的集成开发方法。
开发环境准备
1、SDK安装
下载地址
https://www.hikrobotics.com/cn/machinevision/service/download/?module=0
关键组件
MvCameraControl.dll(核心SDK)
MVS开发工具包(含虚拟相机调试工具)
运行时依赖库(需安装官方Runtime)
2、开发方案选择
方案一 :直接引用DLL(推荐)
需将DLL文件复制到输出目录
需处理32/64位系统兼容性问题
方案二 :源码集成(开发调试更便捷)
直接包含SDK源码文件
可查看方法注释,便于调试
核心代码实现
1、相机初始化与枚举
publicclassCameraHelper
{
privatereadonly ICancheService _cancheService;
publicstring savePathByDB = Path.Combine(Environment.CurrentDirectory, "productPic");
publicCameraHelper(ICancheService cancheService)
{
_cancheService = cancheService;
}
publicstringDeviceListAcq()
{
MyCamera.MV_CC_DEVICE_INFO_LIST m_stDeviceList = new MyCamera.MV_CC_DEVICE_INFO_LIST();
int nRet = MyCamera.MV_CC_EnumDevices_NET(
MyCamera.MV_GIGE_DEVICE | MyCamera.MV_USB_DEVICE,
ref m_stDeviceList);
if (nRet != 0 || m_stDeviceList.nDeviceNum == 0)
return HK_ErrorCode("未找到设备", nRet);
List cbDeviceList = new List();
for (int i = 0; i < m_stDeviceList.nDeviceNum; i++)
{
var device = (MyCamera.MV_CC_DEVICE_INFO)Marshal.PtrToStructure(
m_stDeviceList.pDeviceInfo[i],
typeof(MyCamera.MV_CC_DEVICE_INFO));
var cameraInfo = new CameraInfo();
cameraInfo.device = device;
cameraInfo.device_Hik = new MyCamera();
// 初始化相机...
nRet = cameraInfo.device_Hik.MV_CC_CreateDevice_NET(ref device);
if (nRet != MyCamera.MV_OK) continue;
nRet = cameraInfo.device_Hik.MV_CC_OpenDevice_NET();
if (nRet != MyCamera.MV_OK) continue;
// 设置相机参数...
cameraInfo.device_Hik.MV_CC_SetEnumValue_NET(
"AcquisitionMode",
(uint)MyCamera.MV_CAM_ACQUISITION_MODE.MV_ACQ_MODE_CONTINUOUS);
cbDeviceList.Add(cameraInfo);
}
_cancheService.UpdateCameraSettingByCache(cbDeviceList);
return"";
}
}
2、触发模式实现
publicstringTriggerMode(CameraInfo cameraInfo)
{
int nRet;
// 停止抓图(如果正在运行)
if (cameraInfo.isStartCatchPic)
{
nRet = cameraInfo.device_Hik.MV_CC_StopGrabbing_NET();
if (nRet != MyCamera.MV_OK)
return HK_ErrorCode("相机关闭抓图失败", nRet);
}
// 开启抓图
nRet = cameraInfo.device_Hik.MV_CC_StartGrabbing_NET();
if (nRet != MyCamera.MV_OK)
return HK_ErrorCode("相机开启抓图失败", nRet);
// 设置触发模式
cameraInfo.device_Hik.MV_CC_SetEnumValue_NET(
"TriggerMode",
(uint)MyCamera.MV_CAM_TRIGGER_MODE.MV_TRIGGER_MODE_ON);
if (cameraInfo.isSoft)
{
// 软触发实现
cameraInfo.device_Hik.MV_CC_SetEnumValue_NET(
"TriggerSource",
(uint)MyCamera.MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_SOFTWARE);
nRet = cameraInfo.device_Hik.MV_CC_SetCommandValue_NET("TriggerSoftware");
if (nRet != MyCamera.MV_OK)
return HK_ErrorCode("相机软触发失败", nRet);
}
else
{
// 硬触发实现
cameraInfo.device_Hik.MV_CC_SetEnumValue_NET(
"TriggerSource",
(uint)MyCamera.MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_LINE0);
}
return"";
}
3、图像回调处理
publicvoidImageCallBack(IntPtr pData, ref MyCamera.MV_FRAME_OUT_INFO_EX pFrameInfo, IntPtr pUser)
{
int nIndex = (int)pUser;
var cameraList = _cancheService.GetCameraListByCache();
lock (cameraList[nIndex].m_BufForSaveImageLock)
{
if (!cameraList[nIndex].isSoft)
{
StartCatchPic(cameraList[nIndex], pFrameInfo, pData);
}
}
}
publicstringStartCatchPic(CameraInfo m_MyCameraInfo, MyCamera.MV_FRAME_OUT_INFO_EX pFrameInfo, IntPtr pData = default)
{
// 内存分配与数据拷贝
if (m_MyCameraInfo.m_pSaveImageBuf == IntPtr.Zero || pFrameInfo.nFrameLen > m_MyCameraInfo.m_nSaveImageBufSize)
{
// 内存重分配逻辑...
}
CopyMemory(m_MyCameraInfo.m_pSaveImageBuf, pData, pFrameInfo.nFrameLen);
// 保存图像到文件
var fileName = #34;Dev{m_MyCameraInfo.CanmeraId}_ti{m_MyCameraInfo.m_stFrameInfo.nHostTimeStamp}.jpeg";
var stSaveFileParam = new MyCamera.MV_SAVE_IMG_TO_FILE_PARAM
{
enImageType = MyCamera.MV_SAVE_IAMGE_TYPE.MV_Image_Jpeg,
pData = m_MyCameraInfo.m_pSaveImageBuf,
nDataLen = m_MyCameraInfo.m_stFrameInfo.nFrameLen,
pImagePath = Path.Combine(savePathByDB, fileName)
};
int nRet = m_MyCameraInfo.device_Hik.MV_CC_SaveImageToFile_NET(ref stSaveFileParam);
if (nRet != MyCamera.MV_OK)
return HK_ErrorCode("图片保存失败", nRet);
return#34;pack://siteoforigin:,,,/productPic/{fileName}";
}
关键技术
1、内存管理
使用 Marshal.AllocHGlobal
分配非托管内存
必须成对使用 Marshal.Release
释放内存
线程安全处理:通过 lock
保证多线程环境下的内存操作安全
2、错误处理
统一错误码处理: HK_ErrorCode
方法将错误码转换为可读信息
关键错误日志记录:通过
记录操作日志
_cancheService.UpdateLogging
3、性能优化
图像数据缓存:复用内存缓冲区避免频繁分配
异步处理:图像回调与主业务逻辑解耦
常见问题与解决方案
1、DLL加载失败
现象: 无法加载 dll“MvcameraControl.dll”
解决方案
安装官方Runtime
确保32/64位系统与DLL架构匹配
使用Dependency Walker检查依赖项
2、相机无法枚举
检查项
相机IP配置是否正确(GigE相机)
相机是否被其他程序占用
防火墙是否阻止了相机通信
3、触发模式失效
解决方案
确认相机支持所选触发模式
检查触发源设置是否正确
软触发时需先发送触发命令再采集图像
4、图像保存失败
常见原因
保存路径不存在或无权限
内存拷贝不完整(检查 nFrameLen
与实际数据长度)
像素格式不匹配(检查 enPixelType
)
5、错误码解决方案
1、MV_OK 0x00000000 成功,无错误
解析:-2147483648/0x80000000正常状态返回,执行成功
2、MV_E_HANDLE 0x80000000 错误或无效的句
解析:-2147483648/0x80000000 无效句柄,常见问题如下:
用户没有申请句柄,直接调用接口,新手常犯的错误,要引导去学习我们接口使用流程
用户创建了句柄,但是其他地方销毁了句柄,用户没有注意到,需要仔细排查代码
3、MV_E_SUPPORT 0x80000001 不支持的功能
解析:-2147483647/0x80000001
SDK接口的bayer空域降噪、无损压缩、色彩矫正等ISP功能,需要配合CS-Pro系列相机支持
格式转化时,不同格式的相互转化,超出了算法能力集,详情请仔细查阅SDK接口说明
4、MV_E_BUFOVER 0x80000002 缓存已满
解析:-2147483646/0x80000002
常见于gige驱动启动时报错,低版本SDK在某些网卡上面易发,驱动启动失败后,走socket协议发送接收相机数据,效率低,CPU负载大 推荐使用SDK3.5版本解决此问题
5、MV_E_CALLORDER 0x80000003 函数调用顺序有误
解析:-2147483645/0x80000003
sdk接口调用,有一定流程顺序,例如getimagebuffer在startgrabing之前调用,就违反了接口流程,就会报错顺序调用错误 还比如,没有调用startgrabing接口,就去调用频繁调用stopgrabing接口,也会报此错误
6、MV_E_PARAMETER 0x80000004 错误的参数
解析:-2147483644/0x80000004
常见问题: 常见于格式转化、图像保存等需要补充数据结构的接口调用,部分参数传入错误,或者没有传入,这个时候,要去仔细检查参数的传入是否正确
7、MV_E_NODATA 0x80000007 无数据
解析:-2147483641/0x80000007无数据
相机帧率低,用户调用主动取流接口
getimagebuffer/getoneframetimout频率高于相机出图频率,且超时时间短,没有拿到图片,此时应该打印相机帧号,如帧号连续则为正常现象
相机处于触发模式,没有触发信号给到相机,此时,应该排查用户是否给了软触发或者硬触发信号
相机停流,此时,建议打开MVS,观察相机状态
耐心寻找规律,看看是否跟packsize、scpd、取流超时时间不合理所致
8、MV_E_NOENOUGH_BUF 0x8000000A 传入的内存空间不足
解析:-2147483638/0x8000000A
1、用户自行开辟的内存大小,小于当前相机图像所需要的图像大小,例如用mono8的图像大小,接收RGB的图像
2、用户定义的内存大小,中途更换了分辨率更高的相机,导致所需内存较多
3、相机开启了chunk功能,用户开辟缓存大小,仅考虑了图像宽 高 像素格式,没有考虑到chunk
解决方法:
排查内存开辟大小,建议使用相机payloadsize大小
检查相机图像格式
关闭相机chunk等功能
9、MV_E_UNKNOW 0x800000FF 未知的错误
解析:-2147483137/0x800000FF GenICam未知错误
未知错误,形成原因较难分析,建议如下
更新最新版本的sdk
开启sdk日志等级,通过日志分析形成原因
10、MV_E_GC_GENERIC 0x80000100 通用错误
解析:-2147483392/0x80000100
通用接口调用,关键词写错,例如曝光:ExposureTime,拼写错误就会报错
第三方相机链接,例如迈德威视相机链接MVS,也会报通用错误,这是因为迈德威视不是标准的genicam协议的相机导致的
接口类型用错,例如曝光时float型节点,我们使用了一个int型的节点接口进行读写,访问,那么也会报通用错误
11、MV_E_GC_RANGE 0x80000102 值超出范围
解析:-2147483390/0x80000102
接口传入的参数值,超出相机接受范围,例如,曝光存在上下限,图像宽高存在步进,没有按照步进进行设置等等
12、MV_E_GC_ACCESS 0x80000106 节点访问条件有误
解析:-2147483386/0x80000106
常见的问题类型有: 相机节点不存在或者无法访问,例如,自动曝光,在手动曝光情况下,自动曝光节点会被隐藏,或者其他相机存在这个参数,而使用的相机无此参数,例如线扫相机的行频参数等等,还比如说部分相机无此功能,例如event参数,部分相机固件暂不支持用户调用
13、MV_E_GC_TIMEOUT 0x80000107 超时
解析:-2147483385/0x80000107 GVCP命名包回复超时,一般出现在网络环境不好的情况下,此时应该调用接口加大gvcp命令包等待时间(MV_GIGE_GetGvcpTimeout()),持续出现该报错,应该排查网络环境问题
分析:根据海康SDK提示文件:更新官网最新SDK时,设备网络SDK开发包【库文件】里的HCNetSDK.dll、HCCore.dll、PlayCtrl.dll、SuperRender.dll、AudioRender.dll、HCNetSDKCom文件夹等文件均要加载到程序里面,HCNetSDKCom文件夹(包含里面的功能组件dll库文件)需要和HCNetSDK.dll、HCCore.dll一起加载,放在同一个目录下,且HCNetSDKCom文件夹名不能修改。
解决方法:将海康SDK的头文件放到Debug文件夹.exe文件的存放处:
14、MV_E_ACCESS_DENIED 0x80000203 设备无访问权限
解析:-2147483133/0x80000203常见问题有:
相机被其他软件打开占用,关闭其他软件,检查设备管理器中,可能存在的残留进程
代码debug下,心跳时间问题,等待60s后,可以重新打开(此问题参考心跳问题解决方法,可缩短打开时间)
其余问题,例如一上电就打不开相机,需要重新插拔网线、USB线,就是其他问题,需要具体问题,具体分析
15、MV_E_NETER 0x80000206 网络相关错误
解析:-2147483130/0x80000206
此类报错非常常见,主要分以下集中
相机掉线,能够在日志中发现大量的206报错,此时需要去区分掉线原因,结合相机上电时间、心跳时间、相机权限,日志等信息,综合判断
网线异常,导致相机掉线,也需要具体问题分析
16、MV_E_IP_CONFLICT 0x80000221 设备IP冲突
解析:-2147483103/0x80000221,常见于IP设置时,当前ip已经被其他设备使用,需要更换ip重新设置
17、MV_E_USB_READ 0x80000300 读USB出错
解析:-2147482880/0x80000300
USB读取相机信息失败,此类问题较为复制,与USB接口稳定性、线缆长度、电磁环境相关,往往不好分析,可以尝试插拔一下,或者更换USB接口尝试
18、MV_E_USB_WRITE 0x80000301 写USB出错
解析:-2147482879/0x80000301
同0x80000300一样,不好分析,可以尝试插拔一下,或者更换USB接口尝试
19、MV_E_USB_DRIVER 0x80000305 驱动不匹配或者未装驱动
解析: -2147482875/0x80000305
同0x80000300一样,问题复杂,除了更换USB接口外,还可以尝试更换sdk版本
另外一种场景,比较好解决的是,卸载第三方的usb驱动,比如说halcon驱动
20、错误号64:
NET_DVR_LOADPLAYERSDKFAILED 64 载入当前目录下 Player Sdk 出错
分析:该问题为解决错误107时间引出,问题应该在文件放置目录不对或者库文件内容有缺失导致;解决方法:与错误107相同,将其库文件放置到指定目录;必要时:检查调用Play的文件中是否引入头文件,可引入头文件如“PlayM4.h”或“plaympeg4.h”尝试解决。
开发调试建议
1、使用MVS工具测试
海康官方MVS工具可创建虚拟相机
用于验证SDK基本功能是否正常
2、日志分级
_cancheService.UpdateLogging(new Logging
{
Content = #34;操作信息",
Level = LogLevel.Info, // 或Error/Warn
StartTime = DateTime.UtcNow
});
3、性能监控
监控帧率( nFrameRate
参数)
检查数据包大小( GevSCPSPacketSize
)
总结
海康工业相机C#开发的核心流程包括:
1、环境准备:SDK安装与依赖配置
2、相机枚举与初始化: MV_CC_EnumDevices_NET
与 MV_CC_CreateDevice_NET
3、参数设置:曝光时间、增益、ROI等
4、触发模式配置:软触发/硬触发选择
5、图像采集与回调: MV_CC_StartGrabbing_NET
与回调处理
6、资源释放: MV_CC_DestroyDevice_NET
通过本文的代码示例与问题解决方案,大家可以:
作者:WantRemake
- 上一篇: 数控机床NC语言与PC语言以及PLC语言的应用
- 下一篇: Linux开发工具使用指南
猜你喜欢
- 2025-08-02 Linux开发工具使用指南
- 2025-08-02 数控机床NC语言与PC语言以及PLC语言的应用
- 2025-05-10 热学和湿度超稳定的一维钙钛矿(钙钛矿eqe)
- 2025-05-10 C#上位机基于SMTP实现邮件报警通知
- 2025-05-10 Android平台上最好的几款免费的代码编辑器
- 2025-05-10 CPU缓存一致性:从理论到实战(cpu和缓存)
- 2025-05-10 头文件路径搜索顺序五花八门,有没有规律?
- 2025-05-10 .NET 7 AOT 的使用以及 .NET 与 Go 互相调用
- 2025-05-10 Linux系列:如何用 C#调用 C方法造成内存泄露
- 2025-05-10 测评丨RK3399+RK1808人工智能计算棒(主动模式和被动模式)
- 08-02C|在一个结构体嵌套一个共用体实现一体多用
- 08-02C++中,常用的强制类型转换函数
- 08-02如何使用C语言编程实现一个推箱子游戏?技术核心和算法实现
- 08-02C++20 新特性(24):模板访问权限和typename的放宽
- 08-02C++零基础到工程实践
- 08-02[深度学习] Python人脸识别库face_recognition使用教程
- 08-02AI算法之怎么利用Python实现支持向量机SVM算法
- 08-02【机器学习】SVM支持向量机
- 1521℃桌面软件开发新体验!用 Blazor Hybrid 打造简洁高效的视频处理工具
- 623℃Dify工具使用全场景:dify-sandbox沙盒的原理(源码篇·第2期)
- 526℃MySQL service启动脚本浅析(r12笔记第59天)
- 492℃启用MySQL查询缓存(mysql8.0查询缓存)
- 491℃服务器异常重启,导致mysql启动失败,问题解决过程记录
- 479℃「赵强老师」MySQL的闪回(赵强iso是哪个大学毕业的)
- 460℃mysql服务怎么启动和关闭?(mysql服务怎么启动和关闭)
- 458℃MySQL server PID file could not be found!失败
- 最近发表
- 标签列表
-
- cmd/c (90)
- c++中::是什么意思 (84)
- 标签用于 (71)
- 主键只能有一个吗 (77)
- c#console.writeline不显示 (95)
- pythoncase语句 (88)
- es6includes (74)
- sqlset (76)
- windowsscripthost (69)
- apt-getinstall-y (100)
- node_modules怎么生成 (87)
- chromepost (71)
- flexdirection (73)
- c++int转char (80)
- static函数和普通函数 (76)
- el-date-picker开始日期早于结束日期 (70)
- c语言min函数头文件 (68)
- asynccallback (71)
- localstorage.removeitem (74)
- vector线程安全吗 (70)
- java (73)
- js数组插入 (83)
- mac安装java (72)
- 查看mysql是否启动 (70)
- 无效的列索引 (74)