白底/黑底检测:轮廓与最远弦度量,UI 分色与标注优化
- 算子:输出轮廓顶点及顶点间最远弦(微米标定与原先一致) - 视图:实线轮廓;白底红/黑底绿;尺寸文字置于 ROI 外右侧垂直居中 - 事件与 MainViewModel 载荷改为 BackgroundDefectDetectionItem Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -155,16 +155,16 @@ namespace XplorePlane.Views
|
||||
RegisterBackgroundDefectRoiMouseHandlers();
|
||||
}, Prism.Events.ThreadOption.UIThread);
|
||||
|
||||
// 白底检测:渲染结果
|
||||
// 白底检测:渲染结果(红色标识)
|
||||
ea2?.GetEvent<WhiteBackgroundResultEvent>().Subscribe(payload =>
|
||||
{
|
||||
RenderBackgroundDefectResult(payload.RoiRect, payload.Detections);
|
||||
RenderBackgroundDefectResult(payload.RoiRect, payload.Detections, isBlackBackground: false);
|
||||
}, Prism.Events.ThreadOption.UIThread);
|
||||
|
||||
// 黑底检测:渲染结果
|
||||
// 黑底检测:渲染结果(绿色标识)
|
||||
ea2?.GetEvent<BlackBackgroundResultEvent>().Subscribe(payload =>
|
||||
{
|
||||
RenderBackgroundDefectResult(payload.RoiRect, payload.Detections);
|
||||
RenderBackgroundDefectResult(payload.RoiRect, payload.Detections, isBlackBackground: true);
|
||||
}, Prism.Events.ThreadOption.UIThread);
|
||||
}
|
||||
catch { }
|
||||
@@ -542,12 +542,13 @@ namespace XplorePlane.Views
|
||||
|
||||
private void RenderBackgroundDefectResult(
|
||||
System.Drawing.Rectangle roiRect,
|
||||
System.Collections.Generic.List<(System.Drawing.Point center, int radius, double sizeMm)> detections)
|
||||
System.Collections.Generic.IReadOnlyList<BackgroundDefectDetectionItem> detections,
|
||||
bool isBlackBackground)
|
||||
{
|
||||
var canvas = FindChildByName<System.Windows.Controls.Canvas>(RoiCanvas, "mainCanvas");
|
||||
if (canvas == null || detections == null) return;
|
||||
|
||||
// 绘制ROI矩形(蓝色实线)
|
||||
// 绘制ROI矩形(蓝色实线,两种模式一致)
|
||||
var roiShape = new System.Windows.Shapes.Rectangle
|
||||
{
|
||||
Stroke = System.Windows.Media.Brushes.Blue,
|
||||
@@ -561,52 +562,74 @@ namespace XplorePlane.Views
|
||||
canvas.Children.Add(roiShape);
|
||||
_bgDefectOverlays.Add(roiShape);
|
||||
|
||||
// 绘制每个检测区域(白底为暗区、黑底为亮区,可视化相同)
|
||||
foreach (var (center, radius, sizeMm) in detections)
|
||||
var defectBrush = isBlackBackground
|
||||
? System.Windows.Media.Brushes.LimeGreen
|
||||
: System.Windows.Media.Brushes.Red;
|
||||
|
||||
const int labelPadRightOfRoi = 4;
|
||||
const double labelLineHeight = 15;
|
||||
int validCount = detections.Count(d => d.Contour != null && d.Contour.Count >= 2);
|
||||
double roiMidY = roiRect.Y + roiRect.Height * 0.5;
|
||||
double labelLeft = roiRect.X + roiRect.Width + labelPadRightOfRoi;
|
||||
double labelStartY = roiMidY - validCount * labelLineHeight * 0.5;
|
||||
int labelRow = 0;
|
||||
|
||||
foreach (var d in detections)
|
||||
{
|
||||
// 红色虚线圆
|
||||
var circle = new System.Windows.Shapes.Ellipse
|
||||
if (d.Contour == null || d.Contour.Count < 2) continue;
|
||||
|
||||
var fig = new PathFigure
|
||||
{
|
||||
Stroke = System.Windows.Media.Brushes.Red,
|
||||
StartPoint = new System.Windows.Point(d.Contour[0].X, d.Contour[0].Y),
|
||||
IsClosed = true
|
||||
};
|
||||
if (d.Contour.Count > 1)
|
||||
{
|
||||
fig.Segments.Add(new PolyLineSegment(
|
||||
d.Contour.Skip(1).Select(p => new System.Windows.Point(p.X, p.Y)), true));
|
||||
}
|
||||
|
||||
var geom = new PathGeometry();
|
||||
geom.Figures.Add(fig);
|
||||
var contourPath = new System.Windows.Shapes.Path
|
||||
{
|
||||
Data = geom,
|
||||
Stroke = defectBrush,
|
||||
StrokeThickness = 1,
|
||||
StrokeDashArray = new System.Windows.Media.DoubleCollection { 4, 2 },
|
||||
Width = radius * 2,
|
||||
Height = radius * 2,
|
||||
Fill = System.Windows.Media.Brushes.Transparent,
|
||||
IsHitTestVisible = false
|
||||
};
|
||||
System.Windows.Controls.Canvas.SetLeft(circle, center.X - radius);
|
||||
System.Windows.Controls.Canvas.SetTop(circle, center.Y - radius);
|
||||
canvas.Children.Add(circle);
|
||||
_bgDefectOverlays.Add(circle);
|
||||
canvas.Children.Add(contourPath);
|
||||
_bgDefectOverlays.Add(contourPath);
|
||||
|
||||
// 45°直径标注线(从圆心向左上到右下)
|
||||
double offset = radius * 0.707; // cos(45°) * radius
|
||||
var diamLine = new System.Windows.Shapes.Line
|
||||
var chordLine = new System.Windows.Shapes.Line
|
||||
{
|
||||
X1 = center.X - offset,
|
||||
Y1 = center.Y - offset,
|
||||
X2 = center.X + offset,
|
||||
Y2 = center.Y + offset,
|
||||
Stroke = System.Windows.Media.Brushes.Red,
|
||||
StrokeThickness = 1,
|
||||
X1 = d.ChordP1.X,
|
||||
Y1 = d.ChordP1.Y,
|
||||
X2 = d.ChordP2.X,
|
||||
Y2 = d.ChordP2.Y,
|
||||
Stroke = defectBrush,
|
||||
StrokeThickness = 1.5,
|
||||
IsHitTestVisible = false
|
||||
};
|
||||
canvas.Children.Add(diamLine);
|
||||
_bgDefectOverlays.Add(diamLine);
|
||||
canvas.Children.Add(chordLine);
|
||||
_bgDefectOverlays.Add(chordLine);
|
||||
|
||||
double um = d.SizeMicrometers;
|
||||
string label = um >= 1000 ? $"{um / 1000:F2} mm" : $"{um:F0} μm";
|
||||
|
||||
// 尺寸标注(在斜线右上方)
|
||||
string label = sizeMm >= 1000 ? $"{sizeMm / 1000:F2} mm" : $"{sizeMm:F0} μm";
|
||||
var text = new System.Windows.Controls.TextBlock
|
||||
{
|
||||
Text = label,
|
||||
Foreground = System.Windows.Media.Brushes.Red,
|
||||
Foreground = defectBrush,
|
||||
FontSize = 11,
|
||||
IsHitTestVisible = false
|
||||
};
|
||||
System.Windows.Controls.Canvas.SetLeft(text, center.X + offset + 3);
|
||||
System.Windows.Controls.Canvas.SetTop(text, center.Y - offset - 14);
|
||||
System.Windows.Controls.Canvas.SetLeft(text, labelLeft);
|
||||
System.Windows.Controls.Canvas.SetTop(text, labelStartY + labelRow * labelLineHeight);
|
||||
canvas.Children.Add(text);
|
||||
_bgDefectOverlays.Add(text);
|
||||
labelRow++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user