文 / 镇圭
已过去的十年可以说是前端的 “黄金十年”,乘着 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));
最后得到的结果:
写在最后
机器学习是我这些年了解到最有趣的工具之一,如果你因为之前接触到机器学习时满屏的数学公式望而却步的话,不妨今天就通过这个简单例子去试试吧!