从UV位置图获得3D人脸

2023-05-16

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 Map

global resolution_op
resolution_op = 256
# 设置参数
uv_h = uv_w = 256
image_h = image_w = 256

image_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 vertices


def 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 kpt


kpt = 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 = """ply
    format ascii 1.0
    element vertex {}
    property float x
    property float y
    property float z
    element face {}
    property list uchar int vertex_indices
    end_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.shape
    vertices[:, 0] = np.minimum(np.maximum(vertices[:, 0], 0), w - 1)  # x
    vertices[:, 1] = np.minimum(np.maximum(vertices[:, 1], 0), h - 1)  # y
    ind = np.round(vertices).astype(np.int32)
    colors = image[ind[:, 1], ind[:, 0], :]  # n x 3

    return colors


image_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: str
        vertices: shape = (nver, 3)
        colors: shape = (nver, 3)
        triangles: shape = (ntri, 3)
    '''
    triangles = triangles.copy()
    triangles += 1  # meshlab start with 1

    if obj_name.split('.')[-1] != 'obj':
        obj_name = obj_name + '.obj'

    # write obj
    with open(obj_name, 'w') as f:

        # write vertices & colors
        for 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.shape
        for 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 预测的效果,条纹效果严重。

代码和文件链接

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从UV位置图获得3D人脸 的相关文章

  • 硬核解读 | 一篇文章看透百度XuperChain系统架构

    本期 百度超级链学院 邀请来资深研发工程师 xff0c 为各位开发者带来超硬核解读 xff0c 揭秘百度XuperChain系统架构到底是怎样的 xff01 背景 百度XuperChain在2019年5月底正式宣布开源 在开源后很快获得了开
  • 基于深度学习的视频检测(三) 目标跟踪

    搭建环境 Ubuntu16 04 43 CUDA9 43 cudnn7 43 python3 5 43 源码编译Tensorflow1 4 43 opencv3 3 基于 darkflow yolo v2 和 sort deep sort
  • 基于深度学习的视频检测(六) 行人计数,监控视频人员管理

    搭建 darkflow与 sort deep sort 环境 修改 darkflow net yolov2 predict py span class hljs keyword import span numpy span class hl
  • C++面试 设计模式之单例模式(C++11)

    单例模式 确保一个类只有一个实例 xff0c 并提供了一个全局访问点 单例模式 xff0c 可以说设计模式中最常应用的一种模式了 xff0c 据说也是面试官最喜欢的题目 但是如果没有学过设计模式的人 xff0c 可能不会想到要去应用单例模式
  • 异常检测 Deep One-Class Classification

    ICML 2018 参考 https www zhihu com question 22365729 answer 115048306 https zhuanlan zhihu com p 32784067 https blog csdn
  • TensorFlow和Keras解决数据量过大内存溢出

    将上万张图片的路径一次性读到内存中 xff0c 自己实现一个分批读取函数 xff0c 在该函数中根据自己的内存情况设置读取图片 xff0c 只把这一批图片读入内存中 xff0c 然后交给模型 xff0c 模型再对这一批图片进行分批训练 xf
  • LQ-Nets: Learned Quantization for Highly Accurate and Compact Deep Neural Networks

    ECCV 2018 ABSTRACT 虽然权重和激活值的量化是深度神经网络 xff08 DNN xff09 压缩的有效方法 xff0c 并且具有很大的潜力来提高利用位操作的推理速度 xff0c 但是在量化模型和full precision模
  • 关于事件的理解

    以前的时候 xff0c 事件这个东西虽然说是经常用 xff0c 但是没有真正意义上去理解它 xff0c 为什么要用事件 xff0c 事件有什么好处 xff0c 明明可以直接用方法实现为什么还要去用事件 xff0c 说到底 xff0c 事件就
  • Maven打包常见问题

    Maven打包常见问题 1 Maven 打包时 无法将scope为system的jar文件打包进war和jar中 分析问题 通过对maven打包的生命周期进行分析 在package阶段未将scope为system的jar打包到war或者ja
  • VS2015 无法启动程序“***\\***.exe” 系统找不到指定的文件

    问题 xff1a 无法启动程序 exe 系统找不到指定的文件 解决方案 xff1a 将链接器 gt 常规 gt 输出文件中的内容手动改为 OutDir Target Name TargetExt 或者选择 lt 从父级或项目默认设置继承 g
  • VS2015 MFC 类向导 “未将对象引用设置到对象的实例”

    问题描述 xff1a MFC工程跨机器移动后 xff0c 使用类向导 xff0c 提示 34 未将对象引用设置到对象的实例 34 解决方法 xff1a 删除MFC工程中的 vs目录
  • qt 编译运行步骤

    1 先qmake 由 pro文件生成Makefile文件到构建目录 xff0c makefile文件保存了编译器和连接器的参数选项 还表述了所有源文件之间的关系 源代码文件需要的特定的包含文件 可执行文件要求包含的目标文件模 块及库等 构建
  • VS2015 插件

    Visual Assist 代码颜色 xff0c 关键字高亮 Inden Guides Mode 缩进辅助线 FeinBrace 括号跳转 Toggle Comment 快速注释 解除注释
  • VS内存泄漏定位方法

    内存泄漏检测宏定义 ifdef DEBUG define DEBUG CLIENTBLOCK new CLIENT BLOCK FILE LINE else define DEBUG CLIENTBLOCK endif DEBUG defi
  • tar: 由于前次错误,将以上次的错误状态退出

    问题描述 tar cvfz test tar gz test tar test tar gz xff1a 无法 stat 没有那个文件或目录 test rwt tar 由于前次错误 xff0c 将以上次的错误状态退出 原因分析 xff1a
  • VSCode登录Microsoft账户无效

    现象 经过上述两步 xff0c 并没有弹出登录界面 解决方法 xff1a 使用腾讯电脑管家 电脑诊所 IE浏览器出错崩溃 修复后重新执行上述两步 xff0c 可以正常登录
  • Qt munmap_chunk(): invalid pointer

    现象 xff1a 软件退出时报munmap chunk invalid pointer 产生原因 xff1a 单例了窗口采用的静态变量写法 并且把单例的窗口添加到了另一个窗口中 软件退出时 xff0c 父窗口析构了单例的窗口 Qt的对象管理
  • node.js 跨域访问

    配置 node js http server启动方式 http span class token operator span server span class token operator span p span class token
  • Linux修改系统编码方法总结

    Linux系统安装后 xff0c 发现中文显示乱码 因为系统编码为en US UTF 8 xff0c 应改为支持中文的编码 xff08 即zh CN UTF 8 xff09 检查系统编码 英文环境如下 xff1a root 64 local

随机推荐

  • std::cout输出十六进制数据

    std vector lt uint8 t gt data 0x11 0x22 0x33 0x99 0xff std ofstream ofs 34 test txt 34 std ios app for int i 61 0 i lt d
  • ubuntu 缺少lsusb lspci insmod等

    lsusb gt usbutils lspci gt pciutils insmod gt module init tools
  • hexo知识点

    配置环境 安装Node xff08 必须 xff09 作用 xff1a 用来生成静态页面的 到Node js 官网下载相应平台的最新版本 xff0c 一路安装即可 安装Git xff08 必须 xff09 作用 xff1a 把本地的hexo
  • 安装Ubuntu下的开发工具

    安装Ubuntu下的开发工具 安装Ubuntu下的开发工具 刚安装好的Ubuntu xff0c 还缺乏很多开发工具 这些工具都可以通过网络进行安装 如果网络不佳 xff0c 也可以使用光盘中的工具包 如果要使用光盘中的工具包 xff0c 先
  • 基于深度学习场景分类算法

    目前出现的相对流行的场景分类方法主要有以下三类 xff1a xff08 1 xff09 基于对象的场景分类 xff1a 这种分类方法以对象为识别单位 xff0c 根据场景中出现的特定对象来区分不同的场景 xff1b 基于视觉的场景分类方法大
  • Linear Discriminant Analysis(LDA)

    好久没有整理最近的一些算法了 xff0c 今天趁着跑数据的过程整理一下LDA算法 该算法在很多地方都有使用 xff1a 语音识别 xff0c 说话人识别等等 xff0c 那么今天在这里就为大家详细介绍一下 xff0c 最终把matlab代码
  • MuQSS调度器之设计文档(一)

    MuQSS调度器之设计文档 准备分析Multiple queue skiplist scheduler调度器的实现 此篇是第一篇 本文翻译自sched MuQSS txt文档 很多还没搞懂 xff0c 需要去分析下代码 涉及很多操作系统基础
  • Arcgis Engine中检索 COM 类工厂中 CLSID 为{*} 的组件失败,原因是出现以下错误: 80040111 的解决方法

    最近在学习Arcgis Engine开发时 xff0c 创建实例时经常会出现下列错误 网上搜索到的解决办法有两种 xff1a 1 操作系统版本问题 如果是在Win7 64版本下 xff0c 可能出现该问题 xff0c 需要将把配置管理器里的
  • Ubuntu Server 14.04部署ONOS

    参考官网 xff1a https wiki onosproject org display ONOS Installing 43 and 43 Running 43 ONOS 由于笔者习惯ssh xff0c ubuntu默认没有开启ssh
  • Liunx系列-用户和权限

    rw r r 表示文件类型rw rw 表示文件所有者对文件的权限r r 表示文件所在组对该文件的权限r r 表示其他组对该文件的权限 r表示可读 xff0c 用数字4表示w表示可写 xff0c 用数字2表示x表示可执行 xff0c 用数字1
  • .net core程序发布部署

    发布后的包才能往IIS上放 xff0c 并且必选安装IIS模块里面的服务 xff08 AspNetCoreModuleV2 xff09
  • webapi 内使用jsonp方式(jQuery)

    前端部分代码 后端部分代码 xff1a HttpGet Route 34 ListenExport 34 public HttpResponseMessage ListenExport string url 61 HttpContext C
  • 微信 {"errcode":48001,"errmsg":"api unauthorized, hints: [ req_id: 1QoCla0699ns81 ]"}

    34 errcode 34 48001 34 errmsg 34 34 api unauthorized hints req id 1QoCla0699ns81 34 声明 xff1a 是已认证的服务号 这个问题已解决 xff01 xff0
  • DotNet Core5000端口无法绑定解决方案(Unable to bind to http://localhost:5000 on the IPv6 loopback interface)

    解释 xff1a 5000端口不能够绑定 xff0c 所以绑定到其他端口进行Nginx反向代理 解决方案 第一步 添加host json 34 server urls 34 34 http 8010 34 第二步 centos发布DotNe
  • CentOS服务器署Springboot的java项目最简单操作步骤

    CentOS服务器署Springboot的java项目最简单操作步骤 准备工作 1 首先本地有一个能跑起来正常的 java 项目的 jar 包 2 有一个前端项目 可以仅是一个 index html 文件 3 需要备案好的域名 可选 否则只
  • SQL Server 定时备份

    前言 由于公司的业务需求 xff0c 防止数据丢失 xff0c 防止意外发生 所以需要备份 xff0c 之前没搞过这玩意儿 xff0c 所以自己动手先练习一下 开始 启动SQL Server 代理服务 xff08 确保SQL Server
  • SSIS数据定时同步方案

    第一次接触到SSIS xff0c 借此机会学习一下 SSIS是Microsoft SQL Server Integration Services的简称 xff0c 是生成高性能数据集成解决方案 xff08 包括数据仓库的提取 转换和加载 E
  • SQL Server数据库同步Oracle数据

    第一步 配置Oracle服务 电脑上需要安装Oracle客户端 xff08 因为需要Oracle的驱动 xff09 Oracle win64 11gR2 client 配置Oracle服务 第二步 配置SQL Server链接服务器 xff
  • SR04声波传感器原理详解及其Arduino编程——人人都能玩硬件

    通过前两篇文章 xff0c 我们已经熟悉了Arduino的基本GPIO编程和PC与Arduino的串口通信 接下来我们将开始一边学习各种传感器操作 xff0c 一边深入学习Arduino编程 再开始编程之前 xff0c 首先我们需要熟悉SR
  • 从UV位置图获得3D人脸

    1 这部分主要写从UV位置图获得3D人脸 xff0c 并不包括如何产生UV位置图 我已经获取一张图片的UV位置图 xff0c 如下图 xff1a xff08 a 裁剪后的人脸区域 xff09 xff08 b UV位置图 xff08 仅用来展