【WebAR】微信小程序3D、小程序AR、小程序AI等开源项目2021年3月份更新

前言

2019年7月,微信小程序宣布支持AR,笔者陆续地开发了AR、AI、3D等3个开源项目。

HTML5网页支持开发AR、AI和3D,读者会问“为什么不在小程序内嵌HTML5网页”?

因为iOS版微信中的HTML5网页不能打开手机摄像头,所以无法实现摄像头画面和虚拟模型叠加的AR效果。

Android版微信中的HTML5网页能打开手机摄像头,但其他AR开源项目是用C++编译为JavaScript,需要解决小程序的每个分包大小不能超过2MB和小程序的浏览器兼容性等问题。

一、开源项目介绍

《微信小程序3D》:在小程序中显示全景图片和3D模型,可跟随手机陀螺仪自动旋转。

sanyuered/WeChat-MiniProgram-AR-3D

《微信小程序AI》:在小程序中检测人脸特征点,并在面部位置显示3D模型或2D图像贴纸。

sanyuered/WeChat-MiniProgram-AR-TFJS

《微信小程序AR》:在小程序中检测识别图像,并在识别图像上显示2D图像贴纸。

sanyuered/WeChat-MiniProgram-WebAR

二、更新内容

《微信小程序3D》

1、通过扫描3D模型网址的二维码,替换3D模型。

2、场景中增加了光源使模型有阴影底纹。

3、设置设备像素密度(device pixel ratio)使全景图片显示更清晰等。

《微信小程序AI》

1、将人脸贴纸从2D显示改为3D显示。包含3D眼镜模型和2D猫胡须图像的演示。

2、修改了人脸检测方法:移除了face-api.js库,改为使用google的face-landmarks-detection库。

3、tensorflow.js的版本从1.x版升级到2.1版。

《微信小程序AR》

1、可以将2D图像或3D模型叠加在识别图像上。

2、该项目的人脸检测方法比开源项目《微信小程序AI》的人脸检测方法慢。

3、iOS版本的相机实时检测的速度非常慢,大约每帧3秒,去掉了实时检测的演示。

三、技术实现

1、怎样根据人脸特征点,将3D眼镜模型叠加在相机画面中的眼睛位置?

平移值:从人脸特征点映射图中,选择一个特征点,深度学习模型会检测出该特征点在世界坐标系的坐标。因为该模型没有特征点在双眼中间位置,所以挑选了双眼内侧的3个特征点,通过计算三角形的中心,表示3D模型的位置center。

    var triangle = new THREE.Triangle();
    triangle.set(p0, p1, p2);
    const center = new THREE.Vector3();
    triangle.getMidpoint(center);

旋转值:通过双眼内侧的3个特征点,计算3D模型的旋转值rotation。

    const rotation = new THREE.Matrix4();
    const x = p1.clone().sub(p2).normalize();
    const y = p1.clone().sub(p0).normalize();
    const z = new THREE.Vector3().crossVectors(x, y);
    const y2 = new THREE.Vector3().crossVectors(x, z).normalize();
    const z2 = new THREE.Vector3().crossVectors(x, y2).normalize();
    rotation.makeBasis(x, y2, z2);

缩放值:通过变换前和变换后2个特征点之间的距离,得到3D模型的缩放值scale。(粗略的估计)

    var p1 = prediction.mesh[id1];
    var p1_scaled = prediction.scaledMesh[id1];
    var p2 = prediction.mesh[id2];
    var p2_scaled = prediction.scaledMesh[id2];

    var a = p2[0] - p1[0];
    var b = p2_scaled[0] - p1_scaled[0];
    var scale = b / a;

2、怎样根据图像特征点,将2D猫胡须图像叠加在相机画面中的嘴巴位置?

平移值:从识别图像中选择一个叠加猫胡须的坐标A(x,y),根据图像的变换矩阵H(3x3单应性矩阵),计算该坐标在相机画面中的坐标B(_x,_y)。

    var m00 = td[0], m01 = td[1], m02 = td[2],
        m10 = td[3], m11 = td[4], m12 = td[5],
        m20 = td[6], m21 = td[7], m22 = td[8];
    var x2 = m00 * x + m01 * y + m02;
    var y2 = m10 * x + m11 * y + m12;
    var ws = m20 * x + m21 * y + m22;
    var sc = 1.0 / ws;
    var _x = x2 * sc;
    var _y = y2 * sc;
    return { _x, _y };

旋转和缩放值:根据图像的变换矩阵H(3x3单应性矩阵),计算图像的旋转值rotation和缩放值scale。

    var m00 = td[0],
        m10 = td[3],
        m20 = td[6];
    var norm = Math.sqrt(m00 * m00 +
        m10 * m10 +
        m20 * m20);
    var H = td.map(function (item) {
        return item / norm;
    });
    m00 = H[0];
    m10 = H[3];
    m20 = H[6];
    var m01 = H[1], m02 = H[2],
        m11 = H[4], m12 = H[5],
        m21 = H[7], m22 = H[8];
    var c1 = [m00, m10, m20];
    var c2 = [m01, m11, m21];
    var c3 = [
        m21 * m10 - m20 * m11,
        m20 * m01 - m21 * m00,
        m00 * m11 - m10 * m01];
    var rotation =
        [
        c1[0], c2[0], c3[0], 0,
        c1[1], c2[1], c3[1], 0,
        c1[2], c2[2], c3[2], 0,
            0,     0,     0, 1
        ];
    var scale = 1 / m22;

四、3个开源项目之间的关系

界面显示:《微信小程序3D》

人脸检测:《微信小程序AI》

图像检测:《微信小程序AR》

编辑于 2021-09-08 02:26