admin 发布的文章

方案一、图形学渲染技术

这种方法的优点是驱动人物快速,不需要合成视频。这种方式又可以分为两种,一种是把3d模型放到客户端,一种是把模型放到服务器端。

1.把模型放到客户端(不对应口型)

(1)实现方式

这种方式还有一种更简单的方法,比如让设计师设计几个gif图片,或者矢量图,开口讲话的时候一张图片,不开口讲话的时候另一张图片。

把模型放到客户端的方式,可以用3d模型工具,例如:Blender、Maya或3ds Max,ue5等,生成一个比较小的3d模型,用户每次加载的时候,放到客户端(h5),模型大小大概10多M,可以通过前端js,three.js来控制模型。

(2)实现的样例

1)中国电信:
微信图片_20231115175419.jpg

https://szr.ai.chinatelecom.cn:8093/
2)一个demo
微信截图_20231115175510.png
https://manghe151.sxqichuangkeji.com/h5/Digital1.html
到我的文件夹下看视频,以及数字人模型
在线数字人转换工具:https://3dconvert.nsdt.cloud/conv/to/glb

(3)相关技术文档

模型实例参考:https://manghe151.sxqichuangkeji.com/h5/Digital1.html
参考实现方式:https://blog.csdn.net/weixin_48594833/article/details/132598537
参考代码:

<!DOCTYPE html>
<!-- saved from url=(0053)https://manghe151.sxqichuangkeji.com/h5/Digital1.html -->
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        
        <title></title>
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <script async="" src="./manghe151.sxqichuangkeji.com_h5_Digital1_files/es-module-shims.js"></script>
        <style>
            .dbox {
                width: 100vw;
                height: 100vh;
                box-sizing: border-box;
            }
            * {
                margin: 0px;
            }
        </style>
    </head>
    <body>
        <div class="dbox" id="dbox">

        <canvas data-engine="three.js r148" width="1914" height="936" style="display: block; width: 1914px; height: 936px;"></canvas></div>
    
    <script src="./manghe151.sxqichuangkeji.com_h5_Digital1_files/uni.webview.1.5.2.js"></script> 
     <script>
//         {type="importmap"
//             "imports": {
//                 "three": "./three/build/three.module.js"
//             }
//         }
     </script>
    <script type="module">        
         import * as THREE from "./three/build/three.module.js";
        
        import {
            GLTFLoader
        } from './three/jsm/loaders/GLTFLoader.js';
        import { DRACOLoader    } from './three/jsm/loaders/DRACOLoader.js';

        
        let h = document.getElementById("dbox").clientHeight;
        let w = document.getElementById("dbox").clientWidth;
        //创建一个三维场景
        const scene = new THREE.Scene();
        //创建一个长方体


        //创建相机
        const camera = new THREE.PerspectiveCamera(45, w / h, 0.1, 4000);
        camera.position.set(0, 0.6, 3.8);
        camera.lookAt(0, 0, 0);

        let ambientLight = new THREE.AmbientLight(0xffffff, 1); //设置环境光
        scene.add(ambientLight); //将环境光添加到场景中
//         let pointLight = new THREE.PointLight(0xffffff, 0.5, 1);
//         pointLight.position.set(0, 30, 10); //设置点光源位置
//         scene.add(pointLight); //将点光源添加至场景

        const directionalLight = new THREE.DirectionalLight(0xffffff, 0.1);
        directionalLight.position.set(0, 30, 10);
        scene.add(directionalLight);

        //创建渲染器
        const renderer = new THREE.WebGLRenderer({
            antialias: true,
            alpha: true,
            logarithmicDepthBuffer: true
        });
        renderer.setSize(w, h);
