修复CNC结束时导航合成截图归档
This commit is contained in:
@@ -7,7 +7,11 @@ XplorePlane 系统用于控制平面 CT 设备的各个子系统(射线源、
|
|||||||
### 总体架构
|
### 总体架构
|
||||||
|
|
||||||
- 客户端框架: WPF + Prism MVVM(目标框架 net8.0-windows)
|
- 客户端框架: WPF + Prism MVVM(目标框架 net8.0-windows)
|
||||||
- 图像处理内核: ImageProcessing.Core(算子基类)+ ImageProcessing.Processors(具体算子),基于 EmguCV
|
- 图像处理内核: `XP.ImageProcessing.Processors`,基于 Emgu.CV
|
||||||
|
- `Core/`:包含 `ImageProcessorBase`、`ProcessorParameter` 及 ROI/对齐等核心模型和算子基类
|
||||||
|
- 各功能目录:包含图像变换、滤波、增强、边缘检测、检测分析和模板匹配等具体算子
|
||||||
|
- `ImageProcessingService`:负责算子程序集扫描、反射发现、注册及执行
|
||||||
|
- 统一使用 16 位图像处理通道,并通过适配器兼容 8 位算子
|
||||||
- 相机控制: XP.Camera(Basler pylon SDK 封装,支持软件触发、参数读写)
|
- 相机控制: XP.Camera(Basler pylon SDK 封装,支持软件触发、参数读写)
|
||||||
- 硬件抽象: XP.Common + XP.Hardware.RaySource(射线源控制)
|
- 硬件抽象: XP.Common + XP.Hardware.RaySource(射线源控制)
|
||||||
- 日志: Serilog
|
- 日志: Serilog
|
||||||
@@ -27,11 +31,15 @@ XplorePlane.sln
|
|||||||
├── XP.Hardware.RaySource/ # 射线源控制模块
|
├── XP.Hardware.RaySource/ # 射线源控制模块
|
||||||
├── XP.Hardware.RaySource.Comet.Host/ # Comet 射线源独立 Host 进程
|
├── XP.Hardware.RaySource.Comet.Host/ # Comet 射线源独立 Host 进程
|
||||||
├── XP.Hardware.RaySource.Comet.Messages/# Comet Host 通信消息定义
|
├── XP.Hardware.RaySource.Comet.Messages/# Comet Host 通信消息定义
|
||||||
├── XP.ImageProcessing.Core/ # 图像处理算子基类与核心模型
|
├── XP.ImageProcessing.Processors/ # 图像处理核心与具体算子实现
|
||||||
├── XP.ImageProcessing.Processors/ # 具体图像处理算子实现
|
│ ├── Core/ # 算子基类、参数模型、ROI/对齐模型
|
||||||
├── XP.ImageProcessing.CfgControl/ # 图像处理配置控件
|
│ ├── 图像变换/ # 灰度、旋转、镜像、阈值等
|
||||||
├── XP.ImageProcessing.RoiControl/ # ROI 绘制与测量控件
|
│ ├── 滤波处理/ # 滤波算子
|
||||||
├── XP.ImageProcessing.SmokeTest/ # 图像处理冒烟测试程序
|
│ ├── 图像增强/ # 增强算子
|
||||||
|
│ ├── 边缘检测/ # 边缘检测算子
|
||||||
|
│ ├── 检测分析/ # BGA、QFN、空洞率及测量算子
|
||||||
|
│ └── 定位识别/ # 模板匹配和定位算子
|
||||||
|
├── XP.ImageProcessing.RoiControl/ # ROI 绘制与测量控件
|
||||||
├── XP.Scan/ # 扫描模式相关模块
|
├── XP.Scan/ # 扫描模式相关模块
|
||||||
├── XP.Calibration/ # 校准模块
|
├── XP.Calibration/ # 校准模块
|
||||||
├── XP.ReportEngine/ # 报告生成模块
|
├── XP.ReportEngine/ # 报告生成模块
|
||||||
|
|||||||
@@ -779,10 +779,19 @@ namespace XplorePlane.Services.Cnc
|
|||||||
/// 注意:与 HomeAll()(机械回零,驱动轴到机械零点建立坐标系)不同,MoveToSafePosition 是移动到用户配置的坐标。
|
/// 注意:与 HomeAll()(机械回零,驱动轴到机械零点建立坐标系)不同,MoveToSafePosition 是移动到用户配置的坐标。
|
||||||
/// 运动服务不可用时优雅降级(仿真模式直接返回)。
|
/// 运动服务不可用时优雅降级(仿真模式直接返回)。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private BitmapSource GetInspectionMapOverviewImage(BitmapSource fallbackImage)
|
private BitmapSource GetInspectionMapOverviewImage(BitmapSource fallbackImage)
|
||||||
{
|
{
|
||||||
if (_navigationFrameProvider?.TryGetLatestBitmapSource(out var navigationOverview) == true)
|
if (_navigationFrameProvider?.TryCaptureCompositeBitmapSource(out var compositeOverview) == true)
|
||||||
{
|
{
|
||||||
|
_logger.ForModule<CncExecutionService>().Info(
|
||||||
|
"检查标记图 overview 使用导航窗体合成截图:{0}x{1}",
|
||||||
|
compositeOverview.PixelWidth,
|
||||||
|
compositeOverview.PixelHeight);
|
||||||
|
return compositeOverview;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_navigationFrameProvider?.TryGetLatestBitmapSource(out var navigationOverview) == true)
|
||||||
|
{
|
||||||
_logger.ForModule<CncExecutionService>().Info(
|
_logger.ForModule<CncExecutionService>().Info(
|
||||||
"检查标记图 overview 使用导航相机大视野图:{0}x{1}",
|
"检查标记图 overview 使用导航相机大视野图:{0}x{1}",
|
||||||
navigationOverview.PixelWidth,
|
navigationOverview.PixelWidth,
|
||||||
|
|||||||
@@ -10,8 +10,14 @@ namespace XplorePlane.Services.Hardware.Camera
|
|||||||
|
|
||||||
void UpdateFrame(byte[] pixelData, int width, int height, string pixelFormat);
|
void UpdateFrame(byte[] pixelData, int width, int height, string pixelFormat);
|
||||||
void UpdateFrame(BitmapSource bitmap);
|
void UpdateFrame(BitmapSource bitmap);
|
||||||
|
|
||||||
bool TryGetLatestBitmapSource(out BitmapSource bitmap);
|
/// <summary>注册导航窗体的合成截图回调(相机图像 + 标记叠加层)。</summary>
|
||||||
|
void SetCompositeCapture(Func<BitmapSource> capture);
|
||||||
|
|
||||||
|
/// <summary>获取导航窗体当前实际渲染的合成图像。</summary>
|
||||||
|
bool TryCaptureCompositeBitmapSource(out BitmapSource bitmap);
|
||||||
|
|
||||||
|
bool TryGetLatestBitmapSource(out BitmapSource bitmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>导航摄像头帧提供器</summary>
|
/// <summary>导航摄像头帧提供器</summary>
|
||||||
@@ -26,8 +32,37 @@ namespace XplorePlane.Services.Hardware.Camera
|
|||||||
private int _height;
|
private int _height;
|
||||||
private string _pixelFormat = string.Empty;
|
private string _pixelFormat = string.Empty;
|
||||||
private BitmapSource _bitmap;
|
private BitmapSource _bitmap;
|
||||||
|
private Func<BitmapSource> _compositeCapture;
|
||||||
|
|
||||||
public DateTime? LatestCapturedAtUtc { get; private set; }
|
public DateTime? LatestCapturedAtUtc { get; private set; }
|
||||||
|
|
||||||
|
public void SetCompositeCapture(Func<BitmapSource> capture)
|
||||||
|
{
|
||||||
|
lock (_syncRoot)
|
||||||
|
{
|
||||||
|
_compositeCapture = capture;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryCaptureCompositeBitmapSource(out BitmapSource bitmap)
|
||||||
|
{
|
||||||
|
Func<BitmapSource> capture;
|
||||||
|
lock (_syncRoot)
|
||||||
|
{
|
||||||
|
capture = _compositeCapture;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
bitmap = capture?.Invoke();
|
||||||
|
return bitmap != null && bitmap.PixelWidth > 0 && bitmap.PixelHeight > 0;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
bitmap = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void UpdateFrame(byte[] pixelData, int width, int height, string pixelFormat)
|
public void UpdateFrame(byte[] pixelData, int width, int height, string pixelFormat)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ using System.Windows.Controls;
|
|||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
using System.Windows.Media.Imaging;
|
using System.Windows.Media.Imaging;
|
||||||
|
using XplorePlane.Services.Hardware.Camera;
|
||||||
using XplorePlane.Services.Hardware.Coordinate;
|
using XplorePlane.Services.Hardware.Coordinate;
|
||||||
using XplorePlane.Views.Main.Overlays;
|
using XplorePlane.Views.Main.Overlays;
|
||||||
|
|
||||||
@@ -54,6 +55,17 @@ namespace XplorePlane.Views.Main
|
|||||||
ResolveViewModel();
|
ResolveViewModel();
|
||||||
AttachMarkOverlay();
|
AttachMarkOverlay();
|
||||||
|
|
||||||
|
// 将导航窗体实际渲染结果注册给 CNC 归档服务,包含标记叠加层。
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var frameProvider = AppBootstrapper.Instance?.Container.Resolve<INavigationCameraFrameProvider>();
|
||||||
|
frameProvider?.SetCompositeCapture(CaptureCompositeImage);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_diag.Warning(ex, "注册导航合成截图回调失败");
|
||||||
|
}
|
||||||
|
|
||||||
// 订阅 ViewModel 属性变化,驱动红十字线位置更新
|
// 订阅 ViewModel 属性变化,驱动红十字线位置更新
|
||||||
if (_viewModel != null)
|
if (_viewModel != null)
|
||||||
{
|
{
|
||||||
@@ -71,6 +83,9 @@ namespace XplorePlane.Views.Main
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private BitmapSource? CaptureCompositeImage()
|
private BitmapSource? CaptureCompositeImage()
|
||||||
{
|
{
|
||||||
|
if (!Dispatcher.CheckAccess())
|
||||||
|
return Dispatcher.Invoke(CaptureCompositeImage);
|
||||||
|
|
||||||
var target = cameraDisplayHost;
|
var target = cameraDisplayHost;
|
||||||
if (target == null)
|
if (target == null)
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
Reference in New Issue
Block a user