Pour MAC

https://forums.developer.nvidia.com/t/pytorch-for-jetson-version-1-10-now-available/72048

https://automaticaddison.com/how-to-write-a-python-program-for-nvidia-jetson-nano/

Pour MAC

conda create -n pytorch3d python=3.8
conda activate pytorch3d

Installation de pytorch

conda install pytorch==1.7.1 torchvision==0.8.2 torchaudio==0.7.2 -c pytorch
conda install -c conda-forge -c fvcore -c iopath fvcore iopath
import torch
x = torch.rand(5, 3)
print(x)

Installation pytorch3d

pip install pytorch3d

ou

pip install "git+https://github.com/facebookresearch/pytorch3d.git"

Pour window

Installation de CUDA Toolkit 10.2

https://developer.nvidia.com/cuda-10.2-download-archive?target_os=Windows&target_arch=x86_64&target_version=10&target_type=exelocal

Installation des Outils de génération Microsoft C++

https://visualstudio.microsoft.com/fr/visual-cpp-build-tools/

Travail en local

git clone https://github.com/facebookresearch/pytorch3d.git
conda create -n pytorch3d python=3.8
conda activate pytorch3d
conda install -c pytorch pytorch=1.6.0 torchvision cudatoolkit=10.2
conda install -c conda-forge -c fvcore -c iopath fvcore iopath
curl -LO https://github.com/NVIDIA/cub/archive/1.10.0.tar.gz
tar xzf 1.10.0.tar.gz
conda install jupyter
pip install scikit-image matplotlib imageio plotly opencv-python
pip install -e .

Corrections des 3 fichiers : argument_spec.h et module.h et cast.h

https://github.com/facebookresearch/pytorch3d/issues/323

Lancer le script setup.py avec en parametre install et le param env

CUB_HOME=$PWD/cub-1.10.0
FORCE_CUDA=1

Génération unitaire

import os
import torch
from jedi.api.refactoring import inline
from pytorch3d.io import load_obj, save_obj
from pytorch3d.structures import Meshes
from pytorch3d.utils import ico_sphere
from pytorch3d.ops import sample_points_from_meshes
from pytorch3d.loss import (
    chamfer_distance,
    mesh_edge_loss,
    mesh_laplacian_smoothing,
    mesh_normal_consistency,
)
import numpy as np
from tqdm.notebook import tqdm
#%matplotlib notebook
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import matplotlib as mpl
mpl.rcParams['savefig.dpi'] = 80
mpl.rcParams['figure.dpi'] = 80


# Set the device
if torch.cuda.is_available():
    device = torch.device("cuda:0")
else:
    device = torch.device("cpu")
    print("WARNING: CPU only, this will be slow!")

##
##      1. Load an obj file and create a Meshes object
##
print("1. Load an obj file and create a Meshes object")

# Load the dolphin mesh.
trg_obj = os.path.join('XXXXXXMOLINERO01.obj')

# We read the target 3D model using load_obj
verts, faces, aux = load_obj(trg_obj)

# verts is a FloatTensor of shape (V, 3) where V is the number of vertices in the mesh
# faces is an object which contains the following LongTensors: verts_idx, normals_idx and textures_idx
# For this tutorial, normals and textures are ignored.
faces_idx = faces.verts_idx.to(device)
verts = verts.to(device)

# We scale normalize and center the target mesh to fit in a sphere of radius 1 centered at (0,0,0).
# (scale, center) will be used to bring the predicted mesh to its original center and scale
# Note that normalizing the target mesh, speeds up the optimization but is not necessary!
center = verts.mean(0)
verts = verts - center
scale = max(verts.abs().max(0)[0])
verts = verts / scale

# We construct a Meshes structure for the target mesh
trg_mesh = Meshes(verts=[verts], faces=[faces_idx])

# We initialize the source shape to be a sphere of radius 1
src_mesh = ico_sphere(4, device)

##
##      2. Visualize the source and target meshes
##
print("2. Visualize the source and target meshes")

def plot_pointcloud(mesh, title=""):
    # Sample points uniformly from the surface of the mesh.
    points = sample_points_from_meshes(mesh, 50) #5000
    x, y, z = points.clone().detach().cpu().squeeze().unbind(1)
    fig = plt.figure(figsize=(5, 5))
    ax = Axes3D(fig)
    ax.scatter3D(x, z, -y)
    ax.set_xlabel('x')
    ax.set_ylabel('z')
    ax.set_zlabel('y')
    ax.set_title(title)
    ax.view_init(190, 30)
    plt.show()

