canvas从基础了解 -- 到算法标注框实现

简介: canvas从基础了解 -- 到算法标注框实现

文章目录


canvas必备基础

canvas的本质

绘制图形

绘制矩形

绘制三角形

绘制圆形

绘制图像CanvasRenderingContext2D.drawImage()

图片从顶点铺到画布上

图片从设置(x,y)开始铺到画布上

图像定制大小 铺到画布上

绘制图像时候,画布和图像都在动

绘制文字

实战: canvas绘制图像并标注算法框


canvas必备基础


推荐2个好的学习canvas的地址,一个是mdn的官网,另一个是阮一峰的canvas相关大作。


现在主要针对上面的资料说几点:


canvas的本质


元素用于生成图像。它本身就像一个画布,JavaScript 通过操作它的 API,在上面生成图像。它的底层是一个个像素,基本上是一个可以用 JavaScript 操作的位图(bitmap)。


它与 SVG 图像的区别在于,是脚本调用各种方法生成图像,SVG 则是一个 XML 文件,通过各种子元素生成图像。


绘制图形



绘制矩形


下面展示

// 只支持两种形式的图形绘制:矩形和路径(由一系列点连成的线段)
// 绘制一个填充的矩形
// fillRect(x, y, width, height)
//绘制一个矩形的边框
// strokeRect(x, y, width, height)
// 绘制一个矩形的边框
// 清除指定矩形区域,让清除部分完全透明。
<html>
<head>
    <style>
        body {
            background: gray;
        }
    </style>
</head>
<body>
<canvas id="canvas" width="450" height="450"></canvas>
<script type="application/javascript">
    //<canvas> 只支持两种形式的图形绘制:矩形和路径(由一系列点连成的线段)
    // 绘制一个填充的矩形
    // fillRect(x, y, width, height)
    //绘制一个矩形的边框
    // strokeRect(x, y, width, height)
    // 绘制一个矩形的边框
    // 清除指定矩形区域,让清除部分完全透明。
    // clearRect(x, y, width, height)
    var canvas = document.getElementById("canvas");
    if (canvas.getContext) {
        var ctx = canvas.getContext("2d");
        ctx.fillStyle = "rgb(200,0,0)";
        // 绘制一个填充的矩形。
        ctx.fillRect(10, 10, 55, 50);
        ctx.fillStyle = "rgba(0, 0, 200, 0.5)";
        // 绘制一个矩形的边框
        ctx.strokeRect(130, 130, 155, 150);
        //绘制一个空白的矩形
        ctx.fillStyle = 'red';
        ctx.clearRect(45, 45, 60, 60);
    }
</script>
</body>
</html>

1dc618a0ed9580ce8bfa6facb208c08f.png


绘制三角形


常用的api

以下方法和属性用来绘制路径。


`CanvasRenderingContext2D.beginPath():开始绘制路径。

CanvasRenderingContext2D.closePath():结束路径,返回到当前路径的起始点,会从当前点到起始点绘制一条直线。如果图形已经封闭,或者只有一个点,那么此方法不会产生任何效果。


CanvasRenderingContext2D.moveTo():设置路径的起点,即将一个新路径的起始点移动到(x,y)坐标。

CanvasRenderingContext2D.lineTo():使用直线从当前点连接到(x, y)坐标。

CanvasRenderingContext2D.fill():在路径内部填充颜色(默认为黑色)。

CanvasRenderingContext2D.stroke():路径线条着色(默认为黑色)。

CanvasRenderingContext2D.fillStyle:指定路径填充的颜色和样式(默认为黑色)。

CanvasRenderingContext2D.strokeStyle:指定路径线条的颜色和样式(默认为黑色)。`


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>绘制三角形</title>
</head>
<body onload="draw();">
<canvas id="canvas" width="150" height="150"></canvas>
</body>
<script type="application/javascript">
    function draw() {
        var canvas = document.getElementById("canvas");
        if (canvas.getContext) {
            var ctx = canvas.getContext("2d");
            ctx.beginPath();
            //设置路径的起点,即将一个新路径的起始点移动到(x,y)坐标。
            ctx.moveTo(75, 50);
            //使用直线从当前点连接到(x, y)坐标。
            ctx.lineTo(100, 75);
            ctx.lineTo(100, 25);
            //在路径内部填充颜色(默认为黑色)
            ctx.fill();
        }
    }
</script>
</html>

1dc618a0ed9580ce8bfa6facb208c08f.png


绘制圆形


CanvasRenderingContext2D.arc():通过指定圆心和半径绘制弧形。

CanvasRenderingContext2D.arcTo():通过指定两根切线和半径绘制弧形。

CanvasRenderingContext2D.arc()主要用来绘制圆形或扇形。

