html 识别主题,用HTML5实现人脸识别-用Javascript实现人脸美容

在人脸识别的基础上,我们将使用纯Javascript来实现如下的功能:

识别和标注人脸以及五官

32999944710f7202a3b25e5eedfbcf54.png

对人脸进行美容

afd604834a024edff93a78209e12df58.png

从本文的内容中,你将意识到,Javascript能做的,能实现的,远远比你想象的多。

cca5d5f7c7772fc400a7386e9ca463fe.png

演示

一、实现

1、人脸识别

Face.com有包括检测、识别在内的多个API接口,根据《 用 HTML5 实现人脸识别 》一文,我们已经可以实现图片上传,并得到检测的结果,结果如下:

660a58e02365b472f80364aef0e81488.png

返回的参数

返回参数的详细解释参见 http://developers.face.com/docs/api/return-values/ ,其中tags为多张照片的识别结果,每一个结果包括了耳朵、眼睛、嘴、鼻的中心位置,以及年龄、性别、是否佩戴眼镜、情绪、是否在笑等多种信息。

上传图片并请求接口的代码如下。

function buildRequest(imgSrc) {

document.getElementById("detect") .disabled = true ;

document.getElementById("beauty") .disabled = true ;

var canvas = document .getElementById(‘canvas’);

var ctx = canvas .getContext(‘2d’);

var imgObj = new Image();

imgObj.src = imgSrc ;

canvas.width = imgObj .width;

canvas.height = imgObj .height;

ctx.drawImage(imgObj, 0, 0);

var imgPixels = ctx .getImageData(0, 0, canvas.width, canvas.height);

document.getElementById("bigImg") .style.width = imgObj .width;

var data = canvas .toDataURL(‘image/jpeg’, 1.0);

newblob = dataURItoBlob (data);

var formdata = new FormData();

formdata.append("api_key", "your key");

formdata.append("api_secret", "your secret");

formdata.append("filename","avatar.jpg");

formdata.append("file",newblob);

$.ajax({

url: ‘http://api.face.com/faces/detect.json? attributes = age_est ,gender,mood,smiling,glasses’,

data: formdata,

cache: false,

contentType: false,

processData: false,

dataType:"json",

type: ‘POST’,

success: function (data) {

handleResult(data.photos[0]);

}

});

}

人脸标注

我们将根据人脸识别的结果对五官和面部进行标注。标注的方式有两种,一种是基于Canvas的绘图,一种是传统DIV方式标注。下面我们采用第二种方式,原理是在各个点上画一个3*3的DIV,DIV的背景色为红色,采用绝对定位。接口返回的五官数值为宽高所在点的百分比值,所以需要先进行换算。

标注五官的方法如下:

function drawFacial(data) {

var width = data .width;

var height = data .height;

var points = ["eye_left", "eye_right", "mouth_left", "mouth_center", "mouth_right", "nose", "ear_left", "ear_right"];

for(var i = 0 ; i < points.length ; i++) {

var div = document .createElement(‘div’);

div.style.width = "3px" ;

div.style.height = "3px" ;

div.style.backgroundColor = "red" ;

div.style.position = "absolute" ;

div.className = "facePoint" ;

var values = data .tags[0][points[i]];

if(values != null) {

var left_x = values .x;

div.style.left = left_x * width / 100 – 1 + "px";

var left_y = values .y;

div.style.top = left_y * height / 100 – 1 + "px";

document.body.appendChild(div);

}

}

}

标注人脸区域的方法如下:

function drawFace(data) {

var width = data .width;

var height = data .height;

var faceWidth = data .tags[0].width * width / 100;

var faceHeight = data .tags[0].height * height / 100;

var faceCenter = data .tags[0].center;

var div = document .createElement(‘div’);

div.style.width = faceWidth + "px";

div.style.height = faceHeight + "px";

div.style.borderColor = "red" ;

div.style.borderWidth = "1px" ;

div.style.borderStyle = "dotted" ;

div.style.position = "absolute" ;

div.className = "faceBox" ;

div.style.left = faceCenter .x * width / 100 – faceWidth / 2 – 1 + "px";

div.style.top = faceCenter .y * height / 100 – faceHeight / 2 – 1 + "px";

document.body.appendChild(div);

}

从结果来看,Face.com的检测结果非常精准。

人脸美容

对人脸我们采用两种效果叠加进行美容,分别是增加亮度和模糊度,这样可以让人脸看起来更白,皮肤更好。

1、  增加亮度

增加亮度其实非常简单,只需要在像素点的RGB通道上增加一个固定的值。代码如下:

var imgPixels = ctx .getImageData(faceLeft, faceTop, faceWidth, faceHeight);

var data = imgPixels .data;

adjustment = 5 ;

for (var i = 0 ; i < data.length ; i += 4) {

data[i] += adjustment;

data[i+1] += adjustment;

data[i+2] += adjustment;

}

2、  添加模糊效果

模糊效果较为复杂,平常我们常用到的包括均值模糊和高斯模糊。在HTML5Rocks上有一篇很棒的文章《 IMAGE FILTERSWITH CANVAS 》,里面有各种图像处理效果,我们可以直接应用里面的模糊效果(也即3*3的均值模糊)。

