C# 标注图片

news2024/9/22 11:38:53

画矩形

 画四边形

 保存标注图片

保存标注信息

 代码

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.Drawing.Imaging;
using System.Drawing.Drawing2D;
using System.IO;

namespace lxw_Lable
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private SolidBrush fill_brush = new SolidBrush(Color.FromArgb(100, Color.White));
        private Pen line_color = new Pen(new SolidBrush(Color.Red), 2);
        private Pen pen_yellow = new Pen(new SolidBrush(Color.Yellow), 2);
        private Pen pen_red = new Pen(new SolidBrush(Color.Red), 2);
        private Graphics draw_paint, merge_paint;//中间画板
        private Image tmp_bitmap;//用来保存绘图痕迹
        List<Point> polyPoints = null;//存储绘制多边形的点集
        List<List<Point>> ltPoly = new List<List<Point>>();//图形信息,最终保存和导出
        Rectangle rectA;//存储要用于绘图的矩形
        Image bg_image;//背景图片
        Point start;  //起始点
        Point end;   //结束点
        bool need_draw_tmp;   //在MouseMove事件中判断是否绘制矩形框
        string action_type = "";//绘图动作类型
        bool is_first_down = true;//判断是否第一次按下鼠标

        private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Title = "请选择图片";
            ofd.Filter = "jpg图片|*.JPG|jpeg图片|*.JPEG|gif图片|*.GIF|png图片|*.PNG";//文件类型
            ofd.Multiselect = false;
            if (ofd.ShowDialog() == DialogResult.OK)
            {
                string image_path = ofd.FileName;
                //中间画布
                tmp_bitmap = new Bitmap(image_path);
                //创建空白画板
                draw_paint = Graphics.FromImage(tmp_bitmap);
                bg_image = Image.FromFile(image_path);
                pictureBox1.Image = bg_image;
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            if (pictureBox1.Image == null)
            {
                return;
            }
            SaveFileDialog sfd = new SaveFileDialog();
            sfd.Filter = "jpeg图片|*.JPEG|gif图片|*.GIF|png图片|*.PNG";//设置文件类型
            sfd.FileName = "temp";//设置默认文件名
            sfd.AddExtension = true;//设置自动在文件名中添加扩展名
            if (sfd.ShowDialog() == DialogResult.OK)
            {
                Bitmap bmp = new Bitmap(pictureBox1.Image);
                ImageFormat imageformat = null;
                switch (sfd.FilterIndex)
                {
                    case 1:
                        imageformat = System.Drawing.Imaging.ImageFormat.Jpeg;
                        break;
                    case 2:
                        imageformat = System.Drawing.Imaging.ImageFormat.Gif;
                        break;
                    case 3:
                        imageformat = System.Drawing.Imaging.ImageFormat.Png;
                        break;
                }

                Graphics g = Graphics.FromImage(bmp);
                //画图
                foreach (var item in ltPoly)
                {
                    draw_paint.DrawPolygon(line_color, item.ToArray());
                }
                bmp.Save(sfd.FileName, imageformat);
                bmp.Dispose();
                g.Dispose();
                MessageBox.Show("保存成功!", "注意", MessageBoxButtons.OK, MessageBoxIcon.Information);
                //打开文件
                System.Diagnostics.Process.Start(sfd.FileName.ToString());
                //打开文件夹
                //System.Diagnostics.Process.Start(localFilePath.Substring(0, localFilePath.LastIndexOf("\\")));
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            comboBox1.SelectedIndex = 0;
            action_type = "矩形";
        }

        private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
        {
            if (pictureBox1.Image == null)
            {
                MessageBox.Show("请先选择图片");
                return;
            }

            if (action_type.IndexOf("矩形") >= 0)
            {
                if (e.Button == MouseButtons.Left)
                {
                    start = e.Location;
                    need_draw_tmp = true;
                }
            }
            else if (action_type.IndexOf("四边形") >= 0)
            {
                Graphics g = pictureBox1.CreateGraphics();
                //绘制多边形  low版本
                if (is_first_down)  //首先第一次创建两个点如下(e.X, e.Y),( e.X + 1, e.Y + 1)
                {
                    //first point down
                    if (e.Button == MouseButtons.Left)
                    {
                        is_first_down = false;
                        if (polyPoints == null) polyPoints = new List<Point>();
                        polyPoints.Add(e.Location);
                        need_draw_tmp = true;
                    }
                }
                else
                {
                    //add new point
                    if (e.Button == MouseButtons.Left)
                    {
                        //添加新的点
                        Point point = new Point(e.X, e.Y);
                        polyPoints.Add(point);

                        if (polyPoints.Count > 0 && polyPoints.Count % 4 == 0)
                        {
                            //转化坐标
                            Point temp;
                            List<Point> ltTempPoints = new List<Point>();
                            foreach (var item in polyPoints)
                            {
                                GetImagePixLocation(pictureBox1, item, out temp);
                                ltTempPoints.Add(temp);
                            }
                            polyPoints = ltTempPoints;
                            ltPoly.Add(polyPoints);
                            DrawPloy(true);
                        }
                    }
                }
            }
            end = e.Location;
            pictureBox1.Invalidate();
        }

        private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
        {

            if (action_type.IndexOf("矩形") >= 0)
            {
                //绘制矩形框 并填充
                if (need_draw_tmp)
                {
                    if (e.Button != MouseButtons.Left) return;
                    end = e.Location;
                    pictureBox1.Invalidate();
                }
            }
            else if (action_type.IndexOf("四边形") >= 0)
            {
                //绘制多边形
                if (need_draw_tmp)
                {
                    //if (e.Button != MouseButtons.Left) return;
                    end = e.Location;
                    pictureBox1.Invalidate();//此代码不可省略
                    //Graphics g = pictureBox1.CreateGraphics();
                    //抗锯齿

                }
            }
        }

        private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
        {
            if (action_type.IndexOf("矩形") >= 0)
            {
                //绘制矩形框 
                if (e.Button == MouseButtons.Left)
                {
                    end = e.Location;
                    need_draw_tmp = false;
                }

                Graphics g = pictureBox1.CreateGraphics();
                Point temp_start;
                Point temp_end;
                GetImagePixLocation(pictureBox1, start, out temp_start);
                GetImagePixLocation(pictureBox1, end, out temp_end);
                Rectangle temp_rect = new Rectangle(Math.Min(temp_start.X, temp_end.X),
                    Math.Min(temp_start.Y, temp_end.Y),
                    Math.Abs(temp_start.X - temp_end.X),
                    Math.Abs(temp_start.Y - temp_end.Y));

                draw_paint.DrawRectangle(line_color, temp_rect);//画矩形
                //TODO:  扩充点 可弹出选择框选择标注类型
                Point[] tempPoints = new Point[4];
                tempPoints[0] = new Point(Math.Min(temp_start.X, temp_end.X), Math.Min(temp_start.Y, temp_end.Y));
                tempPoints[2] = new Point(Math.Max(temp_start.X, temp_end.X), Math.Max(temp_start.Y, temp_end.Y));
                tempPoints[1] = new Point(tempPoints[2].X, tempPoints[0].Y);
                tempPoints[3] = new Point(tempPoints[0].X, tempPoints[2].Y);
                ltPoly.Add(tempPoints.ToList());
                pictureBox1.Image = GetMergeBitmap();
                g.Dispose();
            }

        }

        private void pictureBox1_Paint(object sender, PaintEventArgs e)
        {
            PictureBox pic = sender as PictureBox;
            if (action_type.IndexOf("矩形") >= 0)
            {
                //绘制矩形框 并填充
                Pen pen = new Pen(Color.Red, 3);
                pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;     //绘制线的格式
                //绘制矩形框 并填充
                if (need_draw_tmp)
                {
                    //此处是为了在绘制时可以由上向下绘制,也可以由下向上
                    rectA = new Rectangle(Math.Min(start.X, end.X), Math.Min(start.Y, end.Y), Math.Abs(start.X - end.X), Math.Abs(start.Y - end.Y));
                    e.Graphics.DrawRectangle(pen, rectA);



                }
                pen.Dispose();
            }
            else if (action_type.IndexOf("四边形") >= 0)
            {
                //多边形
                if (polyPoints != null)
                {
                    if (need_draw_tmp)
                    {
                        //抗锯齿
                        e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
                        e.Graphics.DrawLine(pen_yellow, polyPoints.First(), end);
                        e.Graphics.DrawLine(pen_red, polyPoints.Last(), end);

                        if (polyPoints.Count > 1)
                        {
                            for (int i = 0; i < polyPoints.Count - 1; i++)
                            {
                                e.Graphics.DrawLine(pen_red, polyPoints[i], polyPoints[i + 1]);
                            }
                        }
                    }
                }
            }

        }

        private Bitmap GetMergeBitmap()
        {
            Bitmap tmp_bmp = (Bitmap)bg_image.Clone();
            merge_paint = Graphics.FromImage(tmp_bmp);
            merge_paint.DrawImage(tmp_bitmap, 0, 0);//将中间画布绘制的内容绘制到原始画布上
            merge_paint.Dispose();
            return tmp_bmp;
        }

        private void GetImagePixLocation(PictureBox pictureBox, System.Drawing.Point pictureBoxPoint, out System.Drawing.Point imagePoint)
        {
            imagePoint = new System.Drawing.Point(0, 0);
            System.Drawing.Size imageSize = pictureBox.Image.Size;
            double scale;
            int detalInHeight = 0;
            int detalInWidth = 0;
            if (Convert.ToDouble(pictureBox.Size.Width) / pictureBox.Size.Height > Convert.ToDouble(imageSize.Width) / imageSize.Height)
            {
                scale = 1.0 * imageSize.Height / pictureBox.Size.Height;
                detalInWidth = Convert.ToInt32((pictureBox.Size.Width * scale - imageSize.Width) / 2.0);
            }
            else
            {
                scale = 1.0 * imageSize.Width / pictureBox.Size.Width;
                detalInHeight = Convert.ToInt32((pictureBox.Size.Height * scale - imageSize.Height) / 2.0);
            }
            imagePoint.X = Convert.ToInt32(pictureBoxPoint.X * scale - detalInWidth);
            imagePoint.Y = Convert.ToInt32(pictureBoxPoint.Y * scale - detalInHeight);
        }

        private void DrawPloy(bool fill = true)
        {
            //绘制矩形框 并填充
            draw_paint.SmoothingMode = SmoothingMode.HighQuality;//抗锯齿
            draw_paint.DrawPolygon(line_color, polyPoints.ToArray());
            //填充多边形
            if (fill)
            {
                draw_paint.FillPolygon(fill_brush, polyPoints.ToArray());
            }
            //TODO:  扩充点 可弹出选择框选择标注类型
            pictureBox1.Image = GetMergeBitmap();
            is_first_down = true;
            need_draw_tmp = false;
            polyPoints = null;
        }

        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            action_type = comboBox1.Text;
        }

        private void button3_Click(object sender, EventArgs e)
        {
            if (ltPoly.Count == 0)
            {
                return;
            }
            string file = "lable.txt";
            FileStream fs = new FileStream(file, FileMode.Create);
            StreamWriter sw = new StreamWriter(fs, Encoding.UTF8);
            foreach (var item in ltPoly)
            {
                sw.WriteLine(string.Format("({0},{1}),({2},{3}),({4},{5}),({6},{7})",
                    item[0].X, item[0].Y,
                    item[1].X, item[1].Y,
                    item[2].X, item[2].Y,
                    item[3].X, item[3].Y
                    ));
            }
            sw.Close();
            fs.Close();
            MessageBox.Show("保存成功!", "注意", MessageBoxButtons.OK, MessageBoxIcon.Information);
            //打开文件
            System.Diagnostics.Process.Start(file);
        }
    }
}

