0
点赞
收藏
分享

微信扫一扫

网管工作实践_02_IP/MAC地址管理工具

凉夜lrs 2024-06-23 阅读 33
3d

1.一个开源的可以运行的项目(face3d/README.md at master · yfeng95/face3d · GitHub)

在配置好环境后,让我们一个一个py文件运行它(我将给出中文注释)

#这里的mat文件就是特定示例的数据的MATLAB文件,在这里是一个人头像的mat文件

注释和说明:

  • 步骤 1:加载网格数据

    • 使用 scipy.io.loadmat 加载来自 Data/example1.mat 文件的顶点、颜色和三角形数据。
  • 步骤 2:变换顶点

    • 计算缩放比例 s,使得顶点在 y 轴上的范围缩放到目标大小 180。
    • 根据角度 [0, 30, 0] 创建旋转矩阵 R
    • 应用 similarity_transform 函数对顶点进行缩放、旋转和平移变换。
  • 步骤 3:添加光照

    • 定义单个光源的位置和强度。
    • 使用 add_light 函数为顶点添加光照效果,生成 lit_colors
  • 步骤 4:变换顶点(相机变换和投影)

    • 使用 lookat_camera 函数将顶点从世界坐标系转换到相机坐标系。
    • 使用 orthographic_project 函数对相机坐标系中的顶点进行正交投影。
  • 步骤 5:渲染(生成2D图像)

    • 设定图像的高度和宽度为 256 像素。
    • 将投影后的顶点转换为图像坐标。
    • 使用 render_colors 函数基于三角形网格和光照处理后的颜色数据生成最终的渲染图像 rendering

这段代码是一个关于3D可变形模型(3DMM)的示例,它展示了如何利用该模型从参数(形状、表情、姿势)生成3D人脸,并将其渲染成2D图像。它与之前提到的 1_pipeline.py 文件是相关联的,因为它们都涉及到了使用 face3d 库中的模型和函数来处理和渲染3D人脸数据。

3DMM(3D Morphable Model)是一种用于生成和表示3D人脸模型的统计模型。它基于统计学原理,通过对大量3D人脸数据进行分析和学习,构建出一个能够表示多种不同人脸形状、表情和纹理的参数化模型。

主要步骤和功能解析:

  1. 导入和设置

    • 导入必要的库和模块,包括 ossyssubprocessnumpyscipy.ioskimage.iomatplotlib.pyplot
    • 将上级目录添加到系统路径,以便能够导入 face3d 库和其子模块。
  2. 初始化和加载模型

    • 使用 MorphableModel 类加载预训练的3DMM模型文件 BFM.mat
    • 通过随机参数获取初始的形状参数 (sp)、表情参数 (ep) 和纹理参数 (tp)。
  3. 生成人脸网格

    • 使用获取的随机参数生成顶点 (vertices) 和颜色信息 (colors)。
    • 将颜色值限制在 [0, 1] 范围内。
  4. 顶点变换和投影

    • 定义缩放系数 s 和旋转角度 angles
    • 使用 transform 方法对顶点进行变换,然后复制到 projected_vertices,表示标准相机和正交投影后的顶点位置。
  5. 渲染生成的3D人脸

    • 设定图像的大小为 256x256 像素。
    • 将变换后的顶点投影到图像坐标系。
    • 使用 render_colors 方法根据三角形网格和颜色信息生成渲染图像 image
  6. 拟合过程

    • 从生成的2D图像中提取关键点坐标 x 和对应的3DMM关键点索引 X_ind
    • 使用 fit 方法对关键点进行拟合,得到拟合后的形状参数 (fitted_sp)、表情参数 (fitted_ep)、缩放、旋转角度和平移参数。
  7. 验证拟合参数

    • 根据拟合后的参数生成新的顶点并进行变换。
    • 将变换后的顶点投影到图像坐标系并渲染成图像,保存为 fitted_image
  8. 结果保存和可视化

    • 打印并比较真实的姿势参数和拟合后的参数。
    • 将生成的图像和拟合后的图像保存到指定的文件夹 results/3dmm 中。
  9. 可视化拟合过程

    • 如果需要,可以将拟合过程中每一步的图像保存下来,生成一个 GIF 动画展示拟合的过程。

该代码展示了如何通过改变3D对象的变换参数(如缩放、旋转)和相机的参数(如位置、方向、投影类型),生成对应的2D图像,并将这些图像合成为GIF动画。这些步骤对于理解3D对象在不同变换下的表现,以及相机模型的应用非常有帮助。

2. 链接:https://pan.baidu.com/s/1s3NjgxuuCnB238GpzN-6Pw 提取码:ucqj

test.py
import numpy as np
import os
from skimage.transform import estimate_transform, warp
import cv2
from predictor import PosPrediction
import matplotlib.pyplot as plt

