150 lines
5.4 KiB
C#
150 lines
5.4 KiB
C#
using Check.Main.Camera;
|
||
using Check.Main.Common;
|
||
using System;
|
||
using System.Collections.Concurrent;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using System.Text;
|
||
using System.Threading.Tasks;
|
||
|
||
namespace Check.Main.Infer
|
||
{
|
||
public static class DetectionCoordinator
|
||
{
|
||
/// <summary>
|
||
/// 定义存储所有相机处理器的字典
|
||
/// 键是相机的唯一编号 (CameraIndex),值是对应的处理器实例。
|
||
/// </summary>
|
||
private static ConcurrentDictionary<int, CameraProcessor> _processors = new ConcurrentDictionary<int, CameraProcessor>();
|
||
/// <summary>
|
||
/// 用于在产品组装时进行同步,确保线程安全
|
||
/// </summary>
|
||
private static ConcurrentDictionary<long, ProductAssembly> _productAssemblies = new ConcurrentDictionary<long, ProductAssembly>();
|
||
/// <summary>
|
||
/// 可用的相机数量
|
||
/// </summary>
|
||
private static int _enabledCameraCount = 0;
|
||
|
||
public static event EventHandler<DetectionResultEventArgs> OnDetectionCompleted;
|
||
public static bool IsDetectionRunning { get; private set; } = false;
|
||
|
||
// OnDetectionCompleted 事件现在也属于这里
|
||
//public static event EventHandler<DetectionResultEventArgs> OnDetectionCompleted;
|
||
|
||
public static void StartDetection()
|
||
{
|
||
if (!IsDetectionRunning)
|
||
{
|
||
IsDetectionRunning = true;
|
||
ThreadSafeLogger.Log("检测统计已启动。");
|
||
}
|
||
}
|
||
|
||
public static void StopDetection()
|
||
{
|
||
if (IsDetectionRunning)
|
||
{
|
||
IsDetectionRunning = false;
|
||
ThreadSafeLogger.Log("检测统计已停止。");
|
||
}
|
||
}
|
||
public static void Initialize(List<CameraSettings> cameraSettings, List<ModelSettings> modelSettings)
|
||
{
|
||
Shutdown(); // 先关闭旧的
|
||
var enabledCameras = cameraSettings.Where(c => c.IsEnabled).ToList();
|
||
_enabledCameraCount = enabledCameras.Count;
|
||
if (_enabledCameraCount == 0) return;
|
||
|
||
foreach (var camSetting in enabledCameras)
|
||
{
|
||
// 找到与相机编号匹配的模型
|
||
var model = modelSettings.FirstOrDefault(m => m.Id == camSetting.ModelID);
|
||
if (model == null)
|
||
{
|
||
ThreadSafeLogger.Log($"[警告] 找不到与相机 #{camSetting.CameraIndex} 匹配的模型,该相机将无法处理图像。");
|
||
continue;
|
||
}
|
||
|
||
var processor = new CameraProcessor(camSetting.CameraIndex,camSetting.ModelID);
|
||
_processors.TryAdd(camSetting.CameraIndex, processor);
|
||
processor.Start();
|
||
}
|
||
ThreadSafeLogger.Log($"检测协调器已初始化,启动了 {_processors.Count} 个相机处理线程。");
|
||
}
|
||
|
||
public static void EnqueueImage(int cameraIndex, Bitmap bmp)
|
||
{
|
||
if (_processors.TryGetValue(cameraIndex, out var processor))
|
||
{
|
||
processor.EnqueueImage(bmp);
|
||
}
|
||
else
|
||
{
|
||
// 如果找不到处理器,必须释放Bitmap防止泄漏
|
||
bmp?.Dispose();
|
||
}
|
||
}
|
||
|
||
// 供 CameraProcessor 回调,用以组装产品
|
||
public static void AssembleProduct(ImageData data, string result)
|
||
{
|
||
var assembly = _productAssemblies.GetOrAdd(data.ProductId, (id) => new ProductAssembly(id, _enabledCameraCount));
|
||
|
||
if (assembly.AddResult(data.CameraIndex, result))
|
||
{
|
||
string finalResult = assembly.GetFinalResult();
|
||
ThreadSafeLogger.Log($"产品 #{assembly.ProductId} 已检测完毕,最终结果: {finalResult}");
|
||
|
||
// 只有在检测运行时,才触发事件
|
||
if (IsDetectionRunning)
|
||
{
|
||
OnDetectionCompleted?.Invoke(null, new DetectionResultEventArgs(finalResult == "OK"));
|
||
}
|
||
|
||
if (_productAssemblies.TryRemove(assembly.ProductId, out var finishedAssembly))
|
||
{
|
||
finishedAssembly.Dispose();
|
||
}
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 命令所有活动的相机处理器重置它们的内部计数器。
|
||
/// </summary>
|
||
public static void ResetAllCounters()
|
||
{
|
||
foreach (var processor in _processors.Values)
|
||
{
|
||
processor.ResetCounter();
|
||
}
|
||
ThreadSafeLogger.Log("所有相机处理器的产品计数器已重置。");
|
||
}
|
||
|
||
public static CameraProcessor GetProcessor(int cameraIndex)
|
||
{
|
||
_processors.TryGetValue(cameraIndex, out var p);
|
||
return p;
|
||
}
|
||
public static IEnumerable<CameraProcessor> GetAllProcessors()
|
||
{
|
||
return _processors.Values;
|
||
}
|
||
|
||
|
||
public static void Shutdown()
|
||
{
|
||
foreach (var processor in _processors.Values)
|
||
{
|
||
processor.Dispose();
|
||
}
|
||
_processors.Clear();
|
||
|
||
foreach (var assembly in _productAssemblies.Values)
|
||
{
|
||
assembly.Dispose();
|
||
}
|
||
_productAssemblies.Clear();
|
||
ThreadSafeLogger.Log("检测协调器已关闭。");
|
||
}
|
||
}
|
||
}
|