
3D , 3D . , , . , , , . , 3D ML , .
.
, , .
IT- âVR/AR & AIâ â PHYGITALISM.
, [1] . . , , :

- , ââ ââ. , , , . 
 
- . , . , , , , . 
 

, . , , , . , . , , . , , , .
, , , . , , RGB-D , Intel Realsense Microsoft Azure Kinect, RGB-D [ (RGB + (depth map)], , , . , , .
, :
, -, . : , ? , , , RGB , ?
. â â (black box), , , / , , , 3D ML (three dimensional data machine learning problems) , Geometrical deep learning, .
, 3D ML :
- ( 3D ),
- 3D ( )
- 3D RGB (2D-to-3D),
- . 
  
 
 .1 3D ML IDF0 scheme.
 
3D ML . , . , / , 3D . [2] â , ( 3D ).
, , âCharacterizing Structural Relationships in Scenes Using Graph Kernelsâ [3] , âFast human pose estimation using 3D Zernike descriptorsâ [4] . 3D ML, . .

.2 â 3D . â , , . N , . [2].
3D ML, , . 3D ML, single image 2D-to-3D, .
, 3D .
â . , , . , , , . .
, , . , . , , , , , .
, , , .
, RGB , .. . , , .. , â , .

.3 3D : 4 , 2D .
3D ML, , , .
Python, 3D:
GitHub.
, , , pytorch CUDA .
import os
os.environ['PYOPENGL_PLATFORM'] = 'egl'
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
%matplotlib inline
import torch
from pytorch3d.utils import ico_sphere
from pytorch3d.loss import (
    chamfer_distance,
    mesh_edge_loss,
    mesh_laplacian_smoothing,
    mesh_normal_consistency
)
from pytorch3d.io import load_obj
from pytorch3d.ops import sample_points_from_meshes
from pytorch3d.structures import Meshes, Textures
from pytorch3d.renderer import (
    look_at_view_transform,
    OpenGLPerspectiveCameras,
    DirectionalLights, 
    RasterizationSettings, 
    MeshRenderer, 
    MeshRasterizer,  
    HardPhongShader
)
from mesh_to_sdf import mesh_to_sdf, sample_sdf_near_surface
import trimesh
from trimesh.voxel.creation import voxelize
if torch.cuda.is_available():
  device = torch.device('cuda:0')
  torch.cuda.set_device(device)
else:
  device = torch.device('cpu')
, [5], .
(Mesh, polygonal models)

â . , FBX, glTF, glb. .obj . , .. : , , , .
.obj ASCII ( .obj ), , , , , .
obj
v -3.4101800e-003 1.3031957e-001 2.1754370e-002
v -8.1719160e-002 1.5250145e-001 2.9656090e-002
v -3.0543480e-002 1.2477885e-001 1.0983400e-003
v -2.4901590e-002 1.1211138e-001 3.7560240e-002
...
f 1069 1647 1578
f 1058 909 939
f 421 1176 238
f 1055 1101 1042
f 238 1059 1126
f 1254 30 1261
f 1065 1071 1
f 1037 1130 1120
f 1570 2381 1585
f 2434 2502 2473
f 1632 1654 1646
...
 :
:
phygital- , , Unity 3D.
, , 3D.
sphere.obj 4 subdivision:
trimesh_sphere = trimesh.primitives.Sphere(subdivisions= 4)
sphere_mesh = ico_sphere(4, device)
verts_rgb = torch.ones_like(sphere_mesh.verts_list()[0])[None]
sphere_mesh.textures = Textures(verts_rgb=verts_rgb.to(device))
bunny.obj:
path_to_model = os.path.join("/data","bunny.obj")
bunny_trimesh = trimesh.load(path_to_model)
if isinstance(bunny_trimesh, trimesh.Scene):
    bunny_trimesh = bunny_trimesh.dump(concatenate=True)
bunny_trimesh.vertices -= bunny_trimesh.center_mass
scaling = 2 / bunny_trimesh.scale
bunny_trimesh.apply_scale(scaling=scaling)
verts, faces_idx, _ = load_obj(path_to_model)
faces = faces_idx.verts_idx
center = verts.mean(0)
verts = verts - center
scale = max(verts.abs().max(0)[0])
verts = verts / scale
verts_rgb = torch.ones_like(verts)[None]  
textures = Textures(verts_rgb=verts_rgb.to(device))
bunny_mesh = Meshes(
    verts=[verts.to(device)],   
    faces=[faces.to(device)], 
    textures=textures
)
â , , , , .
:
cameras = OpenGLPerspectiveCameras(device=device)
raster_settings = RasterizationSettings(
    image_size=1024, 
    blur_radius=0, 
    faces_per_pixel=1, 
)
ambient_color = torch.FloatTensor([[0.0, 0.0, 0.0]]).to(device)
diffuse_color = torch.FloatTensor([[1.0, 1.0, 1.0]]).to(device)
specular_color = torch.FloatTensor([[0.1, 0.1, 0.1]]).to(device)
direction = torch.FloatTensor([[1, 1, 1]]).to(device)
lights = DirectionalLights(ambient_color=ambient_color,
                           diffuse_color=diffuse_color,
                           specular_color=specular_color,
                           direction=direction,
                           device=device)
phong_renderer = MeshRenderer(
    rasterizer=MeshRasterizer(
        cameras=cameras, 
        raster_settings=raster_settings
    ),
    shader=HardPhongShader(
        device=device, 
        cameras=cameras, 
        lights=lights
        )
)
:
distance = 2.0   
elevation = 40.0   
azimuth = 0.0  
R, T = look_at_view_transform(distance, elevation, azimuth, device=device,at=((-0.02,0.1,0.0),))
image_bunny = phong_renderer(meshes_world=bunny_mesh, R=R, T=T)
image_bunny = image_bunny.cpu().numpy()
plt.figure(figsize=(13, 13))
plt.imshow(image_bunny.squeeze())
plt.grid(False)

distance = 3.0   
elevation = 40.0   
azimuth = 0.0  
R, T = look_at_view_transform(distance, elevation, azimuth, device=device,at=((-0.02,0.1,0.0),))
image_sphere = phong_renderer(meshes_world=sphere_mesh, R=R, T=T)
image_sphere = image_sphere.cpu().numpy()
plt.figure(figsize=(13, 13))
plt.imshow(image_sphere.squeeze())
plt.grid(False)

, , , , ( , ). trimesh :
bunny_trimesh.show()

, , , , . , , (watertight mesh) , .
print(
    "     bunny Xi = V - E + F =",
    bunny_trimesh.euler_number
)
print(
    "     sphere Xi = V - E + F =",
    trimesh_sphere.euler_number
)
print("Is bunny mesh watertight:", bunny_trimesh.is_watertight)
print("Is sphere mesh watertight:", trimesh_sphere.is_watertight)
print("  bunny.obj:", bunny_trimesh.volume)
print("  sphere.obj:", trimesh_sphere.volume)
(4/3)*np.pi
Out:
>>     bunny Xi = V - E + F = -2
>>     sphere Xi = V - E + F = 2
>>Is bunny mesh watertight: False
>>Is sphere mesh watertight: True
>>  bunny.obj: 0.3876657353353089
>>  sphere.obj: 4.1887902047863905
>>4.1887902047863905
(Voxels)

( . volumetric + pixel) . 3D , (). . , , , , .vox . (.. pixel and voxel art), .
, , , , , , , , . , , (1 â , 0 â ).
trimesh:
low_idx_bunny = bunny_trimesh.scale / 15
high_idx_bunny = bunny_trimesh.scale / 39
low_idx_sphere = trimesh_sphere.scale / 15
high_idx_sphere = trimesh_sphere.scale / 30
vox_high_bunny = voxelize(bunny_trimesh,pitch=high_idx_bunny)
vox_high_sphere = voxelize(trimesh_sphere,pitch=high_idx_sphere)
print("     :", vox_high_sphere.shape)
print("     :", vox_low_sphere.shape)
print("  :\n",np.array(vox_high_sphere.matrix, dtype=np.uint8)[1])
Out:
>>     : (9, 9, 9)
>>     : (19, 19, 19)
>>  :
array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],
      dtype=uint8)
