Download insightface/thirdparty/face3d/mesh/render.py from AXERA-TECH/Insightface: direct link, hf CLI and curl.
- Browser
- Download file 4.6 kB
-
https://huggingface.co/AXERA-TECH/Insightface/resolve/main/insightface/thirdparty/face3d/mesh/render.py
- Command line
-
hf download hf://AXERA-TECH/Insightface/insightface/thirdparty/face3d/mesh/render.py
-
curl -L -o render.py https://huggingface.co/AXERA-TECH/Insightface/resolve/main/insightface/thirdparty/face3d/mesh/render.py
4.6 kB
| ''' | |
| functions about rendering mesh(from 3d obj to 2d image). | |
| only use rasterization render here. | |
| Note that: | |
| 1. Generally, render func includes camera, light, raterize. Here no camera and light(I write these in other files) | |
| 2. Generally, the input vertices are normalized to [-1,1] and cetered on [0, 0]. (in world space) | |
| Here, the vertices are using image coords, which centers on [w/2, h/2] with the y-axis pointing to oppisite direction. | |
| Means: render here only conducts interpolation.(I just want to make the input flexible) | |
| Author: Yao Feng | |
| Mail: yaofeng1995@gmail.com | |
| ''' | |
| from __future__ import absolute_import | |
| from __future__ import division | |
| from __future__ import print_function | |
| import numpy as np | |
| from time import time | |
| from .cython import mesh_core_cython | |
| def rasterize_triangles(vertices, triangles, h, w): | |
| ''' | |
| Args: | |
| vertices: [nver, 3] | |
| triangles: [ntri, 3] | |
| h: height | |
| w: width | |
| Returns: | |
| depth_buffer: [h, w] saves the depth, here, the bigger the z, the fronter the point. | |
| triangle_buffer: [h, w] saves the tri id(-1 for no triangle). | |
| barycentric_weight: [h, w, 3] saves corresponding barycentric weight. | |
| # Each triangle has 3 vertices & Each vertex has 3 coordinates x, y, z. | |
| # h, w is the size of rendering | |
| ''' | |
| # initial | |
| depth_buffer = np.zeros([h, w]) - 999999. #set the initial z to the farest position | |
| triangle_buffer = np.zeros([h, w], dtype = np.int32) - 1 # if tri id = -1, the pixel has no triangle correspondance | |
| barycentric_weight = np.zeros([h, w, 3], dtype = np.float32) # | |
| vertices = vertices.astype(np.float32).copy() | |
| triangles = triangles.astype(np.int32).copy() | |
| mesh_core_cython.rasterize_triangles_core( | |
| vertices, triangles, | |
| depth_buffer, triangle_buffer, barycentric_weight, | |
| vertices.shape[0], triangles.shape[0], | |
| h, w) | |
| def render_colors(vertices, triangles, colors, h, w, c = 3, BG = None): | |
| ''' render mesh with colors | |
| Args: | |
| vertices: [nver, 3] | |
| triangles: [ntri, 3] | |
| colors: [nver, 3] | |
| h: height | |
| w: width | |
| c: channel | |
| BG: background image | |
| Returns: | |
| image: [h, w, c]. rendered image./rendering. | |
| ''' | |
| # initial | |
| if BG is None: | |
| image = np.zeros((h, w, c), dtype = np.float32) | |
| else: | |
| assert BG.shape[0] == h and BG.shape[1] == w and BG.shape[2] == c | |
| image = BG | |
| depth_buffer = np.zeros([h, w], dtype = np.float32, order = 'C') - 999999. | |
| # change orders. --> C-contiguous order(column major) | |
| vertices = vertices.astype(np.float32).copy() | |
| triangles = triangles.astype(np.int32).copy() | |
| colors = colors.astype(np.float32).copy() | |
| ### | |
| st = time() | |
| mesh_core_cython.render_colors_core( | |
| image, vertices, triangles, | |
| colors, | |
| depth_buffer, | |
| vertices.shape[0], triangles.shape[0], | |
| h, w, c) | |
| return image | |
| def render_texture(vertices, triangles, texture, tex_coords, tex_triangles, h, w, c = 3, mapping_type = 'nearest', BG = None): | |
| ''' render mesh with texture map | |
| Args: | |
| vertices: [3, nver] | |
| triangles: [3, ntri] | |
| texture: [tex_h, tex_w, 3] | |
| tex_coords: [ntexcoords, 3] | |
| tex_triangles: [ntri, 3] | |
| h: height of rendering | |
| w: width of rendering | |
| c: channel | |
| mapping_type: 'bilinear' or 'nearest' | |
| ''' | |
| # initial | |
| if BG is None: | |
| image = np.zeros((h, w, c), dtype = np.float32) | |
| else: | |
| assert BG.shape[0] == h and BG.shape[1] == w and BG.shape[2] == c | |
| image = BG | |
| depth_buffer = np.zeros([h, w], dtype = np.float32, order = 'C') - 999999. | |
| tex_h, tex_w, tex_c = texture.shape | |
| if mapping_type == 'nearest': | |
| mt = int(0) | |
| elif mapping_type == 'bilinear': | |
| mt = int(1) | |
| else: | |
| mt = int(0) | |
| # -> C order | |
| vertices = vertices.astype(np.float32).copy() | |
| triangles = triangles.astype(np.int32).copy() | |
| texture = texture.astype(np.float32).copy() | |
| tex_coords = tex_coords.astype(np.float32).copy() | |
| tex_triangles = tex_triangles.astype(np.int32).copy() | |
| mesh_core_cython.render_texture_core( | |
| image, vertices, triangles, | |
| texture, tex_coords, tex_triangles, | |
| depth_buffer, | |
| vertices.shape[0], tex_coords.shape[0], triangles.shape[0], | |
| h, w, c, | |
| tex_h, tex_w, tex_c, | |
| mt) | |
| return image | |