Browse Source

20251213001数粒算法移植

向羽 孟 2 months ago
parent
commit
b624ead040

+ 0 - 0
MvvmScaffoldFrame48.DLL/ThreadManager/ProcessingAlgorithm.cs → MvvmScaffoldFrame48.DLL/ImageAlgorithm/ProcessingAlgorithm.cs


+ 449 - 0
MvvmScaffoldFrame48.DLL/ImageAlgorithm/ProcessingAlgorithm_CCDShuLi.cs

@@ -0,0 +1,449 @@
+using MvCameraControl;
+using MvvmScaffoldFrame48.DLL.LogTools;
+using MvvmScaffoldFrame48.DLL.ThreadManager;
+using MvvmScaffoldFrame48.Model.StorageModel.ImageAlgorithm.ShuLI;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace MvvmScaffoldFrame48.DLL.ImageAlgorithm
+{
+    public class ProcessingAlgorithm_CCDShuLi : IImageProcessingAlgorithmHikVision
+    {
+        private List<ActiveObjectClassModel> activeObjects = new List<ActiveObjectClassModel>(); // 当前跟踪中的物体
+        private List<ActiveObjectClassModel> lostObjects = new List<ActiveObjectClassModel>();
+        private List<ActiveObjectClassModel> historyActiveObjects = new List<ActiveObjectClassModel>(); // 历史物体
+        BoundRectangleClass BoundRectangle = new BoundRectangleClass();
+        private long currentLine = 0; //行数记录
+        private int ObjectNum = 0;
+        private int ChannelWidth = 0;//每个区域的宽度
+        private ShuLiConfigClassModel shuLiConfig = new ShuLiConfigClassModel();
+        public List<int> ChannelsRoi { get { return _ChannelsRoi; } }
+        private List<int> _ChannelsRoi = new List<int>();
+        private bool IsPrintLightOnError = false;
+        public string AlgorithmName => "ProcessingAlgorithm_CCDShuLi";
+
+        public void Configure(string parameters)
+        {
+            throw new NotImplementedException();
+        }
+
+        public object GetParameters()
+        {
+            throw new NotImplementedException();
+        }
+
+        public string GetSaveJson()
+        {
+            throw new NotImplementedException();
+        }
+
+        public object ProcessImage(IImage imageData, int cameraId)
+        {
+            bool result = ProcessImageSequence(imageData, out List<ActiveObjectClassModel> resultValue);
+            if (result)
+            {
+                return resultValue;
+            }
+            else
+            {
+                return null;
+            }
+        }
+
+        /// <summary>
+        /// 处理图像序列的主入口
+        /// </summary>
+        /// <param name="image">图像像素数据</param>
+        /// <param name="ImageWidth">图像宽</param>
+        /// <param name="currentLine">当前行数</param>
+        /// <returns>检测到的物体总数</returns>
+        public bool ProcessImageSequence(IImage image,out List<ActiveObjectClassModel> resultValue)
+        {
+            bool result = false;
+            for (int i = 0; i < image.Height; i++)
+            {
+                ProcessLine(image, i);
+                currentLine += 1;
+            }
+            //识别到结果并输出
+            // 清理超时未更新的物体
+            lostObjects = activeObjects
+                .Where(o => (currentLine - o.LastSeenLine) > shuLiConfig.MAX_GAP || (o.LastSeenLine - o.StartLine) > shuLiConfig.MAX_Idetify_Height)
+                .ToList();
+
+            resultValue = new List<ActiveObjectClassModel>();
+
+            // 有物体转变为活跃物体,返回值转为true
+            if (lostObjects.Count > 0)
+            {
+                foreach (var item in lostObjects)
+                {
+                    //噪点判定
+                    if (item.Area < shuLiConfig.NoiseFilter_Threshold)
+                    {
+                        item.StateCode = 9;
+                        //LOG.log(string.Format("噪点过滤,噪点面积:{0}", item.Area), 6);
+                        continue;
+                    }
+                    //转为历史物体,添加缺少的参数
+                    item.Num = Interlocked.Increment(ref ObjectNum) + 1;
+                    item.ChannelNO = ActiveChannel(item);
+                    item.EndCheckTime = DateTime.Now;
+                    item.MaxLength = GetActionMaxLength(item.RowsData);
+                    if ((item.LastSeenLine - item.StartLine) > shuLiConfig.MAX_Idetify_Height)
+                    {
+                        item.StateCode = 7;
+                        //FaultLog.RecordLogMessage("ShuLiClass-ProcessLine:非颗粒,视野异常", 3);
+                        TxtLog.log(string.Format("ShuLiClass-ProcessLine:非颗粒,视野异常"), 6);
+                        //Console.WriteLine("ShuLiClass-ProcessLine:非颗粒,视野异常");
+                    }
+                    else if (shuLiConfig.PandingCode != -1)
+                    {
+                        if (item.StateCode != -1)
+                        {
+                            if (item.StateCode == 8)
+                            {
+                                TxtLog.log(string.Format("颗粒编号{0}:疑似叠片或缺损", item.Num));
+                            }
+                        }
+                        else if (item.Area < shuLiConfig.MinArea
+                            && (shuLiConfig.PandingCode == 2 || shuLiConfig.PandingCode == 1))
+                        {
+                            item.StateCode = 5;
+                            TxtLog.log(string.Format("颗粒编号{0}:面积过小", item.Num));
+                            Console.WriteLine("颗粒编号{0}:面积过小", item.Num);
+                        }
+                        else if (item.Area > shuLiConfig.MaxArea
+                            && (shuLiConfig.PandingCode == 2 || shuLiConfig.PandingCode == 1))
+                        {
+                            item.StateCode = 6;
+                            TxtLog.log(string.Format("颗粒编号{0}:面积过大", item.Num));
+                            Console.WriteLine("颗粒编号{0}:面积过大", item.Num);
+                        }
+                        else if (item.MaxLength < shuLiConfig.MIN_Object_LENGTH
+                            && (shuLiConfig.PandingCode == 2 || shuLiConfig.PandingCode == 0))
+                        {
+                            item.StateCode = 2;
+                            TxtLog.log(string.Format("颗粒编号{0}:超短粒", item.Num));
+                            Console.WriteLine("颗粒编号{0}:超短粒", item.Num);
+                        }
+                        else if (item.MaxLength > shuLiConfig.MAX_Object_LENGTH
+                            && (shuLiConfig.PandingCode == 2 || shuLiConfig.PandingCode == 0))
+                        {
+                            item.StateCode = 1;
+                            TxtLog.log(string.Format("颗粒编号{0}:超长粒", item.Num));
+                            Console.WriteLine("颗粒编号{0}:超长粒", item.Num);
+                        }
+                        else
+                        {
+                            item.StateCode = 0;
+                            TxtLog.log(string.Format("颗粒编号{0}:正常粒", item.Num));
+                            Console.WriteLine("颗粒编号{0}:正常粒", item.Num);
+                        }
+                    }
+                    resultValue.Add(item);
+                }
+                if (resultValue.Count > 0)
+                {
+                    result = true;
+                    //LOG.log(string.Format("识别完成,首个颗粒编号:{0},颗粒数量:{1}", OneActive[0].Num, OneActive.Count), 6);
+                    //触发回调事件
+                    //Task.Run(() =>
+                    //{
+                    //    OnWorkCompleted(OneActive);
+                    //});
+                    //ThreadPool.QueueUserWorkItem(_ => OnWorkCompleted(OneActive));
+                }
+            }
+            else
+            {
+                resultValue.Clear();
+            }
+
+            // 累加到总数并从活跃物体转移到历史物体
+            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;
+        }
+
+        /// <summary>
+        /// 处理单行像素数据
+        /// 返回值为false的时候无活跃物体转变为历史物体
+        /// 返回值为true的时候有活跃物体转变为历史物体
+        /// </summary>
+        /// <param name="image">当前行像素数组</param>
+        private bool ProcessLine(IImage imagedata, int RowNo)
+        {
+            Stopwatch stopwatch = Stopwatch.StartNew();
+            bool result = false;
+            // 步骤1:检测当前行的有效区域
+            var currentRegions = FindValidRegions(imagedata, RowNo);
+
+            if (currentRegions.Count == 1)
+            {
+                if (currentRegions[0].End - (currentRegions[0]).Start + 1 == imagedata.Width)
+                {
+                    if (!IsPrintLightOnError)
+                    {
+                        //FaultLog.RecordLogMessage("当前行有效区域为整行,检查视野和光源", 5);
+                        IsPrintLightOnError = true;
+                    }
+                    return false;
+                }
+            }
+            IsPrintLightOnError = false;
+            stopwatch.Stop();
+            if (stopwatch.ElapsedMilliseconds > 1)
+            {
+                //FaultLog.RecordErrorMessage($"ShuLiClass-ProcessLine:图像连通域检测超时,此次识别耗时:{stopwatch.Elapsed}");
+            }
+            stopwatch.Restart();
+            //lock (_lockObj)
+            //{
+                foreach (var region in currentRegions)
+                {
+                    // 查找全部可合并的活跃物体(有重叠+在允许间隔内)
+                    var matcheds = activeObjects.Where(o =>
+                        IsOverlapping(o, region) &&
+                        (currentLine - o.LastSeenLine - 1) <= shuLiConfig.MAX_GAP).ToList();
+                    //当有多个可合并的活跃物体时,将多个物体合并
+                    if (matcheds.Count >= 2)
+                    {
+                        // 合并有效区域队列
+                        var CopeRowsData = new List<RowStartEndColModel>();
+                        matcheds.ForEach(o => CopeRowsData = CopeRowsData.Concat(o.RowsData).ToList());
+                        // 合并有效区域并保存在新的区域中
+                        var MergeMatched = new ActiveObjectClassModel
+                        {
+                            MinStartCol = matcheds.Min(o => o.MinStartCol),
+                            MaxEndCol = matcheds.Max(o => o.MaxEndCol),
+                            StartLine = matcheds.Min(o => o.StartLine),
+                            LastSeenLine = matcheds.Max(o => o.LastSeenLine),
+                            LastSeenLineStartCol = matcheds.Min(o => o.LastSeenLineStartCol),
+                            LastSeenLineEndCol = matcheds.Max(o => o.LastSeenLineEndCol),
+                            StartCheckTime = matcheds.Min(o => o.StartCheckTime),
+                            EndCheckTime = matcheds.Max(o => o.EndCheckTime),
+                            Area = matcheds.Sum(o => o.Area),
+                            RowsData = CopeRowsData,
+                            ImageWidth = matcheds.FirstOrDefault().ImageWidth,
+                            //StateCode = 8
+                        };
+                        // 从活跃区域中删除被合并的区域
+                        matcheds.ForEach(o => activeObjects.Remove(o));
+                        // 保存新的区域到活跃区域中
+                        activeObjects.Add(MergeMatched);
+                    }
+
+                    // 搜获可用且可合并的活跃区域
+                    var matched = activeObjects.FirstOrDefault(o =>
+                        IsOverlapping(o, region) &&
+                        (currentLine - o.LastSeenLine - 1) <= shuLiConfig.MAX_GAP);
+                    if (matched != null)
+                    {
+                        // 合并区域:扩展物体边界并更新状态
+                        matched.MinStartCol = Math.Min(matched.MinStartCol, region.Start);
+                        matched.MaxEndCol = Math.Max(matched.MaxEndCol, region.End);
+                        matched.Area += region.End - region.Start + 1;
+                        matched.LastSeenLine = currentLine;
+                        matched.RowsData.Add(new RowStartEndColModel
+                        {
+                            StartCol = region.Start,
+                            EndCol = region.End,
+                            RowsCol = currentLine,
+                        });
+                        matched.LastSeenLineStartCol = region.Start;
+                        matched.LastSeenLineEndCol = region.End;
+                    }
+                    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> {
+                                new RowStartEndColModel {
+                                    StartCol = region.Start,
+                                    EndCol = region.End,
+                                    RowsCol = currentLine,
+                                }
+                            }
+                        });
+                    }
+                }
+            //}
+            stopwatch.Stop();
+            if (stopwatch.ElapsedMilliseconds > 1)
+            {
+                //FaultLog.RecordErrorMessage($"ShuLiClass-ProcessLine:图像区域合并超时,此次识别耗时:{stopwatch.Elapsed}");
+            }
+
+            currentRegions.Clear();
+
+            return result;
+        }
+        List<ValidRegionModel> regions = new List<ValidRegionModel>();
+        /// <summary>
+        /// 检测有效物体区域(横向连续黑色像素段)
+        /// </summary>
+        /// <param name="line">当前行像素数组</param>
+        /// <returns>有效区域列表(起始/结束位置)</returns>
+        private List<ValidRegionModel> FindValidRegions(IImage image, int RowNo)
+        {
+            regions.Clear();
+            int start = -1; // 当前区域起始标记
+            int end = -1;
+            // 遍历所有像素列
+            if (shuLiConfig.IsIdentifyRoiOpen)
+            {
+                for (int i = (int)image.Width * RowNo + shuLiConfig.IdentifyStartX; i < (int)image.Width * RowNo + shuLiConfig.IdentifyStopX; i++)
+                {
+                    if (image.PixelData[i] < shuLiConfig.RegionThreshold) // 发现黑色像素
+                    {
+                        if (start == -1) start = i % (int)image.Width; // 开始新区域
+                    }
+                    else if (start != -1) // 遇到白色像素且存在进行中的区域
+                    {
+                        end = (i - 1) % (int)image.Width;
+                        // 检查区域宽度是否达标
+                        if (end - start >= shuLiConfig.NoiseFilter_Threshold)
+                        {
+                            regions.Add(new ValidRegionModel()
+                            {
+                                Start = start,
+                                End = end
+                            }); // 记录有效区域
+                        }
+                        start = -1; // 重置区域标记
+                        end = -1;
+                    }
+                }
+            }
+            else
+            {
+                for (int i = (int)image.Width * RowNo; i < (int)image.Width * (RowNo + 1); i++)
+                {
+                    if (image.PixelData[i] < shuLiConfig.RegionThreshold) // 发现黑色像素
+                    {
+                        if (start == -1) start = i % (int)image.Width; // 开始新区域
+                    }
+                    else if (start != -1) // 遇到白色像素且存在进行中的区域
+                    {
+                        end = (i - 1) % (int)image.Width;
+                        // 检查区域宽度是否达标
+                        if (end - start >= shuLiConfig.NoiseFilter_Threshold)
+                        {
+                            regions.Add(new ValidRegionModel()
+                            {
+                                Start = start,
+                                End = end
+                            }); // 记录有效区域
+                        }
+                        start = -1; // 重置区域标记
+                        end = -1;
+                    }
+                }
+            }
+
+
+            // 处理行尾未闭合的区域
+            if (start != -1 && image.Width - start >= shuLiConfig.NoiseFilter_Threshold)
+            {
+                regions.Add(new ValidRegionModel()
+                {
+                    Start = start,
+                    End = (int)image.Width - 1
+                });
+            }
+            return regions;
+        }
+
+        /// <summary>
+        /// 判断区域重叠(与活跃物体的横向坐标重叠检测)
+        /// </summary>
+        /// <param name="obj">活跃物体</param>
+        /// <param name="region">当前区域</param>
+        /// <returns>是否发生重叠</returns>
+        private bool IsOverlapping(ActiveObjectClassModel obj, ValidRegionModel region)
+        {
+            // 判断区域是否不相交的逆条件
+            return !(region.End < obj.LastSeenLineStartCol || region.Start > obj.LastSeenLineEndCol);
+        }
+
+        private bool TryAdd(List<ActiveObjectClassModel> list, ActiveObjectClassModel item, int maxSize)
+        {
+            list.Add(item);
+            if (list.Count > maxSize)
+            {
+                list[list.Count - maxSize].RowsData.Clear();
+            }
+            return true;
+        }
+
+        /// <summary>
+        /// 获取结果最长长边
+        /// </summary>
+        /// <param name="Rows"></param>
+        /// <returns></returns>
+        private double GetActionMaxLength(List<RowStartEndColModel> Rows)
+        {
+            //外轮廓点集
+            List<Point> points = Rows.Select(o => new Point(o.StartCol, (int)o.RowsCol)).ToList();
+            points.AddRange(Rows.Select(o => new Point(o.EndCol, (int)o.RowsCol)).ToList());
+            //获取凸包点集
+            points = BoundRectangle.ConvexHull(points);
+            //获取凸包长度最长的外接矩形
+            var result = BoundRectangle.RotatingCalipers(points);
+            if (result != null)
+            {
+                return result.Height;
+            }
+            else
+            {
+                return 0;
+            }
+        }
+
+
+        /// <summary>
+        /// 通道区域判定
+        /// </summary>
+        /// <param name="activeObject"></param>
+        /// <returns></returns>
+        private int ActiveChannel(ActiveObjectClassModel activeObject)
+        {
+            int result = -1;
+            int StartChannel = activeObject.MinStartCol / ChannelWidth;
+            int EndChannel = activeObject.MaxEndCol / ChannelWidth;
+            if (StartChannel == EndChannel)
+            {
+                result = StartChannel;
+            }
+            else if (EndChannel - StartChannel > 1)
+            {
+                Console.WriteLine("ActiveChannel-Error");
+                //error
+            }
+            else
+            {
+                result = _ChannelsRoi[StartChannel] - activeObject.MinStartCol > activeObject.MaxEndCol - _ChannelsRoi[StartChannel] ? StartChannel : EndChannel;
+            }
+            return result;
+        }
+    }
+}

