最近在做一个和对象识别相关的项目,由于团队内技术栈偏向 JavaScript,在已经用 Python 和 Tensorflow 搭建好了对象识别服务器后,为了不再增加团队成员维护成本,所以尽可能将训练和识别之外的任务交给 Node.js 来做,今天要讲到的图片预处理就是其中之一。
这里对还不了解深度学习的人就几个概念做个简单的解释
对象识别:对象识别可理解为计算机在一张图片中发现某个或某些指定的物体,比如找到里面所有的狗。
训练:计算机学会对象识别这个本领就像人类学会说话一样,需要不断地练习,深度学习中管这个过程叫做 “训练”。
训练集:人类学会说话需要看别人怎么说,听别人的声音等等,这些能够让自己学会说话的信息在深度学习中称为训练集,只不过对象识别中需要的训练集只有图片。
做图片预处理的目的是为了解决对象识别中训练集不足的问题。当对象识别应用于某个专用领域的时候,就会遇到这个问题。如果你是识别一只狗,这样的图片一大把,而且有人已经训练好了,并且可以提供服务给大家使用了。如果你是识别团队内的文化衫,这样的图片就太少了,费了老半天劲拍 100 张,这样的数据量依然少得可怜。要知道网上那些成熟的 AI 服务,训练集随随便便就成千上万,甚至以亿为单位。当然,专用领域一般需求也比较简单,需要识别出来的东西种类不多,特征也比较明显,但是仍然会希望训练集越大越好,这时候就可以对所拥有的图片做一些处理,来生成新的图片,从而扩充当前的训练集,这个过程就叫图片预处理了。
常见的图片预处理方式有以下几种:
旋转。由于旋转的角度可以是任意值,所以需要随机生成一些角度来旋转,这又称为随机旋转。
翻转。相当于在图片旁边放面镜子,新图片就是镜子内的图片,一般有水平翻转和竖直翻转两种。
调节亮度。调节过手机的亮度就能体会这个意思。
调节饱和度。调节过传统电视就能体会到这个意思,饱和度越高,色彩显示越鲜艳,反之给人一种冷色的感觉。
调节色相。这个相当于给整个图片变颜色一样,想象一下以前调出来的绿色电视。
调节对比度。这个会让图片亮的地方更亮,暗的地方更暗。也可以想象一下电视上的对比度调节,不得不说电视机启蒙了这些专业名词。
上述每项操作都需要视场景而选择,目前适用于我们团队的处理方式主要也就是上面这些。还有一些白化、Gamma 处理等操作,由于不是那么直观,有兴趣的人可以自己去了解。
安装 gm
gm 是一个图片处理的 npm 库,性能在 Node.js 库中应该算佼佼者了,它底层默认使用的是 GraphicsMagick,所以你需要先安装 GraphicsMagick,在 Mac 系统中直接用 Homebrew 安装:
brew install graphicsmagick
其他系统的安装方式可以直接前往官网查看。
如果你需要在图片上添加文字,还需要安装 ghostscript,在 Mac 上可以用 brew install ghostscript 安装。由于本文没涉及到这一个功能,所以可以不用安装。同时,需要将 gm 安装在你的项目下:
npm i gm -S
预处理
为了直观,我选了一张图片作为预处理对象:
另外,在本文的示例代码中,每种预处理方法的函数名都是参照 Tensorflow 中 Image 模块的同名方法而定,更多处理图片的方法可以前往 Tensorflow 文档官网自行查看,同时去 gm 官方文档 中寻找相同作用的方法。
翻转
沿 Y 轴翻转用到了 gm 的 .flip 方法:
import gm from 'gm'; /** * 沿 Y 轴翻转,即上下颠倒 * @param inputPath 输入的图像文件路径 * @param outputPath 输出的图像文件路径 * @param callback 处理后的回调函数 */ function flip(inputPath, outputPath, callback) { gm(inputPath) .flip() .write(outputPath, callback); }
翻转后的效果如下图所示:
沿 X 轴翻转用到了 gm 的 .flop 方法:
import gm from 'gm'; /** * 沿 X 轴翻转,即上下颠倒 * @param inputPath 输入的图像文件路径 * @param outputPath 输出的图像文件路径 * @param callback 处理后的回调函数 */ function flop(inputPath, outputPath, callback) { gm(inputPath) .flop() .write(outputPath, callback); }
翻转后的效果如下图所示:
你还可以把 .flip 和 .flop 组合起来使用,形成对角线翻转的效果: