【问题标题】:WPF C# - Incorrect mouse position coordinateWPF C# - 不正确的鼠标位置坐标
【发布时间】:2019-09-23 10:28:06
【问题描述】:

我想通过在图像上绘制矩形来绘制选区,但选区似乎有​​很大的偏差。这是我的代码。

EdgeDetectionWindow.xaml

    <Window x:Class="SenpiCHC.EdgeDetectionWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:SenpiCHC"
        xmlns:codeg="clr-namespace:System;assembly=mscorlib"
        mc:Ignorable="d"
        Title="EdgeDetectionWindow" Width="1270" Height="720"
        WindowState="Maximized"
        WindowStyle="None">
    <Window.Resources>
        <ObjectDataProvider x:Key="dataFromEnum" 
                            MethodName="GetValues"
                            ObjectType="{x:Type codeg:Enum}">
            <ObjectDataProvider.MethodParameters>
                <x:Type TypeName="local:SelectedEdgeDetectionType"/>
            </ObjectDataProvider.MethodParameters>

        </ObjectDataProvider>
    </Window.Resources>
    <Grid>
        <StackPanel>
            <Image x:Name="imgDynamic" 
                   MouseDown="ImgDynamic_MouseDown"
                   MouseMove="ImgDynamic_MouseMove"
                   MouseUp="ImgDynamic_MouseUp"
                   Width="1000"
                   Height="562"/>
            <Button Content="Select file" 
                Margin="30"
                Width="100" 
                x:Name="selectFileBtn"
                Click="SelectFileBtn_Click"/>

            <ComboBox Margin="10"
                      Width="100"
                      x:Name="edgeDetectionCbox"
                      SelectionChanged="EdgeDetectionCbox_SelectionChanged"
                      ItemsSource="{Binding Source={StaticResource dataFromEnum}}">
            </ComboBox>

            <Button Content="Detect now!" 
                    Margin="30"
                    Width="100" 
                    x:Name="detectBtn" 
                    Click="DetectBtn_Click"/>
        </StackPanel>
    </Grid>
</Window>

EdgeDetectionWindow.xaml.cs

 public partial class EdgeDetectionWindow : Window
{

    Image<Bgr, byte> _imgInput;

    private bool IsSelecting = false;
    private double X0, Y0, X1, Y1;
    private Bitmap ImageCopy;

    public EdgeDetectionWindow()
    {
        InitializeComponent();
    }

    private void SelectFileBtn_Click(object sender, RoutedEventArgs e)
    {
        OpenFileDialog openFileDialog = new OpenFileDialog();
        if (openFileDialog.ShowDialog() == true)
        {
            Uri fileUri = new Uri(openFileDialog.FileName);
            imgDynamic.Source = new BitmapImage(fileUri); // Why bitmapimage? //put the imagefile into the window
            ImageCopy = new Bitmap(openFileDialog.FileName);

            _imgInput = new Image<Bgr, byte>(openFileDialog.FileName);
        }
    }

    private void ImgDynamic_MouseDown(object sender, MouseButtonEventArgs e)
    {
        IsSelecting = true;
        X0 = e.GetPosition(imgDynamic).X;
        Y0 = e.GetPosition(imgDynamic).Y;
    }

    private void ImgDynamic_MouseMove(object sender, MouseEventArgs e)
    {
        if (!IsSelecting) return;


        //Save the final point
        X1 = e.GetPosition(this.imgDynamic).X;
        Y1 = e.GetPosition(this.imgDynamic).Y;

        //Make a bitmap to display the rectangle
        Bitmap bm = new Bitmap(ImageCopy);

        //Draw the rectangle
        using (Graphics gr = Graphics.FromImage(bm))
        {
            gr.DrawRectangle(Pens.Red,
                (float)Math.Min(X0, X1), (float)Math.Min(Y0, Y1),
                (float)Math.Abs(X0 - X1), (float)Math.Abs(Y0 - Y1));
        }

        //Display the rectangle
        imgDynamic.Source = BitmapToImageSource(bm);
    }

    private void ImgDynamic_MouseUp(object sender, MouseButtonEventArgs e)
    {
        if (!IsSelecting) return;
        IsSelecting = false; //reset the value

        //Display the rectangle
        imgDynamic.Source = BitmapToImageSource(ImageCopy);
    }

    private void EdgeDetectionCbox_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {

    }

