【研二】2021年项目与技术总结

项目截图

1、智慧哨兵

 

 

2、小派VR面部捕捉交互

 

 

3、智慧楼宇

 

 

4、智慧园区

 

 

5、物流小车

 

 

 

项目技术总结:

1、视频融合投影技术

视频投影技术我们小组进行了相当一段时间的研究,场景中需要两个相机,一个是用来观察的透视相机,另一个透视相机作为投影相机,就类似投影仪的原理。

在初期,我采用的方式是射线检测,获取到投影相机和场景中物体上的所有交点坐标,再传入片元着色器中渲染出最终要的效果,这种方式消耗资源极大,效果不好,不具备实时性。

之后我们从另一条路,解决了这个问题,获取到投影相机的视图投影矩阵,经过矩阵变换就可以得到投影相机视角下所有点的坐标。

c_Position = u_ProjectionMatrix * u_ViewMatrix * modelMatrix * vec4( position, 1.0 );

并且我们可以获取到投影相机下的深度图像

this.renderTarget = new THREE.WebGLRenderTarget(this.height, this.width)
this.renderTarget.depthBuffer = true
this.renderTarget.depthTexture = new THREE.DepthTexture()
this.renderTarget.depthTexture.format = THREE.DepthFormat;
this.renderer.setRenderTarget(this.renderTarget)

通过判断是否大于投影相机下各个像素点的像素值,来判断是否遮挡,最终实现视频投影效果。

 

2、面部捕捉交互技术

1、技术目标:

本项目最终形成的人脸实时面部捕捉表情展示系统能够在pc端展示人脸模型,并且通过opencv处理之后的关键点,重现出实时情况下目标对象的表情,并且根据部分关键点重现出整个面部的表情。系统软件的设计将满足,定制性、可扩展性、模块化、实时性、同步性、直观性以及通用性等要求。

2、技术内容:

工作项内容
前期准备 基本调研与讨论,开发环境搭建
模型准备 搭建人物模型
Blendshape制作模型权重 blend shape绑定人物脸部关键区域
Unity3d集成openface Windows环境下,unity3d直接调用执行openface人脸关键点识别.py脚本
Unity3d场景搭建,以及UI界面搭建 Unity3d下搭建模型场景,包括模型,光源和摄像头位置;搭建UI界面。
Unity3d建立控制脚本 创建C#脚本,通过脚本可以控制blendshape模型的(眼镜,鼻子,嘴部,头部转向),网络部分通过socket实时接收来自python算法端的关键点数据。
Socket接收表情关键点重现表情 接收到数据后,经过处理,实现关键点和blendshape的映射关系,通过模型的blendshape控制接口控制模型的表情运动。

3、实现精灵图文字

  /* 创建字体精灵 */
 makeTextSprite(message, parameters) {
   console.log(message)

   if (parameters === undefined) parameters = {}

   var fontface = Object.prototype.hasOwnProperty.call(parameters, 'fontface')
     ? parameters['fontface'] : 'Arial'

   /* 字体大小 */
   var fontsize = Object.prototype.hasOwnProperty.call(parameters, 'fontsize')
     ? parameters['fontsize'] : 18

   /* 边框厚度 */
   var borderThickness = Object.prototype.hasOwnProperty.call(parameters, 'borderThickness')
     ? parameters['borderThickness'] : 4

   /* 边框颜色 */
   var borderColor = Object.prototype.hasOwnProperty.call(parameters, 'borderColor')
     ? parameters['borderColor'] : { r: 0, g: 0, b: 0, a: 1.0 }

   /* 背景颜色 */
   var backgroundColor = Object.prototype.hasOwnProperty.call(parameters, 'backgroundColor')
     ? parameters['backgroundColor'] : { r: 255, g: 255, b: 255, a: 1.0 }

   /* 创建画布 */
   var canvas = document.createElement('canvas')
   var context = canvas.getContext('2d')

   /* 字体加粗 */
   context.font = 'Bold ' + fontsize + 'px ' + fontface

   /* 获取文字的大小数据,高度取决于文字的大小 */
   var metrics = context.measureText(message)
   var textWidth = metrics.width

   /* 背景颜色 */
   context.fillStyle = 'rgba(' + backgroundColor.r + ',' + backgroundColor.g + ',' +
     backgroundColor.b + ',' + backgroundColor.a + ')'

   /* 边框的颜色 */
   context.strokeStyle = 'rgba(' + borderColor.r + ',' + borderColor.g + ',' +
     borderColor.b + ',' + borderColor.a + ')'
   context.lineWidth = borderThickness

   /* 绘制圆角矩形 */
   this.roundRect(context, borderThickness / 2, borderThickness / 2, textWidth + borderThickness, fontsize * 1.4 + borderThickness, 6)

   /* 字体颜色 */
   context.fillStyle = 'rgba(0, 0, 0, 1.0)'
   context.fillText(message, borderThickness, fontsize + borderThickness)

   /* 画布内容用于纹理贴图 */
   var texture = new THREE.Texture(canvas)
   texture.needsUpdate = true
   // texture.center = new THREE.Vector2(0.5,0.5);
   texture.wrapS = THREE.RepeatWrapping
   texture.wrapT = THREE.RepeatWrapping
   texture.repeat.set(1, 1)
   texture.offset = new THREE.Vector2(0.6, 0.3)

   var spriteMaterial = new THREE.SpriteMaterial({ map: texture, depthWrite: false })
   var sprite = new THREE.Sprite(spriteMaterial)

   console.log(texture)
   console.log(sprite)

   /* 缩放比例 */
   sprite.scale.set(10, 5, 0)
   // console.log(sprite.position.y);

   return sprite
}

