1. 项目概述:多相机并行采集与实时显示系统
在工业视觉检测、自动化生产线监控等场景中,经常需要同时控制多台工业相机进行高速连续采集,并将图像实时显示在操作界面上。这个项目基于C#开发环境,整合Halcon图像处理库和海康威视工业相机SDK,实现了三台相机的同步触发、连续采集和实时显示功能。核心难点在于如何通过回调函数机制高效处理多路图像流,避免界面卡顿和内存泄漏。
海康威视工业相机以其稳定的性能和丰富的接口在工业领域广泛应用,而Halcon作为机器视觉领域的标杆软件,提供了强大的图像处理算法。通过C#将两者结合,既能利用.NET平台的开发效率,又能获得专业级的视觉处理能力。实测在i7处理器、16GB内存的工控机上,三台500万像素相机同时以15fps采集时,CPU占用率可控制在40%以下。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 开发环境准备与SDK配置
2.1 硬件连接与相机配置
三台海康相机需通过千兆网口连接到同一交换机,建议使用工业级六类屏蔽网线。每台相机的IP地址需设置为同一网段的不同地址(如192.168.1.10/11/12),子网掩码255.255.255.0。通过海康官方配置工具MVS(Machine Vision Suite)可快速完成以下操作:
- 修改相机IP并永久写入设备
- 设置合适的曝光时间(通常1-10ms)
- 启用硬件触发模式(如有外部触发需求)
- 配置合适的像素格式(推荐Mono8或BGR8)
注意:工业现场建议为每台相机配置独立的PoE供电交换机,避免因供电不足导致相机重启。
2.2 软件依赖安装
开发环境需要以下组件:
- Visual Studio 2022(社区版即可)
- .NET Framework 4.7.2或更高版本
- Halcon 20.11及以上版本(需正确安装授权)
- 海康威视MVS SDK(版本需与相机固件匹配)
Halcon安装后需特别注意:
bash复制# 检查环境变量是否包含Halcon的bin目录
echo %HALCONROOT%
# 每月许可证更新后需重新运行halcon.lic文件
3. 核心代码实现解析
3.1 相机初始化与回调函数注册
创建CameraController类管理所有相机实例,关键代码如下:
csharp复制public class CameraController
{
private List<HCamera> cameras = new List<HCamera>();
private HalconDotNet.HWindowControl displayWindow;
public void InitializeCameras(List<string> ipList)
{
for (int i = 0; i < ipList.Count; i++)
{
HCamera cam = new HCamera();
cam.Login(ipList[i], 8000, "admin", "password");
cam.SetResolution(2448, 2048);
cam.SetPixelFormat("Mono8");
// 注册回调函数
cam.SetImageCallback(new ImageCallbackDelegate(OnImageReceived), i);
cameras.Add(cam);
}
}
private void OnImageReceived(IntPtr pData, int width, int height, int cameraIndex)
{
// 将图像数据转换为Halcon对象
HImage image = new HImage();
image.GenImage1("byte", width, height, pData);
// 线程安全方式更新UI
displayWindow.BeginInvoke((Action)(() => {
image.DispObj(displayWindow.HalconWindow);
}));
}
}
3.2 多线程图像处理架构
为避免UI线程阻塞,采用生产者-消费者模式:
csharp复制private BlockingCollection<ImageData> imageQueue = new BlockingCollection<ImageData>(10);
// 生产者(回调函数中调用)
private void EnqueueImage(HImage image, int camIdx)
{
if(imageQueue.Count < 8) // 限制队列长度
{
imageQueue.Add(new ImageData{Image=image, CameraIndex=camIdx});
}
else
{
image.Dispose(); // 防止内存泄漏
}
}
// 消费者(独立线程)
private void ProcessImages()
{
while(!cancellationToken.IsCancellationRequested)
{
var imgData = imageQueue.Take();
// 进行图像处理...
imgData.Image.Dispose();
}
}
4. 性能优化关键技巧
4.1 内存管理最佳实践
多相机连续采集时内存管理至关重要:
- 使用对象池复用Halcon的HImage对象
- 在回调函数中立即复制图像数据,不要持有相机缓冲区
- 确保所有Halcon对象在使用后Dispose()
- 定期调用GC.Collect()(仅在低内存时触发)
4.2 显示优化方案
当需要同时显示三路视频时,可采用以下方式提升性能:
csharp复制// 使用Halcon的复合显示方式
HTuple width, height;
image.GetImageSize(out width, out height);
HWindowStack.SetWindowParam(displayWindow.HalconWindow, "flush", "false");
for(int i=0; i<3; i++)
{
HOperatorSet.SetPart(displayWindow.HalconWindow, 0, i*width/3, height, (i+1)*width/3);
images[i].DispObj(displayWindow.HalconWindow);
}
HWindowStack.SetWindowParam(displayWindow.HalconWindow, "flush", "true");
5. 常见问题与解决方案
5.1 相机连接异常处理
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 登录超时 | IP地址错误/网络不通 | 检查网线/Ping测试 |
| 图像断层 | 网络带宽不足 | 降低分辨率/启用压缩 |
| 回调不触发 | 未开启流传输 | 调用StartGrabbing() |
5.2 Halcon授权问题
当出现"HALCON error #5301: No valid license found"时:
- 检查环境变量HALCONROOT是否指向正确目录
- 确认license文件包含所需模块(如Multithreading)
- 每月初需更新license文件(从官网下载)
5.3 多线程同步问题
在回调函数中更新UI时,必须通过Control.BeginInvoke跨线程访问。更安全的做法是使用SynchronizationContext:
csharp复制private SynchronizationContext uiContext;
// 在主线程中初始化
uiContext = SynchronizationContext.Current;
// 在回调中使用
uiContext.Post(_ => {
image.DispObj(displayWindow.HalconWindow);
}, null);
6. 项目扩展与进阶方向
6.1 触发同步采集方案
对于需要精确同步的应用(如运动物体三维重建),可采用:
- 硬件触发:通过PLC发送脉冲信号到所有相机
- PTP协议:利用IEEE 1588实现亚微秒级同步
- 软件同步:通过SDK的SyncControl命令
接线示例:
code复制PLC触发信号 ──┬── 相机1 Trigger IN
├── 相机2 Trigger IN
└── 相机3 Trigger IN
6.2 与ROS系统集成
通过海康的ROS驱动包可实现:
bash复制# 安装驱动
sudo apt-get install ros-noetic-hikvision-camera
# 启动节点
roslaunch hikvision_camera hikvision.launch ip:=192.168.1.10
在工业现场部署时,建议将相机设置为静态IP,并在代码中加入自动重连机制。我遇到过因网络闪断导致采集中断的情况,后来通过以下心跳检测解决了问题:
csharp复制private void HeartbeatCheck()
{
foreach(var cam in cameras)
{
if(!cam.IsGrabbing())
{
cam.Reconnect();
cam.StartGrabbing();
}
}
}