# %matplotlib notebook
plot_pointcloud(trg_mesh, "Target mesh")
plot_pointcloud(src_mesh, "Source mesh")

##
##      3. Optimization loop
##
print("3. Optimization loop")

# We will learn to deform the source mesh by offsetting its vertices
# The shape of the deform parameters is equal to the total number of vertices in src_mesh
deform_verts = torch.full(src_mesh.verts_packed().shape, 0.0, device=device, requires_grad=True)

# The optimizer
optimizer = torch.optim.SGD([deform_verts], lr=1.0, momentum=0.9)

# Number of optimization steps
Niter = 2000
# Weight for the chamfer loss
w_chamfer = 1.0
# Weight for mesh edge loss
w_edge = 1.0
# Weight for mesh normal consistency
w_normal = 0.01
# Weight for mesh laplacian smoothing
w_laplacian = 0.1
# Plot period for the losses
plot_period = 250
loop = tqdm(range(Niter))

chamfer_losses = []
laplacian_losses = []
edge_losses = []
normal_losses = []

#% matplotlib inline

for i in loop:
    # Initialize optimizer
    optimizer.zero_grad()

    # Deform the mesh
    new_src_mesh = src_mesh.offset_verts(deform_verts)

    # We sample 5k points from the surface of each mesh
    sample_trg = sample_points_from_meshes(trg_mesh, 50) #5000
    sample_src = sample_points_from_meshes(new_src_mesh, 50) #5000

    # We compare the two sets of pointclouds by computing (a) the chamfer loss
    loss_chamfer, _ = chamfer_distance(sample_trg, sample_src)

    # and (b) the edge length of the predicted mesh
    loss_edge = mesh_edge_loss(new_src_mesh)

    # mesh normal consistency
    loss_normal = mesh_normal_consistency(new_src_mesh)

    # mesh laplacian smoothing
    loss_laplacian = mesh_laplacian_smoothing(new_src_mesh, method="uniform")

    # Weighted sum of the losses
    loss = loss_chamfer * w_chamfer + loss_edge * w_edge + loss_normal * w_normal + loss_laplacian * w_laplacian

    # Print the losses
    loop.set_description('total_loss = %.6f' % loss)

    # Save the losses for plotting
    chamfer_losses.append(loss_chamfer)
    edge_losses.append(loss_edge)
    normal_losses.append(loss_normal)
    laplacian_losses.append(loss_laplacian)

    # Plot mesh
    if i % plot_period == 0:
        plot_pointcloud(new_src_mesh, title="iter: %d" % i)
        ##
        # Fetch the verts and faces of the final predicted mesh
        final_verts, final_faces = new_src_mesh.get_mesh_verts_faces(0)

        # Scale normalize back to the original target size
        final_verts = final_verts * scale + center

        # Store the predicted mesh using save_obj
        final_obj = os.path.join('./V4/', "frame_%d.obj" % i)
        save_obj(final_obj, final_verts, final_faces)
        ##



    # Optimization step
    loss.backward()
    optimizer.step()

##
##      4. Visualize the loss
##
print("4. Visualize the loss")

fig = plt.figure(figsize=(13, 5))
ax = fig.gca()
ax.plot(chamfer_losses, label="chamfer loss")
ax.plot(edge_losses, label="edge loss")
ax.plot(normal_losses, label="normal loss")
ax.plot(laplacian_losses, label="laplacian loss")
ax.legend(fontsize="16")
ax.set_xlabel("Iteration", fontsize="16")
ax.set_ylabel("Loss", fontsize="16")
ax.set_title("Loss vs iterations", fontsize="16");

##
##      5. Save the predicted mesh
##

# Fetch the verts and faces of the final predicted mesh
final_verts, final_faces = new_src_mesh.get_mesh_verts_faces(0)

# Scale normalize back to the original target size
final_verts = final_verts * scale + center

# Store the predicted mesh using save_obj
final_obj = os.path.join('./V4/', 'final_model.obj')
save_obj(final_obj, final_verts, final_faces)

print("FIN")

Génération à partir d’un dossier

import os
import torch

from pytorch3d.io import load_obj, save_obj
from pytorch3d.structures import Meshes
from pytorch3d.ops import sample_points_from_meshes
from pytorch3d.loss import (
    chamfer_distance,
    mesh_edge_loss,
    mesh_laplacian_smoothing,
    mesh_normal_consistency,
)