:
:
, trimesh :
vox_high_sphere.show()
vox_low_sphere.show()

, - , - , , . . , , , , [6] OGN (Octree Generating Networks), , .
(Point clouds)

. -. () , . . (RGBD), . 2.5D, , , , . RGBD .
, .pcd , .ply . , , â PCL.
.ply :
plyply
format ascii 1.0
obj_info is_cyberware_data 1
obj_info is_mesh 0
obj_info is_warped 0
obj_info is_interlaced 1
obj_info num_cols 512
obj_info num_rows 400
obj_info echo_rgb_offset_x 0.013000
obj_info echo_rgb_offset_y 0.153600
obj_info echo_rgb_offset_z 0.172000
obj_info echo_rgb_frontfocus 0.930000
obj_info echo_rgb_backfocus 0.012660
obj_info echo_rgb_pixelsize 0.000010
obj_info echo_rgb_centerpixel 232
obj_info echo_frames 512
obj_info echo_lgincr 0.000500
element vertex 40256
property float x
property float y
property float z
element range_grid 204800
property list uchar int vertex_indices
end_header
-0.06325 0.0359793 0.0420873 
-0.06275 0.0360343 0.0425949 
-0.0645 0.0365101 0.0404362 
-0.064 0.0366195 0.0414512 
-0.0635 0.0367289 0.0424662 
-0.063 0.0367836 0.0429737 
-0.0625 0.0368247 0.0433543 
-0.062 0.0368657 0.0437349 
-0.0615 0.0369067 0.0441155 
-0.061 0.0369614 0.044623 
...
 :
