Kaynağa Gözat

20260210001 修改线程间传送的数据类型,更改为传输完整的帧信息用于帧数据的判断。修改历史数据保存逻辑。颗粒数据添加了开始帧时间和结束帧时间的记录。

向羽 孟 2 hafta önce
ebeveyn
işleme
430bd30551

+ 1 - 1
MvvmScaffoldFrame48.DLL/ImageAlgorithm/ProcessingAlgorithm.cs

@@ -31,7 +31,7 @@ namespace MvvmScaffoldFrame48.DLL.ThreadManager
         #endregion
 
         #region 公开方法
-        public object ProcessImage(IImage imageData, int cameraId)
+        public object ProcessImage(IFrameOut imageData, int cameraId)
         {
             // 使用当前参数进行图像处理
             Console.WriteLine($"AlgorithmA 处理图像: 阈值={_threshold}, 最小面积={_minArea}");

+ 54 - 24
MvvmScaffoldFrame48.DLL/ImageAlgorithm/ProcessingAlgorithm_CCDShuLi.cs

@@ -1,5 +1,6 @@
 using MvCameraControl;
 using MvvmScaffoldFrame48.DLL.LogTools;
+using MvvmScaffoldFrame48.DLL.SystemTools;
 using MvvmScaffoldFrame48.DLL.ThreadManager;
 using MvvmScaffoldFrame48.Model.StorageModel.ImageAlgorithm.ShuLI;
 using System;
@@ -22,6 +23,12 @@ namespace MvvmScaffoldFrame48.DLL.ImageAlgorithm
         private long currentLine = 0; //行数记录
         private int ObjectNum = 0;
         private int ChannelWidth = 0;//每个区域的宽度
+        public int HistoryNum { get { return _HistoryNum; } }
+        private int _HistoryNum = 0;
+        public int HistoryOkNum {  get { return _HistoryOkNum; } }
+        private int _HistoryOkNum = 0;
+        public int HistoryNgNum {  get { return _HistoryNgNum; } }
+        private int _HistoryNgNum = 0;
         private ShuLiConfigClassModel shuLiConfig = new ShuLiConfigClassModel();
         public List<int> ChannelsRoi { get { return _ChannelsRoi; } }
         private List<int> _ChannelsRoi = new List<int>();
@@ -43,7 +50,7 @@ namespace MvvmScaffoldFrame48.DLL.ImageAlgorithm
             throw new NotImplementedException();
         }
 
