使用 Node.js 将图片中的苹果变成橘子-阿里云开发者社区

开发者社区> AlibabaF2E> 正文

使用 Node.js 将图片中的苹果变成橘子

简介: 图片风格转换在一些相机 App 或者照片编辑 App 中有比较多的应用,可以对图片进行各种转换。Pipcook 已经支持图片风格迁移模型,可以实现很多有趣的图片风格转换。

作者 | 牟牟

前言

为了让大家更好地学习 Pipcook 和机器学习,我们准备了实战系列教程,会分别从前端组件识别、图片风格迁移、AI 作诗以及博客自动分类,这几个具体示例来讲解如何在我们日常开发中使用 Pipcook,如果需要了解 Pipcook 1.0,请阅读文章 AI ❤️ JavaScript, Pipcook 1.0

背景

图片风格转换在一些相机 App 或者照片编辑 App 中有比较多的应用,可以对图片进行各种转换。Pipcook 已经支持图片风格迁移模型,可以实现很多有趣的图片风格转换,比如将马变成斑马:
image.png
或者苹果和橘子的图片互转:
image.png
或者照片和各种风格艺术画之间的相互转换(每种类型需要进行一次模型训练):
image.png
是不是很有趣,让我们瞧瞧如何在 Pipcook 上实现这个功能吧!

Pipeline

首先定义一个 pipeline 配置文件 cycle-gan.json,内容如下:

{
  "plugins": {
    "dataCollect": {
      "package": "@pipcook/plugins-image-classification-data-collect",
      "params": {
        "url": "https://ai-sample.oss-cn-hangzhou.aliyuncs.com/apple2orange.zip"
      }
    },
    "dataAccess": {
      "package": "@pipcook/plugins-pascalvoc-data-access"
    },
    "modelDefine": {
      "package": "@pipcook/plugins-tensorflow-cycle-gan-model-define"
    },
    "modelTrain": {
      "package": "@pipcook/plugins-image-generation-tensorflow-model-train",
      "params": {
        "niter": 50000
      }
    },
    "modelEvaluate": {
      "package": "@pipcook/plugins-image-generation-model-evaluate"
    }
  }
}

我们使用了以下插件来完成我们的 pipeline:

  • @pipcook/plugins-image-classification-data-collect 这个插件用于下载图片分类的数据集,我们需要提供 url 参数,插件会下载并解压数据集。
  • @pipcook/plugins-pascalvoc-data-access 下载好了数据集后,需要将数据集转换为 pascal voc 格式才能被风格转换模型识别,所以我们采用此插件。
  • @pipcook/plugins-tensorflow-cycle-gan-model-define 基于 TensorFlow 实现的 CycleGAN 模型定义插件。
  • @pipcook/plugins-image-generation-tensorflow-model-train 使用这个插件开始模型训练,主要的参数为 niter 训练的周期,调整该参数将会影响训练时长和模型预测效果,在我们的例子中,设置到 50000 可以基本满足。
  • @pipcook/plugins-image-generation-model-evaluate 此插件在训练结束后对模型效果的评估,最终给出的是测试图片生成目标图标的各项 loss 值。

需要注意的是,CycleGAN 模型训练需要比较多的计算资源,建议使用 GPU 服务器进行训练。

训练

准备好 pipeline 配置文件后,在 shell 中执行:

$ pipcook run cycle-gan.json --verbose

start loading plugin @pipcook/plugins-image-classification-data-collect
downloading dataset ...
unzip and collecting data...
create annotation file...
start loading plugin @pipcook/plugins-pascalvoc-data-access
create a result "b1192e00-20ff-4872-adbc-6f7d408ea0fc" for plugin "@pipcook/plugins-pascalvoc-data-access@0.6.3"
start loading plugin @pipcook/plugins-cycle-gan-model-define
create a result "6dda48eb-52da-425e-a95f-748fb8180954" for plugin "@pipcook/plugins-cycle-gan-model-define@0.6.0"
start loading plugin @pipcook/plugins-image-generate-tensorflow-model-train
Model: "dis_B"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_2 (InputLayer)         [(None, 128, 128, 3)]     0         
_________________________________________________________________
conv2d_18 (Conv2D)           (None, 64, 64, 64)        3136      
_________________________________________________________________
leaky_re_lu (LeakyReLU)      (None, 64, 64, 64)        0         
_________________________________________________________________
conv2d_19 (Conv2D)           (None, 32, 32, 128)       131200    
_________________________________________________________________
instance_normalization2d_17  (None, 32, 32, 128)       64        
_________________________________________________________________
leaky_re_lu_1 (LeakyReLU)    (None, 32, 32, 128)       0         
_________________________________________________________________
conv2d_20 (Conv2D)           (None, 16, 16, 256)       524544    
_________________________________________________________________
instance_normalization2d_18  (None, 16, 16, 256)       32        
_________________________________________________________________
leaky_re_lu_2 (LeakyReLU)    (None, 16, 16, 256)       0         
_________________________________________________________________
conv2d_21 (Conv2D)           (None, 16, 16, 512)       2097664   
_________________________________________________________________
instance_normalization2d_19  (None, 16, 16, 512)       32        
_________________________________________________________________
leaky_re_lu_3 (LeakyReLU)    (None, 16, 16, 512)       0         
_________________________________________________________________
conv2d_22 (Conv2D)           (None, 16, 16, 1)         8193      
=================================================================
Total params: 2,764,865
Trainable params: 2,764,865
Non-trainable params: 0
_________________________________________________________________
Model: "dis_A"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_4 (InputLayer)         [(None, 128, 128, 3)]     0         
_________________________________________________________________
conv2d_41 (Conv2D)           (None, 64, 64, 64)        3136      
_________________________________________________________________
leaky_re_lu_4 (LeakyReLU)    (None, 64, 64, 64)        0         
_________________________________________________________________
conv2d_42 (Conv2D)           (None, 32, 32, 128)       131200    
_________________________________________________________________
instance_normalization2d_37  (None, 32, 32, 128)       64        
_________________________________________________________________
leaky_re_lu_5 (LeakyReLU)    (None, 32, 32, 128)       0         
_________________________________________________________________
conv2d_43 (Conv2D)           (None, 16, 16, 256)       524544    
_________________________________________________________________
instance_normalization2d_38  (None, 16, 16, 256)       32        
_________________________________________________________________
leaky_re_lu_6 (LeakyReLU)    (None, 16, 16, 256)       0         
_________________________________________________________________
conv2d_44 (Conv2D)           (None, 16, 16, 512)       2097664   
_________________________________________________________________
instance_normalization2d_39  (None, 16, 16, 512)       32        
_________________________________________________________________
leaky_re_lu_7 (LeakyReLU)    (None, 16, 16, 512)       0         
_________________________________________________________________
conv2d_45 (Conv2D)           (None, 16, 16, 1)         8193      
=================================================================
Total params: 2,764,865
Trainable params: 2,764,865
Non-trainable params: 0
_________________________________________________________________
create a result "b15b7472-d430-4289-9216-a7e2f9ee852c" for plugin "@pipcook/plugins-image-generate-tensorflow-model-train@0.6.0"
start loading plugin @pipcook/plugins-cycle-gan-model-evaluat