+ 2 - 1
MvvmScaffoldFrame48.DLL/MvvmScaffoldFrame48.Dll.csproj

@@ -86,6 +86,7 @@
     <Compile Include="FileTools\PDFGenerate.cs" />
     <Compile Include="ImageAlgorithm\BoundRectangleClass.cs" />
     <Compile Include="ImageAlgorithm\ImageAlgorithmTools.cs" />
+    <Compile Include="ImageAlgorithm\ProcessingAlgorithm_CCDShuLi.cs" />
     <Compile Include="LogTools\TxtLog.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="SystemTools\SystemRunTimeTools.cs" />
@@ -93,7 +94,7 @@
     <Compile Include="ThreadManager\CommunicationThread.cs" />
     <Compile Include="ThreadManager\IImageProcessingAlgorithmHikVision.cs" />
     <Compile Include="ThreadManager\ImageProcessingAlgorithmHikVisionFactory.cs" />
-    <Compile Include="ThreadManager\ProcessingAlgorithm.cs" />
+    <Compile Include="ImageAlgorithm\ProcessingAlgorithm.cs" />
     <Compile Include="ThreadManager\ThreadManager.cs" />
     <Compile Include="UserManager.cs" />
     <Compile Include="WindowsTools\OnScreenKeyboardTools.cs" />

