更新:放出完整源码,供大家学习参考
yStack/SoupImgViewer (github.com)https://github.com/yStack/SoupImgViewer
0. 需求
在HSmartWindowsControlWPF上用鼠标绘制ROI,且显示绘制时的鼠标交互过程,最终效果如下:
1. 基本思路
-
在HSmartWindowControl上布置一层透明的Canvas,用于实时显示鼠标绘制ROI的过程
-
鼠标移动时,在Canvas上用鼠标实时绘制Rectangle等ROI形状,
-
鼠标在Canvas坐标系中的Position信息(x,y)坐标转换到HALCON图像坐标系,变换为Row、Column等信息
-
根据Row、Column信息调用HDrawingObject.CreateDrawingObject()方法生成Halcon原生ROI
-
鼠标左键释放时,隐藏Canvas,将原生ROI附加到窗口中
UI布局如下:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Orientation="Vertical">
<Button Width="75" Height="25" Content="LoadImg" Margin="2.5" Click="Button_Click"></Button>
<CheckBox Content="Rect" Margin="2.5" x:Name="rect_roi" Checked="rect_roi_Checked" Unchecked="rect_roi_Unchecked"></CheckBox>
<CheckBox Content="Ellipse" Margin="2.5" x:Name="ellipse_roi" Checked="ellipse_roi_Checked" Unchecked="ellipse_roi_Unchecked"></CheckBox>
</StackPanel>
<halcon:HSmartWindowControlWPF HKeepAspectRatio="True" Grid.Column="1" x:Name="HalconWindowControl" HInitWindow="HWind_HInitWindow"></halcon:HSmartWindowControlWPF>
<Canvas x:Name="Canvas" Visibility="Collapsed" Grid.Column="1" Background="Transparent" MouseLeftButtonDown="Canvas_MouseLeftButtonDown" MouseUp="Canvas_MouseUp" MouseMove="Canvas_MouseMove"></Canvas>
</Grid>
2. 鼠标事件处理
-
初始化时,在Canvas中添加Rectangle等对象,并将其设置为不可见
private void Init()
{
Canvas.Children.Add(_canvasRect);
Canvas.Children.Add(_canvasEllipse);
Canvas.Children.Add(_cross);
//矩形
_canvasRect.Stroke = new SolidColorBrush(StokeColor);
_canvasRect.StrokeThickness = StokeThickness;
_canvasRect.Width = 0;
_canvasRect.Height = 0;
//圆形
_canvasEllipse.Stroke = new SolidColorBrush(StokeColor);
_canvasEllipse.StrokeThickness = StokeThickness;
//十字
_cross.Stroke = new SolidColorBrush(StokeColor);
_cross.StrokeThickness = StokeThickness;
_cross.Data = PathGeometry.Parse("M0,0 L8,8 M8,0 L0,8");
_cross.Width = 0;
_cross.Height = 0;
// HImagePart随着窗口大小变化实时变动,注册事件用于实时更新坐标变换信息
var dpd = DependencyPropertyDescriptor.FromProperty(HSmartWindowControlWPF.HImagePartProperty, typeof(HSmartWindowControlWPF));
dpd.AddValueChanged(HalconWindowControl, (o, e) =>
{
var imgPart = HalconWindowControl.HImagePart;
_k = imgPart.Height / HalconWindowControl.ActualHeight;
_tx = imgPart.X;
_ty = imgPart.Y;
});
}
-
鼠标左键单击,记录开始点startPoint
private void Canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
_startPoint = e.GetPosition(Canvas);
}
}
-
鼠标移动,在Canvas上实时绘制Rectangle
private void Canvas_MouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed && rect_roi.IsChecked == true)
{
_endPoint = e.GetPosition(Canvas);
_canvasRect.Height = Math.Abs(_endPoint.Y - _startPoint.Y);
_canvasRect.Width = Math.Abs(_endPoint.X - _startPoint.X);
// 左上往右下拖动
if (_endPoint.X > _startPoint.X && _endPoint.Y > _startPoint.Y)
{
Canvas.SetLeft(_canvasRect, _startPoint.X);
Canvas.SetTop(_canvasRect, _startPoint.Y);
//坐标转换,Canvas => HWindow
ConvertPoint(_startPoint.X, _startPoint.Y, _k, _tx, _ty, out double sx, out double sy);
ConvertPoint(_endPoint.X, _endPoint.Y, _k, _tx, _ty, out double ex, out double ey);
_r1 = sy;
_c1 = sx;
_r2 = ey;
_c2 = ex;
}
// 右下往左上拖动
if (_endPoint.X < _startPoint.X && _endPoint.Y < _startPoint.Y)
{
Canvas.SetLeft(_canvasRect, _endPoint.X);
Canvas.SetTop(_canvasRect, _endPoint.Y);
}
}
-
鼠标释放时,添加ROI到HalconWindow中文章来源:https://www.toymoban.com/news/detail-617472.html
private void Canvas_MouseUp(object sender, MouseButtonEventArgs e)
{
if(rect_roi.IsChecked == true)
{
_roi = HDrawingObject.CreateDrawingObject(HDrawingObject.HDrawingObjectType.RECTANGLE1, _r1, _c1, _r2, _c2);
_hwind.AttachDrawingObjectToWindow(_roi);
rect_roi.IsChecked = false;
}
if(ellipse_roi.IsChecked == true)
{
_roi = HDrawingObject.CreateDrawingObject(HDrawingObject.HDrawingObjectType.CIRCLE, _cr, _cc, _cRadius);
_hwind.AttachDrawingObjectToWindow(_roi);
ellipse_roi.IsChecked = false;
}
}
4. 坐标转换
Canvas坐标系和HWindow坐标系之间仅存在缩放、平移这两种变换关系,和相机标定的原理一样,k为缩放系数,tx、ty为平移量文章来源地址https://www.toymoban.com/news/detail-617472.html
private void ConvertPoint(double x, double y, double k, double tx, double ty, out double px, out double py)
{
px = k * x + tx;
py = k * y + ty;
}
到了这里,关于WPF HALCON HSmartWindowControlWPF 鼠标绘制ROI的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!