:
, , .ply PointClud, .obj . , , , , , . .
, pytorch3d, :
num_points_to_sample = 25000
bunny_vert, bunny_norm = sample_points_from_meshes(
    bunny_mesh,
    num_points_to_sample ,
    return_normals=True
)
sphere_vert, sphere_norm = sample_points_from_meshes(
    sphere_mesh,
    num_points_to_sample,
    return_normals=True
)
:
def plot_pointcloud(points, elev=70, azim=-70, title=""):
    
    fig = plt.figure(figsize=(10, 10))
    ax = Axes3D(fig)
    x, y, z = points
    ax.scatter3D(x, z, -y,marker='.')  
    ax.set_xlabel('x')
    ax.set_ylabel('z')
    ax.set_zlabel('y')
    ax.set_title(title)
    ax.view_init(elev, azim)
    plt.show()
(pytorch3d):
points = sample_points_from_meshes(bunny_mesh, 5000)
points = points.clone().detach().cpu().squeeze().unbind(1)
plot_pointcloud(points, elev=190, azim=150, title='Bunny pytotch3d mesh obj')
points = sample_points_from_meshes(sphere_mesh, 3000)
points = points.clone().detach().cpu().squeeze().unbind(1)
plot_pointcloud(points, elev=190, azim=130, title='Sphere pytotch3d mesh obj')

( 3D , , ) , , 3D ML. 2D-to-3D, , PC2Mesh ( ).
/ (CAD models, functions)

