|
|
@@ -1,6 +1,7 @@
|
|
|
// CameraGroup.cs 相机组线程管理类,控制相机采集和识别的线程运行,开放有算法的接口
|
|
|
using MvCameraControl;
|
|
|
using MvvmScaffoldFrame48.DLL.CameraTools;
|
|
|
+using MvvmScaffoldFrame48.DLL.SystemTools;
|
|
|
using MvvmScaffoldFrame48.Model.ResultModel;
|
|
|
using MvvmScaffoldFrame48.Model.StorageModel.SystemConfig;
|
|
|
using System;
|
|
|
@@ -30,8 +31,10 @@ namespace MvvmScaffoldFrame48.DLL.ThreadManager
|
|
|
public Task CameraTask { get; set; }
|
|
|
//图像处理线程
|
|
|
public Task ProcessingTask { get; set; }
|
|
|
- //图像队列
|
|
|
+ //图像队列-ConcurrentQueue
|
|
|
public ConcurrentQueue<IImage> ImageQueue { get; set; }
|
|
|
+ //图像队列-自定义RingBuffer
|
|
|
+ public RingBuffer<IImage> ImageRingBuffer { get; set; }
|
|
|
//信号量
|
|
|
public SemaphoreSlim QueueSemaphore { get; set; }
|
|
|
//取消令牌
|
|
|
@@ -71,9 +74,10 @@ namespace MvvmScaffoldFrame48.DLL.ThreadManager
|
|
|
// 根据配置加载算法
|
|
|
LoadAlgorithmFromConfiguration();
|
|
|
|
|
|
- Camera.FrameGrabbedEvent += CameraCaptureLoop;
|
|
|
+ //ImageRingBuffer = new RingBuffer<IImage>(300);
|
|
|
|
|
|
//Camera.StartReceiveFuntion();
|
|
|
+ Camera.FrameGrabbedEvent += CameraCaptureLoop;
|
|
|
Camera.StartReceiveFuntionSetFrameGrabedEvent();
|
|
|
|
|
|
// 重置取消令牌
|
|
|
@@ -326,6 +330,34 @@ namespace MvvmScaffoldFrame48.DLL.ThreadManager
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// 相机回调取图
|
|
|
+ /// 更换了存储图像的队列
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="sender"></param>
|
|
|
+ /// <param name="e"></param>
|
|
|
+ private void CameraCaptureLoop2(object sender, FrameGrabbedEventArgs e)
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ // 将图像放入队列
|
|
|
+ ImageRingBuffer.TryEnqueue(e.FrameOut.Image.Clone() as IImage);
|
|
|
+ double QuTuYanshi = (DateTime.Now - FromUnixTimestamp((long)e.FrameOut.HostTimeStamp)).TotalMilliseconds;
|
|
|
+ //Console.WriteLine($"相机 {CameraId} 采集到图像,帧号{imageData.FrameNum}");
|
|
|
+ if (QuTuYanshi > 12)
|
|
|
+ {
|
|
|
+ Console.WriteLine($"识别落后时间{QuTuYanshi}");
|
|
|
+ }
|
|
|
+ QueueSemaphore.Release(); // 通知处理线程有新数据
|
|
|
+ e.FrameOut.Dispose();
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ Console.WriteLine($"相机 {CameraId} 采集异常: {ex.Message}");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
/// <summary>
|
|
|
/// 图像处理循环
|
|
|
/// 适用取图频率不高的处理,或者处理速度远快于取图速度的方法
|
|
|
@@ -417,6 +449,55 @@ namespace MvvmScaffoldFrame48.DLL.ThreadManager
|
|
|
Console.WriteLine($"相机 {CameraId} 处理异常: {ex.Message}");
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ private async void ImageProcessingbatchLoop2(CancellationToken token)
|
|
|
+ {
|
|
|
+ const int batchSize = 5; // 每批处理的最大图像数量
|
|
|
+ var batch = new List<IImage>(batchSize); // 存储当前批次的图像
|
|
|
+
|
|
|
+ try
|
|
|
+ {
|
|
|
+ while (!token.IsCancellationRequested)
|
|
|
+ {
|
|
|
+ // 等待至少一张图像数据
|
|
|
+ await QueueSemaphore.WaitAsync(token);
|
|
|
+
|
|
|
+ // 收集一批图像(严格按队列顺序)
|
|
|
+ while (batch.Count < batchSize && ImageRingBuffer.TryDequeue(out IImage imageData))
|
|
|
+ {
|
|
|
+ batch.Add(imageData);
|
|
|
+ if (ImageRingBuffer.Count > 0)
|
|
|
+ {
|
|
|
+ QueueSemaphore.Release(); // 提前释放信号量,唤醒其他等待线程
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 顺序处理当前批次的所有图像
|
|
|
+ foreach (var image in batch)
|
|
|
+ {
|
|
|
+ ProcessImage(image, CameraId); // 严格按顺序执行处理逻辑
|
|
|
+ image.Dispose(); // 处理完成后立即释放资源
|
|
|
+ }
|
|
|
+
|
|
|
+ // 清空当前批次,准备下一轮处理
|
|
|
+ batch.Clear();
|
|
|
+
|
|
|
+ // 如果队列为空,短暂休眠以避免过度占用CPU
|
|
|
+ if (ImageRingBuffer.Count == 0)
|
|
|
+ {
|
|
|
+ await Task.Delay(1, token); // 固定短时间休眠
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch (OperationCanceledException)
|
|
|
+ {
|
|
|
+ // 线程被取消,正常退出
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ Console.WriteLine($"相机 {CameraId} 处理异常: {ex.Message}");
|
|
|
+ }
|
|
|
+ }
|
|
|
#endregion
|
|
|
|
|
|
public DateTime FromUnixTimestamp(long timestamp, bool isMilliseconds = false)
|