+ 18 - 3
MvvmScaffoldFrame48.DLL/ThreadManager/CameraGroup.cs

@@ -39,7 +39,7 @@ namespace MvvmScaffoldFrame48.DLL.ThreadManager
         public IImageProcessingAlgorithmHikVision ImageProcessor { get; set; }
         // 结果发送事件,当图像处理完成时触发
         public event EventHandler<CameraProcessEventArgsResultModel> ProcessResultAvailable;
-        // 相机配置
+        // 参数配置
         public CameraProcessConfigModel Configuration { get; set; }
         #endregion
 
@@ -57,6 +57,7 @@ namespace MvvmScaffoldFrame48.DLL.ThreadManager
             if (Camera.Device == null)
             {
                 Console.WriteLine($"相机 {CameraId} 未初始化");
+                return;
             }
             if (Camera.Device.IsConnected == false)
             {
@@ -187,6 +188,17 @@ namespace MvvmScaffoldFrame48.DLL.ThreadManager
             }
         }
 
+        /// <summary>
+        /// 加载相机配置
+        /// </summary>
+        private void LoadCameraConfiguration()
+        { 
+            if(Configuration != null&& !string.IsNullOrEmpty(Configuration.CameraParameters))
+            {
+
+            }
+        }
+
         /// <summary>
         /// 发送处理结果到通信线程的方法
         /// 多个线程可以共用此方法
