文章目录


MainWindow.xaml

<Window x:Class="WpfApp4.MainWindow"
        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:WpfApp4"
        mc:Ignorable="d"
        Title="MainWindow" Height="600" Width="1050">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="178*"></RowDefinition>
            <RowDefinition Height="17*"></RowDefinition>
        </Grid.RowDefinitions>
        <Viewbox Grid.Row="0" Grid.Column="0" Margin="15,15,15,15">
            <StackPanel Width="330"  Height="400" Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Top" Background="Yellow">
                <Viewbox Stretch="Uniform">
                    <Image 
                   Name="testImage"
                   Stretch="Fill" />

                </Viewbox>
            </StackPanel>

        </Viewbox>
        <Viewbox Grid.Row="0" Height="40" Width="120" Margin="0,480,0,0" VerticalAlignment="Top" HorizontalAlignment="Center">
            <Button Content="加载图片" Grid.Column="0" Grid.Row="0" HorizontalAlignment="Center"   Click="Button_Click" Width="62" />
        </Viewbox>
        <Viewbox Grid.Row="0" Grid.Column="3" Height="40" Width="120" Margin="0,480,0,0" VerticalAlignment="Top" HorizontalAlignment="Center">
            <Button Content="选择图片" Grid.Column="0" Grid.Row="0" HorizontalAlignment="Center"   Click="Button_Click3" Width="62" />
        </Viewbox>
        <Viewbox Grid.Row="0" Grid.Column="1" Margin="15,15,15,15">
            <StackPanel Width="330"  Height="400" Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Top" Background="Green">
                <Viewbox Stretch="Uniform">
                    <Image 
           Name="testImage2"
           Stretch="Fill" />

                </Viewbox>
            </StackPanel>

        </Viewbox>
        <Viewbox Grid.Row="0" Grid.Column="1" Height="40" Width="120" Margin="0,480,0,0" VerticalAlignment="Top" HorizontalAlignment="Center">
            <Button Content="定位图片" Grid.Column="1" Grid.Row="0" HorizontalAlignment="Center"   Click="Button_Click2" Width="62" />
        </Viewbox>
    </Grid>
</Window>

MainWindow.xaml.cs

using Microsoft.Win32;
using OpenCvSharp;
using System.Drawing;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using WpfApp4.UI;
using static System.Net.Mime.MediaTypeNames;

namespace WpfApp4
{

    public partial class MainWindow : System.Windows.Window
    {
        private System.Windows.Rect selectedRoi;
        private Mat template;
        private string selectedImagePath;

        public MainWindow()
        {
            InitializeComponent();
        }

        public static BitmapSource GetImageSouce(Bitmap bitmap)
        {
            BitmapSource img;
            IntPtr hBitmap;

            hBitmap = bitmap.GetHbitmap();
            img = Imaging.CreateBitmapSourceFromHBitmap(
                hBitmap,
                IntPtr.Zero,
                Int32Rect.Empty,
                BitmapSizeOptions.FromEmptyOptions());
            return img;
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            // 读取图像
            if (string.IsNullOrEmpty(selectedImagePath))
            {
                MessageBox.Show("请先选择图片");
                return;
            }

            Mat img = Cv2.ImRead(selectedImagePath);
            Bitmap map = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(img);
            
            testImage.Source = GetImageSouce(map);

            var selectRoiWindow = new SelectRoiWindow(selectedImagePath, (int)testImage.ActualWidth, (int)testImage.ActualHeight);
            if (selectRoiWindow.ShowDialog() == true)
            {
                selectedRoi = selectRoiWindow.Roi;
                template = selectRoiWindow.Template;
                MessageBox.Show($"Selected ROI - X: {selectedRoi.X}, Y: {selectedRoi.Y}, Width: {selectedRoi.Width}, Height: {selectedRoi.Height}");
            }

        }

