鼠标点击事件坐标与找到的棋盘角坐标不匹配或不对齐



我目前正在使用EmguCV库和Kinect一起使用WPF创建一个简单的击中测试。我能够成功地找到棋盘角并将它们存储在矩形列表中,作为矩形的4个角,然后我尝试使用LeftMouseButtonUp事件来获取鼠标位置并检查它是否位于任何矩形的边界。

问题是,我怀疑EmguCV作为棋盘角返回的坐标和鼠标单击事件返回的坐标不对齐,因此它无法检测到命中(即鼠标单击矩形内)。如何使这两个坐标对齐?我错过什么了吗?

XAML:

<Window x:Class="EmguMotionTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525" KeyDown="Window_KeyDown" >
    <Grid>
        <Image Name="rgbImage" Stretch="Fill" MouseLeftButtonUp="rgbImage_MouseLeftButtonUp"/>
        <Line Name="line" Stroke="Red" StrokeThickness="1" Visibility="Visible" />
    </Grid>
</Window>
c#:

public partial class MainWindow : Window
{
    /*Kinect Initialization*/
    KinectSensor _kinectSensor;
    /*Getting the Chessboard corners*/
    PointF[] corners = new PointF[] { };
    PointF[] points = new PointF[4];
    List<PointF> cornerPts = new List<PointF>();
    List<List<PointF>> rectangle = new List<List<PointF>>();
    /*Defining the Chessboard parameters */
    const int width = 4;
    const int height = 4;
    Drawing.Size boardSize = new Drawing.Size(width, height);
    public MainWindow()
    {
        InitializeComponent();
        this.Unloaded += delegate
        {
            _kinectSensor.ColorStream.Disable();
        };
        this.Loaded += delegate
        {
            _kinectSensor = KinectSensor.KinectSensors[0];
            _kinectSensor.ColorStream.Enable();
            _kinectSensor.Start();
            BackgroundWorker bw = new BackgroundWorker();
            bw.DoWork += (a, b) => Pulse();
            bw.RunWorkerCompleted += (c, d) => bw.RunWorkerAsync();
            bw.RunWorkerAsync();
        };
    }
    /*Polling event to retrieve Data from Kinect*/
    private void Pulse()
    {
        using (ColorImageFrame imageFrame = _kinectSensor.ColorStream.OpenNextFrame(200))
        {
            if (imageFrame == null)
                return;
            //Converting a Kinect Color Frame to EmguCV Image
            Image<Bgr, Byte> imageCap = imageFrame.ToOpenCVImage<Bgr, Byte>();
            Image<Gray, Byte> gray = imageCap.Convert<Gray, Byte>();
            corners = CameraCalibration.FindChessboardCorners(gray, boardSize, Emgu.CV.CvEnum.CALIB_CB_TYPE.ADAPTIVE_THRESH | Emgu.CV.CvEnum.CALIB_CB_TYPE.FILTER_QUADS);
            if (corners != null)
            {
                CvInvoke.cvFindCornerSubPix(gray, corners, corners.Length, new Drawing.Size(11, 11), new Drawing.Size(-1, -1), new MCvTermCriteria(30, 0.1));
                CameraCalibration.DrawChessboardCorners(gray, boardSize, corners);
                //Displaying the result in WPF
                this.Dispatcher.Invoke(
                       new Action(() => rgbImage.Source = gray.ToBitmapSource())
                       );
            }
            else
            {
                //Displaying the result in WPF
                this.Dispatcher.Invoke(
                       new Action(() => rgbImage.Source = gray.ToBitmapSource())
                       );
            }
        }
    }
    private void Window_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.Key == Key.Space)
        {
            //Clear out the List of points 
            if (cornerPts != null)
            {
                cornerPts.Clear();
            }
            //Enter all the found corners into an array stored as polygons
            for (int i = 0; i < boardSize.Height - 1; i++)
            {
                for (int j = 0; j < boardSize.Width - 1; j++)
                {
                    //Getting the corners of the squares (Square 1, 2, 3)..
                    int p1 = (i * boardSize.Width) + j;
                    int p2 = (i * boardSize.Width) + j + 1;
                    int p3 = ((i + 1) * boardSize.Width) + j;
                    int p4 = ((i + 1) * boardSize.Width) + j + 1;
                    //Add range method
                    points[0] = corners[p1];
                    points[1] = corners[p2];
                    points[2] = corners[p3];
                    points[3] = corners[p4];
                    cornerPts.AddRange(points);
                    rectangle.Add(new List<PointF>() { points[0], points[1], points[2], points[3] });
                }
            }
        }
        /*To test the corners points are being added correctly */
        if (e.Key == Key.D)
        {
            Console.WriteLine("D button press registered");
            ///*Test Square */
            for (int c = 0; c < rectangle.Count; c++)
            {
                for (int n = 0; n < 4; n++)
                {
                    Console.WriteLine("Triangle no: " + c + "," + n + rectangle[c][n]);
                }
            }
        }
    }
    private void rgbImage_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        System.Windows.Point p = Mouse.GetPosition(rgbImage);
        Console.WriteLine("MouseX: " + p.X + "," + "MouseY: " + p.Y);
        Console.WriteLine("-------------Hit Test---------------");
        /*Test Square */
        for (int c = 0; c < rectangle.Count; c++)
        {
            for (int n = 0; n < 4; n++)
            {
                //Console.WriteLine("Triangle no: " + c + "," + n + rectangle[c][n]);
                if ((p.X > rectangle[c][0].X && p.X < rectangle[c][1].X) && (p.Y > rectangle[c][0].Y && p.Y < rectangle[c][2].Y))
                {
                    Console.WriteLine("Triangle HIT is triangle no: " + c);
                }
            }
        }
    }
}