@@ -226,8 +238,11 @@ namespace MvvmScaffoldFrame48.DLL.ThreadManager
                     // 默认处理逻辑
                 }
 
-                // 发送处理结果
-                SendProcessResult(resultData);
+                if(resultData!=null)
+                {
+                    // 发送处理结果
+                    SendProcessResult(resultData);
+                }
 
                 // 输出处理结果
             }

+ 4 - 0
MvvmScaffoldFrame48.DLL/ThreadManager/IImageProcessingAlgorithmHikVision.cs

@@ -35,6 +35,10 @@ namespace MvvmScaffoldFrame48.DLL.ThreadManager
         /// <returns>参数字典</returns>
         Object GetParameters();
 
+        /// <summary>
+        /// 获取保存的参数
+        /// </summary>
+        /// <returns></returns>
         string GetSaveJson();
     }
 }

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

@@ -1,4 +1,5 @@
 // ImageProcessingAlgorithmFactory.cs 识别算法工厂,用于注册算法实现
+using MvvmScaffoldFrame48.DLL.ImageAlgorithm;
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -22,6 +23,7 @@ namespace MvvmScaffoldFrame48.DLL.ThreadManager
         {
             // 注册所有可用的算法实现
             RegisterAlgorithm<ProcessingAlgorithm>("ProcessingAlgorithm");
+            RegisterAlgorithm<ProcessingAlgorithm_CCDShuLi>("ProcessingAlgorithm_CCDShuLi");
             // 可以继续注册更多算法...
         }
         #endregion

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

