OBJ可视化——UV还原(修正)

前言

前面写过一篇obj格式解析的博客,但是这篇文章中可视化的工作是参考PRNet的源码进行的,后来细细思考了一下,有点问题,具体看下面。

问题来源

PRNet源码的render.py中有个函数render_texture,是作者用于将uv展开图重新映射回3D模型中,具体流程可以看出是:

  • 找到当前三角形的uv坐标和3D坐标

  • 将三个顶点的uv图颜色取平均,作为当前面片的颜色

    tri_tex = (colors[:, triangles[0,:]] + colors[:,triangles[1,:]] + colors[:, triangles[2,:]])/3.
    
  • 将三个顶点的3D深度值取平均,作为当前面片的深度值:

     tri_depth = (vertices[2, triangles[0,:]] + vertices[2,triangles[1,:]] + vertices[2, triangles[2,:]])/3. 
    
  • 按像素着色,若当前像素在3D三角面中,且深度值大于当前像素点记录的深度值,则更新深度值和此3D点的像素,反之不更新不记录。

然而,最近用meshlab看低模人体模型的时候发现一个细节,如下图

在这里插入图片描述

那么问题显而易见了,眼睛这里的三角面的颜色根本不可能是通过三个顶点的平均色产生的

那么可能的解决方法就是,将uv里面的三角面片仿射变换到3D图像中的三角面片。

修正效果

为了验证上述的仿射变换思想是否可行,直接手撕一波,顺便把上一篇博客没有关注的深度值也加进去,整一个完整的代码出来。

读取OBJ信息的代码就不说了,就是一行行遍历,通过第一个字段判断是顶点还是法线还是面片等的信息。

直接进入核心实现:

首先需要通过所有顶点的前两个维度判断当前渲染图的大小:

render_width = int(np.ceil(np.max(vertices[...,0])))
render_height = int(np.ceil(np.max(vertices[...,1])))

最终的渲染图的每个面片必须需要深度信息指引是否渲染,深度值大的覆盖小的:

render_img = np.zeros((render_height,render_width,3),dtype=np.uint8)
depth = np.zeros((render_height,render_width),dtype=np.float32)
depth = depth-9999

为了将uv中的三角面片变换到渲染图中,必须先分别把两个面片取出来

# get uv texture map triangle
triangle_uv = np.float32([[vertex_tex[texcoords[i][0]][0]*height,(1-vertex_tex[texcoords[i][0]][1])*width],
[vertex_tex[texcoords[i][1]][0]*height,(1-vertex_tex[texcoords[i][1]][1])*width],
[vertex_tex[texcoords[i][2]][0]*height,(1-vertex_tex[texcoords[i][2]][1])*width]])
#get corresponding triangle in 3D face model
triangle_3d = np.float32([[vertices[triangles[i][0]][0],vertices[triangles[i][0]][1]],
[vertices[triangles[i][1]][0],vertices[triangles[i][1]][1]],
[vertices[triangles[i][2]][0],vertices[triangles[i][2]][1]]])

接下来进行仿射变换:

 # get affine transform matrixwarp_mat = cv2.getAffineTransform(triangle_uv,triangle_3d)dst = cv2.warpAffine(uv_map,warp_mat,(height,width))

因为是按照面片着色,所以必须获取当前面片的mask:

# get draw mask
mask = np.zeros((height,width,3),dtype=np.uint8)
cv2.drawContours(mask,[triangle_3d[np.newaxis,...].astype(np.int)],-1,(255,255,255),-1) 

当前面片的深度信息

# judge depth
mask_idx = np.argwhere(mask[...,0]==255)
curr_depth = (vertices[triangles[i][0]][2]+vertices[triangles[i][1]][2]+vertices[triangles[i][2]][2])/3  

最开始想的是用render_img = cv2.copyTo(dst,mask,render_img)去按照面片把整个面片复制过去,但是想来可能有面片叠加的情况,所以还是按照PRNet作者思想,逐像素复制。注意根据深度信息去判断是否覆盖当前像素即可:

