c#截取旋转矩形区域内的图像

c#截取旋转矩形区域内的图像

先来看看最终效果。
c#截取旋转矩形区域内的图像_第1张图片
c#截取旋转矩形区域内的图像_第2张图片
因为实际项目中要用到opencvsharp,所以这里面的旋转矩形就直接用opencvsharp里面封装好了的RotatedRect。

        private Size2f cropSize = new Size2f(400, 300);
        private RotatedRect cropRect = new RotatedRect();
        private PictureBox cropRectBox;
        private SolidBrush brush;

        public Form1()
        {
            InitializeComponent();
            brush = new SolidBrush(Color.FromArgb(50, 255, 0, 0));
            cropRectBox = new PictureBox()
            {
                Visible = false,
                BackColor = Color.Transparent,
                SizeMode = PictureBoxSizeMode.Normal,
                BorderStyle = BorderStyle.None,
                Parent = rawImgPb
            };
            cropRectBox.MouseDown += CropRectBox_MouseDown;
            rawImgPb.Image = Image.FromFile("C:\\Users\\Administrator\\Desktop\\测试\\1.jpg");
        }

        private void CropRectBox_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button != MouseButtons.Right)
                return;
            cropRect.Angle += 10;
            ShowCropRectBox(cropRect);
        }

        private void rawImgPb_MouseDown(object sender, MouseEventArgs e)
        {
            cropRect.Center = new Point2f(e.X + cropSize.Width / 2, e.Y + cropSize.Height / 2);
            cropRect.Size = cropSize;
            cropRect.Angle = 0;
            ShowCropRectBox(cropRect);
        }

        private void ShowCropRectBox(RotatedRect cropRect)
        {
            cropRectBox.Show();
            
            var boundRect = cropRect.BoundingRect();
            cropRectBox.Location = new Point(boundRect.X, boundRect.Y);
            cropRectBox.Size = new Size(boundRect.Width, boundRect.Height);
            cropRectBox.Image = new Bitmap(boundRect.Width, boundRect.Height);

            using (var g = Graphics.FromImage(cropRectBox.Image))
            {
                g.Clear(Color.Transparent);
                var pts = cropRect.Points();
                Point[] newPts = new Point[pts.Length];
                for (int i = 0; i < pts.Length; i++)
                {
                    //把裁剪矩形的点转换成裁剪框里面的坐标,这样才能在裁剪框的图片里画出裁剪矩形
                    newPts[i] = cropRectBox.PointToClient(cropRectBox.Parent.PointToScreen(new Point((int)pts[i].X, (int)pts[i].Y)));
                }
                g.FillPolygon(brush, newPts);
            }

            if (cropRect.Angle == 0)
                cropImgPb.Image = GetRoiImage(rawImgPb.Image, new Rectangle(boundRect.X, boundRect.Y, boundRect.Width, boundRect.Height));
            else
                cropImgPb.Image = GetRoiImage(rawImgPb.Image, cropRect);
        }

        public static Bitmap GetRoiImage(Image sourceImg, Rectangle roi)
        {
            if (roi.Width == 0 || roi.Height == 0)
                return null;
            Bitmap resultBitmap = new Bitmap(roi.Width, roi.Height);
            using (Graphics g = Graphics.FromImage(resultBitmap))
            {
                Rectangle resultRectangle = new Rectangle(0, 0, roi.Width, roi.Height);
                g.DrawImage(sourceImg, resultRectangle, roi, GraphicsUnit.Pixel);
            }

            return resultBitmap;
        }

        public static Bitmap GetRoiImage(Image sourceImg, RotatedRect rotatedRoi)
        {
            var source = sourceImg as Bitmap;
            //Pen pen = new Pen(Color.FromArgb(50, 100, 100, 100));
            //Pen pen1 = new Pen(Color.FromArgb(50, 30, 30, 30));
            using (var g = Graphics.FromImage(sourceImg))
            {
                var result = new Bitmap((int)rotatedRoi.Size.Width, (int)rotatedRoi.Size.Height);
                var pt1 = rotatedRoi.Points()[1];
                var radian = rotatedRoi.Angle * Math.PI / 180.0;
                var sin = Math.Sin(radian);
                var cos = Math.Cos(radian);
                //在原图上绕着旋转矩形特定的点,找出旋转之后的对应点,然后把对应点都要偏移到一张新的图像上
                for (int x1 = (int)pt1.X; x1 < pt1.X + result.Width; x1++)
                {
                    for (int y1 = (int)pt1.Y; y1 < pt1.Y + result.Height; y1++)
                    {
                        //g.DrawRectangle(pen1, new Rectangle(x1, y1, 1, 1));
                        var x2 = (x1 - pt1.X) * cos - (y1 - pt1.Y) * sin + pt1.X;
                        var y2 = (x1 - pt1.X) * sin + (y1 - pt1.Y) * cos + pt1.Y;
                        if (x2 < 0 || y2 < 0 || x2 >= source.Width || y2 >= source.Height)
                            continue;
                        //把对应点都要偏移到一张新的图像上
                        var wdith = x1 - (int)pt1.X;
                        var height = y1 - (int)pt1.Y;
                        if (wdith < result.Width && height < result.Height)
                            result.SetPixel(wdith, height, source.GetPixel((int)x2, (int)y2));
                        //g.DrawRectangle(pen, new Rectangle((int)x2, (int)y2, 1, 1));
                    }
                }

                return result;
            }
        }

        public static Mat GetRoiMat(Mat src, RotatedRect rotatedRoi)
        {
            var dst = new Mat((int)rotatedRoi.Size.Height, (int)rotatedRoi.Size.Width,MatType.CV_8UC3);
            var pt1 = rotatedRoi.Points()[1];
            var radian = rotatedRoi.Angle * Math.PI / 180.0;
            var sin = Math.Sin(radian);
            var cos = Math.Cos(radian);
            //在原图上绕着旋转矩形特定的点,找出旋转之后的对应点,然后把对应点都要偏移到一张新的图像上
            for (int x1 = (int)pt1.X; x1 < pt1.X + dst.Width; x1++)
            {
                for (int y1 = (int)pt1.Y; y1 < pt1.Y + dst.Height; y1++)
                {
                    var x2 = (x1 - pt1.X) * cos - (y1 - pt1.Y) * sin + pt1.X;
                    var y2 = (x1 - pt1.X) * sin + (y1 - pt1.Y) * cos + pt1.Y;
                    if (x2 < 0 || y2 < 0 || x2 >= src.Width || y2 >= src.Height)
                        continue;
                    //把对应点都要偏移到一张新的图像上
                    var wdith = x1 - (int)pt1.X;
                    var height = y1 - (int)pt1.Y;
                    if (wdith < dst.Width && height < dst.Height)
                        dst.Set(height, wdith, src.At<Vec3b>((int)y2, (int)x2));
                }
            }

            return dst;
        }

你可能感兴趣的:(c#,图像处理)