# 将图像从浮点数转换为无符号8位整数,将关键点绘制为绿色的圆圈,并返回绘制了关键点的图像。
def draw_kps(img, kps, point_size=2):
    # 将图像从浮点数(范围[0,1])转换为无符号8位整数(范围[0,255])
    img = np.array(img * 255, np.uint8)

    # 遍历每个关键点
    for i in range(kps.shape[0]):
        # 获取当前关键点的坐标(x, y)
        x, y = int(kps[i, 0]), int(kps[i, 1])
        
        # 在图像上绘制圆形(关键点),圆心为 (x, y),颜色为绿色 (0, 255, 0),半径为 point_size
        cv2.circle(img, (x, y), point_size, (0, 255, 0), -1)
    
    # 返回绘制了关键点的图像
    return img


# 找到旋转矩阵,参考https://github.com/YadiraF/face3d
def angle2matrix(angles):
    x, y, z = np.deg2rad(angles[0]), np.deg2rad(angles[1]), np.deg2rad(angles[2])
    # x
    Rx=np.array([[1,              0,                0],
                 [0, np.math.cos(x),  -np.math.sin(x)],
                 [0, np.math.sin(x),   np.math.cos(x)]])
    # y
    Ry=np.array([[ np.math.cos(y), 0, np.math.sin(y)],
                 [              0, 1,              0],
                 [-np.math.sin(y), 0, np.math.cos(y)]])
    # z
    Rz=np.array([[np.math.cos(z), -np.math.sin(z), 0],
                 [np.math.sin(z),  np.math.cos(z), 0],
                 [             0,               0, 1]])

    R=Rz.dot(Ry.dot(Rx))
    return R.astype(np.float32)


# 主要功能代码
# 加载预训练的 Haar 特征级联分类器用于人脸检测
cas = cv2.CascadeClassifier('./Data/cv-data/haarcascade_frontalface_alt2.xml')
#加载测试图像
img = plt.imread('./images/test.jpg')
#转换图像颜色空间
img_gray= cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
#检测图像中的人脸
faces = cas.detectMultiScale(img_gray,2,3,0,(30,30))
#提取人脸检测框的边界框
bbox = np.array([faces[0,0],faces[0,1],faces[0,0]+faces[0,2],faces[0,1]+faces[0,3]])
#在图像上绘制人脸检测框并显示
plt.imshow(cv2.rectangle(img.copy(),(bbox[0],bbox[1]),(bbox[2],bbox[3]),(0,255,0),2))
plt.axis('off')
plt.show()
#确定人脸区域的边界框位置:
left = bbox[0]; top = bbox[1]; right = bbox[2]; bottom = bbox[3]
#计算原始人脸区域的大小:
old_size = (right - left + bottom - top)/2
#确定人脸区域的中心点:
center = np.array([right - (right - left) / 2.0, bottom - (bottom - top) / 2.0])
#确定裁剪后的区域大小:
size = int(old_size*1.6)
#定义原始人脸区域和目标区域的对应点:
src_pts = np.array([[center[0]-size/2, center[1]-size/2],
                    [center[0] - size/2, center[1]+size/2],
                    [center[0]+size/2, center[1]-size/2]])
DST_PTS = np.array([[0,0], [0,255], [255, 0]]) #图像大小256*256
#进行仿射变换:使用 skimage.transform.estimate_transform 函数进行相似性仿射变换,将原始图像中的人脸区域调整到目标大小(256x256像素)
tform = estimate_transform('similarity', src_pts, DST_PTS)
#应用仿射变换并显示结果:
img = img/255.
cropped_img = warp(img, tform.inverse, output_shape=(256, 256))

plt.imshow(cropped_img)
plt.axis('off')
plt.show()

#使用一个预训练的神经网络模型来预测裁剪后人脸图像的关键点位置
#初始化关键点预测器
pos_predictor = PosPrediction(256, 256)
#加载预训练的模型权重
pos_predictor.restore('./Data/net-data/256_256_resfcn256_weight')
#对裁剪后的人脸图像进行关键点预测
cropped_pos = pos_predictor.predict(cropped_img) #网络推断
#将裁剪图的结果重新调整
cropped_vertices = np.reshape(cropped_pos, [-1, 3]).T
z = cropped_vertices[2,:].copy()/tform.params[0,0]
cropped_vertices[2,:] = 1
#将关键点映射回原始图像空间
vertices = np.dot(np.linalg.inv(tform.params), cropped_vertices)
vertices = np.vstack((vertices[:2,:], z))
#重构原始大小的关键点位置矩阵
pos = np.reshape(vertices.T, [256, 256, 3])
#显示深度图像
plt.imshow(pos[...,2],cmap='gray')
plt.axis('off')
plt.show()