Demo下载

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

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

相关文章

【UE5 Cesium】06-Cesium for Unreal 从一个地点飞行到另一个地点(上)

UE版本&#xff1a;5.1 介绍 本文以在墨尔本和悉尼这两个城市间为例&#xff0c;介绍如何使用虚幻5引擎和Cesium for Unreal插件在这两个城市间进行飞行移动&#xff0c;其中墨尔本和悉尼城市的倾斜摄影是Cesium官方仓库中自带的资产&#xff0c;我们引入到自己的Cesium账号…

蓝桥杯专题-试题版-【地宫取宝】【斐波那契】【波动数列】【小朋友排队】

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例点击跳转>软考全系列点击跳转>蓝桥系列 &#x1f449;关于作者 专注于Android/Unity和各种游…

MySQL相关知识点

这里写目录标题 MySQL简介概述配置安装连接&#xff08;企业级&#xff09;数据模型sql语句简介语法分类 数据库设计DDL&#xff08;SQL语句&#xff09;数据库操作idea集成mysql开发图形化工具&#xff08;直接在空java项目里打开mysql数据库&#xff09; 表&#xff08;对表的…

ASEMI代理ST可控硅BTA41封装,BTA41图片

编辑-Z BTA41参数描述&#xff1a; 型号&#xff1a;BTA41 封装&#xff1a;TO-3P RMS导通电流IT(RMS)&#xff1a;40A 非重复浪涌峰值导通电流ITSM&#xff1a;420A 峰值栅极电流IGM&#xff1a;8A 平均栅极功耗PG&#xff1a;1W 存储接点温度范围Tstg&#xff1a;-40…

