|
|
@@ -9,6 +9,7 @@ using System.Diagnostics;
|
|
|
using System.Drawing;
|
|
|
using System.IO;
|
|
|
using System.Linq;
|
|
|
+using System.Runtime.InteropServices.WindowsRuntime;
|
|
|
using System.Threading;
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
@@ -33,6 +34,7 @@ namespace CCDCount.DLL
|
|
|
private int ChannelWidth = 0;//每个区域的宽度
|
|
|
private int IdentifyImageWidth = -1;
|
|
|
private static readonly object _lockObj = new object(); // 专用锁对象\
|
|
|
+ private static readonly object taskLock = new object(); // 异步专用锁
|
|
|
private int ObjectNum = 0;
|
|
|
public int ImageNum { get { return IFrameDatas.Count; } }
|
|
|
#endregion
|
|
|
@@ -96,6 +98,108 @@ namespace CCDCount.DLL
|
|
|
result = ProcessLine(image, i);
|
|
|
currentLine += 1;
|
|
|
}
|
|
|
+
|
|
|
+ //识别到结果并输出
|
|
|
+ lock (_lockObj)
|
|
|
+ {
|
|
|
+ // 清理超时未更新的物体
|
|
|
+ var lostObjects = activeObjects
|
|
|
+ .Where(o => (currentLine - o.LastSeenLine) > shuLiConfig.MAX_GAP || (o.LastSeenLine - o.StartLine) > shuLiConfig.MAX_Idetify_Height)
|
|
|
+ .ToList();
|
|
|
+
|
|
|
+ List<ActiveObjectClass> OneActive = new List<ActiveObjectClass>();
|
|
|
+
|
|
|
+ // 有物体转变为活跃物体,返回值转为true
|
|
|
+ if (lostObjects.Count() > 0)
|
|
|
+ {
|
|
|
+ result = true;
|
|
|
+ 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 = ObjectNum += 1;
|
|
|
+ item.ChannelNO = ActiveChannel(item);
|
|
|
+ item.EndCheckTime = DateTime.Now;
|
|
|
+ OneActive.Add(item);
|
|
|
+ item.MaxLength = GetActionMaxLength(item.RowsData);
|
|
|
+ if ((item.LastSeenLine - item.StartLine) > shuLiConfig.MAX_Idetify_Height)
|
|
|
+ {
|
|
|
+ item.StateCode = 7;
|
|
|
+ FaultLog.RecordLogMessage("ShuLiClass-ProcessLine:非颗粒,视野异常", 3);
|
|
|
+ LOG.log(string.Format("ShuLiClass-ProcessLine:非颗粒,视野异常"), 6);
|
|
|
+ Console.WriteLine("ShuLiClass-ProcessLine:非颗粒,视野异常");
|
|
|
+ }
|
|
|
+ else if (shuLiConfig.PandingCode != -1)
|
|
|
+ {
|
|
|
+ if (item.StateCode != -1)
|
|
|
+ {
|
|
|
+ if (item.StateCode == 8)
|
|
|
+ {
|
|
|
+ LOG.log(string.Format("颗粒编号{0}:疑似叠片或缺损", item.Num));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (item.Area < shuLiConfig.MinArea
|
|
|
+ && (shuLiConfig.PandingCode == 2 || shuLiConfig.PandingCode == 1))
|
|
|
+ {
|
|
|
+ item.StateCode = 5;
|
|
|
+ LOG.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;
|
|
|
+ LOG.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;
|
|
|
+ LOG.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;
|
|
|
+ LOG.log(string.Format("颗粒编号{0}:超长粒", item.Num));
|
|
|
+ Console.WriteLine("颗粒编号{0}:超长粒", item.Num);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ item.StateCode = 0;
|
|
|
+ LOG.log(string.Format("颗粒编号{0}:正常粒", item.Num));
|
|
|
+ Console.WriteLine("颗粒编号{0}:正常粒", item.Num);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (OneActive.Count > 0)
|
|
|
+ {
|
|
|
+ LOG.log(string.Format("识别完成,首个颗粒编号:{0},颗粒数量:{1}", OneActive[0].Num, OneActive.Count), 6);
|
|
|
+ //触发回调事件
|
|
|
+ Task.Run(() =>
|
|
|
+ {
|
|
|
+ OnWorkCompleted(OneActive);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ OneActive = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 累加到总数并从活跃物体转移到历史物体
|
|
|
+ lostObjects.Where(o => o.Area >= shuLiConfig.NoiseFilter_Threshold && o.StateCode != 7 && o.StateCode != 9).ToList().ForEach(o => TryAdd(historyActiveObjects, o, 2500));
|
|
|
+ lostObjects.ForEach(o => activeObjects.Remove(o));
|
|
|
+ }
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
@@ -320,189 +424,14 @@ namespace CCDCount.DLL
|
|
|
}
|
|
|
IsPrintLightOnError = false;
|
|
|
}
|
|
|
- lock (_lockObj)
|
|
|
- {
|
|
|
- // 步骤2:处理当前行每个区域
|
|
|
- for (int i = 0; i < currentRegions.Count; i++)
|
|
|
- {
|
|
|
- var region = currentRegions[i];
|
|
|
- // 查找全部可合并的活跃物体(有重叠+在允许间隔内)
|
|
|
- var matcheds = activeObjects.Where(o =>
|
|
|
- IsOverlapping(o, region) &&
|
|
|
- (currentLine - o.LastSeenLine - 1) <= shuLiConfig.MAX_GAP).ToList();
|
|
|
- //当有多个可合并的活跃物体时,将多个物体合并
|
|
|
- if (matcheds.Count >= 2)
|
|
|
- {
|
|
|
- // 合并有效区域队列
|
|
|
- var CopeRowsData = new List<RowStartEndCol>();
|
|
|
- matcheds.ForEach(o => CopeRowsData = CopeRowsData.Concat(o.RowsData).ToList());
|
|
|
- // 合并有效区域并保存在新的区域中
|
|
|
- var MergeMatched = new ActiveObjectClass
|
|
|
- {
|
|
|
- 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 RowStartEndCol
|
|
|
- {
|
|
|
- StartCol = region.Start,
|
|
|
- EndCol = region.End,
|
|
|
- RowsCol = currentLine,
|
|
|
- });
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- // 创建新物体(首次出现的区域)
|
|
|
- activeObjects.Add(new ActiveObjectClass
|
|
|
- {
|
|
|
- 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 = IdentifyImageWidth,
|
|
|
- RowsData = new List<RowStartEndCol> {
|
|
|
- new RowStartEndCol {
|
|
|
- StartCol = region.Start,
|
|
|
- EndCol = region.End,
|
|
|
- RowsCol = currentLine,
|
|
|
- }
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
- }
|
|
|
- currentRegions.Clear();
|
|
|
- // 更新有效物体的最后一行的起始点
|
|
|
- activeObjects.Where(o => o.LastSeenLine == currentLine).ToList().ForEach(o => o.LastSeenLineStartCol = o.RowsData.Where(p => p.RowsCol == currentLine).Min(p => p.StartCol));
|
|
|
- activeObjects.Where(o => o.LastSeenLine == currentLine).ToList().ForEach(o => o.LastSeenLineEndCol = o.RowsData.Where(p => p.RowsCol == currentLine).Max(p => p.EndCol));
|
|
|
+ MergeCurrentRegions(currentRegions);
|
|
|
|
|
|
- // 步骤3:清理超时未更新的物体
|
|
|
- var lostObjects = activeObjects
|
|
|
- .Where(o => (currentLine - o.LastSeenLine) > shuLiConfig.MAX_GAP || (o.LastSeenLine - o.StartLine) > shuLiConfig.MAX_Idetify_Height)
|
|
|
- .ToList();
|
|
|
-
|
|
|
- List<ActiveObjectClass> OneActive = new List<ActiveObjectClass>();
|
|
|
+ currentRegions.Clear();
|
|
|
+ // 更新有效物体的最后一行的起始点
|
|
|
+ activeObjects.Where(o => o.LastSeenLine == currentLine).ToList().ForEach(o => o.LastSeenLineStartCol = o.RowsData.Where(p => p.RowsCol == currentLine).Min(p => p.StartCol));
|
|
|
+ activeObjects.Where(o => o.LastSeenLine == currentLine).ToList().ForEach(o => o.LastSeenLineEndCol = o.RowsData.Where(p => p.RowsCol == currentLine).Max(p => p.EndCol));
|
|
|
|
|
|
- // 有物体转变为活跃物体,返回值转为true
|
|
|
- if (lostObjects.Count() > 0)
|
|
|
- {
|
|
|
- result = true;
|
|
|
- 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 = ObjectNum += 1;
|
|
|
- item.ChannelNO = ActiveChannel(item);
|
|
|
- item.EndCheckTime = DateTime.Now;
|
|
|
- OneActive.Add(item);
|
|
|
- item.MaxLength = GetActionMaxLength(item.RowsData);
|
|
|
- if ((item.LastSeenLine - item.StartLine) > shuLiConfig.MAX_Idetify_Height)
|
|
|
- {
|
|
|
- item.StateCode = 7;
|
|
|
- FaultLog.RecordLogMessage("ShuLiClass-ProcessLine:非颗粒,视野异常", 3);
|
|
|
- LOG.log(string.Format("ShuLiClass-ProcessLine:非颗粒,视野异常"), 6);
|
|
|
- Console.WriteLine("ShuLiClass-ProcessLine:非颗粒,视野异常");
|
|
|
- }
|
|
|
- else if (shuLiConfig.PandingCode != -1)
|
|
|
- {
|
|
|
- if (item.StateCode != -1)
|
|
|
- {
|
|
|
- if (item.StateCode == 8)
|
|
|
- {
|
|
|
- LOG.log(string.Format("颗粒编号{0}:疑似叠片或缺损", item.Num));
|
|
|
- }
|
|
|
- }
|
|
|
- else if (item.Area < shuLiConfig.MinArea
|
|
|
- && (shuLiConfig.PandingCode == 2 || shuLiConfig.PandingCode == 1))
|
|
|
- {
|
|
|
- item.StateCode = 5;
|
|
|
- LOG.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;
|
|
|
- LOG.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;
|
|
|
- LOG.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;
|
|
|
- LOG.log(string.Format("颗粒编号{0}:超长粒", item.Num));
|
|
|
- Console.WriteLine("颗粒编号{0}:超长粒", item.Num);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- item.StateCode = 0;
|
|
|
- LOG.log(string.Format("颗粒编号{0}:正常粒", item.Num));
|
|
|
- Console.WriteLine("颗粒编号{0}:正常粒", item.Num);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (OneActive.Count > 0)
|
|
|
- {
|
|
|
- LOG.log(string.Format("识别完成,首个颗粒编号:{0},颗粒数量:{1}", OneActive[0].Num, OneActive.Count), 6);
|
|
|
- //触发回调事件
|
|
|
- Task.Run(() =>
|
|
|
- {
|
|
|
- OnWorkCompleted(OneActive);
|
|
|
- });
|
|
|
- }
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- OneActive = null;
|
|
|
- }
|
|
|
-
|
|
|
- // 累加到总数并从活跃物体转移到历史物体
|
|
|
- lostObjects.Where(o => o.Area >= shuLiConfig.NoiseFilter_Threshold && o.StateCode != 7 && o.StateCode != 9).ToList().ForEach(o => TryAdd(historyActiveObjects, o, 2500));
|
|
|
- lostObjects.ForEach(o => activeObjects.Remove(o));
|
|
|
- }
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
@@ -511,9 +440,9 @@ namespace CCDCount.DLL
|
|
|
/// </summary>
|
|
|
/// <param name="line">当前行像素数组</param>
|
|
|
/// <returns>有效区域列表(起始/结束位置)</returns>
|
|
|
- private List<(int Start, int End)> FindValidRegions(IImage image, int RowNo)
|
|
|
+ private List<ValidRegionModelClass> FindValidRegions(IImage image, int RowNo)
|
|
|
{
|
|
|
- List<(int Start, int End)> regions = new List<(int Start, int End)>();
|
|
|
+ List<ValidRegionModelClass> regions = new List<ValidRegionModelClass>();
|
|
|
int start = -1; // 当前区域起始标记
|
|
|
// 遍历所有像素列
|
|
|
if (shuLiConfig.IsIdentifyRoiOpen)
|
|
|
@@ -529,7 +458,11 @@ namespace CCDCount.DLL
|
|
|
// 检查区域宽度是否达标
|
|
|
if (i - start >= shuLiConfig.MIN_OBJECT_WIDTH)
|
|
|
{
|
|
|
- regions.Add((start, (i - 1) % (int)image.Width)); // 记录有效区域
|
|
|
+ regions.Add(new ValidRegionModelClass()
|
|
|
+ {
|
|
|
+ Start = start,
|
|
|
+ End = (i - 1) % (int)image.Width
|
|
|
+ }); // 记录有效区域
|
|
|
}
|
|
|
start = -1; // 重置区域标记
|
|
|
}
|
|
|
@@ -548,7 +481,11 @@ namespace CCDCount.DLL
|
|
|
// 检查区域宽度是否达标
|
|
|
if (i - start >= shuLiConfig.MIN_OBJECT_WIDTH)
|
|
|
{
|
|
|
- regions.Add((start, (i - 1) % (int)image.Width)); // 记录有效区域
|
|
|
+ regions.Add(new ValidRegionModelClass()
|
|
|
+ {
|
|
|
+ Start = start,
|
|
|
+ End = (i - 1) % (int)image.Width
|
|
|
+ }); // 记录有效区域
|
|
|
}
|
|
|
start = -1; // 重置区域标记
|
|
|
}
|
|
|
@@ -559,7 +496,10 @@ namespace CCDCount.DLL
|
|
|
// 处理行尾未闭合的区域
|
|
|
if (start != -1 && image.Width - start >= shuLiConfig.MIN_OBJECT_WIDTH)
|
|
|
{
|
|
|
- regions.Add((start, (int)image.Width - 1));
|
|
|
+ regions.Add(new ValidRegionModelClass() {
|
|
|
+ Start = start,
|
|
|
+ End = (int)image.Width - 1
|
|
|
+ });
|
|
|
}
|
|
|
return regions;
|
|
|
}
|
|
|
@@ -570,7 +510,7 @@ namespace CCDCount.DLL
|
|
|
/// <param name="obj">活跃物体</param>
|
|
|
/// <param name="region">当前区域</param>
|
|
|
/// <returns>是否发生重叠</returns>
|
|
|
- private bool IsOverlapping(ActiveObjectClass obj, (int Start, int End) region)
|
|
|
+ private bool IsOverlapping(ActiveObjectClass obj,ValidRegionModelClass region)
|
|
|
{
|
|
|
// 判断区域是否不相交的逆条件
|
|
|
return !(region.End < obj.LastSeenLineStartCol || region.Start > obj.LastSeenLineEndCol);
|
|
|
@@ -708,6 +648,119 @@ namespace CCDCount.DLL
|
|
|
}
|
|
|
return true;
|
|
|
}
|
|
|
+
|
|
|
+ private bool MergeCurrentRegions(List<ValidRegionModelClass> validRegions)
|
|
|
+ {
|
|
|
+ bool Result = false;
|
|
|
+ ExecuteAsyncOperations(validRegions).GetAwaiter().GetResult();
|
|
|
+ return Result;
|
|
|
+ }
|
|
|
+
|
|
|
+ private async Task ExecuteAsyncOperations(List<ValidRegionModelClass> validRegions)
|
|
|
+ {
|
|
|
+ // 创建异步操作任务列表
|
|
|
+ var tasks = new List<Task<string>>();
|
|
|
+ for (int i = 0; i < validRegions.Count; i++)
|
|
|
+ {
|
|
|
+ tasks.Add(AsyncOperation(validRegions[i],i));
|
|
|
+ }
|
|
|
+
|
|
|
+ try
|
|
|
+ {
|
|
|
+ // 等待所有异步操作完成
|
|
|
+ var results = await Task.WhenAll(tasks);
|
|
|
+ Console.WriteLine($"All operations completed: [{string.Join(", ", results)}]");
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ Console.WriteLine($"One or more operations failed: {ex.Message}");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private async Task<string> AsyncOperation(ValidRegionModelClass region,int i)
|
|
|
+ {
|
|
|
+ // 模拟异步操作,比如网络请求或I/O操作
|
|
|
+ await Task.Run(() => {
|
|
|
+ lock(taskLock)
|
|
|
+ {
|
|
|
+ // 查找全部可合并的活跃物体(有重叠+在允许间隔内)
|
|
|
+ var matcheds = activeObjects.Where(o =>
|
|
|
+ IsOverlapping(o, region) &&
|
|
|
+ (currentLine - o.LastSeenLine - 1) <= shuLiConfig.MAX_GAP).ToList();
|
|
|
+ //当有多个可合并的活跃物体时,将多个物体合并
|
|
|
+ if (matcheds.Count >= 2)
|
|
|
+ {
|
|
|
+ // 合并有效区域队列
|
|
|
+ var CopeRowsData = new List<RowStartEndCol>();
|
|
|
+ matcheds.ForEach(o => CopeRowsData = CopeRowsData.Concat(o.RowsData).ToList());
|
|
|
+ // 合并有效区域并保存在新的区域中
|
|
|
+ var MergeMatched = new ActiveObjectClass
|
|
|
+ {
|
|
|
+ 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 RowStartEndCol
|
|
|
+ {
|
|
|
+ StartCol = region.Start,
|
|
|
+ EndCol = region.End,
|
|
|
+ RowsCol = currentLine,
|
|
|
+ });
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // 创建新物体(首次出现的区域)
|
|
|
+ activeObjects.Add(new ActiveObjectClass
|
|
|
+ {
|
|
|
+ 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 = IdentifyImageWidth,
|
|
|
+ RowsData = new List<RowStartEndCol> {
|
|
|
+ new RowStartEndCol {
|
|
|
+ StartCol = region.Start,
|
|
|
+ EndCol = region.End,
|
|
|
+ RowsCol = currentLine,
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }); // 延迟
|
|
|
+ Console.WriteLine($"Operation {i} completed");
|
|
|
+ return $"Result {i}";
|
|
|
+ }
|
|
|
#endregion
|
|
|
|
|
|
#region 线程方法
|