//         renderer.setPixelRatio(window.devicePixelRatio);
        renderer.shadowMap.enabled = true;
        renderer.outputEncoding = THREE.sRGBEncoding;
        renderer.textureEncoding = THREE.sRGBEncoding;
        document.getElementById("dbox").appendChild(renderer.domElement);



        const loader = new GLTFLoader();

        const clock = new THREE.Clock();

        window.IdleAction = null;
        window.walkAction = null;
        window.walkAction1 = null;
         let mixer = null;
        
         const dracoLoader = new DRACOLoader();
              dracoLoader.setDecoderPath('./three/jsm/libs/draco/gltf/');
              loader.setDRACOLoader(dracoLoader);
        loader.load('https://ptcgtext.oss-cn-chengdu.aliyuncs.com/people2.glb', function(gltf) {
//             console.log('人的模型', gltf);

            // 返回的场景对象gltf.scene插入到threejs场景中
            gltf.scene.position.y=-1.6;
            gltf.scene.position.x=0;
            gltf.scene.scale.set(2.6, 2.6, 2.6)
            mixer = new THREE.AnimationMixer(gltf.scene);
            gltf.scene.traverse(function(child) {
                if (child.isMesh) {
                    child.castShadow = true;
                     child.receiveShadow = true;
        
                }
            });
            wait(gltf);
            
        })

        
        function wait(gltf){
            loader.load('./model/glb/movement.glb', function(gltfmovement) {
                console.log('待机模型', gltfmovement);
                // 返回的场景对象gltf.scene插入到threejs场景中    
                window.IdleAction = mixer.clipAction(gltfmovement.animations[0]);
                window.IdleAction.play();
                hand_fn(gltf);
                
            })
        }
        
        
        function hand_fn(gltf){
            loader.load('./model/glb/mouth1.glb', function(gltfmovement) {
                // console.log('这个手动作数据', gltfmovement);
                // 返回的场景对象gltf.scene插入到threejs场景中
                window.walkAction1 = mixer.clipAction(gltfmovement.animations[0]);
                window.walkAction1.stop();
                speak(gltf);
            })
        }
        
        function speak(gltf){
            loader.load('./model/glb/mouth.glb', function(gltfmovement) {
                // console.log('口型模型', gltfmovement);
                // 返回的场景对象gltf.scene插入到threejs场景中
                window.walkAction = mixer.clipAction(gltfmovement.animations[0]);
                window.walkAction.stop();
                scene.add(gltf.scene);
                animate();
            })
        }
        
    
        
        function animate() {

            const delta = clock.getDelta();
            mixer.update(delta);

            renderer.render(scene, camera);
            //转动,可以忽略
            window.requestAnimationFrame(animate);
            // scene.rotation.y += 0.01;
        }
        
        
    </script>
    <script>
            
        function getMessage(result){//应用向网页传递消息

            if(result==1){
              window.walkAction.play();
              window.walkAction1.play();
            }
            if(result==2){
              window.walkAction.stop(); 
              window.walkAction1.stop();
            }
        }
        
    </script>

方案二、视频合成的方式

2D真人视频合成
优点:输入一个真人图片或者真人视频经过训练,生成一个真人视频
缺点:需要GPU较多,需要分段生成。

方案三 .把模型放到服务器端(可以对应上口型,视频推流方式在客户端显示)

互动数字人(对应开放平台的“客服助理”场景)使用阿里云RTC渠道,平台会将数字人渲染的视频流推到RTC服务器,客户可以使用RTC的客户端SDK进行拉流播放对应视频流;
微信截图_20231116164859.png

微信截图_20231116165442.png

微信截图_20231116165550.png
3d建模使用:虚幻引擎(ue5)

1、后端开发接入服务端 API 接入篇
  
2、前端引入视频流接入篇 集成到网页端数字人视频流
  
3、前端接入语音收音能力,通过RTC上传到虚拟数字人开放平台,即可实现与数字人的语音交互

前后端数据流程图:

p505166.png

参考阿里数字人:
https://help.aliyun.com/document_detail/447761.html?spm=a2c4g.451451.0.0.db0c37a7WlBWlm

口型驱动插件

微信截图_20231116150656.png
参考:https://www.yiihuu.com/a_11791.html

模型视频推流

利用像素流送可以在用户不可见的电脑上远程运行虚幻引擎应用程序。举例而言,这台电脑可以是机构中的一台实体电脑,也可以是云端服务提供的虚拟机。虚幻引擎将使用该电脑可用的资源(CPU、GPU、内存等)来运行游戏逻辑并渲染每一帧。它会不断将此渲染输出编码到一个媒体流送中,再通过一个轻量级的网页服务堆栈进行传递。用户即可在其他电脑和移动设备上运行的标准网页浏览器中查看直播流送。