kubelete源码阅读

kubelet 是运行在每个节点上的主要的“节点代理”&#xff0c;每个节点都会启动 kubelet进程&#xff0c;用来处理 Master 节点下发到本节点的任务&#xff0c;按照 PodSpec 描述来管理Pod 和其中的容器&#xff08;PodSpec 是用来描述一个 pod 的 YAML 或者 JSON 对象&#xf…

ATTCK(四)之ATTCK矩阵战术技术(TTP)逻辑和使用

ATT&CK矩阵战术&技术&#xff08;TTP&#xff09;逻辑和使用 ATT&CK的战术与技术组织结构 ATT&CK矩阵中的所有战术和技术&#xff0c;都可以通过以下链接进行目录结构式的浏览https://attack.mitre.org/techniques/enterprise/&#xff0c;也可以在矩阵里直接…

arcgis栅格影像--镶嵌

1、打开软件导入数据&#xff0c;如下&#xff1a; 2、在搜索栏中搜索“镶嵌至新栅格”&#xff0c;如下&#xff1a; 3、双击打开镶嵌对话框&#xff0c;如下&#xff1a; 4、点击确定按钮&#xff0c;进行栅格镶嵌&#xff0c;镶嵌结果如下&#xff1a; 5、去除黑边&#xff…

若依框架-前端使用教程

