1. 多相机并行采集系统概述
在工业视觉检测、医疗影像采集或安防监控等场景中,经常需要同时控制多台相机进行图像采集。本文基于C#开发环境,结合Halcon图像处理库和海康威视相机SDK,实现了一个三相机并行采集与实时显示系统。系统采用回调函数机制获取图像数据,确保采集过程的低延迟和高效率。
核心方案采用多线程架构,每个相机独立运行在专属线程中,通过海康SDK的异步回调机制获取图像帧,再通过Halcon的窗口控件进行实时渲染。这种设计避免了传统轮询方式带来的性能损耗,特别适合高帧率、多相机的应用场景。
2. 开发环境与工具链配置
2.1 硬件准备
- 海康威视工业相机(支持GigE或USB3.0接口)至少3台
- 千兆以太网交换机(GigE相机需专用交换机)
- 主机配置建议:i5以上CPU,16GB内存,独立显卡
2.2 软件依赖
- Visual Studio 2019/2022(.NET Framework 4.7+)
- Halcon 17+ 运行时库
- 海康威视MVS SDK(本文使用版本2.1.0)
- NuGet包:HalconDotNet(Halcon的.NET封装)
提示:安装MVS SDK时需确保选择完整开发包,安装后检查系统目录下是否存在MvCameraControl.Net.dll
3. 核心架构设计与实现
3.1 类结构设计
系统主要包含两个核心类:
Form2:主窗体类,负责UI布局和相机管理HKcamrea:相机控制类,封装所有相机操作
csharp复制// 相机控制类核心字段
private CCamera m_MyCamera; // 海康相机实例
private bool m_bIsDeviceOpen; // 设备状态标志
private UInt32 m_nCurWidth, m_nCurHeight; // 图像尺寸
private MvGvspPixelType m_emPixelType; // 像素格式
private cbOutputExdelegate ImageCallback; // 回调委托
3.2 多线程管理
每个相机实例运行在独立的Task中,避免阻塞UI线程:
csharp复制Task.Run(() => {
cam1.HKEnum();
cam1.HKCamreaOpen(2);
});
关键点:
- 使用
List<HKcamrea>保存相机实例引用,防止被GC回收 - 每个相机绑定独立的Halcon窗口控件(hSmartWindowControl)
- 通过DeviceNumber区分不同相机设备
4. 相机控制全流程实现
4.1 设备枚举与初始化
csharp复制// 枚举所有可用设备
nRet = CSystem.EnumDevices(CSystem.MV_GIGE_DEVICE | CSystem.MV_USB_DEVICE,
ref ltDeviceList);
// 创建设备句柄
nRet = m_MyCamera.CreateHandle(ref stDevice);
// 打开设备
nRet = m_MyCamera.OpenDevice();
注意事项:
- GigE相机需要配置正确的IP地址段
- USB相机需要安装对应的驱动签名
- 枚举失败时检查防火墙设置和杀毒软件拦截
4.2 图像采集参数配置
csharp复制// 设置连续采集模式(非触发)
nRet = m_MyCamera.SetEnumValue("TriggerMode",
(uint)MV_CAM_TRIGGER_MODE.MV_TRIGGER_MODE_OFF);
// 获取当前分辨率
CIntValue pcWidth = new CIntValue();
m_MyCamera.GetIntValue("Width", ref pcWidth);
m_nCurWidth = (UInt32)pcWidth.CurValue;
// 获取像素格式(决定后续图像处理方式)
CEnumValue pcPixelFormat = new CEnumValue();
m_MyCamera.GetEnumValue("PixelFormat", ref pcPixelFormat);
m_emPixelType = (MvGvspPixelType)pcPixelFormat.CurValue;
4.3 回调函数注册与图像处理
核心回调函数实现:
csharp复制private void ImageCallbackFunc(IntPtr pData, ref MV_FRAME_OUT_INFO_EX pFrameInfo,
IntPtr pUser)
{
HObject ImageTemp;
lock (CbImageLock) // 确保线程安全
{
// 根据像素格式生成Halcon图像
if (m_emPixelType == MvGvspPixelType.PixelType_Gvsp_Mono8)
{
HOperatorSet.GenImage1(out ImageTemp, "byte",
pFrameInfo.nWidth, pFrameInfo.nHeight,
(HTuple)pData);
}
else // 彩色图像
{
HOperatorSet.GenImageInterleaved(out ImageTemp, (HTuple)pData,
"rgb", pFrameInfo.nWidth, pFrameInfo.nHeight, 0,
"byte", 0, 0, 0, 0, 8, 0);
}
// 显示到Halcon窗口
HOperatorSet.GetImageSize(ImageTemp, out HTuple HvWidth, out HTuple HvHeight);
HOperatorSet.SetPart(Cavnvas, 0, 0, HvHeight, HvWidth);
HOperatorSet.DispObj(ImageTemp, Cavnvas);
}
}
关键细节:
- 必须使用
lock保证多线程下的图像操作安全 GenImage1用于8位灰度图像,GenImageInterleaved用于RGB图像SetPart确保图像适配显示窗口尺寸
5. 性能优化与问题排查
5.1 网络相机优化
对于GigE相机,必须设置最优包大小:
csharp复制int nPacketSize = m_MyCamera.GIGE_GetOptimalPacketSize();
if (nPacketSize > 0)
{
nRet = m_MyCamera.SetIntValue("GevSCPSPacketSize", (uint)nPacketSize);
}
5.2 常见错误处理
| 错误代码 | 可能原因 | 解决方案 |
|---|---|---|
| 0x80000000 | 设备未连接 | 检查物理连接和IP配置 |
| 0x80000008 | 权限不足 | 以管理员身份运行程序 |
| 0x8000000A | 资源冲突 | 关闭其他占用相机的软件 |
5.3 内存管理要点
- 及时释放Halcon图像对象:
csharp复制
ImageTemp.Dispose(); - 停止采集时先取消回调注册:
csharp复制m_MyCamera.RegisterImageCallBackEx(null, IntPtr.Zero); - 显式释放相机资源:
csharp复制
m_MyCamera.StopGrabbing(); m_MyCamera.CloseDevice(); m_MyCamera.DestroyHandle();
6. 扩展功能实现
6.1 触发模式切换
系统预留了触发模式接口,可根据需要切换:
csharp复制// 软触发模式
nRet = m_MyCamera.SetEnumValue("TriggerMode",
(uint)MV_CAM_TRIGGER_MODE.MV_TRIGGER_MODE_ON);
// 执行单次软触发
m_MyCamera.MV_CC_SetCommandValue_NET("TriggerSoftware");
// 硬触发配置(LINE0)
nRet = m_MyCamera.SetEnumValue("TriggerSource",
(uint)MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_LINE0);
6.2 多相机同步方案
实现精确同步的两种方式:
- 硬件同步:通过外接触发信号同步所有相机
- PTP同步:启用相机的PTP协议(需硬件支持)
配置示例:
csharp复制// 启用PTP同步
nRet = m_MyCamera.SetEnumValue("GevIEEE1588", 1);
7. 实测效果与参数调优
在实际测试中,三台2048×1536分辨率的相机同时采集时:
- CPU占用:约15-20%(i7-10700)
- 内存占用:每相机约50MB
- 延迟:<50ms(从采集到显示)
优化建议:
- 降低分辨率可显著提升帧率
- 设置合适的曝光时间避免运动模糊
- 使用ROI采集减少数据传输量
8. 开发注意事项
- 线程安全:所有跨线程操作必须加锁,特别是Halcon对象操作
- 异常处理:每个SDK调用都应检查返回值
- 资源释放:确保程序退出时释放所有相机资源
- 日志记录:关键操作记录日志便于排查问题
典型问题记录:
csharp复制// 错误示例:未处理回调中的异常
try {
// 图像处理代码
}
catch (Exception ex) {
Console.WriteLine($"Error in callback: {ex.Message}");
// 可添加重试或恢复逻辑
}
这个多相机采集系统在实际工业检测项目中表现稳定,经过验证可支持最多6台相机同时工作。关键点在于合理的线程分配和资源管理,以及回调函数中的高效图像处理。对于需要更高性能的场景,可以考虑使用Halcon的GPU加速功能或升级硬件配置。