C# OpenCvSharp 透视变换(图像摆正)Demo

news2024/9/28 3:28:15

效果

Demo下载

代码

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();
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/695691.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

王爽《汇编语言》期末考试题库(附答案)

单选题 第一章 PC机的最小信息单位是( )。 A. bit B. 字节 C. 字长 D. 字 A PC机的最小信息单位是比特(bit),常用来表示一位二进制数字(0或1)。字节(byte)是计算机中常用的数据单位,一个字…

vscode中ModuleNotFoundError: No module named ‘torch‘解决方法

文章目录 遇到的问题解决方法参考 遇到的问题 使用vscode训练模型,没有使用远程服务器,使用本地运行代码,显示“ModuleNotFoundError: No module named ‘torch’” 解决方法 这是因为没有选择合适的python解释器。如何选择正确的解释器呢&…

【HDFS实战】HDFS上的数据均衡

HDFS上的数据均衡简介 文章目录 HDFS上的数据均衡简介重新平衡数据节点之间的数据块相关命令 重新平衡DN内磁盘间的数据相关命令PlanExecuteQueryCancelReport 相关配置调试 HDFS上的balance目前有两类: Balancer:节点之间的balanceDisk Balancer&#x…

C# WinForm 学习记录

1.为项目添加dll引用 在“解决方案资源管理器”面板中选择项目,单机鼠标右键,弹出菜单中选择“添加”->“引用”打开引用管理器,选择浏览添加自己需要的dll文件即可 2.位移运算符使用技巧 在进行位移运算时,当数值的二进制数…

设计模式学习笔记——你真的学透单例模式了吗

你真的学透单例模式了吗 一、概述 单例模式(Singleton Pattern)指确保一个类在任何情况下都绝对只有一个实例,并提供一个全局访问点,属于创建型设计模式 二、类图 三、通用写法 public class SingletonTest {public static vo…

使用docker安装redis,修改密码

1、搜索镜像 docker search redis 2、拉取镜像 docker pull redis 3.创建容器 前边是宿主机端口 后面是docker使用的端口 docker run --name redis -p 6379:6379 redis-test --requirepass 123456 这里密码设置为123456 4、如何修改密码 现有的redis创建密码或修改密码…

Python学习——字符串

一、字符串 字符串也是基本数据类型,是一个不可变的字符序列,字符串可以用单引号,双引号,三引号进行定义。 字符串的驻留机制,简而言之,就是相同的字符串只保留一个,后续创建相同字符串的时候&a…

【漏洞案例】云上攻防-记一次打穿云上内网的攻防实战

0x01 外网打点,但在云上 目标单位就给出了一个子域名和一个IP,访问给出的子域名就一个登录框,测试了下忘记密码处有用户名枚举,但登录功能做了登录失败处理,知道用户名也无法进行爆破。 登录时会调用api.target.com域…

CICflowmeter安装使用

项目地址:https://github.com/ahlashkari/CICFlowMeter前置条件:maven,winpcap或其他抓包工具,ideal或 Eclipse 用 ideal 打开项目,发现还需要 jnetpcap 包,但是 maven 仓库好像没有,自己编译 …

思科(Cisco)日志分析工具

作为网络安全管理员,实时监控和分析思科防火墙日志至关重要。对于安全网络,管理员需要: 检测各种网络攻击,并查明攻击的来源和类型(思科实时日志查看器)。跟踪思科防火墙上未经授权的登录尝试。获取有关活…

PHP OA协同办公管理系统mysql数据库web结构apache计算机软件工程网页wamp

一、源码特点 PHP OA协同办公管理系统 是一套完善的web设计系统,对理解php编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。 代码下载 https://download.csdn.net/download/qq_41221322/87959360https://do…

wireshark抓包工具常用功能

wireshark工具面板如下图所示: 本文记录我比较常用的功能。如果有大佬还用过其他功能麻烦指点一二。 抓包、查找、过滤、数据分析。 菜单工具栏: 设置时间戳格式: 为了方便自己查看,把时间戳格式设置为自己认为比较好看的格式…

ThinkPHP6 请求

ThinkPHP6 请求 前言一、 获取请求二、request其他方法三, 请求信息总结 前言 什么是请求,就是 G E T 和 _GET和 G​ET和_POST类似的东西 一、 获取请求 获取请求可以使用$_GET、$_POST、$_REQUEST、$_SERVER、$_SESSION、$_COOKIE、$_ENV等系统变量,也可…

Android——快速设置Quick Settings Tile(创建自定义快速设置磁贴)

Android——快速设置Quick Settings Tile(创建自定义快速设置磁贴) 简介快速设置磁贴的使用场景创建磁贴创建自定义图标创建并声明你的tile服务 管理你的tile服务TileService生命周期选择监听模式Active mode (推荐)Non-active mode Tile状态更新Tile处理…

字节跳动云原生大数据平台运维管理实践

云原生大数据是大数据平台新一代架构和运行形态。随着字节跳动内部业务的快速增长,传统大数据运维平台的劣势开始逐渐暴露,如组件繁多,安装运维复杂,与底层环境过度耦合;对业务方来说缺少开箱即用的日志、监控、告警功…

第7讲:使用ajax技术实现弹出商品详情提示功能(xml数据)

使用ajax技术使用ajax技术实现弹出商品详情提示功能,本案例使用原生态xmlhttprequest对象,GET方法异步通讯,后台使用map保存搜索数据,查询到对应数据后,返回xml格式数据,前端使用responseXML属性返回xml格式…

Android模拟器无法启动

在Android 13版本上,关于“复制”有了新的变化,但是我在我的小米手机(也是Android 13版本的)上测试没有看到对应的变化,所以想运行一个Android 13的模拟器来测试看看,结果死活运行不起来,一直卡…

el-dialog父子传值弹窗实现(弹窗内容较多时分开写)

需求:父组件点击按钮后打开弹窗,但是因为弹窗内容巨多,直接提取出来,只要在父组件点击时才显示弹窗,并且传递值给弹窗做数据回显,编辑或者新增功能都可以。 1.首先建立父子关系 创建个弹窗组件dialog.vue&…

HTML5+CSS3+JS小实例:悬停滚动文字的导航栏

实例:悬停滚动文字的导航栏 技术栈:HTML+CSS+JS 效果: 源码: 【html】 <!DOCTYPE html> <html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"><meta name="viewport" content=…

Sql Server 获取连续日期时间

获取连续日期时间 在项目中&#xff0c;有时候需要按日期/时间统计&#xff0c;例如2023-06-21至2023-06-28期间每一天的数据&#xff0c;如果某一天没有数据&#xff0c;也要查询出来&#xff0c;用NULL处理。 1.示例 2.连续日期效果SQL DECLARE StartDate DATE 2023-06-2…