探测器XP.Hardware.Detector类库为了更好集成新的探测器,统一接口方法,DetectorService重构为通过统一接口;
新增暗场校正和亮场校正帧数配置属性(默认 64,范围 1-128),config 加载校正帧数; 修正探测器IsConnected连接状态的判断逻辑。
This commit is contained in:
@@ -386,6 +386,44 @@ namespace XP.Hardware.Detector.Abstractions
|
||||
/// </summary>
|
||||
public abstract DetectorInfo GetInfo();
|
||||
|
||||
/// <summary>
|
||||
/// 应用探测器参数 | Apply detector parameters
|
||||
/// </summary>
|
||||
public async Task<DetectorResult> ApplyParametersAsync(int binningIndex, int pga, decimal frameRate, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (Status != DetectorStatus.Ready)
|
||||
{
|
||||
return DetectorResult.Failure($"探测器状态不正确,当前状态:{Status} | Detector status incorrect, current status: {Status}");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return await ApplyParametersInternalAsync(binningIndex, pga, frameRate, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var errorResult = DetectorResult.Failure($"应用参数异常 | Apply parameters exception: {ex.Message}", ex);
|
||||
PublishError(errorResult);
|
||||
return errorResult;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取校正能力描述(子类可重写)| Get correction capabilities (subclass can override)
|
||||
/// </summary>
|
||||
public virtual CorrectionCapabilities GetCorrectionCapabilities()
|
||||
{
|
||||
return new CorrectionCapabilities();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 显式失效校正数据(子类可重写)| Explicitly invalidate correction data (subclass can override)
|
||||
/// </summary>
|
||||
public virtual void InvalidateCorrectionData()
|
||||
{
|
||||
// 默认空实现,子类按需重写 | Default empty implementation, subclass overrides as needed
|
||||
}
|
||||
|
||||
// 模板方法,由子类实现 | Template methods, implemented by derived classes
|
||||
protected abstract Task<DetectorResult> InitializeInternalAsync(CancellationToken cancellationToken);
|
||||
protected abstract Task<DetectorResult> StartAcquisitionInternalAsync(CancellationToken cancellationToken);
|
||||
@@ -395,6 +433,7 @@ namespace XP.Hardware.Detector.Abstractions
|
||||
protected abstract Task<DetectorResult> GainCorrectionInternalAsync(int frameCount, CancellationToken cancellationToken);
|
||||
protected abstract Task<DetectorResult> AutoCorrectionInternalAsync(int frameCount, CancellationToken cancellationToken);
|
||||
protected abstract Task<DetectorResult> BadPixelCorrectionInternalAsync(CancellationToken cancellationToken);
|
||||
protected abstract Task<DetectorResult> ApplyParametersInternalAsync(int binningIndex, int pga, decimal frameRate, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// 更新状态并发布事件 | Update status and publish event
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
namespace XP.Hardware.Detector.Abstractions
|
||||
{
|
||||
/// <summary>
|
||||
/// 校正能力描述 | Correction capabilities description
|
||||
/// 描述探测器支持的校正行为和参数范围,不同探测器可返回不同配置
|
||||
/// </summary>
|
||||
public class CorrectionCapabilities
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否需要在校正前停止采集 | Whether to stop acquisition before correction
|
||||
/// </summary>
|
||||
public bool RequiresStopBeforeCorrection { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 是否需要在暗场校正前应用参数 | Whether to apply parameters before dark correction
|
||||
/// </summary>
|
||||
public bool RequiresParameterApplyBeforeDark { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 亮场校正后是否自动执行坏像素校正 | Auto bad pixel correction after gain correction
|
||||
/// </summary>
|
||||
public bool AutoBadPixelAfterGain { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 停止采集后等待时间(ms)| Post-stop delay (ms)
|
||||
/// </summary>
|
||||
public int PostStopDelayMs { get; set; } = 500;
|
||||
|
||||
/// <summary>
|
||||
/// 暗场校正帧数(从配置文件加载)| Dark correction frame count (loaded from config)
|
||||
/// </summary>
|
||||
public int DarkFrameCount { get; set; } = 64;
|
||||
|
||||
/// <summary>
|
||||
/// 亮场校正帧数(从配置文件加载)| Gain correction frame count (loaded from config)
|
||||
/// </summary>
|
||||
public int GainFrameCount { get; set; } = 64;
|
||||
|
||||
/// <summary>
|
||||
/// 校正帧数最小值 | Correction frame count minimum
|
||||
/// </summary>
|
||||
public int FrameCountMin { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// 校正帧数最大值 | Correction frame count maximum
|
||||
/// </summary>
|
||||
public int FrameCountMax { get; set; } = 128;
|
||||
}
|
||||
}
|
||||
@@ -85,5 +85,26 @@ namespace XP.Hardware.Detector.Abstractions
|
||||
/// </summary>
|
||||
/// <returns>探测器信息 | Detector information</returns>
|
||||
DetectorInfo GetInfo();
|
||||
|
||||
/// <summary>
|
||||
/// 应用探测器参数(Binning/PGA/帧率)| Apply detector parameters (Binning/PGA/FrameRate)
|
||||
/// </summary>
|
||||
/// <param name="binningIndex">Binning 索引 | Binning index</param>
|
||||
/// <param name="pga">PGA 灵敏度值 | PGA sensitivity value</param>
|
||||
/// <param name="frameRate">帧率 | Frame rate</param>
|
||||
/// <param name="cancellationToken">取消令牌 | Cancellation token</param>
|
||||
/// <returns>操作结果 | Operation result</returns>
|
||||
Task<DetectorResult> ApplyParametersAsync(int binningIndex, int pga, decimal frameRate, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// 获取校正能力描述 | Get correction capabilities
|
||||
/// </summary>
|
||||
/// <returns>校正能力描述 | Correction capabilities</returns>
|
||||
CorrectionCapabilities GetCorrectionCapabilities();
|
||||
|
||||
/// <summary>
|
||||
/// 显式失效校正数据(参数变更后调用)| Explicitly invalidate correction data (called after parameter change)
|
||||
/// </summary>
|
||||
void InvalidateCorrectionData();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +48,16 @@ namespace XP.Hardware.Detector.Config
|
||||
config.SavePath = ConfigurationManager.AppSettings["Detector:SavePath"] ?? Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Images");
|
||||
config.AutoSave = bool.TryParse(ConfigurationManager.AppSettings["Detector:AutoSave"], out var autoSave) && autoSave;
|
||||
|
||||
// 加载校正帧数配置(钳位到 1-128)| Load correction frame count config (clamp to 1-128)
|
||||
if (int.TryParse(ConfigurationManager.AppSettings["Detector:Correction:DarkFrameCount"], out var darkFrames))
|
||||
{
|
||||
config.DarkCorrectionFrameCount = Math.Clamp(darkFrames, 1, 128);
|
||||
}
|
||||
if (int.TryParse(ConfigurationManager.AppSettings["Detector:Correction:GainFrameCount"], out var gainFrames))
|
||||
{
|
||||
config.GainCorrectionFrameCount = Math.Clamp(gainFrames, 1, 128);
|
||||
}
|
||||
|
||||
// 验证配置 | Validate configuration
|
||||
var validationResult = ValidateConfiguration(config);
|
||||
if (!validationResult.IsSuccess)
|
||||
|
||||
@@ -34,6 +34,16 @@ namespace XP.Hardware.Detector.Config
|
||||
/// </summary>
|
||||
public bool AutoSave { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 暗场校正帧数(1-128,默认 64)| Dark correction frame count (1-128, default 64)
|
||||
/// </summary>
|
||||
public int DarkCorrectionFrameCount { get; set; } = 64;
|
||||
|
||||
/// <summary>
|
||||
/// 亮场校正帧数(1-128,默认 64)| Gain correction frame count (1-128, default 64)
|
||||
/// </summary>
|
||||
public int GainCorrectionFrameCount { get; set; } = 64;
|
||||
|
||||
/// <summary>
|
||||
/// 获取支持的 Binning 选项(显示名称 → 索引)| Get supported binning options (display name → index)
|
||||
/// 子类可重写以提供不同的选项列表
|
||||
|
||||
@@ -111,6 +111,15 @@ namespace XP.Hardware.Detector.Implementations
|
||||
throw new NotImplementedException("iRay 探测器坏像素校正尚未实现 | iRay detector bad pixel correction not implemented yet");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 应用参数(内部实现)| Apply parameters (internal implementation)
|
||||
/// </summary>
|
||||
protected override Task<DetectorResult> ApplyParametersInternalAsync(int binningIndex, int pga, decimal frameRate, CancellationToken cancellationToken)
|
||||
{
|
||||
// TODO: 实现 iRay 探测器参数应用逻辑 | Implement iRay detector parameter application logic
|
||||
throw new NotImplementedException("iRay 探测器参数应用尚未实现 | iRay detector parameter application not implemented yet");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取探测器信息 | Get detector information
|
||||
/// </summary>
|
||||
|
||||
@@ -1155,6 +1155,115 @@ namespace XP.Hardware.Detector.Implementations
|
||||
|
||||
#endregion
|
||||
|
||||
#region 统一接口实现 | Unified Interface Implementations
|
||||
|
||||
/// <summary>
|
||||
/// 应用参数内部实现 | Apply parameters internal implementation
|
||||
/// </summary>
|
||||
protected override Task<DetectorResult> ApplyParametersInternalAsync(int binningIndex, int pga, decimal frameRate, CancellationToken cancellationToken)
|
||||
{
|
||||
return Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger?.Info($"应用参数:Binning={binningIndex},PGA={pga},帧率={frameRate} | Applying parameters: Binning={binningIndex}, PGA={pga}, FrameRate={frameRate}");
|
||||
|
||||
// 设置 Binning 模式 | Set binning mode
|
||||
var binningMode = (BinningMode)binningIndex;
|
||||
var result = XISLApi.Acquisition_SetCameraBinningMode(_hAcqDesc, (uint)binningMode + 1);
|
||||
if (result != XISLApi.HIS_RETURN.HIS_ALL_OK)
|
||||
{
|
||||
return DetectorResult.Failure($"设置 Binning 模式失败 | Failed to set binning mode: {result}");
|
||||
}
|
||||
|
||||
// Binning 变化时失效校正数据 | Invalidate correction data on binning change
|
||||
if (_binningMode != binningMode)
|
||||
{
|
||||
_logger?.Info($"Binning 模式从 {_binningMode} 变更为 {binningMode},校正数据已失效 | Binning changed, correction data invalidated");
|
||||
InvalidateCorrectionData();
|
||||
}
|
||||
_binningMode = binningMode;
|
||||
|
||||
// 设置增益模式 | Set gain mode
|
||||
var gainMode = (GainMode)pga;
|
||||
result = XISLApi.Acquisition_SetCameraGain(_hAcqDesc, (uint)gainMode);
|
||||
if (result != XISLApi.HIS_RETURN.HIS_ALL_OK)
|
||||
{
|
||||
return DetectorResult.Failure($"设置增益模式失败 | Failed to set gain mode: {result}");
|
||||
}
|
||||
|
||||
// PGA 变化时失效校正数据 | Invalidate correction data on PGA change
|
||||
if (_gainMode != gainMode)
|
||||
{
|
||||
_logger?.Info($"PGA 从 {_gainMode} 变更为 {gainMode},校正数据已失效 | PGA changed, correction data invalidated");
|
||||
InvalidateCorrectionData();
|
||||
}
|
||||
_gainMode = gainMode;
|
||||
|
||||
// 设置曝光时间(帧率→微秒)| Set exposure time (frame rate → microseconds)
|
||||
uint exposureUs = frameRate > 0 ? (uint)(1_000_000m / frameRate) : 66667;
|
||||
result = XISLApi.Acquisition_SetTimerSync(_hAcqDesc, ref exposureUs);
|
||||
if (result != XISLApi.HIS_RETURN.HIS_ALL_OK)
|
||||
{
|
||||
return DetectorResult.Failure($"设置曝光时间失败 | Failed to set exposure time: {result}");
|
||||
}
|
||||
_exposureTime = exposureUs;
|
||||
|
||||
_logger?.Info("参数应用成功 | Parameters applied successfully");
|
||||
return DetectorResult.Success("参数应用成功 | Parameters applied successfully");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return DetectorResult.Failure($"应用参数异常 | Apply parameters exception: {ex.Message}", ex);
|
||||
}
|
||||
}, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取 Varex 校正能力描述 | Get Varex correction capabilities
|
||||
/// </summary>
|
||||
public override CorrectionCapabilities GetCorrectionCapabilities()
|
||||
{
|
||||
return new CorrectionCapabilities
|
||||
{
|
||||
RequiresStopBeforeCorrection = true,
|
||||
RequiresParameterApplyBeforeDark = true,
|
||||
AutoBadPixelAfterGain = true,
|
||||
PostStopDelayMs = 500,
|
||||
DarkFrameCount = _config.DarkCorrectionFrameCount,
|
||||
GainFrameCount = _config.GainCorrectionFrameCount,
|
||||
FrameCountMin = 1,
|
||||
FrameCountMax = 128
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 失效校正数据(释放校正缓冲区)| Invalidate correction data (free correction buffers)
|
||||
/// </summary>
|
||||
public override void InvalidateCorrectionData()
|
||||
{
|
||||
if (_pOffsetBuffer != IntPtr.Zero)
|
||||
{
|
||||
Marshal.FreeHGlobal(_pOffsetBuffer);
|
||||
_pOffsetBuffer = IntPtr.Zero;
|
||||
_offsetBufferRows = 0;
|
||||
_offsetBufferColumns = 0;
|
||||
}
|
||||
if (_pGainBuffer != IntPtr.Zero)
|
||||
{
|
||||
Marshal.FreeHGlobal(_pGainBuffer);
|
||||
_pGainBuffer = IntPtr.Zero;
|
||||
}
|
||||
if (_pCorrList != IntPtr.Zero)
|
||||
{
|
||||
Marshal.FreeHGlobal(_pCorrList);
|
||||
_pCorrList = IntPtr.Zero;
|
||||
}
|
||||
_logger?.Debug("校正数据已失效并释放 | Correction data invalidated and freed");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IVarexDetector 接口实现(占位符)| IVarexDetector Interface Implementations (Placeholders)
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -62,7 +62,11 @@ namespace XP.Hardware.Detector.Services
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
return _detector != null && _detector.Status != DetectorStatus.Uninitialized;
|
||||
if (_detector == null) return false;
|
||||
var status = _detector.Status;
|
||||
return status == DetectorStatus.Ready
|
||||
|| status == DetectorStatus.Acquiring
|
||||
|| status == DetectorStatus.Correcting;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -509,64 +513,44 @@ namespace XP.Hardware.Detector.Services
|
||||
|
||||
var detector = GetDetectorOrThrow();
|
||||
|
||||
// 通过 IVarexDetector 接口下发参数 | Apply parameters via IVarexDetector interface
|
||||
if (detector is IVarexDetector varexDetector)
|
||||
// 如果正在采集,先停止 | Stop acquisition first if running
|
||||
bool wasAcquiring = detector.Status == DetectorStatus.Acquiring;
|
||||
if (wasAcquiring)
|
||||
{
|
||||
// 如果正在采集,先停止(XISL SDK 不允许采集中修改参数)| Stop acquisition first if running (XISL SDK does not allow parameter changes during acquisition)
|
||||
bool wasAcquiring = detector.Status == DetectorStatus.Acquiring;
|
||||
if (wasAcquiring)
|
||||
_logger?.Info("探测器正在采集,先停止采集再应用参数 | Detector is acquiring, stopping before applying parameters");
|
||||
var stopResult = await detector.StopAcquisitionAsync(cancellationToken);
|
||||
if (!stopResult.IsSuccess)
|
||||
{
|
||||
_logger?.Info("探测器正在采集,先停止采集再应用参数 | Detector is acquiring, stopping before applying parameters");
|
||||
var stopResult = await detector.StopAcquisitionAsync(cancellationToken);
|
||||
if (!stopResult.IsSuccess)
|
||||
{
|
||||
_lastError = stopResult;
|
||||
_logger?.Error(stopResult.Exception, "停止采集失败,无法应用参数:{Message} | Failed to stop acquisition, cannot apply parameters: {Message}", stopResult.ErrorMessage);
|
||||
return DetectorResult.Failure($"停止采集失败,无法应用参数 | Failed to stop acquisition, cannot apply parameters: {stopResult.ErrorMessage}");
|
||||
}
|
||||
_lastError = stopResult;
|
||||
_logger?.Error(stopResult.Exception, "停止采集失败,无法应用参数:{Message} | Failed to stop acquisition, cannot apply parameters: {Message}", stopResult.ErrorMessage);
|
||||
return DetectorResult.Failure($"停止采集失败,无法应用参数 | Failed to stop acquisition, cannot apply parameters: {stopResult.ErrorMessage}");
|
||||
}
|
||||
|
||||
// 设置 Binning | Set binning
|
||||
var binningResult = await varexDetector.SetBinningModeAsync((BinningMode)binningIndex);
|
||||
if (!binningResult.IsSuccess)
|
||||
{
|
||||
_lastError = binningResult;
|
||||
return binningResult;
|
||||
}
|
||||
|
||||
// 设置增益(PGA)| Set gain (PGA)
|
||||
var gainResult = await varexDetector.SetGainModeAsync((GainMode)pga);
|
||||
if (!gainResult.IsSuccess)
|
||||
{
|
||||
_lastError = gainResult;
|
||||
return gainResult;
|
||||
}
|
||||
|
||||
// 设置曝光时间(帧率→微秒:1000*1000/帧率)| Set exposure time (frame rate → microseconds)
|
||||
uint exposureUs = frameRate > 0 ? (uint)(1_000_000m / frameRate) : 66667;
|
||||
var exposureResult = await varexDetector.SetExposureTimeAsync(exposureUs);
|
||||
if (!exposureResult.IsSuccess)
|
||||
{
|
||||
_lastError = exposureResult;
|
||||
return exposureResult;
|
||||
}
|
||||
|
||||
// 如果之前在采集,恢复采集 | Resume acquisition if it was running before
|
||||
if (wasAcquiring)
|
||||
{
|
||||
_logger?.Info("参数应用完成,恢复连续采集 | Parameters applied, resuming continuous acquisition");
|
||||
var startResult = await detector.StartAcquisitionAsync(cancellationToken);
|
||||
if (!startResult.IsSuccess)
|
||||
{
|
||||
_logger?.Warn("恢复采集失败:{Message}(参数已成功应用)| Failed to resume acquisition: {Message} (parameters were applied successfully)", startResult.ErrorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
_logger?.Info("参数应用成功 | Parameters applied successfully");
|
||||
return DetectorResult.Success("参数应用成功 | Parameters applied successfully");
|
||||
}
|
||||
|
||||
return DetectorResult.Failure("当前探测器不支持参数下发 | Current detector does not support parameter application");
|
||||
// 通过统一接口下发参数(不依赖具体探测器类型)| Apply parameters via unified interface (no dependency on specific detector type)
|
||||
var result = await detector.ApplyParametersAsync(binningIndex, pga, frameRate, cancellationToken);
|
||||
if (!result.IsSuccess)
|
||||
{
|
||||
_lastError = result;
|
||||
_logger?.Error(result.Exception, "应用参数失败:{Message} | Apply parameters failed: {Message}", result.ErrorMessage);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger?.Info("参数应用成功 | Parameters applied successfully");
|
||||
}
|
||||
|
||||
// 如果之前在采集,恢复采集 | Resume acquisition if it was running before
|
||||
if (wasAcquiring)
|
||||
{
|
||||
_logger?.Info("参数应用完成,恢复连续采集 | Parameters applied, resuming continuous acquisition");
|
||||
var startResult = await detector.StartAcquisitionAsync(cancellationToken);
|
||||
if (!startResult.IsSuccess)
|
||||
{
|
||||
_logger?.Warn("恢复采集失败:{Message}(参数已成功应用)| Failed to resume acquisition: {Message} (parameters were applied successfully)", startResult.ErrorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -640,6 +624,29 @@ namespace XP.Hardware.Detector.Services
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前探测器的校正能力描述 | Get correction capabilities of current detector
|
||||
/// 未初始化时返回基于配置文件的默认值
|
||||
/// </summary>
|
||||
public CorrectionCapabilities GetCorrectionCapabilities()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (_detector != null)
|
||||
{
|
||||
return _detector.GetCorrectionCapabilities();
|
||||
}
|
||||
}
|
||||
|
||||
// 未初始化时从配置文件构建默认值 | Build default from config when not initialized
|
||||
var config = GetCurrentConfig();
|
||||
return new CorrectionCapabilities
|
||||
{
|
||||
DarkFrameCount = config?.DarkCorrectionFrameCount ?? 64,
|
||||
GainFrameCount = config?.GainCorrectionFrameCount ?? 64
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取探测器实例或抛出异常 | Get detector instance or throw exception
|
||||
/// </summary>
|
||||
|
||||
@@ -130,5 +130,11 @@ namespace XP.Hardware.Detector.Services
|
||||
/// </summary>
|
||||
/// <returns>探测器配置,未初始化时返回 null | Detector config, null if not initialized</returns>
|
||||
DetectorConfig GetCurrentConfig();
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前探测器的校正能力描述 | Get correction capabilities of current detector
|
||||
/// </summary>
|
||||
/// <returns>校正能力描述,未初始化时返回默认值 | Correction capabilities, default if not initialized</returns>
|
||||
CorrectionCapabilities GetCorrectionCapabilities();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
@@ -8,6 +8,7 @@ using Prism.Mvvm;
|
||||
using XP.Common.GeneralForm.Views;
|
||||
using XP.Common.Localization;
|
||||
using XP.Common.Logging.Interfaces;
|
||||
using XP.Hardware.Detector.Abstractions;
|
||||
using XP.Hardware.Detector.Abstractions.Events;
|
||||
using XP.Hardware.Detector.Abstractions.Enums;
|
||||
using XP.Hardware.Detector.Config;
|
||||
@@ -420,8 +421,10 @@ namespace XP.Hardware.Detector.ViewModels
|
||||
/// </summary>
|
||||
private void OnDetectorStatusChanged(DetectorStatus status)
|
||||
{
|
||||
// 同步连接状态:非 Uninitialized 即视为已连接 | Sync connection status: connected if not Uninitialized
|
||||
IsConnected = status != DetectorStatus.Uninitialized;
|
||||
// 同步连接状态:只有 Ready、Acquiring、Correcting 视为已连接 | Only Ready, Acquiring, Correcting are considered connected
|
||||
IsConnected = status == DetectorStatus.Ready
|
||||
|| status == DetectorStatus.Acquiring
|
||||
|| status == DetectorStatus.Correcting;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -476,9 +479,9 @@ namespace XP.Hardware.Detector.ViewModels
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 校正采集帧数(固定 64 帧,确保校正质量)| Correction frame count (fixed 64 frames for quality)
|
||||
/// 获取校正帧数(从配置加载)| Get correction frame count (loaded from config)
|
||||
/// </summary>
|
||||
private const int CorrectionFrameCount = 64;
|
||||
private CorrectionCapabilities GetCorrectionCaps() => _detectorService.GetCorrectionCapabilities();
|
||||
|
||||
/// <summary>
|
||||
/// 执行暗场校正 | Execute dark correction
|
||||
@@ -500,7 +503,7 @@ namespace XP.Hardware.Detector.ViewModels
|
||||
|
||||
var binningName = _selectedBinningIndex < BinningItems.Count ? BinningItems[_selectedBinningIndex].DisplayName : "?";
|
||||
_logger?.Info("开始暗场校正,Binning={Binning},PGA={PGA},帧率={FrameRate},校正帧数={FrameCount} | Starting dark correction",
|
||||
binningName, _selectedPga, _frameRate, CorrectionFrameCount);
|
||||
binningName, _selectedPga, _frameRate, GetCorrectionCaps().DarkFrameCount);
|
||||
|
||||
// 显示进度条窗口 | Show progress window
|
||||
var progressWindow = new ProgressWindow(
|
||||
@@ -536,9 +539,9 @@ namespace XP.Hardware.Detector.ViewModels
|
||||
return;
|
||||
}
|
||||
|
||||
// 3. 执行暗场校正(固定 64 帧)| Execute dark correction (fixed 64 frames)
|
||||
// 3. 执行暗场校正 | Execute dark correction
|
||||
progressWindow.UpdateProgress(LocalizationHelper.Get("Detector_Progress_AcquiringDarkData"), 30);
|
||||
var result = await _detectorService.DarkCorrectionAsync(CorrectionFrameCount);
|
||||
var result = await _detectorService.DarkCorrectionAsync(GetCorrectionCaps().DarkFrameCount);
|
||||
|
||||
if (result.IsSuccess)
|
||||
{
|
||||
@@ -616,7 +619,7 @@ namespace XP.Hardware.Detector.ViewModels
|
||||
|
||||
var binningName = _selectedBinningIndex < BinningItems.Count ? BinningItems[_selectedBinningIndex].DisplayName : "?";
|
||||
_logger?.Info("开始亮场校正,Binning={Binning},PGA={PGA},帧率={FrameRate},校正帧数={FrameCount} | Starting light correction",
|
||||
binningName, _selectedPga, _frameRate, CorrectionFrameCount);
|
||||
binningName, _selectedPga, _frameRate, GetCorrectionCaps().GainFrameCount);
|
||||
|
||||
// 显示进度条窗口 | Show progress window
|
||||
var progressWindow = new ProgressWindow(
|
||||
@@ -643,9 +646,9 @@ namespace XP.Hardware.Detector.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
// 1. 执行亮场校正(固定 64 帧)| Execute light correction (fixed 64 frames)
|
||||
// 1. 执行亮场校正 | Execute light correction
|
||||
progressWindow.UpdateProgress(LocalizationHelper.Get("Detector_Progress_AcquiringLightData"), 20);
|
||||
var result = await _detectorService.GainCorrectionAsync(CorrectionFrameCount);
|
||||
var result = await _detectorService.GainCorrectionAsync(GetCorrectionCaps().GainFrameCount);
|
||||
|
||||
if (result.IsSuccess)
|
||||
{
|
||||
|
||||
@@ -97,6 +97,7 @@
|
||||
<telerik:RadButton Grid.Column="1"
|
||||
Content="{loc:Localization Detector_ApplyParametersButton}"
|
||||
Command="{Binding ApplyParametersCommand}"
|
||||
IsEnabled="{Binding IsParametersEditable}"
|
||||
Height="32" HorizontalAlignment="Stretch"
|
||||
telerik:StyleManager.Theme="Crystal" Margin="4 0 0 0"/>
|
||||
</Grid>
|
||||
@@ -115,6 +116,7 @@
|
||||
<telerik:RadButton Grid.Column="0"
|
||||
Content="{loc:Localization Detector_DarkCorrectionButton}"
|
||||
Command="{Binding DarkCorrectionCommand}"
|
||||
IsEnabled="{Binding IsParametersEditable}"
|
||||
Height="32" Margin="0 0 4 0" HorizontalAlignment="Stretch"
|
||||
telerik:StyleManager.Theme="Crystal">
|
||||
<telerik:RadButton.Background>
|
||||
@@ -129,6 +131,7 @@
|
||||
<telerik:RadButton Grid.Column="1"
|
||||
Content="{loc:Localization Detector_LightCorrectionButton}"
|
||||
Command="{Binding LightCorrectionCommand}"
|
||||
IsEnabled="{Binding IsParametersEditable}"
|
||||
Height="32" Margin="4 0 0 0" HorizontalAlignment="Stretch"
|
||||
telerik:StyleManager.Theme="Crystal">
|
||||
<telerik:RadButton.Background>
|
||||
|
||||
@@ -66,7 +66,6 @@
|
||||
<add key="Detector:Port" value="5000" />
|
||||
<add key="Detector:SavePath" value="D:\XplorePlane\DetectorImages" />
|
||||
<add key="Detector:AutoSave" value="true" />
|
||||
<!-- Varex 探测器专属配置 | Varex Detector Specific Configuration -->
|
||||
<!-- Binning 模式: Bin1x1, Bin2x2, Bin4x4 | Binning mode: Bin1x1, Bin2x2, Bin4x4 -->
|
||||
<add key="Detector:Varex:BinningMode" value="Bin1x1" />
|
||||
<!-- 增益模式: Low, High | Gain mode: Low, High -->
|
||||
@@ -78,14 +77,13 @@
|
||||
<add key="Detector:Varex:ROI_Y" value="0" />
|
||||
<add key="Detector:Varex:ROI_Width" value="2880" />
|
||||
<add key="Detector:Varex:ROI_Height" value="2880" />
|
||||
<!-- iRay 探测器专属配置 | iRay Detector Specific Configuration -->
|
||||
<!-- 采集模式: Continuous, SingleFrame | Acquisition mode: Continuous, SingleFrame -->
|
||||
<add key="Detector:IRay:AcquisitionMode" value="Continuous" />
|
||||
<!-- 默认增益值 | Default gain value -->
|
||||
<add key="Detector:IRay:DefaultGain" value="1.0" />
|
||||
<!-- 校正配置 | Correction Configuration -->
|
||||
<add key="Detector:Correction:DarkFrameCount" value="10" />
|
||||
<add key="Detector:Correction:GainFrameCount" value="10" />
|
||||
<add key="Detector:Correction:DarkFrameCount" value="64" />
|
||||
<add key="Detector:Correction:GainFrameCount" value="64" />
|
||||
<add key="Detector:Correction:SaveCorrectionData" value="true" />
|
||||
<!-- 操作超时配置 | Operation Timeout Configuration -->
|
||||
<add key="Detector:InitializationTimeout" value="30000" />
|
||||
|
||||
Reference in New Issue
Block a user