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>

然后点击上传文件解析图片文件(注:因接口需要,需把图片文件转换成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; //调用回调函数

        };

    }

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)
                }
            }
        }
    }

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

/**
     * 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)
        }
    }

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

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

canvas图片自适应和居中显示

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

别来…无恙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值