@@ -204,7 +204,7 @@ namespace MvvmScaffoldFrame48.DLL.ThreadManager
             var config = new CameraProcessConfigModel
             {
                 CameraId = cameraId,
-                CameraSN = "00E31768761",
+                CameraSN = "K53474176",
                 IsEnabled = true
             };
 
@@ -260,7 +260,6 @@ namespace MvvmScaffoldFrame48.DLL.ThreadManager
                     CreateCameraConfiguration(0, "ProcessingAlgorithm"),
                 };
             }
-
             //XMLReadWrite.SerializeToXml(_cameraConfigurations, "TestConfig.xml");
         }
 
@@ -275,8 +274,6 @@ namespace MvvmScaffoldFrame48.DLL.ThreadManager
             // 可以在这里添加其他处理逻辑,如更新显示等
             Console.WriteLine($"收到相机{e.CameraId}的处理结果");
         }
-
-
         #endregion
     }
 }

+ 3 - 0
MvvmScaffoldFrame48.MODEL/MvvmScaffoldFrame48.Model.csproj

@@ -68,6 +68,9 @@
     <Compile Include="StorageModel\HikVisionCamera\CameraInfoModel.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="StorageModel\ImageAlgorithm\BoundingRectangleMdoel.cs" />
+    <Compile Include="StorageModel\ImageAlgorithm\ShuLI\ActiveObjectClassModel.cs" />
+    <Compile Include="StorageModel\ImageAlgorithm\ShuLI\ShuLiConfigClassModel.cs" />
+    <Compile Include="StorageModel\ImageAlgorithm\ShuLI\ValidRegionModel.cs" />
     <Compile Include="StorageModel\ProcessingConfig\ProcessingAlgorithmConfigModel.cs" />
     <Compile Include="StorageModel\SystemAlarm\AlarmMessModel.cs" />
     <Compile Include="StorageModel\SystemAlarm\AlarmTypes.cs" />

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