训练预计持续时间12小时,训练完成后,将在当前目录生成output文件夹,里面就是我们训练好的模型了。我们可以使用 npm 对它进行安装:

$ cd output && npm install

风格转换

此时,模型已经准备就绪,我们找一张苹果的图片和一张橘子的图片:
image.png
image.png


const predict = require('./output');
const fs = require('fs');
function saveToFile (base64Data, file) {
  var dataBuffer = new Buffer(base64Data, 'base64');
  fs.writeFile(file, dataBuffer, function(err) {
    if (err) {
      console.log('保存文件失败', err.message);
    } else {
        console.log('保存文件成功:', file);
    }
  });
}
(async () => {
  const orange_from_apple = await predict({ path: '/path/to/apple.jpg', predictType: 'a2b' });
  saveToFile(orange_from_apple, '/path/to/save/orange_from_apple.jpg'); // 生成的橘子图片
  const apple_from_orange = await predict({ path: '/path/to/orange.jpg', predictType: 'b2a' });
  saveToFile(apple_from_orange, '/path/to/save/apple_from_orange.jpg'); // 生成的苹果图片
})();

保存为 apple2orage.js, 然后运行:

$ node ./apple2orange.js
保存文件成功: /path/to/save/orange_from_apple.jpg
保存文件成功: /path/to/save/apple_from_orange.jpg

转换之后的图片:
image.png
image.png
将代码包装一下,一个可以提供苹果和橘子互转的图片风格转换服务就完成啦!

数据集

图片风格转换的数据集目录结构如图:
image.png
其中 train 为训练数据集,用于模型训练,test 为测试数据集,用于模型训练结束后验证模型准确性。

测试数据集和训练数据集包含 A,B 两个文件夹,这两个文件夹内的数据不需要配对,也就是说,A 和 B 文件夹内是无关联的图片,在我们这个例子中,我们只需要在 A 文件夹内放入任意苹果的图片,B 文件夹内放入任意橘子的图片,就可以进行模型训练了。这对我们收集数据来说非常友好,比如你可以将人脸部照片放入 A 文件夹, 二次元的脸部照片放入 B 文件夹,不需要任何标注,就可以完成照片二次元相互转换模型数据集的整理。

进阶

了解了 Pipcook 风格转换的实现后,是不是有上手试一试的冲动呢?同学们可以尝试下面的训练集,也可以自己整理训练数据完成想要的风格变换模型。

总结

读者到这里已经学会如识使用 Pipcook 实现图片风格迁移,下一篇文章,我们将使用 Pipcook 来看看如何通过文本创作类模型来创作中文诗歌。


🎉Pipcook 1.0 系列专题 🎉

AI (爱) JavaScript , Pipcook 1.0 正式发布

Pipcook 团队有话说

使用Pipcook对图片中的前端组件进行分类,饼图、折线图还是柱状图?

设计稿生成代码核心技术揭秘:获取图片中前端组件的位置信息

👉使用 Node.js 将图片中的苹果变成橘子

未完待续...

❤️欢迎大家关注 Alibaba F2E 微信公众号前端智能化技术分享周(6.29-7.3)❤️

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:
AlibabaF2E
使用钉钉扫一扫加入圈子
+ 订阅

阿里经济体前端技术最新内容汇聚在此,由阿里经济体前端委员会官方运营。我们的愿景是建立全球一流的前端团队,链接商业,让数字世界触手可及是我们的使命。阿里经济体前端委员会致力于加强技术前瞻性、推进集体成长、提升国际影响力。同时我们运营着阿里经济体前端的官方公众号:Alibaba F2E,欢迎关注。

官方博客
官网链接