• canvas实现百度AI图片多主体识别效果


    前言

    近期模拟了一个百度AI——图片多主体识别的demo,使用了canvas实现这个功能。相信前端的同事对canvas都不算陌生,那我们就用canvas来看看这个功能是怎么实现的吧。

    什么是canvas。

    1. canvas是html5的一个新标签,属于h5的新特性
    2. canvas标签是一个图形的容器,简单点说就是一块画布,你可以在上画矩形,圆形,三角形,折线等等,也可以用来画logo
    3. 它是通过javascript来画的,即脚本绘制图形

    canvas可以用来做什么

    1. 制作web网页游戏(但是如果代码写的不咋的游戏可能会非常卡)
    2. 数据可视化(这么说你可能不明白,但我告诉你echarts就是基于canvas)
    3. 广告banner的动态效果非常适合用canvas制作
    4. canvas还可以用来内嵌一些网页

    介绍完canvas之后,我们就开始模拟图片多主体识别的效果吧( 注意:本片文章重点不是demo实现的过程,重点是canvas的用法

    期望效果:
    在这里插入图片描述

    首先我们先在节点上创建一个canvas的节点,再添加一个上传文件的节点。

    <div class="canvasBox">
    	<canvas id="canvas" width="900" height="500">canvas>
     div>
    
     <div class="button">
    	<label for="file" class="file_load">本地上传label>
    	<input id="file" onclick="getFiles()" type="file"  style="display:none">
     div>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    然后点击上传文件解析图片文件(注:因接口需要,需把图片文件转换成base64格式)

    /**
    	* 获取上传的文件
     */
       var imgUrl = '' // 定义图片链接
       
       function getFiles() {
    
            var file = document.getElementById('file');
    
            var image = document.querySelector("img");
    
            file.onchange = function (e) {
    
                var fileData = this.files[0];//这是我们上传的文件
    
                if (fileData) {
    
                    imgUrl = window.URL.createObjectURL(fileData)
    
                    getBase64(imgUrl, dataURL => {
    
                        const imgBase64 = encodeURIComponent(dataURL.split(',')[1])
    
                        postImgUrl(accessToken, imgBase64)
    
                    });
    
                }
    
                var reader = new FileReader();
    
                reader.readAsDataURL(fileData);//异步读取文件内容,结果用data:url的字符串形式表示
    
            }
    
        }
    
    
    
    	var imgX = ''
    
        var imgY = ''
    
        // 文件转base64
    
        function getBase64(imgUrl, callback) {
    
            var canvasDom = document.getElementById('canvas')
    
            var ctx = canvas.getContext("2d")
    
            // ctx.clearRect()
    
            let image = new Image();
    
            // 解决跨域问题
    
            image.setAttribute("crossOrigin", "anonymous");
    
            let imageUrl = imgUrl;
    
            image.src = imageUrl;
    
            // image.onload为异步加载
    
            // eslint-disable-next-line no-undef
    
            image.onload = function () {
    
                var canvas = document.createElement("canvas");
    
                canvas.width = image.width;
    
                canvas.height = image.height;
    
                var context = canvas.getContext("2d");
    
    
                context.drawImage(image, 1, 1, canvas.width, canvas.height);
    
                // 这里的dataurl就是base64类型
    
                // 使用toDataUrl将图片转换成jpeg的格式,不要把图片压缩成png,因为压缩成png后base64的字符串可能比不转换前的长!
    
                let dataurl = canvas.toDataURL("image/jpeg", quality);
    
                callback ? callback(dataurl) : null; //调用回调函数
    
            };
    
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91

    base64转换成功后,就需要使用转换后的值作为参数请求接口获取数据(此处接口后端有做跨域调整,故使用时不可直接复制使用)

    	/**
         * 上传图片获取图片识别数据
        */
        var moduelUrl = ''
        function postImgUrl(accessToken, imgBase64) {
            moduelUrl = '/bdapi/rest/2.0/image-classify/v1/multi_object_detect'
    
            const xhr = new XMLHttpRequest()
            const testUrl = `${moduelUrl}?access_token="${accessToken}"`
            xhr.open('POST', `${moduelUrl}?access_token="${accessToken}"`)
            xhr.send(`image=${imgBase64}`);//发送请求 将情头体写在send中
            xhr.onreadystatechange = function () {
                if (xhr.readyState == 4 && xhr.status === 200) {
                    const res = JSON.parse(xhr.responseText)
                    if(res){
                        showImg(imgUrl, res)
                    }
                }
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    请求数据成功后就是渲染图片跟画图

    /**
         * canvas显示图片
        */
        var imgMultiple = 0.5859375 // 按比例缩放图片,后续需要使用到
        function showImg(imgUrl, data){
            //获得canvas画布
            var canvas = document.getElementById("canvas");
            //得到画布的上下文
            var ctx = canvas.getContext("2d");
            ctx.clearRect(0, 0, 1000, 600)
            //创建一个image元素
            let image = new Image();
            //onload一下
            image.onload = function (res) {
                imgWigth = imgMultiple *  image.width
                imgHeight = imgMultiple *  image.height
                imgX = (900 - imgWigth) / 2
                imgY = (500 - imgHeight) / 2
                ctx.drawImage(image, imgX, imgY, imgWigth, imgHeight);
                drawSquare(data)
            }
            //用src设置图片的地址
            image.src = `${imgUrl}`;
        }
    
    
    	/**
         * canvas画正方形
        */
        function drawSquare(data){
            //获得canvas画布
            var canvas = document.getElementById("canvas");
            //得到画布的上下文
            var cxt = canvas.getContext("2d");
            cxt.beginPath()
            var array
            if (data.result) {
                array = data.result
            } else {
                array = data.results
            }
            console.log('draw square', imgMultiple);
            for (let i = 0; i < array.length; i++) {
                const item = array[i];
                const x = item.location.left * imgMultiple + imgX
                const y = item.location.top * imgMultiple + imgY
                const width = item.location.width * imgMultiple
                const height = item.location.height * imgMultiple
                // 设置字体
    			cxt.font = "12px 微软雅黑 bolder"
    			// 设置字体颜色
    			cxt.fillStyle = "#000"
    			cxt.textAlign = "left"
    			// 添加文字和位置
    			cxt.fillText(item.name, x, y - 6);
                cxt.moveTo(x, y)
                cxt.lineTo(x + width, y)
                cxt.lineTo(x + width, y + height)
                cxt.lineTo(x, y + height)
                cxt.lineTo(x, y)
                cxt.strokeStyle = 'red' // 设置或返回用于描边的颜色
                // cxt.fillStyle  = '#008833' // 设置或返回用于填充绘画的颜色
                // cxt.globalCompositeOperation="destination-over"; // 绘制的图
                cxt.stroke()
                // cxt.salce(1 / imgMultiple, 1 / imgMultiple)
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67

    实际实现效果:
    在这里插入图片描述

    当然,前面一开始就已经说明,本次文章的重点不是如何实现图片多主体识别的效果,重点是讲解一下canvas的用法,想更深入了解canvas在图片上画图的朋友接着看下面的文章。

    canvas图片自适应和居中显示

  • 相关阅读:
    c#default 运算符
    Python——字符串
    2023年第六届材料工程与先进制造技术国际会议(MEAMT 2023)
    linux非root安装特定版本的cuda
    go+mysql+redis+vue3简单聊室,第6弹:使用vue3和element-plus调用接口
    Linux多线程
    一个开源的音频分离深度学习项目
    在 Python 中实现 DBSCAN
    C#命名空间 System.IO思维导图
    vue项目代码格式不统一怎么办?一招教你解决
  • 原文地址:https://blog.csdn.net/qq_43942185/article/details/126462064