for idx in range(mask_idx.shape[0]):x = mask_idx[idx,0]y = mask_idx[idx,1]if(curr_depth>=depth[x,y]):render_img[x,y] = dst[x,y]depth[x,y] = curr_depth 

对比一下meshlab和映射三角面的结果

在这里插入图片描述

可以发现中图和右图在颜色上有差距,主要原因在于Meshlab是一款展示3D模型的软件,它内置了灯光,依据3D模型的法线产生了阴影,因此立体感会更强了,而我写的可视化并没有加入法线信息,仅仅是对展开的uv纹理图进行3D映射,所以照片既视感更强。

后记

主要还是对之前忽视的细节做个记录。

完整的python脚本实现放在微信公众号的简介中描述的github中,有兴趣可以去找找,同时文章也同步到微信公众号中,有疑问或者兴趣欢迎公众号私信。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/246558.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Unity中BVH骨骼动画驱动的可视化理论与实现

前言 找了很久使用BVH到unity中驱动骨骼动画的代码,但是都不是特别好用,自己以前写过,原理很简单,这里记录一下。 理论 初始姿态 在BVH或者其它骨骼动画中,一般涉及到三种姿势:A-pose,T-pos…

卡通驱动项目ThreeDPoseTracker——模型驱动解析

前言 之前解析过ThreeDPoseTracker这个项目中的深度学习模型,公众号有兄弟私信一些问题,我刚好对这个项目实现有兴趣,就分析一波源码,顺便把问题解答一下。 这个源码其实包括很多内容:3D姿态估计,坐标平滑…

卡通驱动项目ThreeDPoseTracker——关键点平滑方案解析

前言 之前对ThreeDPoseTracker的深度学习模型和unity中的驱动方法进行过解析,还有一个比较重要的就是从深度学习模型出来的3D关键点数据会有抖动,在ThreeDPoseTracker源码中有做两次平滑,一部分是卡尔曼滤波,还有一部分是低通滤波…

卡通角色表情驱动系列一

前言 分析完ThreeDPoseTracker来做卡通角色的身体驱动,接下来在卡通驱动领域还有一个是表情驱动。对这个真的是一窍不通啊,只能慢慢看论文了。 国际惯例,参考博客/论文: 《Landmark-guided deformation transfer of template f…

opencv相机标定和人头姿态估计案例

前言 头部驱动除了之前关注的表情驱动外,还有眼球驱动和头部方向驱动。本博客基于opencv官方文档和部分开源代码来研究如何基于人脸关键点获取头部的朝向。 国际惯例,参考博客: opencv:Camera Calibration and 3D Reconstruction opencv:…

卡通角色表情驱动系列二

前言 之前介绍了使用传统算法求解BS系数的表情驱动方法,其中提到过的三种方法之一是基于网格形变迁移做的,那么这篇文章就是对《Deformation Transfer for Triangle Meshes》做表情驱动的解析。 国际惯例,参考博客: 论文原文《…

UE自带重定向原理

UE自带重定向方法验证 核心源码在VS的解决方案中的位置: UE4\Source\Developer\AssetTools\Private\AssetTypeActions\AnimSequence.cpp中第3237行RemapTracksToNewSkeleton函数 跳转方法 AssetTypeActions_AnimationAsset.cpp的RetargetNonSkeletonAnimationHa…

【caffe-Windows】caffe+VS2013+Windows无GPU快速配置教程

前言 首先来一波地址: happynear大神的第三方caffe:http://blog.csdn.net/happynear/article/details/45372231 Neil Z大神的第三方caffe:https://initialneil.wordpress.com/2015/01/11/build-caffe-in-windows-with-visual-studio-2013-…

【caffe-Windows】caffe+VS2013+Windows+GPU配置+cifar使用

前言 国际惯例,先来波地址: CUDA WIN7:链接:http://pan.baidu.com/s/1nvyA3Qp 密码:h0f3 官方网址:https://developer.nvidia.com/cuda-toolkit CUDA WIN10:链接:http://pan.baidu.com/s/1…