        private void Button_Click2(object sender, RoutedEventArgs e)
        {

            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.Filter = "Image files (*.bmp;*.jpg;*.png)|*.bmp;*.jpg;*.png|All files (*.*)|*.*";
            string selectedImagePath2 = "";
            if (openFileDialog.ShowDialog() == true)
            {
                selectedImagePath2 = openFileDialog.FileName;
            }

            // 读取图像
            if (string.IsNullOrEmpty(selectedImagePath2))
            {
                MessageBox.Show("请先选择图片");
                return;
            }
            if (template == null)
            {
                MessageBox.Show("请先选择ROI区域");
                return;
            }

            // 读取图像
            Mat img = Cv2.ImRead(selectedImagePath);
            Mat img2 = Cv2.ImRead(selectedImagePath2);

            // 使用模板匹配来定位目标区域
            Mat result = new Mat();
            Mat result2 = new Mat();
            //Cv2.MatchTemplate(img, template, result, TemplateMatchModes.CCoeffNormed);
            //Cv2.MatchTemplate(img2, template, result2, TemplateMatchModes.CCoeffNormed);

            // 定义ROI区域
            OpenCvSharp.Rect roiRect = new OpenCvSharp.Rect((int)selectedRoi.X, (int)selectedRoi.Y, (int)selectedRoi.Width, (int)selectedRoi.Height);
            Mat roiMat = new Mat(img, roiRect);
            Mat roiMat2 = new Mat(img2, roiRect);

            // 使用模板匹配来定位目标区域
            Cv2.MatchTemplate(roiMat, template, result, TemplateMatchModes.CCoeffNormed);
            Cv2.MatchTemplate(roiMat2, template, result2, TemplateMatchModes.CCoeffNormed);

            // 找到匹配结果中最好的位置
            Cv2.MinMaxLoc(result, out _, out double maxVal, out _, out OpenCvSharp.Point maxLoc);
            Cv2.MinMaxLoc(result2, out _, out double maxVal2, out _, out OpenCvSharp.Point maxLoc2);



            // 如果匹配度高于某个阈值,则认为找到了目标
            if (maxVal > 0.8)
            {
                // 绘制绿色框
                OpenCvSharp.Rect roi = new OpenCvSharp.Rect(maxLoc.X, maxLoc.Y, (int)selectedRoi.Width, (int)selectedRoi.Height);
                Cv2.Rectangle(img, roi, new Scalar(0, 0, 255), 10);
                //MessageBox.Show($"Matched ROI - X: {maxLoc.X}, Y: {maxLoc.Y}, Width: {selectedRoi.Width}, Height: {selectedRoi.Height}");
            }
            if (maxVal2 > 0.9)
            {
                // 绘制绿色框
                OpenCvSharp.Rect roi = new OpenCvSharp.Rect(maxLoc2.X, maxLoc2.Y, (int)selectedRoi.Width, (int)selectedRoi.Height);
                Cv2.Rectangle(img2, roi, new Scalar(0, 255, 0), 10);
                //MessageBox.Show($"Matched ROI - X: {maxLoc2.X}, Y: {maxLoc2.Y}, Width: {selectedRoi.Width}, Height: {selectedRoi.Height}");
            }

            MessageBox.Show($"匹配阈值1 {maxVal};匹配阈值2 {maxVal2}");
            // 显示处理后的图像
            Bitmap map = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(img);
            Bitmap map2 = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(img2);
            testImage.Source = GetImageSouce(map);
            testImage2.Source = GetImageSouce(map2);
        }

        private void Button_Click3(object sender, RoutedEventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.Filter = "Image files (*.bmp;*.jpg;*.png)|*.bmp;*.jpg;*.png|All files (*.*)|*.*";
            if (openFileDialog.ShowDialog() == true)
            {
                
                try 
                {
                    selectedImagePath = openFileDialog.FileName;
                    Mat img = Cv2.ImRead(selectedImagePath);
                    Bitmap map = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(img);
                    testImage.Source = GetImageSouce(map);
                }
                catch (Exception x) 
                {
                    Console.WriteLine("Exception:" +x.ToString);
                }

            }
        }
    }
}

opencv.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WpfApp4
{
    internal class opencv
    {
    }
}

Window1.xaml

<Window x:Class="WpfApp4.UI.SelectRoiWindow"
        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:WpfApp4.UI"
        mc:Ignorable="d"
      Title="Select ROI" Height="600" Width="1050">
    <Grid>
        <Grid>
            <!--<Image 
                Name="image"
                Stretch="Uniform" />-->

            <Image Width="330"  Height="400"
                Name="image"
                Stretch="None" />
            <Canvas Name="canvas" Background="Transparent" MouseDown="Canvas_MouseDown" MouseMove="Canvas_MouseMove" MouseUp="Canvas_MouseUp"
                    Width="{Binding ActualWidth, ElementName=image}" Height="{Binding ActualHeight, ElementName=image}"/>


        </Grid>
        <Button Content="保存" HorizontalAlignment="Right" VerticalAlignment="Bottom" Click="SaveButton_Click"/>
        <TextBlock Name="coordinatesTextBlock" HorizontalAlignment="Center" VerticalAlignment="top" Margin="10" Foreground="Black"/>
        <Button Content="加载图像" HorizontalAlignment="Left" VerticalAlignment="Bottom" Click="加载图像" Margin="715,0,0,29" Width="85"/>
    </Grid>
</Window>

