WPF HALCON HSmartWindowControlWPF 鼠标绘制ROI

更新:放出完整源码,供大家学习参考

yStack/SoupImgViewer (github.com)icon-default.png?t=N7T8https://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布局如下:

  
        
            
            
        
        
            
            
            
        
        
        
    

2. 鼠标事件处理

  1. 初始化时,在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;
            });
        }
  1. 鼠标左键单击,记录开始点startPoint


		private void Canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed)
            {
                _startPoint = e.GetPosition(Canvas);
            }
        }
  1. 鼠标移动,在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);
                }
		}
  1. 鼠标释放时,添加ROI到HalconWindow中


		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为平移量


		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,c#,视觉检测)