feat: 模板匹配助手窗口与主视口 ROI 清除逻辑
- 新增模板助手/批量测试窗口、事件与 ViewModel,主窗口入口与 App 注册 - 运行匹配或批量测试前发布清除事件;视口通过 VisualTreeHelper 从父 Panel 移除持久虚线 ROI,避免 FindChild 失败时框残留 - TemplateMatchNative 等相关调整 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -166,6 +166,24 @@ namespace XplorePlane.Views
|
||||
{
|
||||
RenderBackgroundDefectResult(payload.RoiRect, payload.Detections, isBlackBackground: true);
|
||||
}, Prism.Events.ThreadOption.UIThread);
|
||||
|
||||
ea2?.GetEvent<TemplateMatchEnterRoiModeEvent>().Subscribe(() =>
|
||||
{
|
||||
_bgDefectDrawing = false;
|
||||
_bgDefectRoiMode = BackgroundDefectRoiMode.TemplateAssistant;
|
||||
RegisterBackgroundDefectRoiMouseHandlers();
|
||||
SetStatus("模板助手:请在图像上拖拽框选模板区域");
|
||||
}, Prism.Events.ThreadOption.UIThread);
|
||||
|
||||
ea2?.GetEvent<TemplateMatchPreviewResultEvent>().Subscribe(payload =>
|
||||
{
|
||||
RenderTemplateMatchPreview(payload);
|
||||
}, Prism.Events.ThreadOption.UIThread);
|
||||
|
||||
ea2?.GetEvent<TemplateMatchClearRoiOverlayEvent>().Subscribe(() =>
|
||||
{
|
||||
RemoveTemplateAssistantPersistRoi();
|
||||
}, Prism.Events.ThreadOption.UIThread);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
@@ -365,15 +383,21 @@ namespace XplorePlane.Views
|
||||
_bgDefectPreview = null;
|
||||
}
|
||||
ClearBackgroundDefectOverlays(canvas);
|
||||
ClearTemplateMatchOverlays(canvas);
|
||||
RemoveTemplateAssistantPersistRoi();
|
||||
}
|
||||
else
|
||||
{
|
||||
_bgDefectOverlays.Clear();
|
||||
_tmMatchOverlays.Clear();
|
||||
RemoveTemplateAssistantPersistRoi();
|
||||
}
|
||||
|
||||
_bgDefectDrawing = false;
|
||||
_bgDefectRoiMode = BackgroundDefectRoiMode.None;
|
||||
try { RoiCanvas.ReleaseMouseCapture(); } catch { /* 未捕获则无影响 */ }
|
||||
|
||||
SetStatus("已清除所有测量及白底/黑底检测结果");
|
||||
SetStatus("已清除所有测量、白底/黑底检测、模板匹配试跑叠加及模板助手 ROI");
|
||||
}
|
||||
|
||||
private void SaveOriginalImage_Click(object sender, RoutedEventArgs e)
|
||||
@@ -432,7 +456,8 @@ namespace XplorePlane.Views
|
||||
{
|
||||
None,
|
||||
WhiteBackground,
|
||||
BlackBackground
|
||||
BlackBackground,
|
||||
TemplateAssistant
|
||||
}
|
||||
|
||||
private BackgroundDefectRoiMode _bgDefectRoiMode;
|
||||
@@ -440,6 +465,8 @@ namespace XplorePlane.Views
|
||||
private System.Windows.Point _bgDefectStart;
|
||||
private System.Windows.Shapes.Rectangle _bgDefectPreview;
|
||||
private readonly System.Collections.Generic.List<System.Windows.UIElement> _bgDefectOverlays = new();
|
||||
private readonly System.Collections.Generic.List<System.Windows.UIElement> _tmMatchOverlays = new();
|
||||
private System.Windows.Shapes.Rectangle _templateAssistantRoiPersist;
|
||||
private bool _bgDefectMouseHandlersRegistered;
|
||||
|
||||
private void RegisterBackgroundDefectRoiMouseHandlers()
|
||||
@@ -525,6 +552,25 @@ namespace XplorePlane.Views
|
||||
|
||||
if (w < 10 || h < 10) return; // 太小忽略
|
||||
|
||||
// 模板助手:在画布上保留 ROI 矩形(与试跑匹配叠加分开管理)
|
||||
if (completedMode == BackgroundDefectRoiMode.TemplateAssistant)
|
||||
{
|
||||
RemoveTemplateAssistantPersistRoi();
|
||||
_templateAssistantRoiPersist = new System.Windows.Shapes.Rectangle
|
||||
{
|
||||
Stroke = System.Windows.Media.Brushes.DeepSkyBlue,
|
||||
StrokeThickness = 1.5,
|
||||
StrokeDashArray = new System.Windows.Media.DoubleCollection { 4, 2 },
|
||||
Fill = System.Windows.Media.Brushes.Transparent,
|
||||
Width = Math.Max(1, w),
|
||||
Height = Math.Max(1, h),
|
||||
IsHitTestVisible = false
|
||||
};
|
||||
System.Windows.Controls.Canvas.SetLeft(_templateAssistantRoiPersist, x);
|
||||
System.Windows.Controls.Canvas.SetTop(_templateAssistantRoiPersist, y);
|
||||
canvas.Children.Add(_templateAssistantRoiPersist);
|
||||
}
|
||||
|
||||
// 发布ROI绘制完成事件
|
||||
try
|
||||
{
|
||||
@@ -534,12 +580,106 @@ namespace XplorePlane.Views
|
||||
ea?.GetEvent<WhiteBackgroundRoiDrawnEvent>().Publish(rect);
|
||||
else if (completedMode == BackgroundDefectRoiMode.BlackBackground)
|
||||
ea?.GetEvent<BlackBackgroundRoiDrawnEvent>().Publish(rect);
|
||||
else if (completedMode == BackgroundDefectRoiMode.TemplateAssistant)
|
||||
ea?.GetEvent<TemplateMatchRoiDrawnEvent>().Publish(rect);
|
||||
}
|
||||
catch { }
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void ClearTemplateMatchOverlays(System.Windows.Controls.Canvas canvas)
|
||||
{
|
||||
if (canvas != null)
|
||||
{
|
||||
foreach (var el in _tmMatchOverlays)
|
||||
canvas.Children.Remove(el);
|
||||
}
|
||||
_tmMatchOverlays.Clear();
|
||||
}
|
||||
|
||||
private void RemoveTemplateAssistantPersistRoi()
|
||||
{
|
||||
if (_templateAssistantRoiPersist == null) return;
|
||||
var rect = _templateAssistantRoiPersist;
|
||||
_templateAssistantRoiPersist = null;
|
||||
if (VisualTreeHelper.GetParent(rect) is Panel p)
|
||||
p.Children.Remove(rect);
|
||||
}
|
||||
|
||||
private void RenderTemplateMatchPreview(TemplateMatchPreviewPayload payload)
|
||||
{
|
||||
var canvas = FindChildByName<System.Windows.Controls.Canvas>(RoiCanvas, "mainCanvas");
|
||||
if (canvas == null) return;
|
||||
|
||||
ClearTemplateMatchOverlays(canvas);
|
||||
if (payload?.Hits == null || payload.Hits.Count == 0)
|
||||
return;
|
||||
|
||||
var stroke = new SolidColorBrush(Color.FromRgb(255, 140, 0));
|
||||
stroke.Freeze();
|
||||
const int crossHalf = 8;
|
||||
|
||||
foreach (var h in payload.Hits)
|
||||
{
|
||||
var poly = new System.Windows.Shapes.Polygon
|
||||
{
|
||||
Stroke = stroke,
|
||||
StrokeThickness = 2,
|
||||
Fill = Brushes.Transparent,
|
||||
IsHitTestVisible = false,
|
||||
Points = new PointCollection
|
||||
{
|
||||
new System.Windows.Point(h.LtX, h.LtY),
|
||||
new System.Windows.Point(h.RtX, h.RtY),
|
||||
new System.Windows.Point(h.RbX, h.RbY),
|
||||
new System.Windows.Point(h.LbX, h.LbY)
|
||||
}
|
||||
};
|
||||
canvas.Children.Add(poly);
|
||||
_tmMatchOverlays.Add(poly);
|
||||
|
||||
var cx = h.CenterX;
|
||||
var cy = h.CenterY;
|
||||
var hLine = new System.Windows.Shapes.Line
|
||||
{
|
||||
X1 = cx - crossHalf,
|
||||
Y1 = cy,
|
||||
X2 = cx + crossHalf,
|
||||
Y2 = cy,
|
||||
Stroke = stroke,
|
||||
StrokeThickness = 1.5,
|
||||
IsHitTestVisible = false
|
||||
};
|
||||
var vLine = new System.Windows.Shapes.Line
|
||||
{
|
||||
X1 = cx,
|
||||
Y1 = cy - crossHalf,
|
||||
X2 = cx,
|
||||
Y2 = cy + crossHalf,
|
||||
Stroke = stroke,
|
||||
StrokeThickness = 1.5,
|
||||
IsHitTestVisible = false
|
||||
};
|
||||
canvas.Children.Add(hLine);
|
||||
canvas.Children.Add(vLine);
|
||||
_tmMatchOverlays.Add(hLine);
|
||||
_tmMatchOverlays.Add(vLine);
|
||||
|
||||
var tb = new System.Windows.Controls.TextBlock
|
||||
{
|
||||
Text = $"{h.Score:F2}",
|
||||
Foreground = stroke,
|
||||
FontSize = 10,
|
||||
IsHitTestVisible = false
|
||||
};
|
||||
System.Windows.Controls.Canvas.SetLeft(tb, cx + crossHalf + 2);
|
||||
System.Windows.Controls.Canvas.SetTop(tb, cy - 8);
|
||||
canvas.Children.Add(tb);
|
||||
_tmMatchOverlays.Add(tb);
|
||||
}
|
||||
}
|
||||
|
||||
private void RenderBackgroundDefectResult(
|
||||
System.Drawing.Rectangle roiRect,
|
||||
System.Collections.Generic.IReadOnlyList<BackgroundDefectDetectionItem> detections,
|
||||
|
||||
Reference in New Issue
Block a user