XP.Camera 使用说明
基于 .NET 8 WPF 的工业相机控制与标定类库,采用工厂模式 + 统一接口设计,支持多品牌相机扩展。当前已实现 Basler pylon SDK 驱动。
环境要求
- .NET 8 SDK
- Windows 操作系统
- Basler pylon 8 SDK(已安装并配置环境变量)
项目结构
XP.Camera/
├── Core/ # 相机核心抽象
│ ├── ICameraController.cs # 控制器接口 + 工厂接口
│ ├── CameraFactory.cs # 统一工厂(根据品牌创建控制器)
│ ├── CameraModels.cs # CameraInfo、ImageGrabbedEventArgs、GrabErrorEventArgs
│ └── CameraExceptions.cs # CameraException、ConnectionLostException、DeviceNotFoundException
├── Basler/ # Basler 品牌实现
│ └── BaslerCameraController.cs # Basler pylon SDK 实现
├── Converters/ # 数据转换工具
│ └── PixelConverter.cs # 像素数据 → WPF BitmapSource 转换
├── Calibration/ # 相机标定模块
│ ├── CalibrationProcessor.cs # 九点标定(DLT 单应性矩阵,像素→世界坐标)
│ ├── ChessboardCalibrator.cs # 棋盘格标定(Zhang's 方法,内参 + 畸变校正)
│ ├── IDialogService.cs # ICalibrationDialogService 接口
│ ├── DefaultCalibrationDialogService.cs # 默认实现(标准 WPF MessageBox)
│ ├── CalibrationLocalizedStrings.cs # XAML 本地化绑定辅助
│ ├── Controls/ # 标定 UI 控件(UserControl)
│ │ ├── CalibrationControl.xaml/.cs # 九点标定界面
│ │ ├── ChessboardCalibrationControl.xaml/.cs # 棋盘格标定界面
│ │ └── ImageCanvasControl.xaml/.cs # 图像画布(缩放/平移)
│ ├── ViewModels/ # 标定视图模型
│ │ ├── CalibrationViewModel.cs
│ │ └── ChessboardCalibrationViewModel.cs
│ └── Resources/ # 本地化资源
│ ├── CalibrationResources.resx # 中文(默认)
│ ├── CalibrationResources.en-US.resx # 英文
│ └── CalibrationResources.Designer.cs
└── XP.Camera.csproj
所有相机核心类型在 XP.Camera 命名空间下,标定模块在 XP.Camera.Calibration 命名空间下。
项目引用
<ProjectReference Include="..\XP.Camera\XP.Camera.csproj" />
快速开始
1. 通过工厂创建控制器
using XP.Camera;
ICameraFactory factory = new CameraFactory();
using ICameraController camera = factory.CreateController("Basler");
CameraInfo info = camera.Open();
Console.WriteLine($"已连接: {info.ModelName} (SN: {info.SerialNumber})");
2. 依赖注入方式(推荐)
在 Prism / DI 容器中注册:
var config = AppConfig.Load();
containerRegistry.RegisterSingleton<ICameraFactory, CameraFactory>();
containerRegistry.RegisterSingleton<ICameraController>(() =>
new CameraFactory().CreateController(config.CameraType));
相机品牌通过配置文件 config.json 指定:
{
"CameraType": "Basler"
}
3. 实时图像显示(WPF 绑定)
_camera.ImageGrabbed += (s, e) =>
{
var bitmap = PixelConverter.ToBitmapSource(
e.PixelData, e.Width, e.Height, e.PixelFormat);
Application.Current.Dispatcher.Invoke(() => CameraImageSource = bitmap);
};
4. 软件触发采集流程
camera.Open();
camera.SetExposureTime(10000); // 10ms
camera.StartGrabbing();
camera.ExecuteSoftwareTrigger();
camera.StopGrabbing();
camera.Close();
5. 使用标定模块
标定模块完全自包含,可独立使用,无需外部依赖。
棋盘格标定(相机内参 + 畸变校正)
using XP.Camera.Calibration;
using XP.Camera.Calibration.ViewModels;
using XP.Camera.Calibration.Controls;
// 使用默认对话框服务(标准 WPF MessageBox)
var dialogService = new DefaultCalibrationDialogService();
var viewModel = new ChessboardCalibrationViewModel(dialogService);
var window = new Window
{
Title = "棋盘格标定",
Width = 1600, Height = 900,
Content = new ChessboardCalibrationControl { DataContext = viewModel }
};
window.ShowDialog();
九点标定(像素→世界坐标)
var dialogService = new DefaultCalibrationDialogService();
var viewModel = new CalibrationViewModel(dialogService);
var window = new Window
{
Title = "九点标定",
Width = 1400, Height = 850,
Content = new CalibrationControl { DataContext = viewModel }
};
window.ShowDialog();
纯算法调用(不使用 UI)
// 棋盘格标定
var calibrator = new ChessboardCalibrator();
calibrator.CalibrateFromImages(imagePaths, boardWidth: 11, boardHeight: 8, squareSize: 15f, out string error);
calibrator.SaveCalibration("camera_calibration.json");
// 九点标定
var processor = new CalibrationProcessor();
processor.Calibrate(points);
var worldPoint = processor.PixelToWorld(new PointF(100, 200));
自定义对话框服务
如需自定义弹框样式,实现 ICalibrationDialogService 接口即可:
public class MyDialogService : ICalibrationDialogService
{
// 实现所有接口方法,使用自定义 UI 组件...
}
核心接口
ICameraController
| 方法 | 说明 |
|---|---|
Open() |
打开连接,返回 CameraInfo |
Close() |
关闭连接(自动停止采集) |
StartGrabbing() |
以软件触发模式启动采集 |
ExecuteSoftwareTrigger() |
触发一帧采集 |
StopGrabbing() |
停止采集 |
Get/SetExposureTime |
曝光时间(微秒) |
Get/SetGain |
增益值 |
Get/SetWidth/Height |
图像尺寸 |
Get/SetPixelFormat |
像素格式(Mono8 / BGR8 / BGRA8) |
事件
| 事件 | 说明 |
|---|---|
ImageGrabbed |
成功采集一帧图像 |
GrabError |
图像采集失败 |
ConnectionLost |
相机连接意外断开 |
所有事件均在非 UI 线程触发,更新 WPF 界面时需通过
Dispatcher.Invoke调度。
异常处理
| 异常类型 | 场景 |
|---|---|
DeviceNotFoundException |
无可用相机 |
ConnectionLostException |
相机物理断开 |
CameraException |
SDK 操作失败(基类) |
扩展其他品牌相机
- 在
Basler/同级创建新文件夹,实现ICameraController接口 - 在
CameraFactory.cs中注册新品牌 - 配置文件切换品牌即可,业务代码无需修改
线程安全
- 所有公共方法均线程安全
- 事件回调不持有内部锁,不会导致死锁
Open()/Close()幂等,重复调用安全