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

文 / 镇圭

已过去的十年可以说是前端的 “黄金十年”,乘着 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,默认模型

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

最后得到的结果:

写在最后

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

1 Like