查看原文
其他

全民刷军装背后的AI技术及简单实现

2017-07-31 shadow 科技Mix设计Lab




昨天有Design-AI-Lab用户后台留言,问为什么换军装的h5这么火,但没见到有技术文章分析如何实现。


我回复说,大概是比较简单吧,主要工作是图像合成。



后来,我亲自体验了下,反应速度比较慢,大概是因为火了吧,访问者太多;

关键的技术是人脸识别

前端的话,canvas实现图像合成;

整个h5设计不算惊艳,只能算一般;

运营亮点是抓住热点事件,设计了激发用户分享的产品。


再细想一想,决定还是自己动手实现一个,试试整个技术的难度。


于是,通过开发者工具,阅读了

http://www.h5case.com.cn/case/people-cn/81/

的前端源码;



这个H5,

是由人民日报客户端&天天P图出品的;

技术实现: jQuery+Swiper,


Swiper负责简单的页面切换效果;


人脸与军装的图像的合成是后端操作的,前端只负责呈现。


二维码及相关的文字图样是通过html2canvas合成的。



1 关键技术

人脸识别,自动扣图,图像合成。


2 我的实现方案:

  简易版本  UFace  

暂时称之为UFace吧,说不准哪天我有兴致把它更进一步的完善,做个app之类的。


前端采用 jQuery;

后端采用Nodejs+express ;

人脸识别采用 百度AI的人脸检测;


安利下百度AI

http://ai.baidu.com/tech/face/detect

可以做人脸检测、对比、查找等工作。


2.1 先把nodejs环境准备下,


终端输入:

express -e ejs  UFace


自动生成express的初始目录及文件;


2.2 调通全后端接口:


找到 views/index.ejs 文件,添加

<script src=“https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>


找到routes/index.js文件,添加

router.post('/', function(req, res, next) {

  res.send('UFace post ok')

});


终端输入

node bin/www


浏览器访问:

http://localhost:3000/


打开开发者工具,在console里调试接口,输入:

$.post("/", function(data) {

  console.log(data);

});


看到控制台打印出:

UFace post ok


自此,我们的前后端调通了。


2.3 百度AI-人脸识别


在官方网站下载node SDK压缩包。


将下载的 api-node-sdk-version.zip 解压后,复制到工程文件夹中。


进入目录,运行 npm install 安装 sdk 依赖库。


在百度AI中申请好APPID;


继续到routes/index.js文件中,加入

var AipFace = require("baidu-ai").face;


var APP_ID = "994xxx7";

var API_KEY = "WqiVssssssxxvpC7xkAcK96Sf";

var SECRET_KEY = "4exxxxxHGOzy2bZThCyEM0h1";

 //这三个key记得替换为你申请的appid 


var client = new AipFace(APP_ID, API_KEY, SECRET_KEY);


上传本地的一张图片,调试下百度AI接口

var fs = require('fs');

var image = fs.readFileSync('assets/face/face.jpg');

var base64Img = new Buffer(image).toString('base64');


client.detect(base64Img).then(function(result) {  

     console.log(JSON.stringify(result)); 

});


终端打印出获取到的结果,接口获取成功。


2.4 前端上传一张图片,后端以此图片调用人脸识别,返回给前端结果



找到 views/index.ejs 文件,添加

<form id="uface">

    <input type="file" name="files" id="upload">

    <button type="button" onClick="uploadImg()">submit</button>

  </form>


 function uploadImg() {

      var formData = new FormData();

      formData.append("file", $("#upload")[0].files[0]);

      $.ajax({

        type: 'POST',

        url: './file/uploading',

        data: formData,

        processData: false,

        contentType: false,

        success: function(res) {

          var json = JSON.parse(res);

           createFace(json);

  //从后端获取到人脸检测到结果后,调用createFace函数,进行图片合成  

        }

      });

    };


    function createFace(json) {

      var jzimg = $('#jz')[0];

      var img = $('#target')[0];

      var canvas = $('#canvas')[0];

      var ctx = canvas.getContext('2d');


      var sx = json.result[0].location.left,

        sy = json.result[0].location.top,

        swidth = json.result[0].location.width,

        sheight = json.result[0].location.height;


      ctx.drawImage(img, sx, sy, swidth, sheight, 110, 160, 145, 125);

      ctx.globalCompositeOperation = 'source-over';

      ctx.drawImage(jzimg, 0, 0);


    //globalCompositeOperation = 'source-over';  这个是用来把抠出来到人脸,合成到军装里到关键设置,可以合成任意到图片,并保留图片到透明信息哦。

相当于ps里的图层叠加概念


    };


后端获取前端提交的图片,并通过百度AI接口调取识别结果;

找到routes/index.js文件,添加


var multiparty = require('multiparty');

var util=require('util');

var fs = require('fs');


router.post('/file/uploading', function(req, res, next) {


  var form = new multiparty.Form({

    uploadDir: './public/files/'

  });

 

  form.parse(req, function(err, fields, files) {

    var filesTmp = JSON.stringify(files, null, 2);


    if (err) {

      console.log('parse error: ' + err);

    } else {

      console.log('parse files: ' + filesTmp);


      var inputFile = files.file[0];

      var uploadedPath = inputFile.path;


      var image = fs.readFileSync(uploadedPath);

      var base64Img = new Buffer(image).toString('base64');


      client.detect(base64Img).then(function(result) {

          res.send(JSON.stringify(result));

      });


    };


  });


});



3 实验结果



把这张图,传给百度AI,识别出人脸的坐标范围。


先准备好一张军装图,


合成结果见下图:  

识别出人脸范围后,抠出来的人脸图如上。


合成的图像有点生硬,原因是2张图片的边缘没有进行融合,还有识别出来的人像图没有进行色调调整。


我们可以把之前准备好的军装图上做点处理,人脸中间增加带透明度的褐色部分,记得存为png格式。


再测试下结果,

是不是稍微好点,这里有个图像处理的问题,

为了更好的效果,我们需要把抠出来的人脸色调进行调整,并且进行一定的滤镜处理,使得人脸跟军装图融合后,较为统一。


在这里,我就暂时不做这一块处理啦。毕竟我只花了半天时间就实现了这个小demo。


下面还有一些合成的效果。

仅供娱乐。


哈哈哈

猜猜合成的图像都是哪些名人?欢迎留言


   近期热文推荐 : 


人工智能「 服装设计师 」上

人工智能「 服装设计师 」中




本公众号定期更新关于

设计师、程序员发挥创意

互相融合的指南、作品。


主要技术栈:

nodejs、react native、electron


欢迎关注,转发~


欢迎长按二维码

关注本号



您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存