-        public object ProcessImage(IImage imageData, int cameraId)
+        public object ProcessImage(IFrameOut imageData, int cameraId)
         {
             bool result = ProcessImageSequence(imageData, out List<ActiveObjectClassModel> resultValue);
             if (result)
@@ -63,10 +70,10 @@ namespace MvvmScaffoldFrame48.DLL.ImageAlgorithm
         /// <param name="ImageWidth">图像宽</param>
         /// <param name="currentLine">当前行数</param>
         /// <returns>检测到的物体总数</returns>
-        public bool ProcessImageSequence(IImage image,out List<ActiveObjectClassModel> resultValue)
+        public bool ProcessImageSequence(IFrameOut image,out List<ActiveObjectClassModel> resultValue)
         {
             bool result = false;
-            for (int i = 0; i < image.Height; i++)
+            for (int i = 0; i < image.Image.Height; i++)
             {
                 ProcessLine(image, i);
                 currentLine += 1;
@@ -76,6 +83,7 @@ namespace MvvmScaffoldFrame48.DLL.ImageAlgorithm
             lostObjects = activeObjects
                 .Where(o => (currentLine - o.LastSeenLine) > shuLiConfig.MAX_GAP || (o.LastSeenLine - o.StartLine) > shuLiConfig.MAX_Idetify_Height)
                 .ToList();
+            lostObjects.ForEach(o => activeObjects.Remove(o));
 
             resultValue = new List<ActiveObjectClassModel>();
 
@@ -92,10 +100,16 @@ namespace MvvmScaffoldFrame48.DLL.ImageAlgorithm
                         continue;
                     }
                     //转为历史物体,添加缺少的参数
-                    item.Num = Interlocked.Increment(ref ObjectNum) + 1;
+                    item.Num = Interlocked.Increment(ref ObjectNum);
                     //item.ChannelNO = ActiveChannel(item);
                     item.EndCheckTime = DateTime.Now;
                     item.MaxLength = GetActionMaxLength(item.RowsData);
+                    item.PictureEndReadTime = TimeStampTools.FromUnixTimestamp((long)image.HostTimeStamp);
+                    var QutuYanshiTime = (DateTime.Now - item.PictureEndReadTime).TotalMilliseconds;
+                    if (QutuYanshiTime > 30)
+                    {
+                        Console.WriteLine($"结果输出延时超过了30ms,耗时{QutuYanshiTime}");
+                    }
                     if ((item.LastSeenLine - item.StartLine) > shuLiConfig.MAX_Idetify_Height)
                     {
                         item.StateCode = 7;
@@ -168,8 +182,6 @@ namespace MvvmScaffoldFrame48.DLL.ImageAlgorithm
 
             // 累加到总数并从活跃物体转移到历史物体
             resultValue.ForEach(o => TryAdd(historyActiveObjects, o, 2500));
-            //lostObjects.Where(o => o.StateCode != 7 && o.StateCode != 9).ToList().ForEach(o => TryAdd(historyActiveObjects, o, 2500));
-            lostObjects.ForEach(o => activeObjects.Remove(o));
 
             return result;
         }
@@ -180,16 +192,16 @@ namespace MvvmScaffoldFrame48.DLL.ImageAlgorithm
         /// 返回值为true的时候有活跃物体转变为历史物体
         /// </summary>
         /// <param name="image">当前行像素数组</param>
-        private bool ProcessLine(IImage imagedata, int RowNo)
+        private bool ProcessLine(IFrameOut imagedata, int RowNo)
         {
             Stopwatch stopwatch = Stopwatch.StartNew();
             bool result = false;
             // 步骤1:检测当前行的有效区域
-            var currentRegions = FindValidRegions(imagedata, RowNo);
+            var currentRegions = FindValidRegions(imagedata.Image, RowNo);
 
             if (currentRegions.Count == 1)
             {
-                if (currentRegions[0].End - (currentRegions[0]).Start + 1 == imagedata.Width)
+                if (currentRegions[0].End - (currentRegions[0]).Start + 1 == imagedata.Image.Width)
                 {
                     if (!IsPrintLightOnError)
                     {
@@ -231,6 +243,7 @@ namespace MvvmScaffoldFrame48.DLL.ImageAlgorithm
                             LastSeenLineEndCol = matcheds.Max(o => o.LastSeenLineEndCol),
                             StartCheckTime = matcheds.Min(o => o.StartCheckTime),
                             EndCheckTime = matcheds.Max(o => o.EndCheckTime),
+                            PictureStartReadTime = matcheds.Min(o=>o.PictureStartReadTime),
                             Area = matcheds.Sum(o => o.Area),
                             RowsData = CopeRowsData,
                             ImageWidth = matcheds.FirstOrDefault().ImageWidth,
@@ -264,26 +277,27 @@ namespace MvvmScaffoldFrame48.DLL.ImageAlgorithm
                     }
                     else
                     {
-                        // 创建新物体(首次出现的区域)
-                        activeObjects.Add(new ActiveObjectClassModel
-                        {
-                            MinStartCol = region.Start,
-                            MaxEndCol = region.End,
-                            StartLine = currentLine,
-                            LastSeenLine = currentLine,
-                            LastSeenLineStartCol = region.Start,
-                            LastSeenLineEndCol = region.End,
-                            StartCheckTime = DateTime.Now,
-                            Area = region.End - region.Start + 1,
-                            ImageWidth = shuLiConfig.ImageWidth,
-                            RowsData = new List<RowStartEndColModel> {
+                    // 创建新物体(首次出现的区域)
+                    activeObjects.Add(new ActiveObjectClassModel
+                    {
+                        MinStartCol = region.Start,
+                        MaxEndCol = region.End,
+                        StartLine = currentLine,
+                        LastSeenLine = currentLine,
+                        LastSeenLineStartCol = region.Start,
+                        LastSeenLineEndCol = region.End,
+                        StartCheckTime = DateTime.Now,
+                        PictureStartReadTime = TimeStampTools.FromUnixTimestamp((long)imagedata.HostTimeStamp),
+                        Area = region.End - region.Start + 1,
+                        ImageWidth = shuLiConfig.ImageWidth,
+                        RowsData = new List<RowStartEndColModel> {
                                 new RowStartEndColModel {
                                     StartCol = region.Start,
                                     EndCol = region.End,
                                     RowsCol = currentLine,
                                 }
                             }
-                        });
+                    });
                     }
                 }
             //}
@@ -385,12 +399,28 @@ namespace MvvmScaffoldFrame48.DLL.ImageAlgorithm
             return !(region.End < obj.LastSeenLineStartCol || region.Start > obj.LastSeenLineEndCol);
         }
 
+        /// <summary>
+        /// 历史数据队列添加数据
+        /// </summary>
+        /// <param name="list">历史数据队列</param>
+        /// <param name="item">添加的数据</param>
+        /// <param name="maxSize">队列最大数据量</param>
+        /// <returns></returns>
         private bool TryAdd(List<ActiveObjectClassModel> list, ActiveObjectClassModel item, int maxSize)
         {
             list.Add(item);
+            Interlocked.Increment(ref _HistoryNum);
+            if(item.StateCode == 0)
+            {
+                Interlocked.Increment(ref _HistoryOkNum);
+            }
+            else
+            {
+                Interlocked.Increment(ref _HistoryNgNum);
+            }
             if (list.Count > maxSize)
             {
-                list[list.Count - maxSize].RowsData.Clear();
+                list.Remove(list[list.Count - maxSize]);
             }
             return true;
         }

+ 11 - 11
MvvmScaffoldFrame48.DLL/ThreadManager/CameraGroup.cs

@@ -35,9 +35,9 @@ namespace MvvmScaffoldFrame48.DLL.ThreadManager
         //图像处理线程
         public Task ProcessingTask { get; set; }
         //图像队列-ConcurrentQueue
-        public ConcurrentQueue<IImage> ImageQueue { get; set; }
+        public ConcurrentQueue<IFrameOut> ImageQueue { get; set; }
         //图像队列-自定义RingBuffer
-        public LockFreeRingBuffer<IImage> ImageRingBuffer = new LockFreeRingBuffer<IImage>(300);
+        public LockFreeRingBuffer<IFrameOut> ImageRingBuffer = new LockFreeRingBuffer<IFrameOut>(30);
         //信号量
         public SemaphoreSlim QueueSemaphore { get; set; }
         //取消令牌
@@ -231,7 +231,7 @@ namespace MvvmScaffoldFrame48.DLL.ThreadManager
         /// <summary>
         /// 图像处理实现
         /// </summary>
-        private void ProcessImage(IImage imageData, int cameraId)
+        private void ProcessImage(IFrameOut imageData, int cameraId)
         {
             object resultData = null;
 
@@ -281,7 +281,7 @@ namespace MvvmScaffoldFrame48.DLL.ThreadManager
                     if (Camera.GetOnceImage(out IFrameOut imageData))
                     {
                         // 将图像放入队列
-                        ImageQueue.Enqueue(imageData.Image.Clone() as IImage);
+                        ImageQueue.Enqueue(imageData.Clone() as IFrameOut);
                         double QuTuYanshi = (DateTime.Now - TimeStampTools.FromUnixTimestamp((long)imageData.HostTimeStamp)).TotalMilliseconds;
                         //Console.WriteLine($"相机 {CameraId} 采集到图像,帧号{imageData.FrameNum}");
                         if(QuTuYanshi > 12)
@@ -316,7 +316,7 @@ namespace MvvmScaffoldFrame48.DLL.ThreadManager
             try
             {
                 // 将图像放入队列
-                ImageQueue.Enqueue(e.FrameOut.Image.Clone() as IImage);
+                ImageQueue.Enqueue(e.FrameOut.Clone() as IFrameOut);
                 double QuTuYanshi = (DateTime.Now - TimeStampTools.FromUnixTimestamp((long)e.FrameOut.HostTimeStamp)).TotalMilliseconds;
                 //Console.WriteLine($"相机 {CameraId} 采集到图像,帧号{imageData.FrameNum}");
                 if (QuTuYanshi > 12)
@@ -343,7 +343,7 @@ namespace MvvmScaffoldFrame48.DLL.ThreadManager
             try
             {
                 // 将图像放入队列
-                ImageRingBuffer.TryEnqueue(e.FrameOut.Image.Clone() as IImage);
+                ImageRingBuffer.TryEnqueue(e.FrameOut.Clone() as IFrameOut);
                 double QuTuYanshi = (DateTime.Now - TimeStampTools.FromUnixTimestamp((long)e.FrameOut.HostTimeStamp)).TotalMilliseconds;
                 //Console.WriteLine($"相机 {CameraId} 采集到图像,帧号{imageData.FrameNum}");
                 if (QuTuYanshi > 12)
@@ -391,7 +391,7 @@ namespace MvvmScaffoldFrame48.DLL.ThreadManager
                     await QueueSemaphore.WaitAsync(token);
 
                     // 从队列获取图像
-                    if (ImageQueue.TryDequeue(out IImage imageData))
+                    if (ImageQueue.TryDequeue(out IFrameOut imageData))
                     {
                         // 执行图像处理逻辑
                         ProcessImage(imageData, CameraId);
@@ -423,7 +423,7 @@ namespace MvvmScaffoldFrame48.DLL.ThreadManager
         private async void ImageProcessingbatchLoop(CancellationToken token)
         {
             const int batchSize = 5; // 每批处理的最大图像数量
-            var batch = new List<IImage>(batchSize); // 存储当前批次的图像
+            var batch = new List<IFrameOut>(batchSize); // 存储当前批次的图像
 
             try
             {
@@ -433,7 +433,7 @@ namespace MvvmScaffoldFrame48.DLL.ThreadManager
                     await QueueSemaphore.WaitAsync(token);
 
                     // 收集一批图像(严格按队列顺序)
-                    while (batch.Count < batchSize && ImageQueue.TryDequeue(out IImage imageData))
+                    while (batch.Count < batchSize && ImageQueue.TryDequeue(out IFrameOut imageData))
                     {
                         batch.Add(imageData);
                         if (ImageQueue.Count > 0)
@@ -472,7 +472,7 @@ namespace MvvmScaffoldFrame48.DLL.ThreadManager
         private async void ImageProcessingbatchLoop2(CancellationToken token)
         {
             const int batchSize = 5; // 每批处理的最大图像数量
-            var batch = new List<IImage>(batchSize); // 存储当前批次的图像
+            var batch = new List<IFrameOut>(batchSize); // 存储当前批次的图像
 
             try
             {
@@ -482,7 +482,7 @@ namespace MvvmScaffoldFrame48.DLL.ThreadManager
                     await QueueSemaphore.WaitAsync(token);
 
                     // 收集一批图像(严格按队列顺序)
-                    while (batch.Count < batchSize && ImageRingBuffer.TryDequeue(out IImage imageData))
+                    while (batch.Count < batchSize && ImageRingBuffer.TryDequeue(out IFrameOut imageData))
                     {
                         if (imageData == null) continue;
                         batch.Add(imageData);

+ 1 - 1
MvvmScaffoldFrame48.DLL/ThreadManager/IImageProcessingAlgorithmHikVision.cs

@@ -16,7 +16,7 @@ namespace MvvmScaffoldFrame48.DLL.ThreadManager
         /// </summary>
         /// <param name="imageData">输入的图像数据</param>
         /// <returns>处理结果</returns>
-        object ProcessImage(IImage imageData,int cameraId);
+        object ProcessImage(IFrameOut imageData,int cameraId);
 
         /// <summary>
         /// 获取算法名称

+ 2 - 2
MvvmScaffoldFrame48.DLL/ThreadManager/ThreadManager.cs

@@ -61,7 +61,7 @@ namespace MvvmScaffoldFrame48.DLL.ThreadManager
                     _cameraGroups[i] = new CameraGroup
                     {
                         CameraId = i,
-                        ImageQueue = new ConcurrentQueue<IImage>(),
+                        ImageQueue = new ConcurrentQueue<IFrameOut>(),
                         QueueSemaphore = new SemaphoreSlim(0),
                         Camera = new HikCamera(),
                         Configuration = cameraConfig
@@ -72,7 +72,7 @@ namespace MvvmScaffoldFrame48.DLL.ThreadManager
                     _cameraGroups[i] = new CameraGroup
                     {
                         CameraId = i,
-                        ImageQueue = new ConcurrentQueue<IImage>(),
+                        ImageQueue = new ConcurrentQueue<IFrameOut>(),
                         QueueSemaphore = new SemaphoreSlim(0),
                         Camera = new HikCamera(cameraInfo),
                         Configuration = cameraConfig

+ 9 - 0
MvvmScaffoldFrame48.MODEL/StorageModel/ImageAlgorithm/ShuLI/ActiveObjectClassModel.cs

@@ -49,6 +49,15 @@ namespace MvvmScaffoldFrame48.Model.StorageModel.ImageAlgorithm.ShuLI
         /// </summary>
         public DateTime EndCheckTime { get; set; }
         /// <summary>
+        /// 颗粒开始帧的帧生成时间
+        /// </summary>
+        public DateTime PictureStartReadTime { get; set; }
+
+        /// <summary>
+        /// 颗粒结束帧的帧生成时间
+        /// </summary>
+        public DateTime PictureEndReadTime { get; set; }
+        /// <summary>
         /// 物体面积
         /// </summary>
         public int Area { get; set; }