C#使用OpenCvSharp实现透视变换功能

 更新时间:2023年11月15日 10:08:02   作者:天天代码码天天  
这篇文章主要为大家详细介绍了C#如何使用OpenCvSharp实现透视变换的功能,文中的示例代码简洁易懂,具有一定的学习价值,需要的小伙伴可以参考下

效果

实现代码

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.IO;
using OpenCvSharp;
using OpenCvSharp.Extensions;
using System.Reflection;
using System.Drawing.Imaging;
 
namespace OpenCvSharp_透视变换_图像摆正_
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
 
        Bitmap bmp;
        string fileFilter = "*.*|*.bmp;*.jpg;*.jpeg;*.tiff;*.tiff;*.png";
        string img = "";
        private void button2_Click(object sender, EventArgs e)
        {
            index = 0;
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = fileFilter;
            if (ofd.ShowDialog() != DialogResult.OK) return;
            img = ofd.FileName;
            var imagebyte = File.ReadAllBytes(img);
            bmp = new Bitmap(img);
            pictureBox1.Image = new Bitmap(img);
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            Graphics gSave = Graphics.FromImage(bmp);
            System.Drawing.Point imagePoint = new System.Drawing.Point();
 
            GetImagePix(pt[0], out imagePoint);
            DrawFlag(gSave, imagePoint, 1);
            ptDst[0].X = imagePoint.X;
            ptDst[0].Y = imagePoint.Y;
 
            GetImagePix(pt[1], out imagePoint);
            DrawFlag(gSave, imagePoint, 2);
            ptDst[1].X = imagePoint.X;
            ptDst[1].Y = imagePoint.Y;
 
            GetImagePix(pt[2], out imagePoint);
            DrawFlag(gSave, imagePoint, 3);
            ptDst[2].X = imagePoint.X;
            ptDst[2].Y = imagePoint.Y;
 
            GetImagePix(pt[3], out imagePoint);
            DrawFlag(gSave, imagePoint, 4);
            ptDst[3].X = imagePoint.X;
            ptDst[3].Y = imagePoint.Y;
 
            gSave.DrawLine(pen, ptDst[0].X, ptDst[0].Y, ptDst[1].X, ptDst[1].Y);
            gSave.DrawLine(pen, ptDst[1].X, ptDst[1].Y, ptDst[2].X, ptDst[2].Y);
            gSave.DrawLine(pen, ptDst[2].X, ptDst[2].Y, ptDst[3].X, ptDst[3].Y);
            gSave.DrawLine(pen, ptDst[3].X, ptDst[3].Y, ptDst[0].X, ptDst[0].Y);
 
            bmp.Save("temp.jpg", ImageFormat.Jpeg);
 
            gSave.Dispose();
 
            System.Diagnostics.Process.Start(Application.StartupPath);
        }
 
        Pen pen = new Pen(Color.Red, 3);
        Pen pen1 = new Pen(Color.Green, 3);
        Font font = new Font("宋体", 12);
        SolidBrush solidBrush = new SolidBrush(Color.Red);
        int index = 0;
        public System.Drawing.Point[] pt = new System.Drawing.Point[4];
        public System.Drawing.Point[] ptDst = new System.Drawing.Point[4];
 
        private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
        {
            Graphics g = pictureBox1.CreateGraphics();
            if (index > 3)
            {
                //点排序
 
                //连线
                g.DrawLine(pen, pt[0].X, pt[0].Y, pt[1].X, pt[1].Y);
                g.DrawLine(pen, pt[1].X, pt[1].Y, pt[2].X, pt[2].Y);
                g.DrawLine(pen, pt[2].X, pt[2].Y, pt[3].X, pt[3].Y);
                g.DrawLine(pen, pt[3].X, pt[3].Y, pt[0].X, pt[0].Y);
                return;
            }
 
            pt[index].X = e.X;
            pt[index].Y = e.Y;
 
            g.DrawLine(pen, e.X - 5, e.Y, e.X + 6, e.Y);
            g.DrawLine(pen, e.X, e.Y - 5, e.X, e.Y + 6);
 
            ++index;
 
            //string str = (++index).ToString() + string.Format("({0},{1})", e.X, e.Y);
            //g.DrawString(str, font, solidBrush, e.X, e.Y);
 
            if (index > 3)
            {
                //点排序
 
                //连线
                g.DrawLine(pen, pt[0].X, pt[0].Y, pt[1].X, pt[1].Y);
                g.DrawLine(pen, pt[1].X, pt[1].Y, pt[2].X, pt[2].Y);
                g.DrawLine(pen, pt[2].X, pt[2].Y, pt[3].X, pt[3].Y);
                g.DrawLine(pen, pt[3].X, pt[3].Y, pt[0].X, pt[0].Y);
            }
 
            g.Dispose();
        }
 
        private void GetImagePixLocation(System.Drawing.Size pictureBoxSize, System.Drawing.Size imageSize, System.Drawing.Point pictureBoxPoint, out System.Drawing.Point imagePoint)
        {
 
            imagePoint = new System.Drawing.Point(0, 0);
 
            double scale;
 
            int detalInHeight = 0;
 
            int detalInWidth = 0;
 
            if (Convert.ToDouble(pictureBoxSize.Width) / pictureBoxSize.Height > Convert.ToDouble(imageSize.Width) / imageSize.Height)
            {
                scale = 1.0 * imageSize.Height / pictureBoxSize.Height;
                detalInWidth = Convert.ToInt32((pictureBoxSize.Width * scale - imageSize.Width) / 2.0);
            }
 
            else
            {
                scale = 1.0 * imageSize.Width / pictureBoxSize.Width;
                detalInHeight = Convert.ToInt32((pictureBoxSize.Height * scale - imageSize.Height) / 2.0);
            }
 
            imagePoint.X = Convert.ToInt32(pictureBoxPoint.X * scale - detalInWidth);
 
            imagePoint.Y = Convert.ToInt32(pictureBoxPoint.Y * scale - detalInHeight);
 
        }
 
        private void GetImagePix(System.Drawing.Point pictureBoxPoint, out System.Drawing.Point imagePoint)
        {
            GetImagePixLocation(pictureBox1.Size, pictureBox1.Image.Size, pictureBoxPoint, out imagePoint);
        }
        void DrawFlag(Graphics g, System.Drawing.Point e, int index)
        {
            g.DrawLine(pen, e.X - 5, e.Y, e.X + 6, e.Y);
            g.DrawLine(pen, e.X, e.Y - 5, e.X, e.Y + 6);
            string str = string.Format("{0}({1},{2})", index, e.X, e.Y);
            g.DrawString(str, font, solidBrush, e.X, e.Y);
        }
 
        private void button3_Click(object sender, EventArgs e)
        {
            if (index == 0)
            {
                MessageBox.Show("请先使用鼠标左键在图片上选择四个角的点");
                return;
            }
            else
            {
                index = 0;
            }
 
            Mat src = new Mat(img, ImreadModes.Color);
 
            Point2f[] srcPt = new Point2f[4];
            Point2f[] dstPt = new Point2f[4];
 
            //左上 右上 右下 左下
            System.Drawing.Point imagePoint = new System.Drawing.Point();
            GetImagePix(pt[0], out imagePoint);
            srcPt[0].X = imagePoint.X;
            srcPt[0].Y = imagePoint.Y;
 
            GetImagePix(pt[1], out imagePoint);
            srcPt[1].X = imagePoint.X;
            srcPt[1].Y = imagePoint.Y;
 
            GetImagePix(pt[2], out imagePoint);
            srcPt[2].X = imagePoint.X;
            srcPt[2].Y = imagePoint.Y;
 
            GetImagePix(pt[3], out imagePoint);
            srcPt[3].X = imagePoint.X;
            srcPt[3].Y = imagePoint.Y;
 
            dstPt[0] = new Point2f(0, 0);
            dstPt[1] = new Point2f(bmp.Width, 0);
            dstPt[2] = new Point2f(bmp.Width, bmp.Height);
            dstPt[3] = new Point2f(0, bmp.Height);
 
            Mat final = new Mat();
            Mat warpmatrix = Cv2.GetPerspectiveTransform(srcPt, dstPt);//获得变换矩阵
            Cv2.WarpPerspective(src, final, warpmatrix, src.Size());//投射变换,将结果赋给final
 
            if (pictureBox1.Image != null)
            {
                pictureBox1.Image.Dispose();
            }
            pictureBox1.Image = BitmapConverter.ToBitmap(final);
        }
 
        private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
        {
            if (pictureBox1.Image == null)
            {
                return;
            }
 
            int originalWidth = this.pictureBox1.Image.Width;
            int originalHeight = this.pictureBox1.Image.Height;
 
            PropertyInfo rectangleProperty = this.pictureBox1.GetType().GetProperty("ImageRectangle", BindingFlags.Instance | BindingFlags.NonPublic);
            Rectangle rectangle = (Rectangle)rectangleProperty.GetValue(this.pictureBox1, null);
 
            int currentWidth = rectangle.Width;
            int currentHeight = rectangle.Height;
 
            double rate = (double)currentHeight / (double)originalHeight;
 
            int black_left_width = (currentWidth == this.pictureBox1.Width) ? 0 : (this.pictureBox1.Width - currentWidth) / 2;
            int black_top_height = (currentHeight == this.pictureBox1.Height) ? 0 : (this.pictureBox1.Height - currentHeight) / 2;
 
            int zoom_x = e.X - black_left_width;
            int zoom_y = e.Y - black_top_height;
 
            double original_x = (double)zoom_x * rate;
            double original_y = (double)zoom_y * rate;
 
            StringBuilder sb = new StringBuilder();
 
            sb.AppendFormat("原始尺寸:({0},{1})(宽/高)\r\n\r\n", originalWidth, originalHeight);
            sb.AppendFormat("缩放状态图片尺寸:({0},{1})(宽,高)\r\n\r\n", currentWidth, currentHeight);
            sb.AppendFormat("缩放比率:{0}\r\n\r\n", rate);
            sb.AppendFormat("左留白宽度:{0}\r\n\r\n", black_left_width);
            sb.AppendFormat("上留白高度:{0}\r\n\r\n", black_top_height);
            sb.AppendFormat("当前鼠标坐标:({0},{1})(X,Y)\r\n\r\n", e.X, e.Y);
 
            textBox1.Text = sb.ToString();
        }
    }
}

以上就是C#使用OpenCvSharp实现透视变换功能的详细内容,更多关于C# OpenCvSharp透视变换的资料请关注脚本之家其它相关文章!

相关文章

最新评论