1 使用 npm run dev 命令执行本机开发测试时&#xff0c;提出错误信息如下&#xff1a; opensslErrorStack: [ error:03000086:digital envelope routines::initialization error ], library: digital envelope routines, reason: unsupported, code: ERR_OSSL_EVP_UNS…

Web安全——PHP基础

PHP基础 一、PHP简述二、基本语法格式三、数据类型、常量以及字符串四、运算符五、控制语句1、条件控制语句2、循环控制语句 六、php数组1、数组的声明2、数组的操作2.1 数组的合拼2.2 填加数组元素2.3 添加到指定位置2.4 删除某一个元素2.5 unset 销毁指定的元素2.6 修改数组中…

Tune-A-Video:用于文本到视频生成的图像扩散模型的One-shot Tuning

Tune-A-Video: One-Shot Tuning of Image Diffusion Models for Text-to-Video Generation Project&#xff1a;https://tuneavideo.github.io 原文链接&#xff1a;Tnue-A-Video:用于文本到视频生成的图像扩散模型的One-shot Tuning &#xff08;by 小样本视觉与智能前沿&…

基于matlab使用校准相机测量平面物体(附源码)

一、前言 此示例演示如何使用单个校准相机以世界单位测量硬币的直径。 此示例演示如何校准相机&#xff0c;然后使用它来测量平面对象&#xff08;如硬币&#xff09;的大小。这种方法的一个示例应用是测量传送带上的零件以进行质量控制。 二、校准相机 相机校准是估计镜头…