推流组件:
(1)像素流送插件 - 此插件在虚幻引擎中运行。其使用H.264视频压缩对每个渲染帧的最终结果进行编码,将这些视频帧随游戏音频一同打包到媒体流送中,并通过直接点对点连接将该流送发送到一个或多个连线的浏览器上。

(2)信令和Web服务器- 信令和Web服务器负责交涉浏览器和像素流送插件之间的连接,将播放媒体流送的HTML和JavaScript环境提供给浏览器。

参考:
https://docs.unrealengine.com/5.1/zh-CN/customizing-the-player-web-page-in-unreal-engine/
https://blog.csdn.net/H_1512826122/article/details/129400685

BGE是由北京智源人工智能研究院提出的新的embedding模型。

BGE的训练主要由组成:

(1)通用文本上进行预训练;

(2)通用文本上finetinue(采用unlabeled数据);

(3)特定任务上finetinue(采用有labeled数据);

一、预训练

在预训练阶段,作者选择在Wudao数据集上进行,采用的模型架构为RetroMAE[2]。

RetroMAE的模型架构为非对称的encoder-decoder结构。为什么是非对称的呢?因为它的encoder部分是由bert组成(12层transformer的encoder),而它的decoder部分仅有由一层transformer的decoder构成。

在encoder阶段,对sentence进行15%~30%的mask,通过encoder得到句子向量的表示(也就是encoder的[CLS] token):
,在decoder部分,句子被进一步加大噪音,mask的比例为50%~70%,通过增加mask的比例来提升任务的复杂性。而整个预训练的任务则为:在encoder阶段,对被掩码的部分进行重构,也就是MLM(Masked Language Modeling),在decoder阶段对整个句子进行重构,整体loss函数为:
微信截图_20240807143152.png
微信截图_20240807143053.png

相比于transformer中的decoder结构,RetroMAE的作者在这一部分做了一些改进,在文章中称为enhanced-decoder。

微信截图_20240807143958.png

微信截图_20240807144034.png

二、通用文本上finetune

在这个阶段采用的是unlabled data,相信大家跟我一样感到很好奇,标签都没有,那怎么训练模型呢。其实这个unlabled data更准确的说采用的其实是伪标签,整理数据获得伪标签主要有2个步骤:1. 收集大量pair数据,如title-passage;2. 用text2vec-chinese计算文本的相似度,再卡阈值(paper中采用0.43作为阈值),过滤掉置信度比较低的pair;最后形成了100 million pairs这样庞大的数据集。
有了数据之后,模型训练,采用的是大名鼎鼎的对比学习方式:
微信截图_20240807143806.png

三、特定任务上finetinue

在下游任务上进行finetune会存在着一个问题:有些样本可能会互相矛盾,举个例子,一对pair在某个任务上是相似的,而在另一个任务上可能就不相似了。争对这个问题,作者提出了两点解决方案:1. 不同的任务加上不同的指令;2.进行难负例挖掘;最后再在进行改造后的数据集上进行finetune。

一、环境安装

在 pip install -r requirements.txt 时候报错:

 ERROR: Failed building wheel for pyaudio
Successfully built python_speech_features
Failed to build pyaudio
ERROR: Could not build wheels for pyaudio, which is required to install pyproject.toml-based projects

解决办法:

conda install -c conda-forge portaudio
pip install pyaudio

参考:
https://blog.csdn.net/jiaoyangwm/article/details/133743405
https://codeantenna.com/a/5jP2RktVnp
https://blog.csdn.net/matt45m/article/details/134046424

一、数字人定义

数字人是指以数字形式存在于数字空间中,具有拟人或真人的外貌、行为和特点的虚拟人物,也称之为虚拟形象、数字虚拟人、虚拟数字人等。数字人的核心技术 主要包括计算机图形学、动作捕捉、图像渲染、AI等。数字人可以打造更完美的人设,为品牌带来正向价值。互联网、金融、电商平台、消费品牌、汽车出行等领 域纷纷推出数字人,用于品牌营销、智能客服等方向。

二、数字人分类

数字人可以按照不同维度进行分类。

1.人物图形资源的维度

