C#使用OpenCvSharp實(shí)現(xiàn)透視變換功能
更新時(shí)間:2023年11月15日 10:08:02 作者:天天代碼碼天天
這篇文章主要為大家詳細(xì)介紹了C#如何使用OpenCvSharp實(shí)現(xiàn)透視變換的功能,文中的示例代碼簡(jiǎn)潔易懂,具有一定的學(xué)習(xí)價(jià)值,需要的小伙伴可以參考下
效果
實(shí)現(xiàn)代碼
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) { //點(diǎn)排序 //連線 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) { //點(diǎn)排序 //連線 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("請(qǐng)先使用鼠標(biāo)左鍵在圖片上選擇四個(gè)角的點(diǎn)"); 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());//投射變換,將結(jié)果賦給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("縮放狀態(tài)圖片尺寸:({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("當(dāng)前鼠標(biāo)坐標(biāo):({0},{1})(X,Y)\r\n\r\n", e.X, e.Y); textBox1.Text = sb.ToString(); } } }
以上就是C#使用OpenCvSharp實(shí)現(xiàn)透視變換功能的詳細(xì)內(nèi)容,更多關(guān)于C# OpenCvSharp透視變換的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
c#實(shí)現(xiàn)sunday算法實(shí)例
Sunday算法思想跟BM算法很相似,在匹配失敗時(shí)關(guān)注的是文本串中參加匹配的最末位字符的下一位字符,下面是用C#實(shí)現(xiàn)sunday的實(shí)例代碼,有需要的朋友可以參考一下2013-08-08微信公眾平臺(tái)開發(fā)教程(三) 基礎(chǔ)框架搭建
這篇文章主要介紹了微信公眾平臺(tái)開發(fā)教程(三) 基礎(chǔ)框架搭建,具有一定的參考價(jià)值,有需要的可以了解一下。2016-12-12C#序列化與反序列化集合對(duì)象并進(jìn)行版本控制
這篇文章介紹了C#序列化與反序列化集合對(duì)象并實(shí)現(xiàn)版本控制的方法,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-09-09C#圖像處理之圖像目標(biāo)質(zhì)心檢測(cè)的方法
這篇文章主要介紹了C#圖像處理之圖像目標(biāo)質(zhì)心檢測(cè)的方法,可實(shí)現(xiàn)C#計(jì)算圖像質(zhì)心的相關(guān)技巧,需要的朋友可以參考下2015-04-04C#實(shí)現(xiàn)對(duì)數(shù)組進(jìn)行隨機(jī)排序類實(shí)例
這篇文章主要介紹了C#實(shí)現(xiàn)對(duì)數(shù)組進(jìn)行隨機(jī)排序類,實(shí)例分析了C#數(shù)組與隨機(jī)數(shù)操作技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-03-03C# 使用PictureBox實(shí)現(xiàn)圖片按鈕控件的示例步驟
這篇文章主要介紹了C# 使用PictureBox實(shí)現(xiàn)圖片按鈕控件的示例步驟,幫助大家更好的理解和使用c#,感興趣的朋友可以了解下2021-02-02