#人脸关键点
#加载关键点索引和UV映射图
uv_kpt_ind = np.loadtxt('./Data/uv-data/uv_kpt_ind.txt').astype(np.int32)
uv_face = plt.imread('./Data/uv-data/uv_face.png')
#绘制UV映射图中的关键点
plt.imshow(draw_kps(uv_face,uv_kpt_ind.T))
plt.axis('off')
plt.show()
#从三维坐标中提取人脸关键点
face_kps = pos[uv_kpt_ind[1,:],uv_kpt_ind[0,:],:]
plt.imshow(draw_kps(img.copy(),face_kps))
plt.axis('off')
plt.show()
#加载人脸点云索引和绘制
face_ind = np.loadtxt('./Data/uv-data/face_ind.txt').astype(np.int32)
all_vertices = np.reshape(pos, [256*256, -1])
vertices = all_vertices[face_ind, :]
plt.figure(figsize=(8,8))
plt.imshow(draw_kps(img.copy(),vertices[:,:2],1))
plt.axis('off')
plt.show()
#纹理映射
texture = cv2.remap(img, pos[:,:,:2].astype(np.float32), None, interpolation=cv2.INTER_NEAREST, borderMode=cv2.BORDER_CONSTANT,borderValue=(0))
plt.imshow(draw_kps(texture,uv_kpt_ind.T))
plt.axis('off')
plt.show()
#加载三角形索引和纹理
triangles = np.loadtxt('./Data/uv-data/triangles.txt').astype(np.int32)
all_colors = np.reshape(texture, [256*256, -1])
colors = all_colors[face_ind, :]
#计算三角形的深度和纹理
tri_depth = (vertices[triangles[:,0],2 ] + vertices[triangles[:,1],2] + vertices[triangles[:,2],2])/3.
tri_tex = (colors[triangles[:,0] ,:] + colors[triangles[:,1],:] + colors[triangles[:,2],:])/3.
tri_tex = tri_tex*255
#绘制三维纹理贴图
img_3D = np.zeros_like(img,dtype=np.uint8)
for i in range(triangles.shape[0]):
    cnt = np.array([(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])],dtype=np.int32)
    img_3D = cv2.drawContours(img_3D,[cnt],0,tri_tex[i],-1)
plt.imshow(img_3D/255.0)
plt.show()

'''
函数左右
旋转坐标:使用旋转矩阵 trans_mat 将原始顶点 vertices 进行旋转,得到 rotated_vertices。
拉到画布上:计算旋转后顶点的平移量,将顶点平移至画布中心。
生成图像:创建空白的 img_3D 和 mask,用于绘制旋转后的三维纹理贴图。
循环每个三角形:遍历所有三角形 (triangles.shape[0]),并绘制其轮廓。根据轮廓面积选择填充颜色,使得图像具有最大填充面积。
保存和显示:保存旋转后的图像,并显示在屏幕上。'''
def trans_angle(p, trans_mat):
    # 旋转坐标
    rotated_vertices = vertices.dot(trans_mat.T)

    # 把图像拉到画布上
    ori_x = np.min(vertices[:,0])
    ori_y = np.min(vertices[:,1])
    rot_x = np.min(rotated_vertices[:,0])
    rot_y = np.min(rotated_vertices[:,1])
    shift_x = ori_x-rot_x
    shift_y = ori_y-rot_y
    rotated_vertices[:,0] = rotated_vertices[:,0] + shift_x
    rotated_vertices[:,1] = rotated_vertices[:,1] + shift_y

    img_3D = np.zeros_like(img, dtype=np.uint8)
    mask = np.zeros_like(img, dtype=np.uint8)
    fill_area = 0
    for i in range(triangles.shape[0]):
        cnt = np.array([(rotated_vertices[triangles[i,0],0], rotated_vertices[triangles[i,0],1]),
               (rotated_vertices[triangles[i,1],0], rotated_vertices[triangles[i,1],1]),
               (rotated_vertices[triangles[i,2],0], rotated_vertices[triangles[i,2],1])], dtype=np.int32)
        mask = cv2.drawContours(mask, [cnt], 0, (255, 255, 255), -1)
        if np.sum(mask[...,0]) > fill_area:
            fill_area = np.sum(mask[...,0])
            img_3D = cv2.drawContours(img_3D, [cnt], 0, tri_tex[i], -1)
    cv2.imwrite("img/"+str(p)+".jpg", img_3D)
    cv2.imwrite("img/"+str(60-p) + ".jpg", img_3D)
    plt.imshow(img_3D)
    plt.show()
#第一个 for 循环旋转角度从 0 到 29,每次增加 2*i 度。对每个角度调用 trans_angle 函数生成旋转后的图像。
for i in range(30):
    print(i)
    trans_mat = angle2matrix((0,2*i,0))
    trans_angle(i, trans_mat)
#第二个 for 循环旋转角度从 -30 到 -1,每次减小 2*i 度。对每个角度调用 trans_angle 函数生成旋转后的图像,并以 60-p 的格式保存。
for i in range(-30,0):
    i = -31 - i
    p = abs(i) + 60
    print(p)
    trans_mat = angle2matrix((0,2*i,0))
    trans_angle(p, trans_mat)
  • 人脸检测与裁剪:使用 Haar 特征级联分类器检测人脸,并裁剪出检测到的第一个人脸区域。
  • 图像仿射变换:将裁剪后的人脸图像进行仿射变换,调整到固定大小(256x256)的图像。
  • 人脸关键点预测:使用神经网络预测人脸关键点位置。
  • 三维重建
    • 将预测得到的关键点位置映射到三维空间。
    • 使用三角网格和颜色信息对人脸进行纹理贴图和渲染。
    • 最后生成旋转后不同角度的人脸图像。
举报

相关推荐

0 条评论