基于多站点集中汇聚需求的远程调用直播视频汇聚平台解决方案

一、行业背景 随着视频汇聚需求的不断提升&#xff0c;智慧校园、智慧园区等项目中需要将各分支机构的视频统一汇聚到总部&#xff0c;进行统一管控&#xff0c;要满足在监控内部局域网、互联网、VPN网络等TCP/IP环境下&#xff0c;为用户提供低成本、高扩展、强兼容、高性能的…

ModaHub魔搭社区:如何基于向量数据库+LLM(大语言模型),打造更懂你的企业专属Chatbot?

目录 1、为什么Chatbot需要大语言模型向量数据库? 2、什么是向量数据库? 3、LLM大语言模型ADB-PG:打造企业专属Chatbot 4、ADB-PG:内置向量检索全文检索的一站式企业知识数据库 5、总结 1、为什么Chatbot需要大语言模型向量数据库? 这个春天,最让人震感的科技产品莫过…

6.28作业

作业1 结构体不能被继承&#xff0c;类可以被继承结构体默认的都是公共&#xff0c;类默认是私有的 转载【结构体和类的区别】 结构体是值类型&#xff0c;类是引用类型 结构体存在栈中&#xff0c;类存在堆中 结构体成员不能使用protected访问修饰符&#xff0c;而类可以 结…

vsCode 运行 报错信息 yarn : 无法加载文件 C:\Program Files\nodejs\yarn.ps1

检索说是 PowerShell 执行策略&#xff0c;默认设置是Restricted不去加载配置文件或运行脚本。需要去做相应的变更&#xff0c; 修改配置为 RemoteSigned 管理员身份打开 PowerShell&#xff0c;执行命令&#xff0c;修改PowerShell 执行策略 set-ExecutionPolicy RemoteSigne…

2023.6.28

类和结构体区别&#xff1a; 1&#xff0c;类可以进行封装&#xff08;有访问权限等&#xff09;&#xff0c;结构体无&#xff1b; 2&#xff0c;类有&#xff1a;封装&#xff0c;继承&#xff0c;多态三大特征&#xff0c;结构体只有变量和函数。 #include <iostream&g…

面试题小计(1)

Https加密过程、与三次握手 三次握手是传输层的概念&#xff0c;HTTPS通常是 SSL HTTP 的简称&#xff0c;目前使用的 HTTP/HTTPS 协议是基于 TCP 协议之上的&#xff0c;因此也需要三次握手。要在 TCP 三次握手建立链接之后&#xff0c;才会进行 SSL 握手的过程&#xff08;…

Linux在线升级JDK版本(不用去官网下载安装包)

Linux在线升级JDK版本 ​ 只要3个命令 确保系统已连接到互联网&#xff1a;确保你的 Linux 系统已连接到互联网&#xff0c;以便下载和安装新的 JDK 版本。 更新软件包管理器&#xff1a;运行以下命令来更新系统的软件包管理器&#xff08;在不同的 Linux 发行版中&#xff0…

(3)深度学习学习笔记-简单线性模型

文章目录 一、线性模型二、实例1.pytorch求导功能2.简单线性模型&#xff08;人工数据集&#xff09; 来源 一、线性模型 一个简单模型&#xff1a;假设一个房子的价格由卧室、卫生间、居住面积决定&#xff0c;用x1&#xff0c;x2&#xff0c;x3表示。 那么房价y就可以认为yw…

大数据分析与机器学习的结合:实现智能决策

章节一&#xff1a;引言 在当今数字化时代&#xff0c;大数据分析和机器学习已经成为推动技术创新和业务发展的关键要素。大数据的快速增长和复杂性使得传统的数据处理方法变得不再有效。而机器学习作为一种自动化的数据分析方法&#xff0c;能够从海量数据中挖掘出有价值的信…