使用Node.js做深度学习中的图像预处理团队成员不再有维护成本,所以训练和识别以外的任务尽可能交给Node.js。今天要讲的图像预处理就是其中之一。这里简单解释几个概念,供不了解深度学习的同学参考。物体识别:物体识别可以理解为计算机在一张图片中找到一个或一些指定的物体,比如找到其中所有的狗。训练:计算机学习物体识别的能力就像人类学习说话一样。需要不断的练习。在深度学习中,这个过程被称为“训练”。训练集:人类要学会说话,需要看别人说什么,听别人的声音等。使他们学会说话的信息在深度学习中称为训练集,但训练集所需的训练集物体识别只是图片。图像预处理的目的是解决目标识别中训练集不足的问题。当对象识别应用于特定域时会遇到此问题。如果你是识别一只狗,这样的图片很多,而且已经有人训练过了,可以提供服务给大家使用。如果是识别球队中的文化衫,这样的图太少了。100张照片拍了很久,这样的数据量还是少得可怜。要知道互联网上那些成熟的AI服务,训练集随便几万,甚至上亿为单位。当然,专业的一般要求比较简单。需要鉴别的东西种类不多,特征也比较明显。但是,您仍然希望训练集尽可能大。这时候,你可以对你已有的图片做一些处理,生成新的图片。图片,从而扩展当前的训练集,这个过程称为图片预处理。常见的图像预处理方法有:旋转。由于旋转角度可以是任意值,因此需要随机生成一些角度进行旋转,也称为随机旋转。翻动。相当于在图片旁边放一面镜子,新图片就是镜子里的图片,一般有水平翻转和垂直翻转两种。调整亮度。您可以通过调整手机的亮度来了解这一点。调整饱和度。把传统电视调整一下就可以体会到这个意思。饱和度越高,色彩显示越鲜艳,否则会给人一种冷色的感觉。调整色调。这相当于改变了整个图片的颜色。想象一下之前被调出的绿色电视。调整对比度。这将使图像的亮区更亮,暗区更暗。您还可以想象电视上的对比度调整。不得不说,电视启发了这些专业术语。以上每一个操作都需要根据场景来选择。目前我们团队适用的处理方式主要有以上几种。还有一些操作,例如白化和Gamma处理。由于不是那么直观,有兴趣的可以自行理解。安装gmgm是一个用于图像处理的npm库。它的性能应该被认为是Node.js库中最好的。其底层默认使用GraphicsMagick,所以需要先安装GraphicsMagick,Mac系统直接用Homebrew安装:brewinstall可以直接去官网查看其他系统graphicsmagick的安装方法。如果需要给图片添加文字,还需要安装ghostscript,Mac上可以用brewinstallghostscript安装。由于本文不涉及此功能,故无需安装。同时需要在你的项目下安装gm:npmigm-Spreprocessing为了直观起见,我选择了一张图片作为预处理对象:另外,在本文的示例代码中,函数名每个预处理方法都是基于Tensorflow中Image模块中的同名方法。更多处理图片的方法,可以自己去Tensorflow文档官网查看,同时去gm官方文档找同样效果的方法。flip沿Y轴翻转使用gm的.flip方法:importgmfrom'gm';/***沿Y轴翻转,即上下颠倒*@paraminputPath输入图片文件路径*@paramoutputPath输出图片文件路径*@paramcallback处理后的回调函数*/functionflip(inputPath,outputPath,callback){gm(inputPath).flip().write(outputPath,callback);}翻转后的效果如下图所示:X轴gm的.flop方法用于翻转:importgmfrom'gm';/***沿X轴翻转,即倒置*@paraminputPath输入图像文件路径*@paramoutputPath输出图像文件路径*@paramcallback处理后的回调函数*/functionflop(inputPath,outputPath,callback){gm(inputPath).flop().write(outputPath,callback);}翻转后的效果如下图所示:也可以结合.flip和.flop组合使用,形成对角线翻转的效果:如果把原图看成一个前端组件,也就是一个购物按钮组,里面每个按钮的背景都可以定制。由多种元素组成,那么上面的翻转图片可以看作是同一个组件,即可以作为训练集。有时候,翻转的效果并不是你想要的。可能翻转之后,不应该认为和原图是一回事。此时,这种方法有局限性。与调节亮度相比,调节亮度更为通用。不管是哪种画面,调好亮度后,里面的东西还是和原来一样。gm的.modulate方法用于调节亮度:/***adjustbrightness*@paraminputPath输入图像文件路径*@paramoutputPath输出图像文件路径*@parambrightness图像亮度值,参考值为100,即高于100Higher为增加亮度,低于100为减少亮度*@paramcallback处理后的回调函数*/functionadjustBrightness(inputPath,outputPath,brightness,callback){gm(inputPath).modulate(brightness,100,100)。write(outputPath,callback);}.modulate方法是一个多功能方法,可以同时调整图像的亮度、饱和度和色相。这三个特征对应于该方法的三个参数。这里我们只调整Brightness,所以只改变第一个参数(高于100为增加亮度,低于100为降低亮度),其他保持100底值不变。我生成了亮度从0到200的图片,对比了一下,选择了一个亮度处理比较合适的范围。0到200之间可以看到亮度差10的相邻图片的区别(提示:每张图片的左上角都标出了图片的亮度):可以看到亮度小于60的图片太暗了,细节不够明显。亮度150以上的图片太亮了,细节不够明显。多张图片综合对比后,我觉得[60,140]区间的图片质量较好,与原图相比不会损失太多细节。我们来看一下亮度分别为50和60的两张图片,其实它们看起来就像一张图片,这不符合训练集的多样性原则,更何况是亮度差为1的两张图片。所以最终决定作为训练集的两张相邻图片的亮度差为20,这样差异比较明显,比如两张亮度为80,亮度为100的图片。最后,有将是4张通过调整亮度生成的新图片。从一张亮度为60的图片开始,亮度每增加20,就选择加入到训练集中,直到亮度为140的图片,亮度为100的图片不算在内。Adjustingsaturation调整饱和度也是使用.modulate方式,只是调整了第二个参数:/***Adjustsaturation*@paraminputPath输入图片文件路径*@paramoutputPath输出图片文件路径*@paramsaturation图像饱和度的值,底值为100,高于100为增加饱和度,低于100为降低饱和度*@paramcallback处理后的回调函数*/functionadjustSaturation(inputPath,outputPath,saturation,callback){gm(inputPath).modulate(100,saturation,100).write(outputPath,callback);}同时调整亮度,确定训练集中饱和度的范围和相邻两张图片的饱和度差值。可以看到饱和度差为10的相邻图片的区别(温馨提示:图片的饱和度在每张图片的左上角标注):调整饱和度产生的图片细节没有丢失,而且大部分其中可以作为训练集中的图片,和亮度一样,饱和度相差20的两张图片差异很明显。另外,饱和度大于140时,画面变化不明显。所以调整饱和度产生的新图片就是6张图片。从一张饱和度为0的图片开始,饱和度每增加20,就选择加入到训练集中,直到饱和度为140的图片,饱和度为100的图片不算。调整色调调整色调的方法是这个场景中最有用的方法,产生最多的训练集。我们先看一下色调相邻10的图片之间的差距(提示:每张图片的左上角标有图片的Hue):几乎每张图片都可以作为新的训练集。由于色相调整范围只能在0到200之间,所以从一张色相为0的图片开始,每增加10个色相就加入训练集,直到色相190的图片,色相100的图片不是算了。这会产生20张图像作为训练集。至于调整色相的代码,和亮度、饱和度一样,只是第三个参数变了:/***调整色相*@paraminputPath输入图片文件路径*@paramoutputPath输出图片文件路径*@paramhue图像色调值,底值为100,高于100为增加色调,低于100为降低色调*@paramcallback处理后回调函数*/functionadjustHue(inputPath,outputPath,hue,callback){gm(inputPath).modulate(100,100,hue).write(outputPath,callback);}调整色调不是万能的,只适用于这种场景。当然我们团队的需求也和这个场景差不多。但是如果你正在训练一个人工智能来识别梨,告诉它有一个蓝色的梨显然是不合适的。调整对比度gm的.contrast方法用于调整对比度:/***调整对比度*@paraminputPath输入图像文件路径*@paramoutputPath输出图像文件路径*@parammultiplier调整对比度因子,默认为0,可以是负值,n表示增加n倍对比度,-n表示降低n倍对比度*@paramcallback处理后的回调函数*/functionadjustContrast(inputPath,outputPath,multiplier,callback){gm(inputPath).contrast(multiplier).write(outputPath,callback);}下面是对比度因子在-10到10之间的图像,可以看到图像质量较好的区间是[-5,2],其他的会丢失一些细节。另外,相邻对比度因子的图片差异也很明显,所以每张图片都可以作为训练集,所以多了7张图片。总结通过以上5种方法,可以在一张图片的基础上得到40张附加图片,即训练集是原来的40倍。这还是在没有多种方法混合使用的情况下,如果混合使用,恐怕要多上百倍。gm还支持对图片的其他处理方式,大家自己去发现吧。每种方法在特定场景下都有其局限性,需要您进行选择。希望大家都有自己满意的训练集。宣传欢迎大家Star作者的Github。另外,欢迎大家关注作者的公众号获取最新文章:
