10 分钟入门 -- 基于浏览器与YOLO 的图像识别

avatar
阿里巴巴 前端委员会智能化小组 @阿里巴巴

文/镇圭


已过去的十年可以说是前端的“黄金十年”,乘着 Web 2.0 的东风各类前端工具与框架从百花齐放到逐渐稳定,我们是这个时代的见证者。但回顾 2019 年的前端却没有新“焦点”出现,那么站在 2020 年这个未来十年的起点上眺望,前端会往什么样的方向发展呢?可以预见的是在人工智能浪潮的裹挟下,智能化注定会与研发生产的各个领域碰撞出新的火花,前端一定也不会例外。

本文希望尽可能零门槛得通过一个最简单基于浏览器的图像识别 Demo,激起大家的兴趣,共同投身到“前端智能化”的时代成为时代的开垦者。

序言


全 Demo 代码共 100 行左右,完成了图片上传并分类的功能,完全运行在浏览器端,模型采用基于 tfjs 的 Tiny YOLO 模型(约 40M 大小)

YOLO 是什么?


YOLO 是用于(实时)目标检测的模型。 目标检测是很多计算机视觉任务的基础,用于在一张图中找到特定的物体,目标检测不仅要求我们识别分类这些物体,同时要求我们标记出物体的位置

YOLO 的全称是 you only look once,顾名思义只需要浏览一次就可以识别出图中的物体的类别和位置。

用官网原话讲,more than 1000x faster than R-CNN and 100x faster than Fast R-CNN,因此YOLO 非常适用于实时的目标检测。

功能拆解


问把大象装进冰箱需要几步?

1.加载模型


通过 downloadModel方法下载模型,即(tf.loadModel)[js.tensorflow.org/api/0.8.0/#…],默认模型

import yolo, { downloadModel } from 'tfjs-yolo-tiny';
const model = await downloadModel();

2.上传图像


通过 input 组件上传单张图片并展示,不赘述了

file.onchange = async function () {
    const fileData = this.files[0]
    const type = /^image/
    if (!type.test(fileData.type)) {
        //  省略
    }
    const reader = new FileReader()
    reader.readAsDataURL(fileData)
    reader.onload = async function (e) {
        image.setAttribute("src", this.result)
        image.onload = async function () {
            //  省略
        }
    }
}

3.通过 YOLO 识别


通过 Tiny YOLO 的 JS 库执行即可得到识别结果,执行获得的结果 boxes 为识别数据的数组,包含边界框(bounding box)的坐标,分类名称与置信度

const imageTensor = imageUtil.tensor(image)
// 将图片线性resize到模型所需的416X416
const boxes = await yolo(tf.image.resizeBilinear(imageTensor, [416, 416]), model)


其中imageUtil.tensor方法将 HTMLImageElement 变为模型所要求的 Tensor3D(即三阶的张量 —— Rank-3 tensor)

// 将HTMLImageElement变为tensor [height, width, channels]
const imageTensor = tf.fromPixels(this.imageElement);
// 根据图的最短边剧中裁剪,讲长方形变为正方形
const croppedImage = this.cropImage(imageTensor);
// 扩展现有三阶tensor变为4阶 [batch, height, width, channels]
const batchedImage = croppedImage.expandDims(0);
// 通过除以255做归一化
return batchedImage.toFloat().div(tf.scalar(255));


最后得到的结果

写在最后


机器学习是我这些年了解到最有趣的工具之一,如果你因为之前接触到机器学习时满屏的数学公式望而却步的话,不妨今天就通过这个简单例子去试试吧!