<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>人脸检测 &#8211; 萧邦的博客</title>
	<atom:link href="https://www.zlhlab.top/tag/%e4%ba%ba%e8%84%b8%e6%a3%80%e6%b5%8b/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.zlhlab.top</link>
	<description>If not me who, If not now when</description>
	<lastBuildDate>Thu, 07 Sep 2017 15:39:27 +0000</lastBuildDate>
	<language>zh-Hans</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.8.6</generator>
	<item>
		<title>Face++人脸检测与识别初试</title>
		<link>https://www.zlhlab.top/face%e4%ba%ba%e8%84%b8%e6%a3%80%e6%b5%8b%e4%b8%8e%e8%af%86%e5%88%ab%e5%88%9d%e8%af%95/</link>
		
		<dc:creator><![CDATA[萧邦]]></dc:creator>
		<pubDate>Thu, 07 Sep 2017 15:37:14 +0000</pubDate>
				<category><![CDATA[技术]]></category>
		<category><![CDATA[canvas]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[人脸检测]]></category>
		<guid isPermaLink="false">https://www.zlhlab.top/?p=292</guid>

					<description><![CDATA[项目背景： 最近被人民日报换军装的H5刷爆朋友圈，于是有汽车厂商想做类似的项目。用于旅游照片换脸分享朋友圈，植<div class="more-link">
				 <a href="https://www.zlhlab.top/face%e4%ba%ba%e8%84%b8%e6%a3%80%e6%b5%8b%e4%b8%8e%e8%af%86%e5%88%ab%e5%88%9d%e8%af%95/" class="link-btn theme-btn"><span>Read More </span> <i class="fa fa-caret-right"></i></a>
			</div>]]></description>
										<content:encoded><![CDATA[<h4>项目背景：</h4>
<p>最近被人民日报换军装的H5刷爆朋友圈，于是有汽车厂商想做类似的项目。用于旅游照片换脸分享朋友圈，植入汽车公众号进行宣传。</p>
<p>可是之前没有类似的项目经验，于是搜集相关代码和当前人脸识别市场进行调研。主要有以下几大阵营：</p>
<blockquote>
<ol>
<li>Face++<a href="https://www.faceplusplus.com.cn/" title="https://www.faceplusplus.com.cn/" target="_blank">https://www.faceplusplus.com.cn/</a></li>
<li>腾讯优图和天天P图。天天P图和腾讯优图是不同部门负责<a href="http://open.youtu.qq.com/welcome/experience" title="http://open.youtu.qq.com/welcome/experience" target="_blank">http://open.youtu.qq.com/welcome/experience</a></li>
<li>百度AI开发平台<a href="http://ai.baidu.com/tech/face" title="http://ai.baidu.com/tech/face" target="_blank">http://ai.baidu.com/tech/face</a></li>
<li>其他阵营，如美图秀秀等</li>
</ol>
</blockquote>
<p>人民日报换军装的H5，就是由天天P图公司制作的。</p>
<h4>对比API和技术支持</h4>
<p>Face++、腾迅优图API以及百度AI平台图像处理方面产品线都比较全，都在进行产品线更新。</p>
<ol>
<li>首先联系的Face++, Face++不支持换军装定制开发。</li>
<li>然后联系腾讯优图，说会转个天天P图的同事，然后一直没有回音。</li>
<li>最后在腾讯优图找到了换军装的Demo，里面找到了作者联系方式，报价10+万。</li>
<li>没有联系百度公司。</li>
</ol>
<p>估计成本太高，客户后面就没有了反馈。<br />
等待总是漫长的，作为技术总是爱折腾和尝试。以下是进行的折腾之旅：</p>
<h4>思路一 Face++背景融合：</h4>
<p>用户上传个人全身照，选择场景进行图片叠加处理。</p>
<h5>1. 注册开发者获取api_key和api_secret</h5>
<p>进行接口权限认证和数据请求需要用到。</p>
<h5>2. 上传原始图片</h5>
<p><a href="https://www.zlhlab.top/wp-content/uploads/2017/09/facetest2.jpg" title="facetest2" target="_blank"><img decoding="async" src="https://www.zlhlab.top/wp-content/uploads/2017/09/facetest2.jpg" alt="facetest2" title="facetest2"></a></p>
<h5>3. 获取灰度图</h5>
<p>发送原始图片，获取返回的灰度图。</p>
<pre class="line-numbers prism-highlight" data-start="1"><code class="language-javascript">var params = $('form').serializeArray();
$.ajax({
    url: 'https://api-cn.faceplusplus.com/humanbodypp/beta/segment',
    type: 'POST',
    data: params,
    dataType: 'json',
    success: function(data){
        console.log(data);
        var grayImg =  'data:image/jpeg;base64,'+data.result;
        $('#resultImg').attr('src', grayImg);
        $('#addedImg').attr('src', clipImgWithGrayImg( grayImg));
    },
    error: function (msg) {
        console.log(msg);
    }
});
</code></pre>
<p>调用接口返回二进制数据流，增加<code>data:image/jpeg;base64,</code>前缀，即可使用<code>img</code>读取图片。</p>
<p><a href="https://www.zlhlab.top/wp-content/uploads/2017/09/2Q.jpg" title="灰度图" target="_blank"><img decoding="async" src="https://www.zlhlab.top/wp-content/uploads/2017/09/2Q.jpg" alt="灰度图" title="灰度图"></a></p>
<h5>4. 裁剪原始图片与背景图片融合</h5>
<p>根据获取的灰度图，使用canvas对原图进行像素级操作，裁剪原图。针对非人像部分，进行像素透明操作。可以进行对边界部分进行参数调节操作，如下：</p>
<pre class="line-numbers prism-highlight" data-start="1"><code class="language-javascript">&lt;!-- 已知灰度图裁切原始图片 --&gt;
function clipImgWithGrayImg(grayImg) {
    var canvas = document.getElementById("myCanvas");
    var image = document.getElementById("resultImg");
    image.crossOrigin="Anonymous";

    &lt;!-- 将得到的图像绘制在Canvas对象中的代码如下：--&gt;
        canvas.width=image.width;
    canvas.height=image.height;
    var ctx=canvas.getContext("2d");
    ctx.drawImage(image, 0, 0);
    &lt;!-- 从Canvas对象中获取图像像素数据的代码如下：--&gt;

        var canvasData = ctx.getImageData(0, 0, canvas.width, canvas.height);
    &lt;!-- 读取像素值与实现灰度计算的代码如下：--&gt;

        for ( var x = 0; x &lt; canvasData.width; x++) {
            for ( var y = 0; y &lt; canvasData.height; y++) {

                // Index of the pixel in the array
                var idx = (x + y * canvasData.width) * 4;
                var r = canvasData.data[idx + 0];
                var g = canvasData.data[idx + 1];
                var b = canvasData.data[idx + 2];

                if (r &lt; 128 || g &lt; 128 || b &lt; 128) {
                    canvasData.data[idx + 3] = 0; // Alpha channel
                }
            }
        }

    var data = canvasData.data;
    ctx.clearRect(0,0, canvas.width, canvas.height);
    var srcImage = document.getElementById("srcImg");
    ctx.drawImage(srcImage, 0, 0);
    srcImage.crossOrigin="Anonymous";

    &lt;!-- 从Canvas对象中获取图像像素数据的代码如下：--&gt;
        var canvasData2 = ctx.getImageData(0, 0, canvas.width, canvas.height);

    for ( var j = 0; j &lt; canvasData2.width; j++) {
        for ( var k = 0; k &lt; canvasData2.height; k++) {
            // Index of the pixel in the array
            var idx = (j + k * canvasData2.width) * 4;
            canvasData2.data[idx + 3] = data[idx + 3];
        }
    }

    ctx.putImageData(canvasData2,0,0);
    return canvas.toDataURL();
}

</code></pre>
<p>与背景图合成结果：</p>
<p><a href="https://www.zlhlab.top/wp-content/uploads/2017/09/4R@3TD56IKKS46T6DC1.png" title="图像融合" target="_blank"><img decoding="async" src="https://www.zlhlab.top/wp-content/uploads/2017/09/4R@3TD56IKKS46T6DC1.png" alt="图像融合" title="图像融合"></a></p>
<p>总结：边界判断还需要优化，不能够满足商用的完美融合需求。</p>
<h4>思路二 人脸检测与人脸替换：</h4>
<p>使用换脸的正常流程： 人脸检测&#8211;&gt;人脸特征提取&#8211;&gt;模型脸型匹配&#8211;&gt;替换人脸&#8211;&gt;肤色更换</p>
<h5>1. 获取人脸检测数据</h5>
<p>上传图片，调用人脸检测的接口，获取人脸特征数。</p>
<pre class="line-numbers prism-highlight" data-start="1"><code class="language-javascript">var params = $('form').serializeArray();
$.ajax({
    url: 'https://api-cn.faceplusplus.com/facepp/v3/detect', // 人脸检测API
    type: 'POST',
    data: params,
    dataType: 'json',
    crossDomain: true,
    success: function(data){
        console.log(data);
        if (data.faces.length &gt; 0) {
            drawFace(data.faces[0].face_rectangle, data.faces[0].landmark);
        }
    },
    error: function (msg) {
        console.log(msg);
    }
});
</code></pre>
<h5>2. 识别人脸</h5>
<p>调用Face++人脸识别接口，返回的特征可以正常匹配，但是人脸的位置异常。</p>
<p><a href="https://www.zlhlab.top/wp-content/uploads/2017/09/WL311WKAIBD_2S1@9HW.png" title="人脸识别" target="_blank"><img decoding="async" src="https://www.zlhlab.top/wp-content/uploads/2017/09/WL311WKAIBD_2S1@9HW.png" alt="人脸识别" title="人脸识别"></a></p>
<p>代码如下：</p>
<pre class="line-numbers prism-highlight" data-start="1"><code class="language-javascript">&lt;!-- 显示面部区域draw face --&gt;
function drawFace(rect, landmark) {
    var canvas = document.getElementById("myCanvas");
    var image = document.getElementById("srcImg");
    image.crossOrigin="Anonymous";
    var points = [
        {'x': landmark.contour_left1.x, 'y':landmark.contour_left1.y},
        {'x': landmark.contour_left2.x, 'y':landmark.contour_left2.y},
        {'x': landmark.contour_left3.x, 'y':landmark.contour_left3.y},
        {'x': landmark.contour_left4.x, 'y':landmark.contour_left4.y},
        {'x': landmark.contour_left5.x, 'y':landmark.contour_left5.y},
        {'x': landmark.contour_left6.x, 'y':landmark.contour_left6.y},
        {'x': landmark.contour_left7.x, 'y':landmark.contour_left7.y},
        {'x': landmark.contour_left8.x, 'y':landmark.contour_left8.y},
        {'x': landmark.contour_left9.x, 'y':landmark.contour_left9.y},
        {'x': landmark.contour_chin.x, 'y':landmark.contour_chin.y},
        {'x': landmark.contour_right9.x, 'y':landmark.contour_right9.y},
        {'x': landmark.contour_right8.x, 'y':landmark.contour_right8.y},
        {'x': landmark.contour_right7.x, 'y':landmark.contour_right7.y},
        {'x': landmark.contour_right6.x, 'y':landmark.contour_right6.y},
        {'x': landmark.contour_right5.x, 'y':landmark.contour_right5.y},
        {'x': landmark.contour_right4.x, 'y':landmark.contour_right4.y},
        {'x': landmark.contour_right3.x, 'y':landmark.contour_right3.y},
        {'x': landmark.contour_right2.x, 'y':landmark.contour_right2.y},
        {'x': landmark.contour_right1.x, 'y':landmark.contour_right1.y},
        {'x': landmark.right_eyebrow_right_corner.x, 'y':landmark.right_eyebrow_right_corner.y},
        {'x': landmark.right_eyebrow_upper_middle.x, 'y':landmark.right_eyebrow_upper_middle.y},
        {'x': landmark.left_eyebrow_upper_middle.x, 'y':landmark.left_eyebrow_upper_middle.y},
        {'x': landmark.left_eyebrow_left_corner.x, 'y':landmark.left_eyebrow_left_corner.y}
    ];

    &lt;!-- 将得到的图像绘制在Canvas对象中的代码如下：--&gt;
        canvas.width=image.width;
    canvas.height=image.height;
    var ctx=canvas.getContext("2d");
    ctx.drawImage(image, 0, 0);
    ctx.beginPath();
    ctx.rect(rect.top, rect.left, rect.width, rect.height);
    $.each(points, function (index, item) {
        if (index === 0) {
            ctx.moveTo(item.x, item.y);
        } else {
            ctx.lineTo(item.x, item.y);
        }
    });
    ctx.closePath();
    ctx.strokeStyle = "green";
    ctx.stroke();
}
</code></pre>
<h5>3. 人脸替换</h5>
<p>待完成</p>
<h5>4. 制作滤镜，更换肤色</h5>
<p>待完成</p>
<h4>总结</h4>
<p>换脸H5中，还是有过程需要完成。当前主要涉及Face++的接口调用和Canvas图片处理能力。商用过程，还有很多情况需要考虑，比如人脸位置检测与校验、滤镜换肤。听说腾讯优图1个月左右会开放换脸API，敬请期待。</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
