canvas实现图片标注,绘制区域
使用canvas绘制通过多边形标注区域
AI视频项目中需要分析图片,需要前台绘制区域,后端获取坐标然后识别图像,通过canvas
获取点然后连线绘图
HEML代码段
<div class="areaDrawing"><img src="@/assets/images/snapPhotos.png" /><canvas ref="canvas" style="position: absolute; top: 0; left: 0;" :width="canvasWidth":height="canvasHeight"></canvas></div>
CSS代码段
.areaDrawing {position: relative;width: 400px; // 绘图区域宽度height: 300px; // 绘图区域高度img {position: absolute;top: 0;left: 0;height: 100%;width: 100%;}
}
script代码段
<script>
// 脚本开始
export default {data() {return {canvasWidth: 400, // 画布的宽度canvasHeight: 300, // 画布的高度imageSrc: 'your_image_url_here', // 图像的URL地址context: null, // 画布上下文points: [], // 用于存储点的数组isDragging: false, // 是否正在拖拽draggingIndex: -1, // 当前拖拽的点的索引Drawing: false,//控制绘制};},methods: {// 处理点击事件,用于添加新点handleCanvasClick(event) {console.log(this.points.length, 'this.points.length');// 检查是否开启绘制if (!this.Drawing || this.points.length >= 4) {return;}// 获取点击点的坐标const rect = this.$refs.canvas.getBoundingClientRect();const x = event.clientX - rect.left;const y = event.clientY - rect.top;// 检查是否有重复点const isDuplicate = this.points.some(point => {return Math.abs(point.x - x) < 5 && Math.abs(point.y - y) < 5;});// 如果没有重复点,则添加新点并重新绘制if (!isDuplicate) {this.points.push({ x, y });this.redraw();}// 如果点的数量大于等于4个,则绘制多边形if (this.points.length >= 4) {this.drawPolygon(this.points);}},// 处理鼠标按下事件handleMouseDown(event) {if (this.Drawing) {return}// 获取鼠标按下点的坐标const rect = this.$refs.canvas.getBoundingClientRect();const x = event.clientX - rect.left;const y = event.clientY - rect.top;// 查找当前拖拽的点的索引this.draggingIndex = this.points.findIndex(point => {return Math.abs(point.x - x) < 5 && Math.abs(point.y - y) < 5;});// 如果存在拖拽的点,则设置拖拽状态为trueif (this.draggingIndex !== -1) {this.isDragging = true;}},// 处理鼠标移动事件handleMouseMove(event) {// 如果正在拖拽,则更新当前拖拽点的坐标并重新绘制if (this.isDragging) {const rect = this.$refs.canvas.getBoundingClientRect();const x = event.clientX - rect.left;const y = event.clientY - rect.top;this.points[this.draggingIndex].x = x;this.points[this.draggingIndex].y = y;this.redraw();}},// 处理鼠标释放事件handleMouseUp() {// 重置拖拽状态和拖拽点的索引this.isDragging = false;this.draggingIndex = -1;},// 绘制点drawPoint(x, y) {this.context.beginPath();this.context.arc(x, y, 5, 0, 2 * Math.PI, false);this.context.fillStyle = 'blue';this.context.fill();this.context.lineWidth = 1;this.context.strokeStyle = 'blue';this.context.stroke();},// 重新绘制画布redraw() {// 清空画布this.context.clearRect(0, 0, this.canvasWidth, this.canvasHeight);// 绘制多边形this.drawPolygon(this.points);// 绘制所有点,并连接相邻点this.points.forEach((point, index) => {this.drawPoint(point.x, point.y);if (index > 0) {this.context.beginPath();this.context.moveTo(this.points[index - 1].x, this.points[index - 1].y);this.context.lineTo(point.x, point.y);this.context.strokeStyle = 'blue';this.context.lineWidth = 1;this.context.stroke();}});// 连接第一个点和最后一个点,形成闭合的多边形if (this.points.length > 3) {this.context.beginPath();this.context.moveTo(this.points[this.points.length - 1].x, this.points[this.points.length - 1].y);this.context.lineTo(this.points[0].x, this.points[0].y);this.context.strokeStyle = 'blue';this.context.lineWidth = 1;this.context.stroke();}},// 绘制多边形drawPolygon(points) {if (points.length >= 2) {this.context.beginPath();this.context.moveTo(points[0].x, points[0].y);for (let i = 1; i < points.length; i++) {this.context.lineTo(points[i].x, points[i].y);}if (points.length === 4) {this.context.closePath();this.context.strokeStyle = 'red';this.context.lineWidth = 2;this.context.stroke();}}},// 动画方法,用于拖拽时重新绘制画布animate() {if (this.isDragging) {this.redraw();requestAnimationFrame(this.animate);}},//开始绘制handleDrawing() {this.Drawing = true;},//绘制微调resetDrawing() {this.Drawing = false;},//清除绘制clearDrawing() {this.points.length = 0;this.redraw()},},mounted() {// 获取画布上下文this.context = this.$refs.canvas.getContext('2d');// 添加事件监听器this.$refs.canvas.addEventListener('click', this.handleCanvasClick);this.$refs.canvas.addEventListener('mousedown', this.handleMouseDown);this.$refs.canvas.addEventListener('mousemove', this.handleMouseMove);this.$refs.canvas.addEventListener('mouseup', this.handleMouseUp);this.$refs.canvas.addEventListener('mouseleave', this.handleMouseUp);// 绑定动画方法的上下文this.animate = this.animate.bind(this);},
};
// 脚本结束
</script>
相关文章:
canvas实现图片标注,绘制区域
使用canvas绘制通过多边形标注区域 AI视频项目中需要分析图片,需要前台绘制区域,后端获取坐标然后识别图像,通过canvas 获取点然后连线绘图 HEML代码段 <div class"areaDrawing"><img src"/assets/images/snapPhotos…...

SELECT COUNT(*) 会造成全表扫描吗?
前言 SELECT COUNT(*)会不会导致全表扫描引起慢查询呢? SELECT COUNT(*) FROM SomeTable 网上有一种说法,针对无 where_clause 的 COUNT(*),MySQL 是有优化的,优化器会选择成本最小的辅助索引查询计数,其实反而性能…...
python考前复习(90题)
文章目录 1.Python特性的是( )。 A. 面向对象 B. 高可移植性 C. 开源、免费 2.临时改变Python语言安装源应当使用的选项是 –index-url 3.Python脚本文件的扩展名为( ) .py 4.安装Python语言的软件包使用的命令是( ) pip install 5 . (单选题)以下哪项是…...

根据SpringBoot Guides完成进行示例学习(详细步骤)
目录 1.打开Spring | Guides官网,或者直接搜索springboot都可 2.选择要学习的内容 3.根据提示的网址,Git到本地 4.将文件用IDEA打开,根据教程完成示例,这里不做细致讲解 5.运行项目 6.在终端查看运行结果 以Scheduling Task…...

waf、yakit和ssh免密登录
WAF安全狗 脏数据适用于所有漏洞绕过waf,但是前提条件垃圾信息必须放在危险信息前,是不能打断原有数据包的结构,不能影响后端对数据包的解析。 以DVWA靶场文件上传为例 新建php文件 上传文件被安全狗拦截 使用bp抓包查看 在数据包Content-…...

【AIGC核心技术剖析】大型语言和视觉助手——LLaVA(论文+源码)
🔥 [新!LLaVA-1.5 在 11 个基准测试上实现了 SoTA,只需对原始 LLaVA 进行简单的修改,利用所有公共数据,在单个 1-A8 节点上在 ~100 天内完成训练,并超越使用数十亿级数据的方法。 LLaVA代表了一种新颖的端到端训练大型多模态模型,结合了视觉编码器和骆马 对于通用的视…...
IBM的WAS简介与基本使用手册
IBM的WAS简介与基本使用手册 1. 基本介绍 WebSphereApplication Server(简称WAS)是IBM的应用服务器 基本结构:单元(cell) ——> 多个节点(node) ——> 多个服务(server) ——> 多个应用(app) 单元是整个分布式网络中一个或多个节点的逻辑分组单元是一个配置概念, 是…...

Deno 快速入门
目录 1、简介 2、安装Deno MacOS下安装 Windows下安装 Linux 下安装 3、创建并运行TypeScript程序 4、内置Web API和Deno命名空间 5、运行时安全 6、导入JavaScript模块 7、远程模块和Deno标准库 8、使用deno.json配置您的项目 9、Node.js API和npm包 10、配置IDE…...

【计算机网络笔记】OSI参考模型基本概念
系列文章目录 什么是计算机网络? 什么是网络协议? 计算机网络的结构 数据交换之电路交换 数据交换之报文交换和分组交换 分组交换 vs 电路交换 计算机网络性能(1)——速率、带宽、延迟 计算机网络性能(2)…...
ConnectTimeout和ReadTimeout所代表的意义
ConnectTimeout和ReadTimeout所代表的意义 ConnectTimeout 指的是建立连接所用的时间,适用于网络状况正常的情况下,两端连接所用的时间。在java中,网络状况正常的情况下,例如使用HttpClient或者HttpURLConnetion连接时设置参数c…...
使用Python计算平面多边形间最短距离,数据需要从excel表格中导入
使用Python计算平面多边形间最短距离,数据需要从excel表格中导入, * 多边形种类包括(圆形、矩形、六边形、五边形、跑道形/胶囊形), * Python代码需要使用gjk算法进行判断两个多边形间是否重叠, * 如果未重…...

华为数通方向HCIP-DataCom H12-831题库(多选题:1-20)
第01题 如图所示,路由器所有的接口开启OSPF,图中标识的ip地址为设备的Loopback0接口的IP地址,R1、R2,R3的Loopback0通告在区域1,R4的Loopback0通告在区域0、R5的Lopback0通告在区域2,下列哪些IP地址之间可以相互Ping通? A、10.0.3.3和10.0.5.5 B、10.0.4.4和10.0.2.2 …...

CCC数字钥匙设计【NFC】--通过NFC进行车主配对Phase3
1、车主配对流程介绍 车主配对可以通过车内NFC进行,若支持UWB测距,也可以通过蓝牙/UWB进行。通过NFC进行车主配对总共有5个Phase。本文档主要对Phase3进行介绍。 1) Phase0:准备阶段; 2) Phase1:启动流程࿱…...

开源OA协同办公系统,集成Flowable流程引擎 可拖拽创建个性表单
源码下载:https://download.csdn.net/download/m0_66047725/88403340 源码下载2: 关注我留言 开源OA协同办公系统,集成Flowable流程引擎 可拖拽创建个性表单。基于RuoYi-VUE版本开发。 1、使用RuoYi-Vue的基础上开发。 2、集成flowable&a…...

为什么嵌入通常优于TF-IDF:探索NLP的力量
塔曼纳 一、说明 自然语言处理(NLP)是计算机科学的一个领域,涉及人类语言的处理和分析。它用于各种应用程序,例如聊天机器人、情绪分析、语音识别等。NLP 中的重要任务之一是文本分类,我们根据文本的内容将文本分类为不…...

oracle-AWR报告生成方法
AWR报告生成方法 1. 以oracle用户登陆服务器 2. 进入到要保存awr报告的目录 3. 以sysdba身份连接数据库 sqlplus / as sysdba4. 执行生成AWR报告命令 ?/rdbms/admin/awrrpt.sql5. 选择AWR报告的文件格式 6. 选择生成多少天的AWR报告 7. 选择报告的快照起始和结束ID 8. 输入生…...
笙默考试管理系统-MyExamTest----codemirror(37)
笙默考试管理系统-MyExamTest----codemirror(36) 目录 一、 笙默考试管理系统-MyExamTest 二、 笙默考试管理系统-MyExamTest 三、 笙默考试管理系统-MyExamTest 四、 笙默考试管理系统-MyExamTest 五、 笙默考试管理系统-MyExamTest 笙默考试…...

【Unity3D编辑器拓展】Unity3D的IMGUI、GUI、GUILayout、EditorGUI、EditorGUILayout、OnGUI【全面总结】
推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享简书地址我的个人博客 大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。 一、前言 在开发中,常常会遇到要使用OnGUI的地方。 也会遇到…...

11. 机器学习 - 评价指标2
文章目录 混淆矩阵F-scoreAUC-ROC 更多内容: 茶桁的AI秘籍 Hi, 你好。我是茶桁。 上一节课,咱们讲到了评测指标,并且在文章的最后提到了一个矩阵,我们就从这里开始。 混淆矩阵 在我们实际的工作中,会有一个矩阵&am…...

Nginx的代理和负载均衡
一、nginx的代理方式 1.1 七层代理 七层代理:基于http协议,对请求的内容进行处理,然后转发到后端服务器 七层代理是客户端请求代理服务器,由代理服务器转发客户端的http请求,转发到内部的服务器进行处理(服务器可以是…...

深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录
ASP.NET Core 是一个跨平台的开源框架,用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录,以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...
IGP(Interior Gateway Protocol,内部网关协议)
IGP(Interior Gateway Protocol,内部网关协议) 是一种用于在一个自治系统(AS)内部传递路由信息的路由协议,主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...
Python爬虫实战:研究feedparser库相关技术
1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...
在Ubuntu中设置开机自动运行(sudo)指令的指南
在Ubuntu系统中,有时需要在系统启动时自动执行某些命令,特别是需要 sudo权限的指令。为了实现这一功能,可以使用多种方法,包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法,并提供…...

基于Docker Compose部署Java微服务项目
一. 创建根项目 根项目(父项目)主要用于依赖管理 一些需要注意的点: 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件,否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...
基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解
JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用,结合SQLite数据库实现联系人管理功能,并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能,同时可以最小化到系统…...
怎么开发一个网络协议模块(C语言框架)之(六) ——通用对象池总结(核心)
+---------------------------+ | operEntryTbl[] | ← 操作对象池 (对象数组) +---------------------------+ | 0 | 1 | 2 | ... | N-1 | +---------------------------+↓ 初始化时全部加入 +------------------------+ +-------------------------+ | …...

【版本控制】GitHub Desktop 入门教程与开源协作全流程解析
目录 0 引言1 GitHub Desktop 入门教程1.1 安装与基础配置1.2 核心功能使用指南仓库管理日常开发流程分支管理 2 GitHub 开源协作流程详解2.1 Fork & Pull Request 模型2.2 完整协作流程步骤步骤 1: Fork(创建个人副本)步骤 2: Clone(克隆…...
第22节 Node.js JXcore 打包
Node.js是一个开放源代码、跨平台的、用于服务器端和网络应用的运行环境。 JXcore是一个支持多线程的 Node.js 发行版本,基本不需要对你现有的代码做任何改动就可以直接线程安全地以多线程运行。 本文主要介绍JXcore的打包功能。 JXcore 安装 下载JXcore安装包&a…...
创客匠人:如何通过创始人IP打造实现知识变现与IP变现的长效增长?
在流量红利逐渐消退的当下,创始人IP的价值愈发凸显。它不仅能够帮助中小企业及个人创业者突破竞争壁垒,还能成为企业品牌影响力的核心资产。然而,市场上IP孵化机构鱼龙混杂,如何选择一家真正具备长期价值的合作伙伴?创…...