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。
桂棹兮兰桨,击空明兮溯流光。