1. 这部分主要写从UV位置图获得3D人脸,并不包括如何产生UV位置图。

我已经获取一张图片的UV位置图,如下图:

(a. 裁剪后的人脸区域)                             (b. UV位置图 (仅用来展示的))            (c. UV纹理图)

a, b, c 三张图片shape都是(255, 255, 3) , UV位置图 b 并不是真正的 UV位置图,  只是将UV位置图转化成图像显示出来。

接下来, 利用a, b 获取 a中人脸对应的3D模型。

2. 主要代码

"""
如何 从 Position Map 产生 3D Face
"""
import numpy as np
import os
from skimage.io import imread, imsave# 类似 超参数
uv_kpt_ind = np.loadtxt("datas/uv-data/uv_kpt_ind.txt").astype(np.int32)  # 2 x 68 get kpt
face_ind = np.loadtxt("datas/uv-data/face_ind.txt").astype(np.int32)  # get valid vertices in the pos map
triangles = np.loadtxt("datas/uv-data/triangles.txt").astype(np.int32)  # ntri x 3# 测试一个例子
face_url = "datas/image00050.jpg"
face_texture_url = "datas/image00050_tex.jpg"
# Label 是 npy 数据, 可不是  position map图像(只是用来显示看的)
face_posmap_url = "datas/image00050.npy"  #  真正的 UV Position Mapglobal resolution_op
resolution_op = 256
# 设置参数
uv_h = uv_w = 256
image_h = image_w = 256image_posmap = np.load(face_posmap_url)
print(image_posmap.shape)
print(np.max(image_posmap))# 从 Position Map 获取 顶点
def get_vertices(pos):'''Args:pos: the 3D position map. shape = (256, 256, 3).Returns:vertices: the vertices(point cloud). shape = (num of points, 3). n is about 40K here.'''all_vertices = np.reshape(pos, [resolution_op ** 2, -1])vertices = all_vertices[face_ind, :]  # face_ind 是什么呢?return verticesdef get_landmarks(pos):"""Args:pos: the 3D position map. shape = (256, 256, 3).Returns:kpt: 68 3D landmarks. shape = (68, 3).:param pos::return:"""kpt = pos[uv_kpt_ind[1, :], uv_kpt_ind[0, :], :]return kptkpt = get_landmarks(image_posmap)
print(kpt.shape)  # (68, 3)  68个关键点vertices = get_vertices(image_posmap)
print(vertices.shape)  # (43867, 3) PRNet 人脸是 43867 个顶点# 保存顶点  不保存纹理
def dump_to_ply(vertex, tri, wfp):header = """plyformat ascii 1.0element vertex {}property float xproperty float yproperty float zelement face {}property list uchar int vertex_indicesend_header"""n_vertex = vertex.shape[1]  # ((3, 43867))n_face = tri.shape[1]   # ((3, 86906))header = header.format(n_vertex, n_face)with open(wfp, 'w') as f:f.write(header + '\n')for i in range(n_vertex):  # 顶点x, y, z = vertex[:, i]f.write('{:.4f} {:.4f} {:.4f}\n'.format(x, y, z))for i in range(n_face):  # 三角形idx1, idx2, idx3 = tri[:, i]f.write('3 {} {} {}\n'.format(idx1 - 1, idx2 - 1, idx3 - 1))print('Dump tp {}'.format(wfp))save_prefix = "results/"
name = face_url.split("/")[-1].split(".")[0] + ".ply"
print(name)
face_ply = os.path.join(save_prefix, name)# 保存 顶点信息 shape 成功
dump_to_ply(vertices.T, triangles.T, face_ply)   # 切记 tri 是 /Data/uv-data/triangles.txt 中的三角# 保存 带上 color/texture 信息
def get_colors(image, vertices):"""Args:pos: the 3D position map. shape = (256, 256, 3).Returns:colors: the corresponding colors of vertices. shape = (num of points, 3). n is 45128 here."""[h, w, _] = image.shapevertices[:, 0] = np.minimum(np.maximum(vertices[:, 0], 0), w - 1)  # xvertices[:, 1] = np.minimum(np.maximum(vertices[:, 1], 0), h - 1)  # yind = np.round(vertices).astype(np.int32)colors = image[ind[:, 1], ind[:, 0], :]  # n x 3return colorsimage_face = imread(face_url)  # face_url 是 剪切后为(256, 256, 3)的人脸图像
[h, w, c] = image_face.shape
print(h, w, c)
image_face = image_face / 255.
colors = get_colors(image_face, vertices)  # 从人脸 和 顶点 中获取 color (43867, 3)
print(colors.shape)# 写入 .obj文件,具有colors (texture)
def write_obj_with_colors(obj_name, vertices, triangles, colors):''' Save 3D face model with texture represented by colors.Args:obj_name: strvertices: shape = (nver, 3)colors: shape = (nver, 3)triangles: shape = (ntri, 3)'''triangles = triangles.copy()triangles += 1  # meshlab start with 1if obj_name.split('.')[-1] != 'obj':obj_name = obj_name + '.obj'# write objwith open(obj_name, 'w') as f:# write vertices & colorsfor i in range(vertices.shape[0]):# s = 'v {} {} {} \n'.format(vertices[0,i], vertices[1,i], vertices[2,i])s = 'v {} {} {} {} {} {}\n'.format(vertices[i, 0], vertices[i, 1], vertices[i, 2], colors[i, 0],colors[i, 1], colors[i, 2])f.write(s)# write f: ver ind/ uv ind[k, ntri] = triangles.shapefor i in range(triangles.shape[0]):# s = 'f {} {} {}\n'.format(triangles[i, 0], triangles[i, 1], triangles[i, 2])s = 'f {} {} {}\n'.format(triangles[i, 2], triangles[i, 1], triangles[i, 0])f.write(s)
name = face_url.split("/")[-1].split(".")[0] + ".obj"
save_vertices = vertices.copy()
save_vertices[:, 1] = h - 1 - save_vertices[:, 1]  # 这一步 不可缺少; (43867, 3)
write_obj_with_colors(os.path.join(save_prefix, name), save_vertices, triangles, colors)  # save 3d face(can open with meshlab)