1dc618a0ed9580ce8bfa6facb208c08f.png


用arc函数绘制不同的圆弧


var canvas = document.getElementById('game');
var ctx = canvas.getContext('2d');
ctx.filSytle = "rgba(200,200,100,0.6)";
//绘制下半圆
ctx.beginPath();
ctx.arc(100,110,50,0,Math.PI);
ctx.closePath();
ctx.fill();
//绘制上半圆
ctx.beginPath();
ctx.arc(100,90,50,0,Math.PI,true);
ctx.closePath();
ctx.fill();
//绘制左半圆
ctx.beginPath();
ctx.arc(230,100,50, Math.PI/2,Math.PI*3/2);
ctx.closePath();
ctx.fill();
//绘制右半圆
ctx.beginPath();
ctx.arc(250, 100, 50 , Math.PI*3/2, Math.PI/2);
ctx.closePath();
ctx.fill();
// 绘制一个接近于圆的形状
ctx.beginPath();
ctx.arc(180, 240, 50 , Math.PI*7/6, Math.PI*2/3);
ctx.closePath();
ctx.fill();
// 绘制一段小圆弧
ctx.beginPath();
ctx.arc(150, 250, 50 , Math.PI*7/6, Math.PI*2/3, true);
ctx.closePath();
ctx.fill();

1dc618a0ed9580ce8bfa6facb208c08f.png


绘制图像CanvasRenderingContext2D.drawImage()


Canvas API 允许将图像文件写入画布,做法是读取图片后,使用drawImage()方法将这张图片放上画布。


CanvasRenderingContext2D.drawImage()有三种使用格式。


ctx.drawImage(image, dx, dy);

ctx.drawImage(image, dx, dy, dWidth, dHeight);

ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);


image:图像元素

sx:图像内部的横坐标,用于映射到画布的放置点上。

sy:图像内部的纵坐标,用于映射到画布的放置点上。

sWidth:图像在画布上的宽度,会产生缩放效果。如果未指定,则图像不会缩放,按照实际大小占据画布的宽度。

sHeight:图像在画布上的高度,会产生缩放效果。如果未指定,则图像不会缩放,按照实际大小占据画布的高度。

dx:画布内部的横坐标,用于放置图像的左上角

dy:画布内部的纵坐标,用于放置图像的右上角

dWidth:图像在画布内部的宽度,会产生缩放效果。

dHeight:图像在画布内部的高度,会产生缩放效果。


图片从顶点铺到画布上


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>图像处理</title>
    <!--    ctx.drawImage(image, dx, dy);-->
    <!--    ctx.drawImage(image, dx, dy, dWidth, dHeight);-->
    <!--    ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);-->
</head>
<body>
<canvas id="myCanvas"></canvas>
<script>
    // var canvas = document.getElementById('myCanvas');
    // var ctx = canvas.getContext('2d');
    // var img = new Image();
    // img.src = 'https://img-home.csdnimg.cn/images/20220921102650.png';
    // img.onload = function () {
    //     ctx.drawImage(img, 0, 0);
    // };
    var canvas = document.getElementById('myCanvas');
    var ctx = canvas.getContext('2d');
    var image = new Image(60, 45);
    image.onload = drawImageActualSize;
    image.src = '../images/2.png';
    function drawImageActualSize() {
        canvas.width = this.naturalWidth;
        canvas.height = this.naturalHeight;
        ctx.drawImage(this, 0, 0, this.naturalWidth, this.naturalHeight);
    }
</script>
</body>
</html>


图片从设置(x,y)开始铺到画布上


<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>practice9-DrawImage</title>
  <style type="text/css">
    *{
      padding:0;
      margin: 0;
    }
    body{
      text-align: center;
      padding-top: 20px;
    }
    canvas{
      box-shadow: 0 0 10px #333333;
      margin: 0 auto;
    }
  </style>
</head>
<body onload="draw()">
<canvas id="canvas" width="800" height="600"></canvas>
<script>
  function draw(){
    var ctx = document.getElementById('canvas');
    if (canvas.getContext) {
      var ctx = canvas.getContext('2d');
      //定义图片
      var img = new Image();
      img.src = '../images/2.png';
      //确保图片被加载完成
      img.onload = function() {
        //使用drawImage绘制到画布上面
        ctx.drawImage(this,5,5);
      }
    }else{
      alert('请更新浏览器!!!');
    }
  }
</script>
</body>
</html>


图像定制大小 铺到画布上


<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>practice9-DrawImage</title>
  <style type="text/css">
    *{
      padding:0;
      margin: 0;
    }
    body{
      text-align: center;
      padding-top: 20px;
    }
    canvas{
      box-shadow: 0 0 10px #333333;
      margin: 0 auto;
    }
  </style>
