对我们项目中的关键技术实现进行总结:
一、3DMax关键技术实现
1、一下的关于3DMax中对于人物的设计和操作均需要在对3DMax基础知识熟练掌握的情况下进行的。
2、 骨骼架设:首先对导入到3DMax中的人物模型进行架设骨骼,首先,先加载一个人,锁定住,别让他乱动。用biped工具建立一个基本骨骼——可以从脚部位置往上拖拽鼠标来建立。在运动命令面板,点biped卷展栏的 figure mode在各视图中,使用旋转缩放位移的方式,调整骨骼的位置与模型的位置,让二者对齐。 PS: 1双击骨骼,可以让骨骼的子物体全部选中。2 若选中骨骼时,复制的选项 是灰色的,就用新建命令 给他起个 名字就可以了。3 任务骨骼的匹配不是一次性就能完成的,需要在各个阶段进行调整,系统给出的Biped物体是一个固定的比例,调整好后使用。将骨骼绑定到模型上选中模型,如果有打组的请解组。进入修改命令面板,选择physique修改命令。单击 按钮,H 键打开选择对话框,双击Bip01物体。弹出对话框后,单击 进行解算。解算完毕后可以看到黄色的“筋”。3DMax假设骨骼是一个细致的工作,需要骨骼与皮肤之间完全契合,这样在后面的制作过程中才能够比较顺利
3、 蒙皮知识:做好骨骼后,要使动画的时候模型跟着骨骼做运动就要使用蒙皮,使模型附着在骨骼上面。这样骨骼动的时候,模型会随之而动。所以蒙皮就是相当于在原来的骨骼上面覆盖上一层皮肤,这样可以使得骨骼在动的时候会带动模型动起来。但是蒙皮的时候应注意防止部分骨骼没有真正的附在皮肤的下面。蒙皮是将骨骼控制模型的形态节点,达到合理的绑定效果,所谓的形态节点就是外部轮廓。蒙皮分两种:柔性和刚性,效果不同,作用也不同。一般刚性绑定中也可直接p给骨骼,父子级关系,也能达到想要结果。
4、 封套处理:先通过调节封套的大小来调节每个骨骼部分的影响范围,注意内圈控制到外圈的一半就可以了。封套时注意某一块皮肤会受到几根骨骼的影响,然后随之进行调整,还要注意某块皮肤收到那根骨骼的影响等一系列问题。
5、 调权重问题:权重就是蒙了皮的骨骼对物体定点的影响程度,使用Zbrush的Trans pose功能进行动作调整,只需要给模型设置动态线,通过遮照进行简易的权重设置(非常方便),就可以给模型调整Pose。当然,Transpose这种简易的蒙皮是会有些许不正常的变形的,但可以通过Zbrush雕刻的方式很快的弥补。权重调整是一个比较仔细的货,需要自己注意每一块的影响程度的大小,根据这个来设置合适的权重问题。
6、 动画制作:在动画的制作中首先需要做的便是设置一些需要的动作。然后在关键帧打开的情况下就可以设计自己需要的动作,再设计好之后就可以进行动画渲染,在导出诸侯还和Photoshop的联合使用,增加动画的视觉效果。
7、 在3DMax上面将需要的动画制作好之后便可以渲染导出,然后后续工作将在unity3D上进行动画具体的操作
二、Server关键技术实现
1、 分词
分词借用庖丁分词。同时加以盘古分词词库以及词素进行辅助分词。
2、 匹配
使用特殊的数据结构,架构字典树来存储规则库内的规则进行匹配从而达到节约空间,相比传统的最长匹配有对应句子有较为准确的回答。同时也这种字典树的结构也从一定程度上有着良好的消歧作用。
3、 情感分析
使用人工神经网络的BP模型进行情感分析。此处借用了台湾大学中文通用情感词典(NTUSD)进行训练人工神经网络。同时结合人工神经网络改进从输入层到输出层的权值的梯度下降算法。结合上下文从而进行对用户情感的分析,继而从答案库中选中较好的回答,使得回答符合当前的语境,增强用户体验。
4、 学习
这里使用的将用户的问题和答案进行分词并且加载在内存中并且在之后存储。
5、 专业模块
在专业领域我们收集大量的信息和领域知识。通过判断决定是否触发专业模块知识。
三、Unity3D关键技术实现
1、2D文字聊天界面------------------NGUI插件
2、3D语音聊天界面------------------科大讯飞语音文本的转换
3、UNITY与Android进行交互
4、UNITY融合3D人物模型
5、UNITY与服务器端进行交互-------------------TCP/IP协议
首先,从你进入软件开始,你就建立了和服务器的联系。这是一段和服务器的长连接,直到你退出此软件。
2D文字聊天界面大致实现了文字输入、发送消息、接收消息、你可以通过点击按钮让机器人开启聊天模式或者学习模式、又或是进入3D语音聊天界面或者退出。在assets文件夹下导入NGUI(使用的是3.6.8版本的.unitypackage)包,点击按钮时有声音和透明度、阴影的变化,通过给按钮添加声音.....这样的组件,使得用户体验得到提高,每当点击发送按钮实例化一个prefab呈现在聊天对话框中,你可以看见你发送的文字和你从服务器接收到的返回的对话,通过点击聊天对话框的文字,你的消息可以合拢关闭暂时隐藏,这是使用NGUI插件的UI Play Tween.script,通过服务器端发送回来的消息附带着标识字符,可以使人物做出相应的动作,画面的层次感是通过调节两个照相机的DEPTH、PROJECTION、SIZE、CLIPPING PLANES实现的,学习模式和聊天模式的相互切换则是通过向服务器发送标识字符来实现模式切换。
3D语音聊天界面重在动画,把动画过度的condition设置为下个动画为TRUE,当收到服务器端的标识字符,就把它设置为TRUE,人物就产生动画的过度。在人物模型的四个方向搭建照相机,调节照相机在最终屏幕上出现的位置,经过四棱锥对光的折射和反射,四个照相机所拍摄到的场景恰恰使其投影到了四棱锥中心,形成了立体。背景中,地势是用unity的Terrain,勾出起伏的地势,铺上texture草坪和树,给四个照相机添加天空盒子组件。同时,你也可以在3D界面通过按钮点击实现去2D文字聊天界面或者退出此程序。
UNITY和Android的交互:
AndroidJavaClass jc =
new AndroidJavaClass(“com.unity3d.player.UnityPlayer”);
AndroidJavaObject activity=jc.GetStatic<AndroidJavaObject>(“currentActivity”);
得到AndroidJavaClass类并且获得AndroidJavaObject 的activity对象,通过activity.Call(“”,args)函数的第一个参数(函数名)可以调用Android端的一个函数,args传递了此函数的参数,
UnityPlayer.UnitySendMessage
("AndroidManager", "AndroidCallBack",””);在安卓端将从科大讯飞翻译过后的文本传送给了以AndroidManager命名的类中AndroidCallBack为名的函数,由此实现了安卓和unity的交互。
UNITY和3DMAX动画模型的融合: 在assets包下导入3DMAX动画模型的包,创建一个Animator Controller,实现一个动画向下一个动画的过度,将动画模型加入场景,给每一个动画模型加上此动画控制器,使得动画控制的条件为下一个动画为true时,当从服务器接收到标识符时,就使他产生不同的动画,这样就实现了根据对话内容让模型做出相应的动作。
UNITY和服务器的通信:通过TCP/IP协议进行通信,使用SOCKET建立和对应IP对应端口号的连接,开启一个线程去等待着接收由服务器端发送过来的消息,读入时编码方式使用UTF-8,发送字符串通过socket,BeginSend方法实现发送。
四、文本语音输入输出关键技术实现
语音转文本部分是调用的科大讯飞的在线语音,它的激发方式是按键,通过按钮触发开启安卓设备的录音,此部分需要在源码中写入关于安卓权限的要求,来调用安卓的录音权限,当按钮被激发,则开始进入语音录制阶段,将麦克风所录下的语音实时的传给云端的科大讯飞服务器。、
从声音之中得到文本:
public void GetWordFromVoice() {
boolean isShowDialog = mSharedPreferences.getBoolean("iat_show", true);
if (isShowDialog) {
showIatDialog();
} else {
if (null == iatRecognizer) {
iatRecognizer = SpeechRecognizer.createRecognizer(this);
}
if (iatRecognizer.isListening()) {
iatRecognizer.stopListening();
} else {
}
}
}
所借用的接口是科大讯飞开放平台提供的接口,实现实时的语音传输,通过云端的服务器利用科大讯飞的语音包将语音转为文字,传回客户端,这样就实现了客户端的语音转文字,拿到需要的文字之后,客户端的处理方式是将收到的text文本传入unity3D之中,再通过unity3d将文字text发送给服务器端,下一步由服务器进行语音的智能识别,主谓短语的切分,调用相关的库进行回复。
以下是调用VoiceToText的接口的方法:
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button1:
VoiceToWord voice = new VoiceToWord(MainActivity.this,"54ae8c54");
voice.GetWordFromVoice();
break;
}
}
声音监听:
private SpeechListener listener = new SpeechListener() {
@Override
public void onData(byte[] arg0) {
}
@Override
public void onCompleted(SpeechError error) {
if (error != null) {
System.out.println("user login success");
}
}
文本转语音,使用的是科大讯飞的接口,因为此作品之中语音包不是重点,所以语音包的转换我们统一调用的科大讯飞的语音包接口,依旧是在线的文字转语音,客户端将来自智能自然语音识别的服务器的text文本以文字的形式发送给科大讯飞的云端服务器,科大讯飞的云端服务器完成将文字转化为语音的步骤,再将语音实时的传送回来,由客户端将语音读出,此处需要申请客户端(安卓)的扬声器的权限,由扬声器将传回的语音读出。
有关的安卓的权限的要求:
<!-- 讯飞语音权限开始 -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<!-- 讯飞语音权限结束 -->
如果您愿意花几块钱请我喝杯茶的话,可以用手机扫描下方的二维码,通过 支付宝 捐赠。我会努力写出更好的文章。
(捐赠不显示捐赠者的个人信息,如需要,请注明您的联系方式)
Thank you for your kindly donation!!