3. obj, ply 文件 用 MeshLab  打开后的效果:

.ply 文件效果:

.obj 文件效果:

从原始UV位置图产生3D人脸,条纹现象不是特别严重, PRNet 预测的效果,条纹效果严重。

代码和文件链接

https://github.com/DongPoLI/Face-3D-Study/tree/master/generate_position_map
————————————————
版权声明:本文为CSDN博主「挡不住三千问的BlueCat」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_23944915/article/details/105046742

从UV位置图获得3D人脸相关推荐

  1. 一文为你详解2D与3D人脸识别有什么区别?

    最近业界内刮起了一股"人脸识别安全"的大讨论,小到个人大到超市以及银行,都在使用这个刷脸认证或支付,说它好吧,确实解决了无接触,快速高效等问题,你说它不好吧,也是有原因的,比如最明 ...

  2. 3D人脸重建——PRNet网络输出的理解

    前言 之前有款换脸软件不是叫ZAO么,分析了一下,它的实现原理绝对是3D人脸重建,而非deepfake方法,找了一篇3D重建的论文和源码看看.这里对源码中的部分函数做了自己的理解和改写. 国际惯例,参 ...

  3. 七点人脸姿态估计_Github开源库简单配置即可上线的3D人脸检测工具箱

    [导读]人脸识别/检测是计算机视觉方向的一个基础的任务.小编在Github中找到了一个轻松配置即可上线使用的3D人脸检测工具箱,该工具箱包括多种特性:2D稀疏点.稠密点.3D.深度图.PNCC.UV纹 ...

  4. DECA:基于单张静态图像,进行 3D 人脸建模

    作者|神经三羊 来源|HyperAI超神经 By 超神经 内容概要:本文罗列了 3D 人脸建模常用的 3 大方法,以及基于静态图像进行人脸建模的 3 个方法.文末分享了一个 DECA 教程. 关键词: ...

  5. 最新3D人脸技术综述

    点击我爱计算机视觉标星,更快获取CVML新技术 目录 导语 3D人脸基础知识 初识3D人脸 相机模型 3D相机 3D人脸数据 3D人脸相关任务 常见Pipeline 3D人脸识别 3D人脸重建 总结 ...

  6. 一分钟详解3D人脸技术

    点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 目录 导语 3D人脸基础知识 初识3D人脸 相机模型 3D相机 3D人脸数据 3D人脸相关任务 常见P ...

  7. 2D与3D人脸识别有什么本质上的区别?

    https://www.zhihu.com/question/324123433/answer/681365180 https://www.zhihu.com/question/324123433/a ...

  8. 3D人脸技术漫游指南

    目录 导语 3D人脸基础知识 初识3D人脸 相机模型 3D相机 3D人脸数据 3D人脸相关任务 常见Pipeline 3D人脸识别 3D人脸重建 总结 导语 随着深度学习技术的推进,人脸相关任务研究也 ...

  9. 3D人脸重建硕博论文阅读

    基于人脸单视图的3D人脸重建方法研究(华南理工) 摘要 基于人脸正视图来开展 3D 人脸重建.在选择人脸正面图像后,采用主动形状模型(Active Shape Model,ASM)算法进行人脸对齐,从 ...

最新文章

  1. 精确监听AbsListView滚动至底部
  2. 文件操作工具类FileUtil
  3. 阿里云mysql5.7 窗口函数_关于阿里云centos版本,mysql5.7的一些注意事项
  4. 30 个提高Web 程序执行效率的好经验[转]
  5. Java番外篇4——BigInteger与BigDecimal
  6. 制作首页的显示列表(2017.11.29)
  7. c语言10怎么打开文件,Lecture 10 C语言文件操作
  8. CSS布局中应用BFC的例子
  9. 《大话操作系统——扎实project实践派》(8.2)(除了指令集.完)
  10. AKOJ-2021-逆序对(归并,二分)
  11. html如何转换成中文,html中文乱码怎么解决怎么造成如何避免中文乱码
  12. 香蕉树上第一根芭蕉——关于C语言中链表(动态链表静态链表)使用说明
  13. RecorderManager安卓仿微信自定义音视频录制第三方库
  14. python之html网页转PDF
  15. 我的奋斗之黑马第一天
  16. 【7】win10 病毒和威胁防护服务停止,立即重启报错
  17. More Effective C++之 Item M35:让自己习惯使用标准C++语言
  18. 云计算基础技术及解决方案介绍 - ZCCT考试
  19. OllyDBG 破解入门教程
  20. MATLAB与STK互联46:在场景中加入某个国家作为Area Target对象(GIS命令使用)

热门文章

  1. Windows10 + Visual Studio 2017 + CMake +OpenCV编译、开发环境配置及测试
  2. linux fcntl 函数 文件描述符选项控制
  3. windbg拦截驱动
  4. Linux 下查看文件的命令介绍
  5. 字符编码总结(UTF-8,UNICODE)
  6. 高级语言的编译:链接及装载过程介绍
  7. Linux内核子系统
  8. java string s_Java字符串:“String s=新字符串(”愚蠢“);
  9. 安装bigsur卡在12分钟_Big Sur为什么安装不了?macOS Big Sur无法完成安装的解决办法!...
  10. java maven清理打包运行