0da799c486fd79bd3fe15c16dba075df.png

原图

291ca33d8e2be0b4e896dbbec015c341.png

锐化

325f8aa8f56a1a9bb56d51aa6f91dc6f.png

索贝尔滤镜

代码如下:

var Filters = {};

Filters.convolute = function (pixels, weights, opaque) {

var side = Math .round(Math.sqrt(weights.length));

var halfSide = Math .floor(side/2);

var src = pixels .data;

var sw = pixels .width;

var sh = pixels .height;

// pad output by the convolution matrix

var w = sw ;

var h = sh ;

var output = Filters .createImageData(w, h);

var dst = output .data;

// go through the destination image pixels

var alphaFac = opaque ? 1 : 0;

for (var y = 0 ; y < h ; y++) {

for (var x = 0 ; x < w ; x++) {

var sy = y ;

var sx = x ;

var dstOff = (y*w+x)*4;

// calculate the weighed sum of the source image pixels that

// fall under the convolution matrix

var r = 0 , g = 0 , b = 0 , a = 0 ;

for (var cy = 0 ; cy < side ; cy++) {

for (var cx = 0 ; cx < side ; cx++) {

var scy = sy + cy – halfSide;

var scx = sx + cx – halfSide;

if (scy > = 0 && scy < sh && scx > = 0 && scx < sw ) {

var srcOff = (scy*sw+scx)*4;

var wt = weights [cy*side+cx];

r += src[srcOff] * wt;

g += src[srcOff+1] * wt;

b += src[srcOff+2] * wt;

a += src[srcOff+3] * wt;

}

}

}

dst[dstOff] = r;

dst[dstOff+1] = g;

dst[dstOff+2] = b;

dst[dstOff+3] = a + alphaFac*(255-a);

}

}

return output;

};

Filters.tmpCanvas = document .createElement(‘canvas’);

Filters.tmpCtx = Filters .tmpCanvas.getContext(‘2d’);

Filters.createImageData = function (w,h) {

return this.tmpCtx.createImageData(w,h);

};

最后对Canvas里的图像叠加两种效果的代码如下:

var width = data .width;

var height = data .height;

var faceWidth = data .tags[0].width * width / 100;

var faceHeight = data .tags[0].height * height / 100;

var faceCenter = data .tags[0].center;

var faceLeft = faceCenter .x * width / 100 – faceWidth / 2;

var faceTop = faceCenter .y * height / 100 – faceHeight / 2;

var canvas = document .getElementById(‘canvas’);

var ctx = canvas .getContext(‘2d’);

var imgPixels = ctx .getImageData(faceLeft, faceTop, faceWidth, faceHeight);

var data = imgPixels .data;

adjustment = 5 ;

for (var i = 0 ; i < data.length ; i += 4) {

data[i] += adjustment;

data[i+1] += adjustment;

data[i+2] += adjustment;

}

imgPixels = Filters .convolute(imgPixels, [ 1/9, 1/9, 1/9,

1/9, 1/9, 1/9,

1/9, 1/9, 1/9 ], 1);

ctx.putImageData(imgPixels, faceLeft, faceTop, 1, 1, faceWidth – 3, faceHeight – 3);

这样,我们完成了所有的代码。是不是相当的有成就感?看起来我们完成了相当新颖而酷炫的工作。

二、思考

1、  美容滤镜是否有其他实现的方式?

之前我介绍过CSS3滤镜,它有虚化和亮度调节两个方法可以方便直接的为图片添加滤镜效果,可以在《 遇见 CSS3 滤镜 》这篇文章里了解到。

2、我们还可以实现哪些美容效果?

1)去红眼

检测到眼睛位置后,我们可以采用一定范围内的滤镜,把这个范围内的红色转换为黑色,从而实现去红眼效果。

2)眼睛放大

检测到眼睛位置后,我们还可以采用一定的算法,实现眼睛放大的效果。要体验这个效果,可以下载 百度魔图 客户端体验。

35d2fd75b3c4fa08957112f7d3872237.png

百度魔图-强大的图片处理客户端

3)背景虚化

背景虚化效果基本和我们文中提到的效果是相反的方式。

3、  文中的效果是否还可以优化?

例如是否可以把文中美容的区域将正方形变为椭圆形,更为贴近人脸的形状?其实并不难,读者有兴趣可深入思考和实现。

4、  除了美容,我们还能完成什么样的功能?

Face.com提供了三个功能演示:人脸Tag、情景照片、人脸查找。对于应用开发者来说,从来不缺乏创意,例如Face.com图片检测返回的参数里包括图片旋转角度,我们可以利用这个参数实现图片批量自动旋转的功能(我最近在整理旅游的照片时就深深的理解了这个功能的便利性和必要性)。或者基于微博的图片爱情速配App?我期待更有创意和使用价值idea的出现。

欢迎加入我爱机器学习QQ14群:336582044

getqrcode.jpg

微信扫一扫,关注我爱机器学习公众号

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值