【一些网站的收集】包含机器学习深度学习大牛主页等

数学概念部分 旋转矩阵、欧拉角、四元数的比较 欧拉角和四元数的表示 四元数与旋转 B样条曲线 非常好的概率统计学习的主页 误差方差偏差 编程语言学习 C#编程视频 OpenGL编程NeHe OpenGL官网 OpenGL“我叫MT“纯手工3D动画制作之1——基础介绍 【强大】非常好的Op…

Eureka源码分析

Eureka源码分析 Eureka server入口: Spring.factories PS: 意味着如果加载EurekaServerAutoConfiguration成功,需要 ConditionalOnBean(EurekaServerMarkerConfiguration.Marker.class)需加载成功. 通过Bean注入了很多类 本质上, eureka-server包含很多事件: EurekaInstanceC…

matlab程序中,如何解决矢量长度必须相同的问题

主要原因就是画图的x和y长度不一样,我用一个例子说明。 问题代码: clear all;close all;clc;x 0 : 1: 9;y sin(x);n 2*length(x);yi interpft(y, n);xi 0 : 0.5 : 10;hold on ;plot(x, y ,ro);plot(xi, yi, b.-);plot(x, sin(x),m--);legend(原始…

matlab 功率谱分析函数psd用法

psd简介 PSD(power spectrum analysis)功率谱分析,PSD在给定频带上的积分计算信号在该频带上的平均功率。与均值-平方谱相反,这个光谱中的峰值并没有反映出给定频率的能量。 单边PSD包含了信号的总功率在频率间隔从DC到一半的奈奎斯特速率。双侧PSD包含…

linux tar (打包、压缩、解压)命令

打包程序:tar c: 创建文档t: 列出存档内容x:提取存档f: filename 要操作的文档名v:详细信息 一:打包 打包:是指把文件整合在一起,不压缩 1.将文件打包:tar cf a.tar…

虚拟机添加硬盘扩容

1.设置→添加→硬盘 2.选择磁盘类型 3.开启虚拟机 4.用ls 命令查看:ls /dev/sd* 5.最后就可以对sdb进行分区操作 这里好麻烦,等我有空,在补上! . . .

利用matlab将三维数据画成三维立体图

首先先分析对象。将数据利用matlab画出图,最开始是导入数据,然后处理数据,最后将处理的数据画出来。 所以我将它分为三个步骤。 第一步:导入数据 如果是mat数据。可以直接load如果是txt数据。可以用txtread如果是excel数据。可…

世界坐标、相机坐标、图像坐标、像素坐标的原理、关系,并用matlab仿真

世界坐标、相机坐标、图像坐标、像素坐标的原理、关系,并用matlab仿真 照相机是日常生活中最常见的。它能把三维的空间图片等比例缩小投影在照片上,称为一个二维图像。 以下我们就讲一讲原理,并相应的进行matlab仿真。 在学之前&#xff0…

matlab 三维高程根据图片颜色给对应点赋予颜色

目录 1. 问题分析 2. 技术分析 3. 程序代码 4. 代码运行结果 1. 问题分析 日常工作尤其是测绘、地质、遥感行业,需要画DEM模型,并在这个模型的基础上,进行着色、渲染。比如,地质分析地面三维地表形变之时,需要根据D…

matlab 计算N天前(后)的日期

注意时间的格式:是字符串、数字还是日期? 下面是计算明天、今天、昨天的日期。 day1 datetime(datestr(now,yyyy-mm-dd))caldays(1)%tomorrowday0 datetime(datestr(now,yyyy-mm-dd))%todayday_1 datetime(datestr(now,yyyy-mm-dd))-caldays(1)%yest…

CAT arguments dimensions are not consistent.CAT参数的维度不一致。

错误实例: 在写符号矩阵的时候常常会出现下面错误: 错误:CAT arguments dimensions are not consistent. CAT参数的维度不一致。 举个栗子: clear; close all; clc; syms A_0 B_0 B C D E F G H ;T_3 [2*A_0 C-D*1i H G*1i;C…