4、实现视频卡片

/**
* 创建视频卡片
* @param {*} position 位置
*/
createVideoCard(position, videoUrl) {

 let ImageLoader = new THREE.ImageLoader();
 // load方法回调函数,按照路径加载图片,返回一个html的元素img对象
 ImageLoader.load('/texture/border.png', (img)=> {
     // image对象作为参数,创建一个纹理对象Texture
     let texture2 = new THREE.Texture(img);
     // 下次使用纹理时触发更新
     texture2.needsUpdate = true;
     let material2 = new THREE.MeshPhongMaterial({
       shininess: 30,
       map: texture2, //设置纹理贴图
       transparent: true,
       side:THREE.DoubleSide,
       polygonOffset: true,
       polygonOffsetFactor: 4,
       polygonOffsetUtils: -4
    });

     console.log('加载border');
     const geometry2 = new THREE.PlaneGeometry( 4.5 , 2.5 );
     let mesh2 = new THREE.Mesh(geometry2, material2); //网格模型对象Mesh
     mesh2.position.copy(mesh.position);
     videoCardGroup.add(mesh2);
  },
   null, error=>{
     console.error(error)
  });

 // load方法回调函数,按照路径加载图片,返回一个html的元素img对象
 ImageLoader.load('/texture/borderline.png', (img)=> {
     // image对象作为参数,创建一个纹理对象Texture
     let texture2 = new THREE.Texture(img);
     // 下次使用纹理时触发更新
     texture2.needsUpdate = true;
     let material3 = new THREE.MeshPhongMaterial({
       shininess: 30,
       map: texture2, //设置纹理贴图
       transparent: true,
       side:THREE.DoubleSide,
       polygonOffset: true,
       polygonOffsetFactor: 4,
       polygonOffsetUtils: -4
    });

     const geometry3 = new THREE.PlaneGeometry( 2 , 2 );
     let mesh3 = new THREE.Mesh(geometry3, material3); //网格模型对象Mesh
     mesh3.position.copy(position);
     videoCardGroup.add(mesh3);
     this.scene.add(videoCardGroup); //网格模型添加到场景中
     videoCardGroup.visible = true;
  },
   null, error=>{
     console.error(error)
     return error;
  });

   return videoCardGroup;
}

 

5、实现绘制防区

可以绘制圆形防区和多边形防区,使用three.js中的ShapeGeometry来实现画多边形,THREE.CircleGeometry来实现绘制圆形防区。

//根据点画防区
 initPolygonDefence(defencePointNode, floor, deviceSn){
   let obj = this.scene.getObjectByName("mainModel");
   let node = [];
   for(let i = 0; i< defencePointNode.length; i++) {
     node.push(new THREE.Vector2(defencePointNode[i].x, defencePointNode[i].z))
  }
   let areaGeometry = new THREE.ShapeGeometry( new THREE.Shape( node ) );
     
   let areaMaterial = new THREE.MeshBasicMaterial( { color: 0x9ACD32, side: THREE.DoubleSide,    transparent:true, opacity:0.5} );
   let area = new THREE.Mesh( areaGeometry, areaMaterial);
   area.name = '已添加防区';
   area.rotation.x = Math.PI /2;
   area.deviceSn = deviceSn;
   this.scene.add(area);
}

 

 

posted @ 2022-02-28 17:52  rainbring  阅读(146)  评论(0)    收藏  举报