</head>
<body onload="draw()">
<canvas id="canvas" width="800" height="600"></canvas>
<!--用法二:定图像的宽度和高度,将图像放大或者缩小-->
<!--context.drawImage(img,x,y,width,height);-->
<script>
  function draw(){
    var ctx = document.getElementById('canvas');
    if (canvas.getContext) {
      var ctx = canvas.getContext('2d');
      //定义图片
      var img = new Image();
      img.src = '../images/2.png';
      //确保图片被加载完成
      img.onload = function() {
        //使用drawImage绘制到画布上面
        ctx.drawImage(this,50,50,300,300);
      }
    }else{
      alert('请更新浏览器!!!');
    }
  }
</script>
</body>
</html>


画布是800x600.


ctx.drawImage(this,50,50,300,300);图像从(50,50)坐标开始铺图像只显示宽300高300.


绘制图像时候,画布和图像都在动


1dc618a0ed9580ce8bfa6facb208c08f.png

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>practice9-DrawImage</title>
    <style type="text/css">
        *{
            padding:0;
            margin: 0;
        }
        body{
            text-align: center;
            padding-top: 20px;
        }
        canvas{
            box-shadow: 0 0 10px #333333;
            margin: 0 auto;
        }
    </style>
</head>
<body onload="draw()">
<canvas id="canvas" width="800" height="600"></canvas>
<script>
    function draw(){
        var ctx = document.getElementById('canvas');
        if (canvas.getContext) {
            var ctx = canvas.getContext('2d');
            //定义图片
            var img = new Image();
            img.src = '../images/2.png';
            //确保图片被加载完成
            img.onload = function() {
                //使用drawImage绘制到画布上面
                ctx.drawImage(this,100,100,100,100,50,50,700,500);
            }
        }else{
            alert('请更新浏览器!!!');
        }
    }
</script>
</body>
</html>


绘制文字


1dc618a0ed9580ce8bfa6facb208c08f.png

CanvasRenderingContext2D.fillText(text, x, y [, maxWidth])
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>绘制文字</title>
</head>
<body>
    <canvas id="myCanvas"></canvas>
  <script>
    var canvas = document.getElementById('myCanvas');
    var ctx = canvas.getContext('2d');
    //(填充的字符串,横坐标,纵坐标)
    ctx.fillText('Hello world', 50, 50);
  </script>
</body>
</html>


好了有了上面的知识后,就开始实战了。


实战: canvas绘制图像并标注算法框


比如我这里有个算法:

格式为:


var dtcoord = [{x: 50, y: 50, w: 100, h: 100, txt: "抽烟", conf: "0.38"},{x: 100, y: 200, w: 120, h: 100, txt: "抽烟", conf: "0.95"}];
var gtcoord = [{x: 20, y: 20, w: 100, h: 100, txt: "未带安全帽", conf: "0.93"},{x: 260, y: 260, w: 100, h: 100, txt: "未带安全帽", conf: "0.92"}];


要实现的效果为:

1dc618a0ed9580ce8bfa6facb208c08f.png

红色框标注抽烟算法,

黄色框标注未带安全帽算法

源码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div class="item-img">
    <canvas id="myCanvas" width="1280" height="650">
    </canvas>
