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

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


canvas必备基础

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

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

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>

绘制三角形

常用的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>

绘制圆形

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

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

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

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

推荐这篇文字介绍的arc参数很详细:

Canvas的arc函数绘制圆和图形

绘制图像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.

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

<!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>

绘制文字

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"}];

要实现的效果为:

  • 红色框标注抽烟算法,
  • 黄色框标注未带安全帽算法
    源码如下:
<!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的基础知识,简单使用,最后来一个算法标注框的实现案例。


相关文章
|
5月前
|
机器学习/深度学习 XML 算法
算法金 | 自动帮你完成物体检测标注?这个工具你必须了解一下
Auto-Annotate是一款基于半监督学习的自动图像标注工具,旨在简化对象检测任务中的标注工作。利用少量标注数据,该工具能为大规模图像数据集生成标签,提高效率。支持自定义置信度阈值,适用于多类别检测和模型原型开发。通过pip安装,命令行或Python代码调用。虽然不能完全替代手动标注,但能有效减少标注量,适用于持续学习和模型更新。工具使用涉及模型选择、参数配置,如置信度阈值的调整,以平衡准确性和覆盖率。
74 0
算法金 | 自动帮你完成物体检测标注?这个工具你必须了解一下
|
机器学习/深度学习 数据采集 存储
基于深度学习LSTM的古代汉语切分标注算法及语料库研究(下)
基于深度学习LSTM的古代汉语切分标注算法及语料库研究(下)
803 0
基于深度学习LSTM的古代汉语切分标注算法及语料库研究(下)
|
机器学习/深度学习 传感器 人工智能
基于深度学习LSTM的古代汉语切分标注算法及语料库研究(上)
基于深度学习LSTM的古代汉语切分标注算法及语料库研究
25928 0
基于深度学习LSTM的古代汉语切分标注算法及语料库研究(上)
|
XML 前端开发 算法
canvas从基础了解 -- 到算法标注框实现
canvas从基础了解 -- 到算法标注框实现
243 0
canvas从基础了解 -- 到算法标注框实现
|
前端开发 小程序 算法
【微信小程序】基于百度大脑人体检测、人脸识别以及调用阿里垃圾分类识别小程序利用canvas完成人脸画图、分割手部部分图片算法
【微信小程序】基于百度大脑人体检测、人脸识别垃圾分类人体出现在镜头里用红色框将人脸圈出来、用黄色框将手部圈出来,定时器触发后,通过百度返回的top+、left+、width+、height+将拍照的截图用canvas画出来,最后保存上传到阿里云垃圾分类识别检测博主用的是手部关键点识别,手部截取包括手肘部分,当出现手肘没有手掌时会出现截取不到目标的问题,目前解决办法:定时器设置时间长一点供演示员做好调整,另外就是出现手掌,可以尽量把掌心打开方便识别这样手肘部分就不会被检测到了在截取的时候canvas用不了..
318 0
【微信小程序】基于百度大脑人体检测、人脸识别以及调用阿里垃圾分类识别小程序利用canvas完成人脸画图、分割手部部分图片算法
|
机器学习/深度学习 算法 Python
ML之SVM:基于sklearn的svm算法实现对支持向量的数据进行标注
ML之SVM:基于sklearn的svm算法实现对支持向量的数据进行标注
ML之SVM:基于sklearn的svm算法实现对支持向量的数据进行标注
|
26天前
|
算法 安全 数据安全/隐私保护
基于game-based算法的动态频谱访问matlab仿真
本算法展示了在认知无线电网络中,通过游戏理论优化动态频谱访问,提高频谱利用率和物理层安全性。程序运行效果包括负载因子、传输功率、信噪比对用户效用和保密率的影响分析。软件版本:Matlab 2022a。完整代码包含详细中文注释和操作视频。
|
11天前
|
算法 数据挖掘 数据安全/隐私保护
基于FCM模糊聚类算法的图像分割matlab仿真
本项目展示了基于模糊C均值(FCM)算法的图像分割技术。算法运行效果良好,无水印。使用MATLAB 2022a开发,提供完整代码及中文注释,附带操作步骤视频。FCM算法通过隶属度矩阵和聚类中心矩阵实现图像分割,适用于灰度和彩色图像,广泛应用于医学影像、遥感图像等领域。
|
12天前
|
算法 调度
基于遗传模拟退火混合优化算法的车间作业最优调度matlab仿真,输出甘特图
车间作业调度问题(JSSP)通过遗传算法(GA)和模拟退火算法(SA)优化多个作业在并行工作中心上的加工顺序和时间,以最小化总完成时间和机器闲置时间。MATLAB2022a版本运行测试,展示了有效性和可行性。核心程序采用作业列表表示法,结合遗传操作和模拟退火过程,提高算法性能。