AR人脸识别 Three

Posted aichitudousien

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AR人脸识别 Three相关的知识,希望对你有一定的参考价值。

@

概述

如有不明白的可以加QQ:2354528292;wx: aichitudousien
更多教学视频请访问:https://space.bilibili.com/236087412
源码获取:https://item.taobao.com/item.htm?spm=a21dvs.23580594.0.0.3c3a3d0d66B2fR&ft=t&id=714757394880

这一期来使用Three.js和tensorflow.js来完成一个AR人脸识别的项目,主要使用的前端框架为Vue,项目中主要的功能点有可以实现人脸替换,在摄像头检测检测到人脸后会将人脸替换成一个预先准备好的人脸模型,然后我们人脸移动和变化的时候模型会跟随移动和变化,在模型上我们可以画线,画logo, 可以自由作图,然后还具备返回上一步和删除的功能
先来看一下视频效果:

[video(video-oWcdKHJf-1635568682533)(type-csdn)(url-https://live.csdn.net/v/embed/179480)(image-https://vedu.csdnimg.cn/7a362f85990344878c15538d9e26373d/snapshots/fae2529810534d3ea3a3bee6ca4f8c72-00004.jpg)(title-AR人脸识别)]

tensorflow.js介绍

three.js库就不介绍了,相信大家也已经很熟悉了,主要来介绍一下tensorflow.js这个库。
Tensorflow.js是一个基于deeplearn.js构建的库,可直接在浏览器上创建深度学习模块。使用它可以在浏览器上创建CNN(卷积神经网络)、RNN(循环神经网络)等等,且可以使用终端的GPU处理能力训练这些模型。因此,可以不需要服务器GPU来训练神经网络。这一次我们就主要使用tensorflow.js来完成人脸识别。

项目搭建

前端框架是vue,版本使用的是2.6,three.js版本使用的124版本,tensorflow使用了@tensorflow-models/face-landmarks-detection,tensorflow/tfjs-backend-webgl, tensorflow/tfjs-converter,tensorflow/tfjs-core

初始化摄像头

前端界面很简单,就一点小图标就可以了,随便写一点样式就ok

  1. 在vue文件中调用init函数
let useCamera = true, video;
export async function init() 
	if (useCamera) 
     await setupCamera();
     video.play();
     video.width = video.videoWidth;
     video.height = video.videoHeight;
     await facemesh.init(video);
  	

  1. 设置相机参数
async function setupCamera() 
  video = document.createElement(\'video\');
  // navigator.mediaDevices.getUserMedia 提示用户给予使用媒体输入的许可,媒体输入会产生一个MediaStream,里面包含了请求的媒体类型的轨道。

  const stream = await navigator.mediaDevices.getUserMedia(
    // 关闭音频
    audio: false,
    video: 
      // 在移动设备上面,表示优先使用前置摄像头
      facingMode: \'user\',
      // 判断是否是移动端,如果是移动端就自适应,PC端为640*640
      width: mobile ? undefined : 640,
      height: mobile ? undefined : 640
    
  );
  
  video.srcObject = stream;
  return new Promise((resolve) => 
    // 在视频的元数据加载后执行 JavaScript
    video.onloadedmetadata = () => 
      resolve(video);
    ;
  );

  1. 初始化tensorflow
    tf.setBackend 设置负责创建张量并对这些张量执行操作的后端(cpu、webgl、wasm)等, 这里主要使用webgl,最大人脸识别数为1
const state = 
  backend: \'webgl\',
  maxFaces: 1
;
async function init(video) 
  // tf.setBackend 设置负责创建张量并对这些张量执行操作的后端(cpu、webgl、wasm等
  await tf.setBackend(state.backend);

  // facemesh.load 输入中检测到的最大人脸数
  model = await faceLandmarksDetection.load(
    faceLandmarksDetection.SupportedPackages.mediapipeFacemesh,
    
      maxFaces: state.maxFaces,
      detectorModelUrl: \'model/blazeface/model.json\',
      // 用于指定自定义 iris 模型 url 或tf.io.IOHandler对象的可选参数
      irisModelUrl: \'model/iris/model.json\',
      // 用于指定自定义 facemesh 模型 url 或tf.io.IOHandler对象的可选参数
      modelUrl: \'model/facemesh/model.json\'
    
  );

这里有一个大坑。detectorModelUrl,irisModelUrl,modelUrl如果不设置路径会自动去https://tfhub.dev/上获取人脸检测模型,但是这个网站在国内是无法访问的,所以我们需要修改一下路径,我们可以去https://hub.tensorflow.google.cn/网站上下载我们所需要的人脸检测模型,将包文件下载下来后替换对应的路径就可以了
具体的说明文档可以在此链接上找到:https://www.npmjs.com/package/@tensorflow-models/face-landmarks-detection

此时我们应该可以看到摄像头的运行状态已经开启了

初始化three.js

这里就是一个常规的初始化three.js的步骤,我们创建一个和video视频一样大的three.js场景

threeEl = await three.init(video);
async function init(video) 
  width = video ? video.width : 640;
  const height = video ? video.height : 640;
  const ratio = width / height;
  const fov = 50;
  const near = 1;
  const far = 5000;
  camera = new THREE.PerspectiveCamera(fov, ratio, near, far);
  camera.position.z = height;
  camera.position.x = -width / 2;
  camera.position.y = -height / 2;

  renderer = new THREE.WebGLRenderer( antialias: true, alpha: true );
  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.setSize(width, height);
  scene = new THREE.Scene();
  if (video) 
    // 创建video贴图
    addVideoSprite(video);
  

  // 初始化射线
  raycaster = new THREE.Raycaster();

  // 增加人脸模型
  await addObjMesh();

  return renderer.domElement;

关键步骤,将video作为贴图附加到小精灵上,这样我们就可以在three.js中呈现我们的视频了,到了这里项目实现的原理也已经可以明白了,通过video标签获取视频流,然后将视频流作为贴图附加到对应的mesh上,此时我们就可以做任何想做的事情了,添加模型,添加mesh,任何three.js可以完成的
增加mesh

function addVideoSprite(video) 
  videoTexture = new THREE.Texture(video);
  videoTexture.minFilter = THREE.LinearFilter;
  const videoSprite = new THREE.Sprite(
    new THREE.MeshBasicMaterial(
      map: videoTexture,
      depthWrite: false
    )
  );
  const width = video.width;
  const height = video.height;
  videoSprite.center.set(0.5, 0.5);
  videoSprite.scale.set(width, height, 1);
  videoSprite.position.copy(camera.position);
  videoSprite.position.z = 0;
  scene.add(videoSprite);

增加人脸模型

function addObjMesh() 
  const loader = new OBJLoader();
  return new Promise((resolve, reject) => 
    loader.load(\'model/facemesh.obj\', (obj) => 
      obj.traverse((child) => 
        if (child instanceof THREE.Mesh) 
          const mat = new THREE.MeshNormalMaterial(
            side: THREE.DoubleSide
          );
          if (!params.debug) 
            mat.transparent = true;
            mat.opacity = 0;
          
          baseMesh = new THREE.Mesh(child.geometry, mat);
          scene.add(baseMesh);
          resolve();
        
      );
    );
  );

生成了场景,也生成了小精灵,这是我们只要将场景渲染即可,在使用window.requestAnimationFrame(update)渲染的时候一定要更新我们的视频贴图,并将视频贴图的needsUpdate设置为true,不然是不会更新的

function update(facemesh) 
  if (videoTexture) 
    videoTexture.needsUpdate = true;
  

  renderer.render(scene, camera);

此时我们的界面中应该就可以看到实时视频了

ok,此我们来进行个实验,在视频的中间添加一个会旋转的box
代码很简单

var geometry = new THREE.BoxBufferGeometry( 200, 200, 200 );
var material = new THREE.MeshBasicMaterial( color: 0x00ff00, depthTest:false );
cube = new THREE.Mesh( geometry, material );
cube.position.copy(camera.position)
cube.position.z = 0;
scene.add( cube );

这样我们就可以看到我们的视频中间会出现一个box,那此时我们就可以思考了,我们手机里面的ar应用,比如拍摄到固定的位置出现一些模型,动画,或者图片i介绍,那我们是不是都可以完成了呢


这篇文章就介绍到这里,下一篇我们接着介绍如何生成人脸模型~

人脸识别---基于深度学习和稀疏表达的人脸识别算法

1 介绍

本文将介绍一种基于深度学习和稀疏表达的人脸识别算法。

首先。利用深度学习框架(VGGFace)提取人脸特征;其次,利用PCA对提取的特征进行降维;最后,利用稀疏表达分类实现特征匹配。我採用CMC曲线评价在AR数据库上的识别性能。最后我还提供了整个过程的code。


2 基于深度学习和稀疏表达的人脸识别算法

2.1 利用VGGFace提取人脸特征

以下介绍利用VGGFace对人脸特征进行提取。我们利用的数据库为AR数据库。数据库的图比例如以下:
技术分享
接下来我们利用VGGFace对人脸特征进行提取。

  • 我们利用Matconvent作为深度学习框架,Matconvent能够到http://www.vlfeat.org/matconvnet/上下载,我採用的1.0-beta19。也能够下载最新版本号。
  • VGGFace的deep model能够到http://www.robots.ox.ac.uk/~vgg/software/vgg_face/上进行下载,我採用的是Matconvnet的版本号。模型大概1.01G。
    如果VGGFace的模型为F,图片为x。那么提取的特征为y=F(x).

2.2 PCA对人脸特征进行降维

利用pca对数据降维,VGGFace提取出的特征为4096维。对提取的特征进行降维最后降到128维。

2.3 稀疏表达的人脸匹配

数据库一共同拥有C个人,每个人有k张图片,那么每个人的特征字典为Dc={fc1,fc2,,fck}, 那么C个人就组成一个Gallery特征字典D={D1,D2,?,DC}。给一定probe人脸x, 那么特征为y=F(x), 则稀疏表达能够有例如以下表达:

||x||1,Dx=y

当中x为稀疏编码。


最后我们能够利用稀疏表达分类器来识别这个probe人脸x:

mincrc(y)=||y?Dcδc(x)||22

3 Code

function cnn_vgg_faces()
%CNN_VGG_FACES  Demonstrates how to use VGG-Face
clear all
clc
addpath PCA
run(fullfile(fileparts(mfilename(‘fullpath‘)),...
    ‘..‘, ‘matlab‘, ‘vl_setupnn.m‘)) ;
net = load(‘data/models/vgg-face.mat‘) ;
list = dir(‘../data/AR‘);
C = 100;
img_list = list(3:end);
index = [1, 10];
%% 建立基于VGGFace的Gallery字典
dictionary = [];
for i = 1:C
    disp(i)
    numEachGalImg(i) = 0;
    for j = 1:2
        im = imread(strcat(‘../data/AR/‘,img_list((i-1)*26+index(j)).name));
        im_ = single(im) ; % note: 255 range
        im_ = imresize(im_, net.meta.normalization.imageSize(1:2)) ;
        for k = 1:3
            im1_(:,:,k) = im_;
        end
        im2_ = bsxfun(@minus,im1_,net.meta.normalization.averageImage) ;
        res = vl_simplenn(net, im2_) ;
        feature_p(:,j) = res(36).x(:);
    end
    numEachGalImg(i) = numEachGalImg(i) + size(feature_p,2);
    dictionary = [dictionary feature_p];
end
%% PCA对特征进行降维
FaceContainer = double(dictionary‘);
[pcaFaces W meanVec] = fastPCA(FaceContainer,128);
X = pcaFaces;
[X,A0,B0] = scaling(X);
LFWparameter.mean = meanVec;
LFWparameter.A = A0;
LFWparameter.B = B0;
LFWparameter.V = W;
imfo = LFWparameter;
train_fea = (double(FaceContainer)-repmat(imfo.mean, size(FaceContainer,1), 1))*imfo.V;
dictionary = scaling(train_fea,1,imfo.A,imfo.B);
for i = 1:size(dictionary, 1)
    dictionary(i,:) = dictionary(i,:)/norm(dictionary(i,:));
end
dictionary = double(dictionary);
totalGalKeys = sum(numEachGalImg);
cumNumEachGalImg = [0; cumsum(numEachGalImg‘)];

%% 利用稀疏编码进行特征匹配
% sparse coding parameters
if ~exist(‘opt_choice‘, ‘var‘)
    opt_choice = 1;
end
num_bases = 128;
beta = 0.4;
batch_size = size(dictionary, 1);
num_iters = 5;
if opt_choice==1
    sparsity_func= ‘L1‘;
    epsilon = [];
elseif opt_choice==2
    sparsity_func= ‘epsL1‘;
    epsilon = 0.01;
end

Binit = [];

fname_save = sprintf(‘../results/sc_%s_b%d_beta%g_%s‘, sparsity_func, num_bases, beta, datestr(now, 30));

AtA = dictionary*dictionary‘;
for i = 1:C
    fprintf(‘%s  \n‘,num2str(i));
    tic
    im = imread(strcat(‘../data/AR/‘,img_list((i-1)*26+26).name));
    im_ = single(im) ; % note: 255 range
    im_ = imresize(im_, net.meta.normalization.imageSize(1:2)) ;
    for k = 1:3
        im1_(:,:,k) = im_;
    end
    im2_ = bsxfun(@minus,im1_,net.meta.normalization.averageImage) ;
    res = vl_simplenn(net, im2_) ;
    feature_p = res(36).x(:);
    feature_p  = (double(feature_p)‘-imfo.mean)*imfo.V;
    feature_p = scaling(feature_p,1,imfo.A,imfo.B);
    feature_p = feature_p/norm(feature_p, 2);
    [B S stat] = sparse_coding(AtA,0, dictionary‘, double(feature_p‘), num_bases, beta, sparsity_func, epsilon, num_iters, batch_size, fname_save, Binit);
    for m = 1:length(numEachGalImg)
        AA = S(cumNumEachGalImg(m)+1:cumNumEachGalImg(m+1),:);
        X1 = dictionary(cumNumEachGalImg(m)+1:cumNumEachGalImg(m+1),:);
        recovery = X1‘*AA;
        YY(m) = mean(sum((recovery‘-double(feature_p)).^2));
    end
    score(:,i) = YY;
    toc
end
accuracy = calrank(score1,1:1,‘ascend‘);
fprintf(‘rank-1:%d/%%\n‘,accuracy*100);

文中以
calrank能够计算得到CMC曲线:參见http://blog.csdn.net/hlx371240/article/details/53482752
最后得到rank-1为82%。
整个代码见资源,因为vgg-face 太大,能够自己到vgg的官网下载,然后放到../matconvnet-1.0-beta19\examples\data\models中。

以上是关于AR人脸识别 Three的主要内容,如果未能解决你的问题,请参考以下文章

毕业设计/Matlab系列基于PCA和BP神经网络的人脸识别系统(基于AR人脸库)

毕业设计/Matlab系列基于PCA和BP神经网络的人脸识别系统(基于AR人脸库)

基于Python PCA+SVM+KFold方法人脸识别(AR人脸数据集)

基于卷积神经网络的人脸表情识别应用--AR川剧变脸

人脸实时签到(three.js+tracking.js)基于浏览器

人脸识别---基于深度学习和稀疏表达的人脸识别算法