C# winform picturebox 选中区域

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace OpencvSharp411
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        public class MyRectangleF
        {
            public float X { get; set; }
            public float Y { get; set; }
            public float Width { get; set; }
            public float Height { get; set; }
        }

        private MyRectangleF selectedRegion = new MyRectangleF();

        private void Form1_Load(object sender, EventArgs e)
        {
            var image = new Bitmap(AppDomain.CurrentDomain.BaseDirectory + "templates\\" + "6622df65-c19d-184a-d47f-be2fdf7d72ce_01.tif");
            makePictureBoxSelectable(picRegion, image, selectedRegion);
        }

        private void makePictureBoxSelectable(PictureBox picBox, Bitmap actualImage, MyRectangleF destRegion)
        {
            Action ResetImage = delegate()
            {
                if (picBox.Width <= 0 || picBox.Height <= 0)
                    return;

                var size = getMaxDisplaySize(actualImage.Width, actualImage.Height, picBox.Width, picBox.Height);
                var resizedImage = new Bitmap(size.Width, size.Height);
                using (Graphics graphics = Graphics.FromImage(resizedImage))
                    graphics.DrawImage(actualImage, 0, 0, size.Width, size.Height);
                picBox.Image = resizedImage;
            };

            var isMouseDown = false;
            var startPoint = new Point();
            var endPoint = new Point();
            Point? lastStartPoint = null;
            Point? lastEndPoint = null;
            picBox.SizeMode = PictureBoxSizeMode.CenterImage;
            ResetImage();

            picBox.MouseDown += delegate(object sender, MouseEventArgs e)
            {
                var region = getImageRegion(picBox);
                if (region == null)
                    return;

                if (e.Location.X < region.X || e.Location.X > region.X + region.Width)
                    return;

                if (e.Location.Y < region.Y || e.Location.Y > region.Y + region.Height)
                    return;

                ResetImage();
                lastStartPoint = startPoint;
                lastEndPoint = endPoint;

                startPoint = e.Location;
                endPoint = startPoint;

                isMouseDown = true;
                picBox.Capture = true;
            };

            picBox.MouseUp += delegate(object sender, MouseEventArgs e)
            {
                if (!isMouseDown)
                    return;

                isMouseDown = false;
                picBox.Capture = false;

                var minMove = 20;   //设置选中精度
                if (e.Location.X - startPoint.X < minMove && e.Location.Y - startPoint.Y < minMove)
                {
                    if (lastStartPoint != null && lastEndPoint != null)
                    {
                        startPoint = lastStartPoint.Value;
                        endPoint = lastEndPoint.Value;
                        return;
                    }
                }

                endPoint = e.Location;

                drawPictureBoxImageRectangle(picBox, startPoint, e.Location);

                var region = getImageRegion(picBox);
                if (e.Location.X < region.X || e.Location.X > region.X + region.Width)
                    return;

                if (e.Location.Y < region.Y || e.Location.Y > region.Y + region.Height)
                    return;

                var newRegion = new Rectangle(startPoint.X, startPoint.Y, endPoint.X - startPoint.X, endPoint.Y - startPoint.Y);
                var image = getImageRegion(picBox);

                destRegion.X = (float)(newRegion.X - image.Left) / image.Width;
                destRegion.Y = (float)(newRegion.Y - image.Top) / image.Height;
                destRegion.Width = (float)newRegion.Width / image.Width;
                destRegion.Height = (float)newRegion.Height / image.Height;
            };

            picBox.MouseMove += delegate(object sender, MouseEventArgs e)
            {
                if (!isMouseDown)
                    return;

                var region = getImageRegion(picBox);
                if (e.Location.X < region.X || e.Location.X > region.X + region.Width)
                    return;

                if (e.Location.Y < region.Y || e.Location.Y > region.Y + region.Height)
                    return;

                drawPictureBoxRectangle(picBox, startPoint, e.Location);
            };

            picBox.SizeChanged += delegate(object sender, EventArgs e)
            {
                ResetImage();

                if (selectedRegion != null)
                {
                    var ratedRegion = selectedRegion;
                    var image = getImageRegion(picBox);
                    var defaultRegion = new Rectangle((int)(image.Width * ratedRegion.X) + image.Left
                        , (int)(image.Height * ratedRegion.Y) + image.Top
                        , (int)(image.Width * ratedRegion.Width)
                        , (int)(image.Height * ratedRegion.Height));
                    startPoint = defaultRegion.Location;
                    endPoint = new Point(defaultRegion.Left + defaultRegion.Width, defaultRegion.Top + defaultRegion.Height);
                }

                drawPictureBoxImageRectangle(picBox, startPoint, endPoint);
            };
        }

        Rectangle getImageRegion(PictureBox pictureBox)
        {
            var picHeight = pictureBox.Width * pictureBox.Image.Height / pictureBox.Image.Width;
            if (picHeight > pictureBox.Height)
            {
                var imageHeight = pictureBox.Height;
                var imageWidth = imageHeight * pictureBox.Image.Width / pictureBox.Image.Height;
                return new Rectangle((pictureBox.Width - imageWidth) / 2, (pictureBox.Height - imageHeight) / 2, imageWidth, imageHeight);
            }
            else
            {
                var imageWidth = pictureBox.Width;
                var imageHeight = imageWidth * pictureBox.Image.Height / pictureBox.Image.Width;
                return new Rectangle((pictureBox.Width - imageWidth) / 2, (pictureBox.Height - imageHeight) / 2, imageWidth, imageHeight);
            }
        }

        Size getMaxDisplaySize(int imageWidth, int imageHeight, int pictureBoxWidth, int pictureBoxHeight)
        {
            double widthRatio = (double)pictureBoxWidth / (double)imageWidth;
            double heightRatio = (double)pictureBoxHeight / (double)imageHeight;
            double ratio = Math.Min(widthRatio, heightRatio);

            int displayWidth = (int)(imageWidth * ratio);
            int displayHeight = (int)(imageHeight * ratio);

            return new Size(displayWidth, displayHeight);
        }

        void drawPictureBoxRectangle(PictureBox pictureBox, Point start, Point end)
        {
            pictureBox.Refresh();
            Graphics g1 = pictureBox.CreateGraphics();
            g1.DrawRectangle(new Pen(Color.Blue, 2), new Rectangle((int)start.X, (int)start.Y, (int)end.X - (int)start.X, (int)end.Y - (int)start.Y));
        }

        void drawPictureBoxImageRectangle(PictureBox pictureBox, Point start, Point end)
        {
            var image = new Bitmap(pictureBox.Image);
            start.X = start.X - (pictureBox.Width - image.Width) / 2;
            start.Y = start.Y - (pictureBox.Height - image.Height) / 2;
            end.X = end.X - (pictureBox.Width - image.Width) / 2;
            end.Y = end.Y - (pictureBox.Height - image.Height) / 2;

            using (Graphics g = Graphics.FromImage(image))
            {
                g.DrawRectangle(new Pen(Color.Blue, 2), new Rectangle((int)start.X, (int)start.Y, (int)end.X - (int)start.X, (int)end.Y - (int)start.Y));
            }
            pictureBox.Image = image;
        }

        void ShowImage(OpenCvSharp.Mat image, string title = "image")
        {
            OpenCvSharp.Cv2.NamedWindow(title, OpenCvSharp.WindowMode.Normal); // 设置窗口属性为可调整大小

            // 获取屏幕尺寸
            int screen_width = Screen.PrimaryScreen.Bounds.Width;
            int screen_height = Screen.PrimaryScreen.Bounds.Height;

            // 计算最大显示尺寸
            int max_size = (int)(Math.Min(screen_width, screen_height) * 0.8); // 取屏幕尺寸的 80%
            double scale = Math.Min(1.0, Math.Min(1.0 * max_size / image.Cols, 1.0 * max_size / image.Rows)); // 计算缩放比例

            var display_image = new OpenCvSharp.Mat();
            OpenCvSharp.Cv2.Resize(image, display_image, new OpenCvSharp.Size(), scale, scale); // 缩小图像
            OpenCvSharp.Cv2.ImShow(title, display_image); // 显示图像
            OpenCvSharp.Cv2.ResizeWindow(title, display_image.Cols, display_image.Rows); // 调整窗口大小为图像大小
            OpenCvSharp.Cv2.WaitKey(0); // 等待按键
        }

        private void btnShow_Click(object sender, EventArgs e)
        {
            var img = OpenCvSharp.Cv2.ImRead(AppDomain.CurrentDomain.BaseDirectory + "templates\\" + "6622df65-c19d-184a-d47f-be2fdf7d72ce_01.tif", OpenCvSharp.ImreadModes.Grayscale);
            var rect = new OpenCvSharp.Rect((int)(img.Width * selectedRegion.X), (int)(img.Height * selectedRegion.Y), (int)(img.Width * selectedRegion.Width), (int)(img.Height * selectedRegion.Height));
            var cropped = new OpenCvSharp.Mat(img, rect);
            ShowImage(cropped, "考号");
            OpenCvSharp.Cv2.WaitKey();
        }
    }
}

 上例中使用了opencvsharp 纯粹是为了使用它的show函数来验证我们选择的区域是否正确。如果只是为了实现选中区域,可以不用引入opencvsharp。

 

 

posted on 2022-12-14 14:30  空明流光  阅读(532)  评论(0编辑  收藏  举报

导航