</div>
<!--原文链接:https://blog.csdn.net/weixin_43994675/article/details/119763634-->
</body>
<!--推荐2个网站:https://www.bookstack.cn/read/webapi-tutorial/spilt.5.docs-websocket.md-->
<!--https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API/Tutorial/Using_images-->
<script>
    var dtcoord = [{x: 50, y: 50, w: 100, h: 100, txt: "抽烟", conf: "0.38"},{x: 100, y: 200, w: 120, h: 100, txt: "抽烟", conf: "0.95"}];
    var gtcoord = [{x: 20, y: 20, w: 100, h: 100, txt: "未带安全帽", conf: "0.93"},{x: 260, y: 260, w: 100, h: 100, txt: "未带安全帽", conf: "0.92"}];
    queryCanvasInfo();
    //获取canvas节点
    function queryCanvasInfo() {
        var c = document.getElementById("myCanvas");
        var ctx = c.getContext('2d');
        //定义图片
        var img = new Image();
        createCanvasImg(c, ctx, img, "2.png");
    }
    //创建图片画布
    function createCanvasImg(c, ctx, img, imgURL) {
        img.src = imgURL;
        img.onload = () => {
            //图片加载时
            ctx.clearRect(0, 0, c.width, c.height); //清空这个范围的画布
            let a = img.width / img.height; //计算原始图片的宽高比例
            console.log(img.width, img.height, 999);
            if (img.width > img.height) {
                //当图片宽度大于高度则写死宽度按高度调整比例
                maxW = c.width; //最大宽度要等于画布的宽度
                maxH = maxW / a;
            } else {
                //相反
                (maxH = c.height), (maxW = maxH * a);
            }
            times = img.width / maxW; //计算原图与canvas的比例
            canvasInfo(maxW, maxH, img, ctx); //重新绘制图片
        };
    }
    //绘制图片
    function canvasInfo(maxW, maxH, img, ctx) {
        let w = maxW, //计算缩放的宽度
            h = maxH; //计算缩放的高度
        ctx.drawImage(
            img, //图片实例
            0,
            0, //x轴y轴的边距
            w,
            h //图片的宽高
        );
        canvasRect(dtcoord, "dt", ctx);
        canvasRect(gtcoord, "gt", ctx);
    }
    //标注框绘制
    function canvasRect(list, txt, ctx) {
        list.forEach((item) => {
            console.log(item)
            if (!item) return;
            x = Number(item.x) / times,
                y = Number(item.y) / times,
                w = Number(item.w) / times,
                h = Number(item.h) / times;
            ctx.lineWidth = "2"; //框的粗细
            if (txt == "gt") {
                ctx.strokeStyle = "yellow"; //gt选中的标注框为红色
            } else {
                ctx.strokeStyle = "red"; //dt选中的标注框为红色
            }
            console.log(2222)
            //开始绘制
            console.log(x, y, w, h)
            ctx.strokeRect(x, y, w, h);
            //文本
            //CanvasRenderingContext2D.fillText(text, x, y [, maxWidth])
            ctx.fillStyle = '#fff';
            ctx.fillText(item.conf, (x + w/2) , y-2);
            // ctx.beginPath();
            // ctx.moveTo(x-, y);
            // ctx.lineTo(x+w, y);
            // ctx.lineTo(x+w, y+h);
            // ctx.lineTo(x, y+h);
            // ctx.fill()
        });
    }
</script>
</html>


本文主要介绍了canvas的基础知识,简单使用,最后来一个算法标注框的实现案例。



相关文章
|
6月前
|
机器学习/深度学习 XML 算法
算法金 | 自动帮你完成物体检测标注?这个工具你必须了解一下
Auto-Annotate是一款基于半监督学习的自动图像标注工具,旨在简化对象检测任务中的标注工作。利用少量标注数据,该工具能为大规模图像数据集生成标签,提高效率。支持自定义置信度阈值,适用于多类别检测和模型原型开发。通过pip安装,命令行或Python代码调用。虽然不能完全替代手动标注,但能有效减少标注量,适用于持续学习和模型更新。工具使用涉及模型选择、参数配置,如置信度阈值的调整,以平衡准确性和覆盖率。
87 0
算法金 | 自动帮你完成物体检测标注?这个工具你必须了解一下
|
7月前
|
XML 前端开发 算法
canvas从基础了解 -- 到算法标注框实现
canvas从基础了解 -- 到算法标注框实现
|
机器学习/深度学习 数据采集 存储
基于深度学习LSTM的古代汉语切分标注算法及语料库研究(下)
基于深度学习LSTM的古代汉语切分标注算法及语料库研究(下)
830 0
基于深度学习LSTM的古代汉语切分标注算法及语料库研究(下)
|
机器学习/深度学习 传感器 人工智能
基于深度学习LSTM的古代汉语切分标注算法及语料库研究(上)
基于深度学习LSTM的古代汉语切分标注算法及语料库研究
25944 0
基于深度学习LSTM的古代汉语切分标注算法及语料库研究(上)
|
JavaScript 算法 前端开发
【前端算法】JS实现数字千分位格式化
JS实现数字千分位格式化的几种思路,以及它们之间的性能比较
356 1
|
算法 API
算法基础学习2——冒泡排序
要比较的每一对元素是相邻的,从下标为0开始,到最后一个元素,如果下标设为 j,则相邻元素下标值为 j +1,搜索到最后一个元素:j+1<a.length,而 a.length - 1 = i ;所以终止条件是 j < i
135 0
算法基础学习2——冒泡排序
|
机器学习/深度学习 算法 Java
算法基础学习1——时间复杂度和空间复杂度
算法基础学习1——时间复杂度和空间复杂度
129 0
算法基础学习1——时间复杂度和空间复杂度
|
存储 前端开发 算法
一行代码解决LeetCode实现 strStr()使用JavaScript解题|前端学算法
一行代码解决LeetCode实现 strStr()使用JavaScript解题|前端学算法
170 0
一行代码解决LeetCode实现 strStr()使用JavaScript解题|前端学算法
|
搜索推荐 Java
Java基础数组-冒泡排序算法
Java基础数组-冒泡排序算法
Java基础数组-冒泡排序算法
一则有趣的算法题:两个栈实现一个队列
一则有趣的算法题:两个栈实现一个队列