数字人可分为2D和3D两大类,2D、2.5D、3D这三种,2D是最常见的用一段语音去驱动一张照片,2.5D比2D多一些肢体动作,3D是UE建模

2.外形上

可分为2D真人、2D卡通、3D卡通、3D风格化、3D写实、3D超写实、3D高保真等多种。

写实和风格化之间的显著区别是,写实你被限制使事物看起来“真实”,就是要强化他们的视觉语言。风格化里您可以自由发挥的形状和颜色,夸大或删除细节,在任何方向增强外观和感觉。这样做将打破现实的幻觉,因为它不再被视写实的,它将不属于我们的世界。
bdc_r.jpg
c225c2ec.png

3.驱动的维度

可分为真人驱动和AI驱动两种。 根据商业和功能维度,可分为内容/IP型、功能服务型和虚拟分身等三种。

三、技术开发流程

1.人物形象采集(视频采集/3D扫描)

(1)人物建模
建模技术发展推动外貌更接近人的超写实数字人制作
门槛和周期进一步下降
(2)物理仿真
物理仿真算法迭代推动服装动态展示趋向真实

(3)人物渲染
渲染引擎的迭代发展和GPU算力的提升推动数字人渲
染画面更加精细和实时化

(4)声音建模

1.素材采集

(1)图片采集
(2)视频采集
(3)声音采集

2.素材清洗

(1)视频降噪
(2)音频降噪
(2)背景分离
(3)人物提取

3.数字人建模

(1)动作捕捉模型
肢体动作建模

(2)面捕模型
面部捕捉技术向更简单的硬件、更细腻的表情、更自动化的流程方向发展
(3)嘴型模型
嘴型和音频映射建模
(4)ASR模型
音频与文本建模
(5)AI驱动模型
AI驱动算法,通过语音驱动肢体动作、面部表情、嘴型细节关联映射,数据进行模型
训练,得到相关模型,并智能合成

4.结果合成

(1)图像合成模型
(2)语音合成
(3)视频合成
(4)3D渲染

四、开源算法

1.Gan方案的

(1) Wav2Lip:

优缺点:开源可复现
https://github.com/Rudrabha/Wav2Lip

(2)PaddleBoBo :不推荐

优缺点:使用的Wav2Lip,只能在woindows系统
https://github.com/JiehangXie/PaddleBoBo

2.Diffusion

DiffTalk:https://github.com/sstzal/DiffTalk
DiffusionVideoEditing:https://github.com/DanBigioi/DiffusionVideoEditing

3.Nerf

RAD-NeRF:https://github.com/ashawkey/RAD-NeRF

ER-NeRF: https://github.com/Fictionarry/ER-NeRF/tree/main

AD-NeRF: https://github.com/YudongGuo/AD

https://github.com/OpenTalker/video-retalking

其他开源方案:
https://github.com/OpenTalker/video-retalking
https://juejin.cn/post/7199809805363789882

参考:
http://www.ffner.com/2023726140734-9286.html?11
https://zhuanlan.zhihu.com/p/648734603
https://zhuanlan.zhihu.com/p/656328699

1.MiniGPT-5

1.5 CLIP
1.8 PLIP

2.BLIP
3.BLIP-2

参考内容:
1.https://www.bilibili.com/read/cv25429299/

>> X光影像路径:./data/Xray/861_1.png

>> 用户:这是一张什么图?
>> XrayGLM:这张图片显示的是一张肺部检查的X光片。

>> 用户:请描述这张胸部X光片的诊断结果
>> XrayGLM:心脏大小正常,肺部清晰。没有急性心肺疾病的证据。

>> 用户:是否存在肺气肿?
>> XrayGLM:没有肺气肿。心脏大小正常,肺部清晰。没有发现急性心肺疾病的证据。

>> 用户:平时饮食该注意什么?
>> XrayGLM:饮食应该健康,均衡。建议增加蛋白质的摄入量,
因为蛋白质有助于维持肌肉和骨骼的健康。多食用蔬菜、水果、
全谷物以及健康的脂肪来源如橄榄油、鱼类等可以帮助获得足
够的维生素和矿物质。此外,避免过度饮酒或吸烟,这些习惯
可能会对心脏健康产生负面影响。