(. . ) . , , , , , . (), CAD CAM . , . , , CAD .
, , : , , , , , ( [5]).
3D ML .. signed distance function (SDF) â , . .
3D , .. , â , .
, :
: . , DeepSDF [10]. mesh_to_sdf, SDF 3D .
SDF :
center_mass = bunny_trimesh.center_mass
query_points = np.array([[center_mass],[[3,3,3]]])
for point in query_points:
    print(
        "SDF{0} = {1}".format(point[0],mesh_to_sdf(bunny_trimesh,point)[0])
)
Out:
>>SDF[-0.00036814  0.01044934 -0.00012521] = -0.26781705021858215
>>SDF[3. 3. 3.] = 4.746691703796387
center_mass = trimesh_sphere.center_mass
query_points = np.array([[center_mass],[[3,3,3]]])
for point in query_points:
    print(
        "SDF{0} = {1}".format(point[0],mesh_to_sdf(trimesh_sphere,point)[0])
)
Out:
>>SDF[ 0.0000000e+00  0.0000000e+00 -8.8540061e-18] = -0.9988667964935303
>>SDF[3. 3. 3.] = 4.195330619812012
SDF, :
points, sdf = sample_sdf_near_surface(trimesh_sphere, number_of_points=5000)
fig = plt.figure(figsize=(20, 18))
ax = fig.add_subplot(111, projection="3d")
ax.view_init(elev=70, azim=-70)
ax.scatter(points[:, 0], points[:, 1], zs=-points[:, 2], c=sdf, cmap="hot_r")
points, sdf = sample_sdf_near_surface(bunny_trimesh, number_of_points=5000)
fig = plt.figure(figsize=(20, 18))
ax = fig.add_subplot(111, projection="3d")
ax.view_init(elev=70, azim=-70)
ax.scatter(points[:, 0], points[:, 1], zs=-points[:, 2], c=sdf, cmap="hot_r")

, SDF .
raymarching , ( SDF). GitHub (raymarch_sdf.ipynb) raymarchng . , , raymarching :

, - , SDF. . SDF ( ). . , . . . , 1024.
3D . , SDF .
, ( Unity) ( ).

:
:
, . , , Multiresolution IsoSurface Extraction, Occupancy Net [5], , [7].

.4 Multiresolution IsoSurface Extraction. . . . .
, : G â V â . , . , , . , 3D. .

.5 . 6 ââ â , .
, , . 3. . â â, , . , [8] [9], , (data driven), . , Occupancy Net., , , .
, â data science . , , .
: , â ? , , , .
, , 3D ML, 3D ML , 2D-to-3D .
- . : , . , . / , , 2018 ., 1408 . 
 
- Novotni, Marcin and Reinhard Klein. âShape retrieval using 3D Zernike descriptors.â Computer-Aided Design 36 (2004): 1047-1062. [project page] 
 
- Fisher, Matthew & Savva, Manolis & Hanrahan, Pat. (2011). Characterizing Structural Relationships in Scenes Using Graph Kernels. ACM Trans. Graph⊠30. 34. 10.1145/2010324.1964929. 
 
- BerjĂłn, Daniel & MorĂĄn, Francisco. (2012). Fast human pose estimation using 3D Zernike descriptors. Proceedings of SPIE â The International Society for Optical Engineering. 8290. 19-. 10.1117/12.908963. 
 
- Mescheder, Lars & Oechsle, Michael & Niemeyer, Michael & Nowozin, Sebastian & Geiger, Andreas. (2018). Occupancy Networks: Learning 3D Reconstruction in Function Space. [code] 
 
- Tatarchenko, Maxim & Dosovitskiy, Alexey & Brox, Thomas. (2017). Octree Generating Networks: Efficient Convolutional Architectures for High-resolution 3D Outputs. [code] 
 
- Bao, Fan & Sun, Yankui & Tian, Xiaolin & Tang, Zesheng. (2007). Multiresolution Isosurface Extraction with View-Dependent and Topology Preserving. 2007 IEEE/ICME International Conference on Complex Medical Engineering, CME 2007. 521-524. 10.1109/ICCME.2007.4381790. 
 
- J. C. Carr, R. K. Beatson, J. B. Cherrie, T. J. Mitchell, W. R. Fright, B. C. McCallum, and T. R. Evans. Reconstruction and representation of 3d objects with radial basis functions. In SIGGRAPH, pages 67â76. ACM, 2001 
 
- M. Kazhdan and H. Hoppe. Screened poisson surface reconstruction. ACM TOG, 32(3):29, 2013. 
 
- J. J. Park, P. Florence, J. Straub, R. Newcombe, and S. Lovegrove. DeepSDF: Learning continuous signed distance functions for shape representation. arXiv.org, 2019. [code]