@@ -0,0 +1,105 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MvvmScaffoldFrame48.Model.StorageModel.ImageAlgorithm.ShuLI
+{
+    public class ActiveObjectClassModel
+    {
+        /// <summary>
+        /// 活动物体编号
+        /// </summary>
+        public int Num { get; set; }
+        /// <summary>
+        /// 有效物体的每一行数据
+        /// </summary>
+        public List<RowStartEndColModel> RowsData;
+        /// <summary>
+        /// 物体起始列坐标
+        /// </summary>
+        public int MinStartCol { get; set; }
+        /// <summary>
+        /// 物体结束列坐标
+        /// </summary>
+        public int MaxEndCol { get; set; }
+        /// <summary>
+        /// 上一行起始列坐标
+        /// </summary>
+        public int LastSeenLineStartCol { get; set; }
+        /// <summary>
+        /// 上一行结束列坐标
+        /// </summary>
+        public int LastSeenLineEndCol { get; set; }
+        /// <summary>
+        /// 最开始出现的行号
+        /// </summary>
+        public long StartLine { get; set; }
+        /// <summary>
+        /// 最后出现的行号
+        /// </summary>
+        public long LastSeenLine { get; set; }
+        /// <summary>
+        /// 检测开始时间
+        /// </summary>
+        public DateTime StartCheckTime { get; set; }
+        /// <summary>
+        /// 检测结束时间
+        /// </summary>
+        public DateTime EndCheckTime { get; set; }
+        /// <summary>
+        /// 物体面积
+        /// </summary>
+        public int Area { get; set; }
+
+        /// <summary>
+        /// 整个物体的最长长度(任意角度)
+        /// </summary>
+        public double MaxLength { get; set; }
+        /// <summary>
+        /// 通道编号
+        /// </summary>
+        public int ChannelNO { get; set; }
+        /// <summary>
+        /// 图像宽度
+        /// </summary>
+        public int ImageWidth { get; set; }
+        /// <summary>
+        /// 状态码
+        /// -1:初始值-未赋值
+        /// 0:正常
+        /// 1:超长粒
+        /// 2:超短粒
+        /// 3:超宽粒
+        /// 4:超窄粒
+        /// 5:超大粒
+        /// 6:超小粒
+        /// 7:非颗粒视野异常遮挡
+        /// 8:疑似叠粒或缺损粒
+        /// 9;噪点
+        /// </summary>
+        public int StateCode { get; set; } = -1;
+        /// <summary>
+        /// 批次号
+        /// </summary>
+        public string BatchNumber { get; set; }
+    }
+
+    // 活动物体跟踪类
+    public class RowStartEndColModel
+    {
+        /// <summary>
+        /// 当前有效区行数
+        /// </summary>
+        public long RowsCol { get; set; }
+        /// <summary>
+        /// 当前行有效区域起始列坐标
+        /// </summary>
+        public int StartCol { get; set; }
+        /// <summary>
+        /// 当前行有效区域结束列坐标
+        /// </summary>
+        public int EndCol { get; set; }
+    }
+}