    private void DetectBtn_Click(object sender, RoutedEventArgs e)
    {

        if (edgeDetectionCbox.SelectedItem.ToString().Equals("Canny"))
        {
            //Receive input from inputbox
            CannyInputDialogue popup = new CannyInputDialogue();
            popup.ShowDialog();
            int tresh = int.Parse(popup.Tresh);
            int treshLinking = int.Parse(popup.TreshLinking);

            //Do canny
            //Create grayscale
            Image<Gray, byte> _imgCanny = new Image<Gray, byte>(_imgInput.Width, _imgInput.Height, new Gray(0)); //canny  with 0 intensity gray image
            _imgCanny = _imgInput.Canny(tresh, treshLinking);

            //Display the image because imgDynamic.Source cannot display image from emgucv directly
            Bitmap display = _imgCanny.ToBitmap();
            imgDynamic.Source = BitmapToImageSource(display);


        }
        else if (edgeDetectionCbox.SelectedItem.ToString().Equals("RobertCross"))
        {
            //Do robertcross

        }
        else if (edgeDetectionCbox.SelectedItem.ToString().Equals("Laplacian"))
        {
            //Do laplacian
            LaplacianInputDialogue popup = new LaplacianInputDialogue();
            popup.ShowDialog();
            int apertureSize = int.Parse(popup.ApertureSize);
            //Do grayscale
            Image<Gray, byte> _imgGray = _imgInput.Convert<Gray, byte>(); //somehow it has to be converted(?)

            //Do sobel
            Image<Gray, float> _imgLaplacian = new Image<Gray, float>(_imgInput.Width, _imgInput.Height); //canny  with 0 intensity gray image
            _imgLaplacian = _imgGray.Laplace(apertureSize);

            //Display the image because imgDynamic.Source cannot display image from emgucv directly
            Bitmap display = _imgLaplacian.ToBitmap();
            imgDynamic.Source = BitmapToImageSource(display);

        }
        else if (edgeDetectionCbox.SelectedItem.ToString().Equals("Sobel"))
        {
            //Receive input from inputbox
            SobelInputDialogue popup = new SobelInputDialogue();
            popup.ShowDialog();
            int xorder = int.Parse(popup.Xorder);
            int yorder = int.Parse(popup.Yorder);
            int apertureSize = int.Parse(popup.ApertureSize);

            //Do grayscale
            Image<Gray, byte> _imgGray = _imgInput.Convert<Gray, byte>(); //somehow it has to be converted(?)

            //Do sobel
            Image<Gray, float> _imgSobel = new Image<Gray, float>(_imgInput.Width, _imgInput.Height); //canny  with 0 intensity gray image
            _imgSobel = _imgGray.Sobel(xorder, yorder, apertureSize);

            //Display the image because imgDynamic.Source cannot display image from emgucv directly
            Bitmap display = _imgSobel.ToBitmap();
            imgDynamic.Source = BitmapToImageSource(display);

        }


    }

    BitmapImage BitmapToImageSource(Bitmap bitmap)
    {
        using (MemoryStream memory = new MemoryStream())
        {
            bitmap.Save(memory, System.Drawing.Imaging.ImageFormat.Bmp);
            memory.Position = 0;
            BitmapImage bitmapimage = new BitmapImage();
            bitmapimage.BeginInit();
            bitmapimage.StreamSource = memory;
            bitmapimage.CacheOption = BitmapCacheOption.OnLoad;
            bitmapimage.EndInit();

            return bitmapimage;
        }
    }
}

我已经尝试将 e.GetPosition() 参数放到 this 或 imgDynamic 中,但它仍然相差很大。有什么解决方法吗?如果我的代码非常混乱,我很抱歉,因为我仍在努力了解更多信息。

【问题讨论】:

  • 首先,您不应该在 WPF 应用程序中使用 WinForms System.Drawing.Bitmap 类。要在图像顶部绘制选择矩形,请使用 Rectangle。然后从源 BitmapImage 创建一个 CroppedBitmap。如果您能详细说明您的实际目标,我们或许可以提供更合适的方法。
  • 我打算创建一个应用程序,在该应用程序中,用户将选择用户将其确定为对象的区域并在所选区域上应用边缘检测。然后应用程序将以像素为单位计算对象的面积(在应用边缘检测之后)。不过我还是不知道该怎么做。

标签: c# wpf


【解决方案1】:

为了在图像上绘制选择矩形,您可以简单地在图像顶部添加一个带有 RectangleGeometry 的 Path 元素,如下所示:

<Canvas>
    <Image Source="C:\Users\Public\Pictures\Sample Pictures\Koala.jpg"
           MouseLeftButtonDown="ImageMouseLeftButtonDown"
           MouseLeftButtonUp="ImageMouseLeftButtonUp"
           MouseMove="ImageMouseMove"/>

    <Path x:Name="selectionPath" Stroke="Magenta" StrokeThickness="2"/>
</Canvas>

使用这些事件处理程序:

private Point mousePos;

private void ImageMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    var image = (Image)sender;

    image.CaptureMouse();
    mousePos = e.GetPosition(image);
    selectionPath.Data = new RectangleGeometry(new Rect(mousePos, mousePos));
}

private void ImageMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
    var image = (Image)sender;

    image.ReleaseMouseCapture();
    selectionPath.Data = null;
}

private void ImageMouseMove(object sender, MouseEventArgs e)
{
    var rect = selectionPath.Data as RectangleGeometry;

    if (rect != null)
    {
        var image = (Image)sender;

        rect.Rect = new Rect(mousePos, e.GetPosition(image));
    }
}

【讨论】:

    猜你喜欢
    • 2012-06-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-30
    • 2019-02-07
    • 2014-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多