from tqdm.notebook import tqdm

# Set the device
if torch.cuda.is_available():
    device = torch.device("cuda:0")
else:
    device = torch.device("cpu")
    print("WARNING: CPU only, this will be slow!")

# Load files
files = os.listdir('./in')

def hybridation(trg_name, src_name):
    print("1. Load an obj file and create a Meshes object")

    ### TRG
    trg_obj = os.path.join('in/'+trg_name)

    verts, faces, aux = load_obj(trg_obj)
    faces_idx = faces.verts_idx.to(device)
    verts = verts.to(device)

    center_trg = verts.mean(0)
    verts = verts - center_trg
    scale_trg = max(verts.abs().max(0)[0])
    verts = verts / scale_trg

    trg_mesh = Meshes(verts=[verts], faces=[faces_idx])

    ### SRC
    src_obj = os.path.join('in/'+src_name)

    verts, faces, aux = load_obj(src_obj)
    faces_idx = faces.verts_idx.to(device)
    verts = verts.to(device)

    center = verts.mean(0)
    verts = verts - center
    scale = max(verts.abs().max(0)[0])
    verts = verts / scale

    src_mesh = Meshes(verts=[verts], faces=[faces_idx])

    print("2. Optimization loop")

    # We will learn to deform the source mesh by offsetting its vertices
    # The shape of the deform parameters is equal to the total number of vertices in src_mesh
    deform_verts = torch.full(src_mesh.verts_packed().shape, 0.0, device=device, requires_grad=True)

    # The optimizer
    optimizer = torch.optim.SGD([deform_verts], lr=1.0, momentum=0.9)

    # Number of optimization steps
    Niter = 2 #2000
    # Weight for the chamfer loss
    w_chamfer = 1.0
    # Weight for mesh edge loss
    w_edge = 1.0
    # Weight for mesh normal consistency
    w_normal = 0.01
    # Weight for mesh laplacian smoothing
    w_laplacian = 0.1
    # Plot period for the losses
    plot_period = 250
    loop = tqdm(range(Niter))

    chamfer_losses = []
    laplacian_losses = []
    edge_losses = []
    normal_losses = []

    for i in loop:
        # Initialize optimizer
        optimizer.zero_grad()

        # Deform the mesh
        new_src_mesh = src_mesh.offset_verts(deform_verts)

        # We sample 5k points from the surface of each mesh
        sample_trg = sample_points_from_meshes(trg_mesh, 5) #5000
        sample_src = sample_points_from_meshes(new_src_mesh, 5) #5000

        # We compare the two sets of pointclouds by computing (a) the chamfer loss
        loss_chamfer, _ = chamfer_distance(sample_trg, sample_src)

        # and (b) the edge length of the predicted mesh
        loss_edge = mesh_edge_loss(new_src_mesh)

        # mesh normal consistency
        loss_normal = mesh_normal_consistency(new_src_mesh)

        # mesh laplacian smoothing
        loss_laplacian = mesh_laplacian_smoothing(new_src_mesh, method="uniform")

        # Weighted sum of the losses
        loss = loss_chamfer * w_chamfer + loss_edge * w_edge + loss_normal * w_normal + loss_laplacian * w_laplacian

        # Print the losses
        loop.set_description('total_loss = %.6f' % loss)

        # Save the losses for plotting
        chamfer_losses.append(loss_chamfer)
        edge_losses.append(loss_edge)
        normal_losses.append(loss_normal)
        laplacian_losses.append(loss_laplacian)

        # Optimization step
        loss.backward()
        optimizer.step()

    print("4. Save the predicted mesh")

    # Fetch the verts and faces of the final predicted mesh
    final_verts, final_faces = new_src_mesh.get_mesh_verts_faces(0)

    # Scale normalize back to the original target size
    final_verts = final_verts * scale_trg + center_trg

    # Store the predicted mesh using save_obj
    final_obj = os.path.join('./out/', trg_name[:-4]+'@'+src_name[:-4]+'.obj')
    save_obj(final_obj, final_verts, final_faces)

    print("5. End")

for trg_name in files:
    if '.obj' in trg_name:
        for src_name in files:
            if '.obj' in src_name:
                if trg_name != src_name:
                    print(trg_name[:-4]+'@'+src_name[:-4])
                    hybridation(trg_name, src_name)