优秀的编程知识分享平台

网站首页 > 技术文章 正文

C# 海康工业相机对接流程、技巧及常见问题

nanyue 2025-08-02 20:29:29 技术文章 1 ℃



转自: 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

出处:cnblogs.com/SmallChen/p/18792448
声明:网络内容,仅供学习,尊重版权,侵权速删,歉意致谢!

最近发表
标签列表