Window1.xaml.cs

using OpenCvSharp;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using static System.Net.Mime.MediaTypeNames;


namespace WpfApp4.UI
{
    /// <summary>
    /// SelectRoiWindow.xaml 的交互逻辑
    /// </summary>
    public partial class SelectRoiWindow : System.Windows.Window
    {
        private System.Windows.Point startPoint;
        private System.Windows.Shapes.Rectangle rect;
        private bool isDrawing = false;
        public System.Windows.Rect Roi { get; private set; }
        public Mat Template { get; private set; }
        private double scaleX, scaleY;


        public SelectRoiWindow(string imagePath, int targetWidth, int targetHeight)
        {
            InitializeComponent();
            Mat img = Cv2.ImRead(imagePath);
            if (targetWidth <= 0 || targetHeight <= 0)
            {
                targetHeight = targetWidth = 800;
            }

            // 缩放图像
            Mat resizedImg = new Mat();
            Cv2.Resize(img, resizedImg, new OpenCvSharp.Size(targetWidth, targetHeight));

            // 计算缩放比例
            scaleX = (double)img.Width / targetWidth;
            scaleY = (double)img.Height / targetHeight;

            Bitmap map = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(resizedImg);
            image.Width = resizedImg.Cols;
            image.Height = resizedImg.Height;
            image.Source = GetImageSouce(map);
            image.Stretch = Stretch.Fill;


            //image.ActualHeight = targetHeight;
            //image.ActualWidth = targetWidth;
            Template = resizedImg;
        }


        public static BitmapSource GetImageSouce(Bitmap bitmap)
        {
            BitmapSource img;
            IntPtr hBitmap;

            hBitmap = bitmap.GetHbitmap();
            img = Imaging.CreateBitmapSourceFromHBitmap(
                hBitmap,
                IntPtr.Zero,
                Int32Rect.Empty,
                BitmapSizeOptions.FromEmptyOptions());
            return img;
        }
        private void Canvas_MouseDown(object sender, MouseButtonEventArgs e)
        {
            startPoint = e.GetPosition(canvas);
            rect = new System.Windows.Shapes.Rectangle
            {
                Stroke = System.Windows.Media.Brushes.Green,
                StrokeThickness = 2
            };
            Canvas.SetLeft(rect, startPoint.X);
            Canvas.SetTop(rect, startPoint.Y);
            canvas.Children.Add(rect);
            isDrawing = true;
        }

        private void Canvas_MouseMove(object sender, MouseEventArgs e)
        {
            if (isDrawing)
            {
                canvas.Height = image.ActualHeight;
                canvas.Width = image.ActualWidth;
                var pos = e.GetPosition(canvas);
                var x = Math.Min(pos.X, startPoint.X);
                var y = Math.Min(pos.Y, startPoint.Y);
                var w = Math.Abs(pos.X - startPoint.X);
                var h = Math.Abs(pos.Y - startPoint.Y);
                rect.Width = w;
                rect.Height = h;
                Canvas.SetLeft(rect, x);
                Canvas.SetTop(rect, y);
                coordinatesTextBlock.Text = $"X: {x}, Y: {y}, Width: {w}, Height: {h}";
            }
        }

        private void Canvas_MouseUp(object sender, MouseButtonEventArgs e)
        {
            isDrawing = false;
            var imagePosition = image.TransformToAncestor(this).Transform(new System.Windows.Point(0, 0));
            var canvasPosition = canvas.TransformToAncestor(this).Transform(new System.Windows.Point(0, 0));
            var offsetX = canvasPosition.X - imagePosition.X;
            var offsetY = canvasPosition.Y - imagePosition.Y;
            var a = image.ActualHeight;
            var n = image.ActualWidth;
            // 计算实际ROI
            double roiX = (Canvas.GetLeft(rect) - offsetX) * scaleX;
            double roiY = (Canvas.GetTop(rect) - offsetY) * scaleY;
            double roiWidth = rect.Width * scaleX;
            double roiHeight = rect.Height * scaleY;

            Roi = new System.Windows.Rect(roiX, roiY, roiWidth, roiHeight);
        }

        private void 加载图像(object sender, RoutedEventArgs e)
        {
            Mat img = Cv2.ImRead(@"C:\Users\HZ-3-10-0153\Pictures\Camera Roll\1.bmp");
            Bitmap map = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(img);
            image.Height = 828;
            image.Width = 802;
            image.Source = GetImageSouce(map);
            image.Stretch = Stretch.Fill;
        }

        private void SaveButton_Click(object sender, RoutedEventArgs e)
        {
            DialogResult = true;
            Close();
        }

    }
}
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