鼠标位置必须根据图像进行缩放。要获得正确的像素值

那么在Pulse()方法中提取位图的PixelWidth和PixelHeight并根据图像控件缩放鼠标位置

/*Polling event to retrieve Data from Kinect*/
    private void Pulse()
    {
        using (ColorImageFrame imageFrame = _kinectSensor.ColorStream.OpenNextFrame(200))
        {
            if (imageFrame == null)
                return;
            //Converting a Kinect Color Frame to EmguCV Image
            Image<Bgr, Byte> imageCap = imageFrame.ToOpenCVImage<Bgr, Byte>();
            Image<Gray, Byte> gray = imageCap.Convert<Gray, Byte>();
            corners = CameraCalibration.FindChessboardCorners(gray, boardSize, Emgu.CV.CvEnum.CALIB_CB_TYPE.ADAPTIVE_THRESH | Emgu.CV.CvEnum.CALIB_CB_TYPE.FILTER_QUADS);
            if (corners != null)
            {
                CvInvoke.cvFindCornerSubPix(gray, corners, corners.Length, new Drawing.Size(11, 11), new Drawing.Size(-1, -1), new MCvTermCriteria(30, 0.1));
                CameraCalibration.DrawChessboardCorners(gray, boardSize, corners);
                pixelWidth = gray.ToBitmapSource().PixelWidth;
                pixelHeight = gray.ToBitmapSource().PixelHeight;
                //Displaying the result in WPF
                this.Dispatcher.Invoke(
                       new Action(() => rgbImage.Source = gray.ToBitmapSource())
                       );
            }
            else
            {
                //Displaying the result in WPF
                this.Dispatcher.Invoke(
                       new Action(() => rgbImage.Source = gray.ToBitmapSource())
                       );
            }
        }
    }
    private void rgbImage_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        System.Windows.Point p = Mouse.GetPosition(rgbImage);
        var pixelMousePosX = e.GetPosition(rgbImage).X * pixelWidth / rgbImage.ActualWidth;
        var pixelMousePosY = e.GetPosition(rgbImage).Y * pixelHeight / rgbImage.ActualHeight;
        Console.WriteLine("MousePixelX: " + pixelMousePosX + "," + "MousePixelY: " + pixelMousePosY);
        /*Test Square */
        for (int c = 0; c < rectangle.Count; c++)
        {
            for (int n = 0; n < 4; n++)
            {
                if ((pixelMousePosX > rectangle[c][0].X && pixelMousePosX < rectangle[c][1].X) && (pixelMousePosY > rectangle[c][0].Y && pixelMousePosY < rectangle[c][2].Y))
                {
                    Console.WriteLine("Triangle HIT is triangle no: " + c);
                }
            }
        }
    }

相关内容

  • 没有找到相关文章

最新更新