+ 96 - 0
MvvmScaffoldFrame48.MODEL/StorageModel/ImageAlgorithm/ShuLI/ShuLiConfigClassModel.cs

@@ -0,0 +1,96 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MvvmScaffoldFrame48.Model.StorageModel.ImageAlgorithm.ShuLI
+{
+    public class ShuLiConfigClassModel
+    {
+        /// <summary>
+        /// 绑定相机的SN序列号
+        /// </summary>
+        public string CameraSN { get; set; } = string.Empty;
+        /// <summary>
+        /// 图像宽度
+        /// </summary>
+        public int ImageWidth { get; set; }
+        /// <summary>
+        /// 二值化阈值
+        /// </summary>
+        public int RegionThreshold { get; set; } = 30;
+        /// <summary>
+        /// 允许物体中断的最大连续行数
+        /// </summary>
+        public int MAX_GAP { get; set; } = 2;
+        /// <summary>
+        /// 单个物体允许的最大高度
+        /// </summary>
+        public int MAX_Idetify_Height { get; set; } = 2000;
+        /// <summary>
+        /// 合格物体的最小横向像素数
+        /// </summary>
+        public int MIN_OBJECT_WIDTH { get; set; } = 15;
+        /// <summary>
+        /// 合格物体的最大横向像素数
+        /// </summary>
+        public int MAX_OBJECT_WIDTH { get; set; } = 4000;
+        /// <summary>
+        /// 合格物体的最小竖向像素
+        /// </summary>
+        public int MIN_OBJECT_HEIGHT { get; set; } = 15;
+        /// <summary>
+        /// 合格物体的最大竖向像素
+        /// </summary>
+        public int MAX_OBJECT_HEIGHT { get; set; } = 200;
+        /// <summary>
+        /// 合格物体的最长长度
+        /// </summary>
+        public int MAX_Object_LENGTH { get; set; } = 1000;
+        /// <summary>
+        /// 合格物体的最短长度
+        /// </summary>
+        public int MIN_Object_LENGTH { get; set; } = 5;
+        /// <summary>
+        /// 判定标准识别码
+        /// -1  为无效不进行颗粒合格判定
+        /// 0 为使用宽高进行合格判定
+        /// 1 为使用面积进行合格判定
+        /// 2 为使用宽高和面积进行合格判定
+        /// </summary>
+        public int PandingCode { get; set; } = 0;
+        /// <summary>
+        /// 合格物体的最大面积
+        /// </summary>
+        public int MaxArea { get; set; } = 1000000;
+        /// <summary>
+        /// 合格物体的最小面积
+        /// </summary>
+        public int MinArea { get; set; } = 0;
+        /// <summary>
+        /// 噪声过滤阈值(面积过滤)
+        /// </summary>
+        public int NoiseFilter_Threshold { get; set; } = 5;
+        /// <summary>
+        /// 识别区域起始X坐标
+        /// </summary>
+        public int IdentifyStartX { get; set; } = 0;
+        /// <summary>
+        /// 识别区域结束X坐标
+        /// </summary>
+        public int IdentifyStopX { get; set; } = 0;
+        /// <summary>
+        /// 是否开启识别区域
+        /// </summary>
+        public bool IsIdentifyRoiOpen { get; set; } = false;
+        /// <summary>
+        /// 通道数量
+        /// </summary>
+        public int Channel { get; set; } = 1;
+        /// <summary>
+        /// 是否为配置文件读取
+        /// </summary>
+        public bool IsLoadCanfig { get; set; } = false;
+    }
+}

+ 14 - 0
MvvmScaffoldFrame48.MODEL/StorageModel/ImageAlgorithm/ShuLI/ValidRegionModel.cs

@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MvvmScaffoldFrame48.Model.StorageModel.ImageAlgorithm.ShuLI
+{
+    public class ValidRegionModel
+    {
+        public int Start { get; set; }
+        public int End { get; set; }
+    }
+}

+ 1 - 0
MvvmScaffoldFrame48.VIEWMODEL/ViewModel/MainViewModel.cs

@@ -40,6 +40,7 @@ namespace MvvmScaffoldFrame48.ViewModel.ViewModel
         public MainViewModel()
         {
             ThreadManager MainThreadManager = ThreadManager.Instance;
+            //ThreadManager MainThreadManager = ThreadManager.GetThreadManager
             MainThreadManager.StartCameraGroup(0);
             MainThreadManager.StartCommunication();
         }