mirror of
https://github.com/facebookresearch/pytorch3d.git
synced 2025-08-02 03:42:50 +08:00
510 lines
55 KiB
HTML
510 lines
55 KiB
HTML
<!DOCTYPE html><html lang=""><head><meta charSet="utf-8"/><meta http-equiv="X-UA-Compatible" content="IE=edge"/><title>PyTorch3D · A library for deep learning with 3D data</title><meta name="viewport" content="width=device-width, initial-scale=1.0"/><meta name="generator" content="Docusaurus"/><meta name="description" content="A library for deep learning with 3D data"/><meta property="og:title" content="PyTorch3D · A library for deep learning with 3D data"/><meta property="og:type" content="website"/><meta property="og:url" content="https://pytorch3d.org/"/><meta property="og:description" content="A library for deep learning with 3D data"/><meta property="og:image" content="https://pytorch3d.org/img/pytorch3dlogoicon.svg"/><meta name="twitter:card" content="summary"/><meta name="twitter:image" content="https://pytorch3d.org/img/pytorch3dlogoicon.svg"/><link rel="shortcut icon" href="/img/pytorch3dfavicon.png"/><link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css"/><script>
|
||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
|
||
|
||
ga('create', 'UA-157376881-1', 'auto');
|
||
ga('send', 'pageview');
|
||
</script><script type="text/javascript" src="https://buttons.github.io/buttons.js"></script><script src="/js/scrollSpy.js"></script><link rel="stylesheet" href="/css/main.css"/><script src="/js/codetabs.js"></script></head><body><div class="fixedHeaderContainer"><div class="headerWrapper wrapper"><header><a href="/"><img class="logo" src="/img/pytorch3dfavicon.png" alt="PyTorch3D"/><h2 class="headerTitleWithLogo">PyTorch3D</h2></a><div class="navigationWrapper navigationSlider"><nav class="slidingNav"><ul class="nav-site nav-site-internal"><li class=""><a href="/docs/why_pytorch3d" target="_self">Docs</a></li><li class=""><a href="/tutorials" target="_self">Tutorials</a></li><li class=""><a href="https://pytorch3d.readthedocs.io/" target="_self">API</a></li><li class=""><a href="https://github.com/facebookresearch/pytorch3d" target="_self">GitHub</a></li></ul></nav></div></header></div></div><div class="navPusher"><div class="docMainWrapper wrapper"><div class="container docsNavContainer" id="docsNav"><nav class="toc"><div class="toggleNav"><section class="navWrapper wrapper"><div class="navBreadcrumb wrapper"><div class="navToggle" id="navToggler"><div class="hamburger-menu"><div class="line1"></div><div class="line2"></div><div class="line3"></div></div></div><h2><i>›</i><span></span></h2><div class="tocToggler" id="tocToggler"><i class="icon-toc"></i></div></div><div class="navGroups"><div class="navGroup"><h3 class="navGroupCategoryTitle">Tutorials</h3><ul class=""><li class="navListItem"><a class="navItem" href="/tutorials/">Overview</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle">3D operators</h3><ul class=""><li class="navListItem"><a class="navItem" href="/tutorials/deform_source_mesh_to_target_mesh">Fit Mesh</a></li><li class="navListItem"><a class="navItem" href="/tutorials/bundle_adjustment">Bundle Adjustment</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle">Rendering</h3><ul class=""><li class="navListItem"><a class="navItem" href="/tutorials/render_textured_meshes">Render Textured Meshes</a></li><li class="navListItem"><a class="navItem" href="/tutorials/render_densepose">Render DensePose Meshes</a></li><li class="navListItem"><a class="navItem" href="/tutorials/render_colored_points">Render Colored Pointclouds</a></li><li class="navListItem"><a class="navItem" href="/tutorials/fit_textured_mesh">Fit a Mesh with Texture via Rendering</a></li><li class="navListItem navListItemActive"><a class="navItem" href="/tutorials/camera_position_optimization_with_differentiable_rendering">Camera Position Optimization with Differentiable Rendering</a></li><li class="navListItem"><a class="navItem" href="/tutorials/fit_textured_volume">Fit a volume via raymarching</a></li><li class="navListItem"><a class="navItem" href="/tutorials/fit_simple_neural_radiance_field">Fit a simplified NeRF via raymarching</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle">Dataloaders</h3><ul class=""><li class="navListItem"><a class="navItem" href="/tutorials/dataloaders_ShapeNetCore_R2N2">Data loaders for ShapeNetCore and R2N2</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle">Implicitron</h3><ul class=""><li class="navListItem"><a class="navItem" href="/tutorials/implicitron_volumes">Training a custom volumes function with implicitron</a></li><li class="navListItem"><a class="navItem" href="/tutorials/implicitron_config_system">Implicitron config system deep dive</a></li></ul></div></div></section></div><script>
|
||
var coll = document.getElementsByClassName('collapsible');
|
||
var checkActiveCategory = true;
|
||
for (var i = 0; i < coll.length; i++) {
|
||
var links = coll[i].nextElementSibling.getElementsByTagName('*');
|
||
if (checkActiveCategory){
|
||
for (var j = 0; j < links.length; j++) {
|
||
if (links[j].classList.contains('navListItemActive')){
|
||
coll[i].nextElementSibling.classList.toggle('hide');
|
||
coll[i].childNodes[1].classList.toggle('rotate');
|
||
checkActiveCategory = false;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
coll[i].addEventListener('click', function() {
|
||
var arrow = this.childNodes[1];
|
||
arrow.classList.toggle('rotate');
|
||
var content = this.nextElementSibling;
|
||
content.classList.toggle('hide');
|
||
});
|
||
}
|
||
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
createToggler('#navToggler', '#docsNav', 'docsSliderActive');
|
||
createToggler('#tocToggler', 'body', 'tocActive');
|
||
|
||
var headings = document.querySelector('.toc-headings');
|
||
headings && headings.addEventListener('click', function(event) {
|
||
var el = event.target;
|
||
while(el !== headings){
|
||
if (el.tagName === 'A') {
|
||
document.body.classList.remove('tocActive');
|
||
break;
|
||
} else{
|
||
el = el.parentNode;
|
||
}
|
||
}
|
||
}, false);
|
||
|
||
function createToggler(togglerSelector, targetSelector, className) {
|
||
var toggler = document.querySelector(togglerSelector);
|
||
var target = document.querySelector(targetSelector);
|
||
|
||
if (!toggler) {
|
||
return;
|
||
}
|
||
|
||
toggler.onclick = function(event) {
|
||
event.preventDefault();
|
||
|
||
target.classList.toggle(className);
|
||
};
|
||
}
|
||
});
|
||
</script></nav></div><div class="container mainContainer"><div class="wrapper"><div class="tutorialButtonsWrapper"><div class="tutorialButtonWrapper buttonWrapper"><a class="tutorialButton button" download="" href="https://colab.research.google.com/github/facebookresearch/pytorch3d/blob/stable/docs/tutorials/camera_position_optimization_with_differentiable_rendering.ipynb" target="_blank"><img class="colabButton" align="left" src="/img/colab_icon.png"/>Run in Google Colab</a></div><div class="tutorialButtonWrapper buttonWrapper"><a class="tutorialButton button" download="" href="/files/camera_position_optimization_with_differentiable_rendering.ipynb" target="_blank"><svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="file-download" class="svg-inline--fa fa-file-download fa-w-12" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><path fill="currentColor" d="M224 136V0H24C10.7 0 0 10.7 0 24v464c0 13.3 10.7 24 24 24h336c13.3 0 24-10.7 24-24V160H248c-13.2 0-24-10.8-24-24zm76.45 211.36l-96.42 95.7c-6.65 6.61-17.39 6.61-24.04 0l-96.42-95.7C73.42 337.29 80.54 320 94.82 320H160v-80c0-8.84 7.16-16 16-16h32c8.84 0 16 7.16 16 16v80h65.18c14.28 0 21.4 17.29 11.27 27.36zM377 105L279.1 7c-4.5-4.5-10.6-7-17-7H256v128h128v-6.1c0-6.3-2.5-12.4-7-16.9z"></path></svg>Download Tutorial Jupyter Notebook</a></div><div class="tutorialButtonWrapper buttonWrapper"><a class="tutorialButton button" download="" href="/files/camera_position_optimization_with_differentiable_rendering.py" target="_blank"><svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="file-download" class="svg-inline--fa fa-file-download fa-w-12" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><path fill="currentColor" d="M224 136V0H24C10.7 0 0 10.7 0 24v464c0 13.3 10.7 24 24 24h336c13.3 0 24-10.7 24-24V160H248c-13.2 0-24-10.8-24-24zm76.45 211.36l-96.42 95.7c-6.65 6.61-17.39 6.61-24.04 0l-96.42-95.7C73.42 337.29 80.54 320 94.82 320H160v-80c0-8.84 7.16-16 16-16h32c8.84 0 16 7.16 16 16v80h65.18c14.28 0 21.4 17.29 11.27 27.36zM377 105L279.1 7c-4.5-4.5-10.6-7-17-7H256v128h128v-6.1c0-6.3-2.5-12.4-7-16.9z"></path></svg>Download Tutorial Source Code</a></div></div><div class="tutorialBody">
|
||
<script
|
||
src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.10/require.min.js">
|
||
</script>
|
||
<script
|
||
src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min.js">
|
||
</script>
|
||
<div class="notebook">
|
||
<div class="cell border-box-sizing code_cell rendered">
|
||
<div class="input">
|
||
<div class="prompt input_prompt">In [ ]:</div>
|
||
<div class="inner_cell">
|
||
<div class="input_area">
|
||
<div class="highlight hl-ipython3"><pre><span></span><span class="c1"># Copyright (c) Meta Platforms, Inc. and affiliates. All rights reserved.</span>
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||
</div>
|
||
<div class="inner_cell">
|
||
<div class="text_cell_render border-box-sizing rendered_html">
|
||
<h1 id="Camera-position-optimization-using-differentiable-rendering">Camera position optimization using differentiable rendering<a class="anchor-link" href="#Camera-position-optimization-using-differentiable-rendering">¶</a></h1><p>In this tutorial we will learn the [x, y, z] position of a camera given a reference image using differentiable rendering.</p>
|
||
<p>We will first initialize a renderer with a starting position for the camera. We will then use this to generate an image, compute a loss with the reference image, and finally backpropagate through the entire pipeline to update the position of the camera.</p>
|
||
<p>This tutorial shows how to:</p>
|
||
<ul>
|
||
<li>load a mesh from an <code>.obj</code> file</li>
|
||
<li>initialize a <code>Camera</code>, <code>Shader</code> and <code>Renderer</code>,</li>
|
||
<li>render a mesh</li>
|
||
<li>set up an optimization loop with a loss function and optimizer</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||
</div>
|
||
<div class="inner_cell">
|
||
<div class="text_cell_render border-box-sizing rendered_html">
|
||
<h2 id="0.-Install-and-import-modules">0. Install and import modules<a class="anchor-link" href="#0.-Install-and-import-modules">¶</a></h2>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||
</div>
|
||
<div class="inner_cell">
|
||
<div class="text_cell_render border-box-sizing rendered_html">
|
||
<p>Ensure <code>torch</code> and <code>torchvision</code> are installed. If <code>pytorch3d</code> is not installed, install it using the following cell:</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing code_cell rendered">
|
||
<div class="input">
|
||
<div class="prompt input_prompt">In [ ]:</div>
|
||
<div class="inner_cell">
|
||
<div class="input_area">
|
||
<div class="highlight hl-ipython3"><pre><span></span><span class="kn">import</span> <span class="nn">os</span>
|
||
<span class="kn">import</span> <span class="nn">sys</span>
|
||
<span class="kn">import</span> <span class="nn">torch</span>
|
||
<span class="n">need_pytorch3d</span><span class="o">=</span><span class="kc">False</span>
|
||
<span class="k">try</span><span class="p">:</span>
|
||
<span class="kn">import</span> <span class="nn">pytorch3d</span>
|
||
<span class="k">except</span> <span class="ne">ModuleNotFoundError</span><span class="p">:</span>
|
||
<span class="n">need_pytorch3d</span><span class="o">=</span><span class="kc">True</span>
|
||
<span class="k">if</span> <span class="n">need_pytorch3d</span><span class="p">:</span>
|
||
<span class="k">if</span> <span class="n">torch</span><span class="o">.</span><span class="n">__version__</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s2">"2.1."</span><span class="p">)</span> <span class="ow">and</span> <span class="n">sys</span><span class="o">.</span><span class="n">platform</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s2">"linux"</span><span class="p">):</span>
|
||
<span class="c1"># We try to install PyTorch3D via a released wheel.</span>
|
||
<span class="n">pyt_version_str</span><span class="o">=</span><span class="n">torch</span><span class="o">.</span><span class="n">__version__</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">"+"</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s2">"."</span><span class="p">,</span> <span class="s2">""</span><span class="p">)</span>
|
||
<span class="n">version_str</span><span class="o">=</span><span class="s2">""</span><span class="o">.</span><span class="n">join</span><span class="p">([</span>
|
||
<span class="sa">f</span><span class="s2">"py3</span><span class="si">{</span><span class="n">sys</span><span class="o">.</span><span class="n">version_info</span><span class="o">.</span><span class="n">minor</span><span class="si">}</span><span class="s2">_cu"</span><span class="p">,</span>
|
||
<span class="n">torch</span><span class="o">.</span><span class="n">version</span><span class="o">.</span><span class="n">cuda</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s2">"."</span><span class="p">,</span><span class="s2">""</span><span class="p">),</span>
|
||
<span class="sa">f</span><span class="s2">"_pyt</span><span class="si">{</span><span class="n">pyt_version_str</span><span class="si">}</span><span class="s2">"</span>
|
||
<span class="p">])</span>
|
||
<span class="o">!</span>pip<span class="w"> </span>install<span class="w"> </span>fvcore<span class="w"> </span>iopath
|
||
<span class="o">!</span>pip<span class="w"> </span>install<span class="w"> </span>--no-index<span class="w"> </span>--no-cache-dir<span class="w"> </span>pytorch3d<span class="w"> </span>-f<span class="w"> </span>https://dl.fbaipublicfiles.com/pytorch3d/packaging/wheels/<span class="o">{</span>version_str<span class="o">}</span>/download.html
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="c1"># We try to install PyTorch3D from source.</span>
|
||
<span class="o">!</span>pip<span class="w"> </span>install<span class="w"> </span><span class="s1">'git+https://github.com/facebookresearch/pytorch3d.git@stable'</span>
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing code_cell rendered">
|
||
<div class="input">
|
||
<div class="prompt input_prompt">In [ ]:</div>
|
||
<div class="inner_cell">
|
||
<div class="input_area">
|
||
<div class="highlight hl-ipython3"><pre><span></span><span class="kn">import</span> <span class="nn">os</span>
|
||
<span class="kn">import</span> <span class="nn">torch</span>
|
||
<span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="nn">np</span>
|
||
<span class="kn">from</span> <span class="nn">tqdm.notebook</span> <span class="kn">import</span> <span class="n">tqdm</span>
|
||
<span class="kn">import</span> <span class="nn">imageio</span>
|
||
<span class="kn">import</span> <span class="nn">torch.nn</span> <span class="k">as</span> <span class="nn">nn</span>
|
||
<span class="kn">import</span> <span class="nn">torch.nn.functional</span> <span class="k">as</span> <span class="nn">F</span>
|
||
<span class="kn">import</span> <span class="nn">matplotlib.pyplot</span> <span class="k">as</span> <span class="nn">plt</span>
|
||
<span class="kn">from</span> <span class="nn">skimage</span> <span class="kn">import</span> <span class="n">img_as_ubyte</span>
|
||
|
||
<span class="c1"># io utils</span>
|
||
<span class="kn">from</span> <span class="nn">pytorch3d.io</span> <span class="kn">import</span> <span class="n">load_obj</span>
|
||
|
||
<span class="c1"># datastructures</span>
|
||
<span class="kn">from</span> <span class="nn">pytorch3d.structures</span> <span class="kn">import</span> <span class="n">Meshes</span>
|
||
|
||
<span class="c1"># 3D transformations functions</span>
|
||
<span class="kn">from</span> <span class="nn">pytorch3d.transforms</span> <span class="kn">import</span> <span class="n">Rotate</span><span class="p">,</span> <span class="n">Translate</span>
|
||
|
||
<span class="c1"># rendering components</span>
|
||
<span class="kn">from</span> <span class="nn">pytorch3d.renderer</span> <span class="kn">import</span> <span class="p">(</span>
|
||
<span class="n">FoVPerspectiveCameras</span><span class="p">,</span> <span class="n">look_at_view_transform</span><span class="p">,</span> <span class="n">look_at_rotation</span><span class="p">,</span>
|
||
<span class="n">RasterizationSettings</span><span class="p">,</span> <span class="n">MeshRenderer</span><span class="p">,</span> <span class="n">MeshRasterizer</span><span class="p">,</span> <span class="n">BlendParams</span><span class="p">,</span>
|
||
<span class="n">SoftSilhouetteShader</span><span class="p">,</span> <span class="n">HardPhongShader</span><span class="p">,</span> <span class="n">PointLights</span><span class="p">,</span> <span class="n">TexturesVertex</span><span class="p">,</span>
|
||
<span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||
</div>
|
||
<div class="inner_cell">
|
||
<div class="text_cell_render border-box-sizing rendered_html">
|
||
<h2 id="1.-Load-the-Obj">1. Load the Obj<a class="anchor-link" href="#1.-Load-the-Obj">¶</a></h2><p>We will load an obj file and create a <strong>Meshes</strong> object. <strong>Meshes</strong> is a unique datastructure provided in PyTorch3D for working with <strong>batches of meshes of different sizes</strong>. It has several useful class methods which are used in the rendering pipeline.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||
</div>
|
||
<div class="inner_cell">
|
||
<div class="text_cell_render border-box-sizing rendered_html">
|
||
<p>If you are running this notebook locally after cloning the PyTorch3D repository, the mesh will already be available. <strong>If using Google Colab, fetch the mesh and save it at the path <code>data/</code></strong>:</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing code_cell rendered">
|
||
<div class="input">
|
||
<div class="prompt input_prompt">In [ ]:</div>
|
||
<div class="inner_cell">
|
||
<div class="input_area">
|
||
<div class="highlight hl-ipython3"><pre><span></span><span class="o">!</span>mkdir<span class="w"> </span>-p<span class="w"> </span>data
|
||
<span class="o">!</span>wget<span class="w"> </span>-P<span class="w"> </span>data<span class="w"> </span>https://dl.fbaipublicfiles.com/pytorch3d/data/teapot/teapot.obj
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing code_cell rendered">
|
||
<div class="input">
|
||
<div class="prompt input_prompt">In [ ]:</div>
|
||
<div class="inner_cell">
|
||
<div class="input_area">
|
||
<div class="highlight hl-ipython3"><pre><span></span><span class="c1"># Set the cuda device </span>
|
||
<span class="k">if</span> <span class="n">torch</span><span class="o">.</span><span class="n">cuda</span><span class="o">.</span><span class="n">is_available</span><span class="p">():</span>
|
||
<span class="n">device</span> <span class="o">=</span> <span class="n">torch</span><span class="o">.</span><span class="n">device</span><span class="p">(</span><span class="s2">"cuda:0"</span><span class="p">)</span>
|
||
<span class="n">torch</span><span class="o">.</span><span class="n">cuda</span><span class="o">.</span><span class="n">set_device</span><span class="p">(</span><span class="n">device</span><span class="p">)</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="n">device</span> <span class="o">=</span> <span class="n">torch</span><span class="o">.</span><span class="n">device</span><span class="p">(</span><span class="s2">"cpu"</span><span class="p">)</span>
|
||
|
||
<span class="c1"># Load the obj and ignore the textures and materials.</span>
|
||
<span class="n">verts</span><span class="p">,</span> <span class="n">faces_idx</span><span class="p">,</span> <span class="n">_</span> <span class="o">=</span> <span class="n">load_obj</span><span class="p">(</span><span class="s2">"./data/teapot.obj"</span><span class="p">)</span>
|
||
<span class="n">faces</span> <span class="o">=</span> <span class="n">faces_idx</span><span class="o">.</span><span class="n">verts_idx</span>
|
||
|
||
<span class="c1"># Initialize each vertex to be white in color.</span>
|
||
<span class="n">verts_rgb</span> <span class="o">=</span> <span class="n">torch</span><span class="o">.</span><span class="n">ones_like</span><span class="p">(</span><span class="n">verts</span><span class="p">)[</span><span class="kc">None</span><span class="p">]</span> <span class="c1"># (1, V, 3)</span>
|
||
<span class="n">textures</span> <span class="o">=</span> <span class="n">TexturesVertex</span><span class="p">(</span><span class="n">verts_features</span><span class="o">=</span><span class="n">verts_rgb</span><span class="o">.</span><span class="n">to</span><span class="p">(</span><span class="n">device</span><span class="p">))</span>
|
||
|
||
<span class="c1"># Create a Meshes object for the teapot. Here we have only one mesh in the batch.</span>
|
||
<span class="n">teapot_mesh</span> <span class="o">=</span> <span class="n">Meshes</span><span class="p">(</span>
|
||
<span class="n">verts</span><span class="o">=</span><span class="p">[</span><span class="n">verts</span><span class="o">.</span><span class="n">to</span><span class="p">(</span><span class="n">device</span><span class="p">)],</span>
|
||
<span class="n">faces</span><span class="o">=</span><span class="p">[</span><span class="n">faces</span><span class="o">.</span><span class="n">to</span><span class="p">(</span><span class="n">device</span><span class="p">)],</span>
|
||
<span class="n">textures</span><span class="o">=</span><span class="n">textures</span>
|
||
<span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||
</div>
|
||
<div class="inner_cell">
|
||
<div class="text_cell_render border-box-sizing rendered_html">
|
||
<h2 id="2.-Optimization-setup">2. Optimization setup<a class="anchor-link" href="#2.-Optimization-setup">¶</a></h2>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||
</div>
|
||
<div class="inner_cell">
|
||
<div class="text_cell_render border-box-sizing rendered_html">
|
||
<h3 id="Create-a-renderer">Create a renderer<a class="anchor-link" href="#Create-a-renderer">¶</a></h3><p>A <strong>renderer</strong> in PyTorch3D is composed of a <strong>rasterizer</strong> and a <strong>shader</strong> which each have a number of subcomponents such as a <strong>camera</strong> (orthographic/perspective). Here we initialize some of these components and use default values for the rest.</p>
|
||
<p>For optimizing the camera position we will use a renderer which produces a <strong>silhouette</strong> of the object only and does not apply any <strong>lighting</strong> or <strong>shading</strong>. We will also initialize another renderer which applies full <strong>Phong shading</strong> and use this for visualizing the outputs.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing code_cell rendered">
|
||
<div class="input">
|
||
<div class="prompt input_prompt">In [ ]:</div>
|
||
<div class="inner_cell">
|
||
<div class="input_area">
|
||
<div class="highlight hl-ipython3"><pre><span></span><span class="c1"># Initialize a perspective camera.</span>
|
||
<span class="n">cameras</span> <span class="o">=</span> <span class="n">FoVPerspectiveCameras</span><span class="p">(</span><span class="n">device</span><span class="o">=</span><span class="n">device</span><span class="p">)</span>
|
||
|
||
<span class="c1"># To blend the 100 faces we set a few parameters which control the opacity and the sharpness of </span>
|
||
<span class="c1"># edges. Refer to blending.py for more details. </span>
|
||
<span class="n">blend_params</span> <span class="o">=</span> <span class="n">BlendParams</span><span class="p">(</span><span class="n">sigma</span><span class="o">=</span><span class="mf">1e-4</span><span class="p">,</span> <span class="n">gamma</span><span class="o">=</span><span class="mf">1e-4</span><span class="p">)</span>
|
||
|
||
<span class="c1"># Define the settings for rasterization and shading. Here we set the output image to be of size</span>
|
||
<span class="c1"># 256x256. To form the blended image we use 100 faces for each pixel. We also set bin_size and max_faces_per_bin to None which ensure that </span>
|
||
<span class="c1"># the faster coarse-to-fine rasterization method is used. Refer to rasterize_meshes.py for </span>
|
||
<span class="c1"># explanations of these parameters. Refer to docs/notes/renderer.md for an explanation of </span>
|
||
<span class="c1"># the difference between naive and coarse-to-fine rasterization. </span>
|
||
<span class="n">raster_settings</span> <span class="o">=</span> <span class="n">RasterizationSettings</span><span class="p">(</span>
|
||
<span class="n">image_size</span><span class="o">=</span><span class="mi">256</span><span class="p">,</span>
|
||
<span class="n">blur_radius</span><span class="o">=</span><span class="n">np</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="mf">1.</span> <span class="o">/</span> <span class="mf">1e-4</span> <span class="o">-</span> <span class="mf">1.</span><span class="p">)</span> <span class="o">*</span> <span class="n">blend_params</span><span class="o">.</span><span class="n">sigma</span><span class="p">,</span>
|
||
<span class="n">faces_per_pixel</span><span class="o">=</span><span class="mi">100</span><span class="p">,</span>
|
||
<span class="p">)</span>
|
||
|
||
<span class="c1"># Create a silhouette mesh renderer by composing a rasterizer and a shader. </span>
|
||
<span class="n">silhouette_renderer</span> <span class="o">=</span> <span class="n">MeshRenderer</span><span class="p">(</span>
|
||
<span class="n">rasterizer</span><span class="o">=</span><span class="n">MeshRasterizer</span><span class="p">(</span>
|
||
<span class="n">cameras</span><span class="o">=</span><span class="n">cameras</span><span class="p">,</span>
|
||
<span class="n">raster_settings</span><span class="o">=</span><span class="n">raster_settings</span>
|
||
<span class="p">),</span>
|
||
<span class="n">shader</span><span class="o">=</span><span class="n">SoftSilhouetteShader</span><span class="p">(</span><span class="n">blend_params</span><span class="o">=</span><span class="n">blend_params</span><span class="p">)</span>
|
||
<span class="p">)</span>
|
||
|
||
|
||
<span class="c1"># We will also create a Phong renderer. This is simpler and only needs to render one face per pixel.</span>
|
||
<span class="n">raster_settings</span> <span class="o">=</span> <span class="n">RasterizationSettings</span><span class="p">(</span>
|
||
<span class="n">image_size</span><span class="o">=</span><span class="mi">256</span><span class="p">,</span>
|
||
<span class="n">blur_radius</span><span class="o">=</span><span class="mf">0.0</span><span class="p">,</span>
|
||
<span class="n">faces_per_pixel</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span>
|
||
<span class="p">)</span>
|
||
<span class="c1"># We can add a point light in front of the object. </span>
|
||
<span class="n">lights</span> <span class="o">=</span> <span class="n">PointLights</span><span class="p">(</span><span class="n">device</span><span class="o">=</span><span class="n">device</span><span class="p">,</span> <span class="n">location</span><span class="o">=</span><span class="p">((</span><span class="mf">2.0</span><span class="p">,</span> <span class="mf">2.0</span><span class="p">,</span> <span class="o">-</span><span class="mf">2.0</span><span class="p">),))</span>
|
||
<span class="n">phong_renderer</span> <span class="o">=</span> <span class="n">MeshRenderer</span><span class="p">(</span>
|
||
<span class="n">rasterizer</span><span class="o">=</span><span class="n">MeshRasterizer</span><span class="p">(</span>
|
||
<span class="n">cameras</span><span class="o">=</span><span class="n">cameras</span><span class="p">,</span>
|
||
<span class="n">raster_settings</span><span class="o">=</span><span class="n">raster_settings</span>
|
||
<span class="p">),</span>
|
||
<span class="n">shader</span><span class="o">=</span><span class="n">HardPhongShader</span><span class="p">(</span><span class="n">device</span><span class="o">=</span><span class="n">device</span><span class="p">,</span> <span class="n">cameras</span><span class="o">=</span><span class="n">cameras</span><span class="p">,</span> <span class="n">lights</span><span class="o">=</span><span class="n">lights</span><span class="p">)</span>
|
||
<span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||
</div>
|
||
<div class="inner_cell">
|
||
<div class="text_cell_render border-box-sizing rendered_html">
|
||
<h3 id="Create-a-reference-image">Create a reference image<a class="anchor-link" href="#Create-a-reference-image">¶</a></h3><p>We will first position the teapot and generate an image. We use helper functions to rotate the teapot to a desired viewpoint. Then we can use the renderers to produce an image. Here we will use both renderers and visualize the silhouette and full shaded image.</p>
|
||
<p>The world coordinate system is defined as +Y up, +X left and +Z in. The teapot in world coordinates has the spout pointing to the left.</p>
|
||
<p>We defined a camera which is positioned on the positive z axis hence sees the spout to the right.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing code_cell rendered">
|
||
<div class="input">
|
||
<div class="prompt input_prompt">In [ ]:</div>
|
||
<div class="inner_cell">
|
||
<div class="input_area">
|
||
<div class="highlight hl-ipython3"><pre><span></span><span class="c1"># Select the viewpoint using spherical angles </span>
|
||
<span class="n">distance</span> <span class="o">=</span> <span class="mi">3</span> <span class="c1"># distance from camera to the object</span>
|
||
<span class="n">elevation</span> <span class="o">=</span> <span class="mf">50.0</span> <span class="c1"># angle of elevation in degrees</span>
|
||
<span class="n">azimuth</span> <span class="o">=</span> <span class="mf">0.0</span> <span class="c1"># No rotation so the camera is positioned on the +Z axis. </span>
|
||
|
||
<span class="c1"># Get the position of the camera based on the spherical angles</span>
|
||
<span class="n">R</span><span class="p">,</span> <span class="n">T</span> <span class="o">=</span> <span class="n">look_at_view_transform</span><span class="p">(</span><span class="n">distance</span><span class="p">,</span> <span class="n">elevation</span><span class="p">,</span> <span class="n">azimuth</span><span class="p">,</span> <span class="n">device</span><span class="o">=</span><span class="n">device</span><span class="p">)</span>
|
||
|
||
<span class="c1"># Render the teapot providing the values of R and T. </span>
|
||
<span class="n">silhouette</span> <span class="o">=</span> <span class="n">silhouette_renderer</span><span class="p">(</span><span class="n">meshes_world</span><span class="o">=</span><span class="n">teapot_mesh</span><span class="p">,</span> <span class="n">R</span><span class="o">=</span><span class="n">R</span><span class="p">,</span> <span class="n">T</span><span class="o">=</span><span class="n">T</span><span class="p">)</span>
|
||
<span class="n">image_ref</span> <span class="o">=</span> <span class="n">phong_renderer</span><span class="p">(</span><span class="n">meshes_world</span><span class="o">=</span><span class="n">teapot_mesh</span><span class="p">,</span> <span class="n">R</span><span class="o">=</span><span class="n">R</span><span class="p">,</span> <span class="n">T</span><span class="o">=</span><span class="n">T</span><span class="p">)</span>
|
||
|
||
<span class="n">silhouette</span> <span class="o">=</span> <span class="n">silhouette</span><span class="o">.</span><span class="n">cpu</span><span class="p">()</span><span class="o">.</span><span class="n">numpy</span><span class="p">()</span>
|
||
<span class="n">image_ref</span> <span class="o">=</span> <span class="n">image_ref</span><span class="o">.</span><span class="n">cpu</span><span class="p">()</span><span class="o">.</span><span class="n">numpy</span><span class="p">()</span>
|
||
|
||
<span class="n">plt</span><span class="o">.</span><span class="n">figure</span><span class="p">(</span><span class="n">figsize</span><span class="o">=</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">10</span><span class="p">))</span>
|
||
<span class="n">plt</span><span class="o">.</span><span class="n">subplot</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
|
||
<span class="n">plt</span><span class="o">.</span><span class="n">imshow</span><span class="p">(</span><span class="n">silhouette</span><span class="o">.</span><span class="n">squeeze</span><span class="p">()[</span><span class="o">...</span><span class="p">,</span> <span class="mi">3</span><span class="p">])</span> <span class="c1"># only plot the alpha channel of the RGBA image</span>
|
||
<span class="n">plt</span><span class="o">.</span><span class="n">grid</span><span class="p">(</span><span class="kc">False</span><span class="p">)</span>
|
||
<span class="n">plt</span><span class="o">.</span><span class="n">subplot</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
|
||
<span class="n">plt</span><span class="o">.</span><span class="n">imshow</span><span class="p">(</span><span class="n">image_ref</span><span class="o">.</span><span class="n">squeeze</span><span class="p">())</span>
|
||
<span class="n">plt</span><span class="o">.</span><span class="n">grid</span><span class="p">(</span><span class="kc">False</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||
</div>
|
||
<div class="inner_cell">
|
||
<div class="text_cell_render border-box-sizing rendered_html">
|
||
<h3 id="Set-up-a-basic-model">Set up a basic model<a class="anchor-link" href="#Set-up-a-basic-model">¶</a></h3><p>Here we create a simple model class and initialize a parameter for the camera position.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing code_cell rendered">
|
||
<div class="input">
|
||
<div class="prompt input_prompt">In [ ]:</div>
|
||
<div class="inner_cell">
|
||
<div class="input_area">
|
||
<div class="highlight hl-ipython3"><pre><span></span><span class="k">class</span> <span class="nc">Model</span><span class="p">(</span><span class="n">nn</span><span class="o">.</span><span class="n">Module</span><span class="p">):</span>
|
||
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">meshes</span><span class="p">,</span> <span class="n">renderer</span><span class="p">,</span> <span class="n">image_ref</span><span class="p">):</span>
|
||
<span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">()</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">meshes</span> <span class="o">=</span> <span class="n">meshes</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">device</span> <span class="o">=</span> <span class="n">meshes</span><span class="o">.</span><span class="n">device</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">renderer</span> <span class="o">=</span> <span class="n">renderer</span>
|
||
|
||
<span class="c1"># Get the silhouette of the reference RGB image by finding all non-white pixel values. </span>
|
||
<span class="n">image_ref</span> <span class="o">=</span> <span class="n">torch</span><span class="o">.</span><span class="n">from_numpy</span><span class="p">((</span><span class="n">image_ref</span><span class="p">[</span><span class="o">...</span><span class="p">,</span> <span class="p">:</span><span class="mi">3</span><span class="p">]</span><span class="o">.</span><span class="n">max</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">1</span><span class="p">)</span><span class="o">.</span><span class="n">astype</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">float32</span><span class="p">))</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">register_buffer</span><span class="p">(</span><span class="s1">'image_ref'</span><span class="p">,</span> <span class="n">image_ref</span><span class="p">)</span>
|
||
|
||
<span class="c1"># Create an optimizable parameter for the x, y, z position of the camera. </span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">camera_position</span> <span class="o">=</span> <span class="n">nn</span><span class="o">.</span><span class="n">Parameter</span><span class="p">(</span>
|
||
<span class="n">torch</span><span class="o">.</span><span class="n">from_numpy</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">([</span><span class="mf">3.0</span><span class="p">,</span> <span class="mf">6.9</span><span class="p">,</span> <span class="o">+</span><span class="mf">2.5</span><span class="p">],</span> <span class="n">dtype</span><span class="o">=</span><span class="n">np</span><span class="o">.</span><span class="n">float32</span><span class="p">))</span><span class="o">.</span><span class="n">to</span><span class="p">(</span><span class="n">meshes</span><span class="o">.</span><span class="n">device</span><span class="p">))</span>
|
||
|
||
<span class="k">def</span> <span class="nf">forward</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
|
||
<span class="c1"># Render the image using the updated camera position. Based on the new position of the </span>
|
||
<span class="c1"># camera we calculate the rotation and translation matrices</span>
|
||
<span class="n">R</span> <span class="o">=</span> <span class="n">look_at_rotation</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">camera_position</span><span class="p">[</span><span class="kc">None</span><span class="p">,</span> <span class="p">:],</span> <span class="n">device</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">device</span><span class="p">)</span> <span class="c1"># (1, 3, 3)</span>
|
||
<span class="n">T</span> <span class="o">=</span> <span class="o">-</span><span class="n">torch</span><span class="o">.</span><span class="n">bmm</span><span class="p">(</span><span class="n">R</span><span class="o">.</span><span class="n">transpose</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="bp">self</span><span class="o">.</span><span class="n">camera_position</span><span class="p">[</span><span class="kc">None</span><span class="p">,</span> <span class="p">:,</span> <span class="kc">None</span><span class="p">])[:,</span> <span class="p">:,</span> <span class="mi">0</span><span class="p">]</span> <span class="c1"># (1, 3)</span>
|
||
|
||
<span class="n">image</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">renderer</span><span class="p">(</span><span class="n">meshes_world</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">meshes</span><span class="o">.</span><span class="n">clone</span><span class="p">(),</span> <span class="n">R</span><span class="o">=</span><span class="n">R</span><span class="p">,</span> <span class="n">T</span><span class="o">=</span><span class="n">T</span><span class="p">)</span>
|
||
|
||
<span class="c1"># Calculate the silhouette loss</span>
|
||
<span class="n">loss</span> <span class="o">=</span> <span class="n">torch</span><span class="o">.</span><span class="n">sum</span><span class="p">((</span><span class="n">image</span><span class="p">[</span><span class="o">...</span><span class="p">,</span> <span class="mi">3</span><span class="p">]</span> <span class="o">-</span> <span class="bp">self</span><span class="o">.</span><span class="n">image_ref</span><span class="p">)</span> <span class="o">**</span> <span class="mi">2</span><span class="p">)</span>
|
||
<span class="k">return</span> <span class="n">loss</span><span class="p">,</span> <span class="n">image</span>
|
||
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||
</div>
|
||
<div class="inner_cell">
|
||
<div class="text_cell_render border-box-sizing rendered_html">
|
||
<h2 id="3.-Initialize-the-model-and-optimizer">3. Initialize the model and optimizer<a class="anchor-link" href="#3.-Initialize-the-model-and-optimizer">¶</a></h2><p>Now we can create an instance of the <strong>model</strong> above and set up an <strong>optimizer</strong> for the camera position parameter.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing code_cell rendered">
|
||
<div class="input">
|
||
<div class="prompt input_prompt">In [ ]:</div>
|
||
<div class="inner_cell">
|
||
<div class="input_area">
|
||
<div class="highlight hl-ipython3"><pre><span></span><span class="c1"># We will save images periodically and compose them into a GIF.</span>
|
||
<span class="n">filename_output</span> <span class="o">=</span> <span class="s2">"./teapot_optimization_demo.gif"</span>
|
||
<span class="n">writer</span> <span class="o">=</span> <span class="n">imageio</span><span class="o">.</span><span class="n">get_writer</span><span class="p">(</span><span class="n">filename_output</span><span class="p">,</span> <span class="n">mode</span><span class="o">=</span><span class="s1">'I'</span><span class="p">,</span> <span class="n">duration</span><span class="o">=</span><span class="mf">0.3</span><span class="p">)</span>
|
||
|
||
<span class="c1"># Initialize a model using the renderer, mesh and reference image</span>
|
||
<span class="n">model</span> <span class="o">=</span> <span class="n">Model</span><span class="p">(</span><span class="n">meshes</span><span class="o">=</span><span class="n">teapot_mesh</span><span class="p">,</span> <span class="n">renderer</span><span class="o">=</span><span class="n">silhouette_renderer</span><span class="p">,</span> <span class="n">image_ref</span><span class="o">=</span><span class="n">image_ref</span><span class="p">)</span><span class="o">.</span><span class="n">to</span><span class="p">(</span><span class="n">device</span><span class="p">)</span>
|
||
|
||
<span class="c1"># Create an optimizer. Here we are using Adam and we pass in the parameters of the model</span>
|
||
<span class="n">optimizer</span> <span class="o">=</span> <span class="n">torch</span><span class="o">.</span><span class="n">optim</span><span class="o">.</span><span class="n">Adam</span><span class="p">(</span><span class="n">model</span><span class="o">.</span><span class="n">parameters</span><span class="p">(),</span> <span class="n">lr</span><span class="o">=</span><span class="mf">0.05</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||
</div>
|
||
<div class="inner_cell">
|
||
<div class="text_cell_render border-box-sizing rendered_html">
|
||
<h3 id="Visualize-the-starting-position-and-the-reference-position">Visualize the starting position and the reference position<a class="anchor-link" href="#Visualize-the-starting-position-and-the-reference-position">¶</a></h3>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing code_cell rendered">
|
||
<div class="input">
|
||
<div class="prompt input_prompt">In [ ]:</div>
|
||
<div class="inner_cell">
|
||
<div class="input_area">
|
||
<div class="highlight hl-ipython3"><pre><span></span><span class="n">plt</span><span class="o">.</span><span class="n">figure</span><span class="p">(</span><span class="n">figsize</span><span class="o">=</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">10</span><span class="p">))</span>
|
||
|
||
<span class="n">_</span><span class="p">,</span> <span class="n">image_init</span> <span class="o">=</span> <span class="n">model</span><span class="p">()</span>
|
||
<span class="n">plt</span><span class="o">.</span><span class="n">subplot</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
|
||
<span class="n">plt</span><span class="o">.</span><span class="n">imshow</span><span class="p">(</span><span class="n">image_init</span><span class="o">.</span><span class="n">detach</span><span class="p">()</span><span class="o">.</span><span class="n">squeeze</span><span class="p">()</span><span class="o">.</span><span class="n">cpu</span><span class="p">()</span><span class="o">.</span><span class="n">numpy</span><span class="p">()[</span><span class="o">...</span><span class="p">,</span> <span class="mi">3</span><span class="p">])</span>
|
||
<span class="n">plt</span><span class="o">.</span><span class="n">grid</span><span class="p">(</span><span class="kc">False</span><span class="p">)</span>
|
||
<span class="n">plt</span><span class="o">.</span><span class="n">title</span><span class="p">(</span><span class="s2">"Starting position"</span><span class="p">)</span>
|
||
|
||
<span class="n">plt</span><span class="o">.</span><span class="n">subplot</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
|
||
<span class="n">plt</span><span class="o">.</span><span class="n">imshow</span><span class="p">(</span><span class="n">model</span><span class="o">.</span><span class="n">image_ref</span><span class="o">.</span><span class="n">cpu</span><span class="p">()</span><span class="o">.</span><span class="n">numpy</span><span class="p">()</span><span class="o">.</span><span class="n">squeeze</span><span class="p">())</span>
|
||
<span class="n">plt</span><span class="o">.</span><span class="n">grid</span><span class="p">(</span><span class="kc">False</span><span class="p">)</span>
|
||
<span class="n">plt</span><span class="o">.</span><span class="n">title</span><span class="p">(</span><span class="s2">"Reference silhouette"</span><span class="p">);</span>
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||
</div>
|
||
<div class="inner_cell">
|
||
<div class="text_cell_render border-box-sizing rendered_html">
|
||
<h2 id="4.-Run-the-optimization">4. Run the optimization<a class="anchor-link" href="#4.-Run-the-optimization">¶</a></h2><p>We run several iterations of the forward and backward pass and save outputs every 10 iterations. When this has finished take a look at <code>./teapot_optimization_demo.gif</code> for a cool gif of the optimization process!</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing code_cell rendered">
|
||
<div class="input">
|
||
<div class="prompt input_prompt">In [ ]:</div>
|
||
<div class="inner_cell">
|
||
<div class="input_area">
|
||
<div class="highlight hl-ipython3"><pre><span></span><span class="n">loop</span> <span class="o">=</span> <span class="n">tqdm</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="mi">200</span><span class="p">))</span>
|
||
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">loop</span><span class="p">:</span>
|
||
<span class="n">optimizer</span><span class="o">.</span><span class="n">zero_grad</span><span class="p">()</span>
|
||
<span class="n">loss</span><span class="p">,</span> <span class="n">_</span> <span class="o">=</span> <span class="n">model</span><span class="p">()</span>
|
||
<span class="n">loss</span><span class="o">.</span><span class="n">backward</span><span class="p">()</span>
|
||
<span class="n">optimizer</span><span class="o">.</span><span class="n">step</span><span class="p">()</span>
|
||
|
||
<span class="n">loop</span><span class="o">.</span><span class="n">set_description</span><span class="p">(</span><span class="s1">'Optimizing (loss </span><span class="si">%.4f</span><span class="s1">)'</span> <span class="o">%</span> <span class="n">loss</span><span class="o">.</span><span class="n">data</span><span class="p">)</span>
|
||
|
||
<span class="k">if</span> <span class="n">loss</span><span class="o">.</span><span class="n">item</span><span class="p">()</span> <span class="o"><</span> <span class="mi">200</span><span class="p">:</span>
|
||
<span class="k">break</span>
|
||
|
||
<span class="c1"># Save outputs to create a GIF. </span>
|
||
<span class="k">if</span> <span class="n">i</span> <span class="o">%</span> <span class="mi">10</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
|
||
<span class="n">R</span> <span class="o">=</span> <span class="n">look_at_rotation</span><span class="p">(</span><span class="n">model</span><span class="o">.</span><span class="n">camera_position</span><span class="p">[</span><span class="kc">None</span><span class="p">,</span> <span class="p">:],</span> <span class="n">device</span><span class="o">=</span><span class="n">model</span><span class="o">.</span><span class="n">device</span><span class="p">)</span>
|
||
<span class="n">T</span> <span class="o">=</span> <span class="o">-</span><span class="n">torch</span><span class="o">.</span><span class="n">bmm</span><span class="p">(</span><span class="n">R</span><span class="o">.</span><span class="n">transpose</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="n">model</span><span class="o">.</span><span class="n">camera_position</span><span class="p">[</span><span class="kc">None</span><span class="p">,</span> <span class="p">:,</span> <span class="kc">None</span><span class="p">])[:,</span> <span class="p">:,</span> <span class="mi">0</span><span class="p">]</span> <span class="c1"># (1, 3)</span>
|
||
<span class="n">image</span> <span class="o">=</span> <span class="n">phong_renderer</span><span class="p">(</span><span class="n">meshes_world</span><span class="o">=</span><span class="n">model</span><span class="o">.</span><span class="n">meshes</span><span class="o">.</span><span class="n">clone</span><span class="p">(),</span> <span class="n">R</span><span class="o">=</span><span class="n">R</span><span class="p">,</span> <span class="n">T</span><span class="o">=</span><span class="n">T</span><span class="p">)</span>
|
||
<span class="n">image</span> <span class="o">=</span> <span class="n">image</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="o">...</span><span class="p">,</span> <span class="p">:</span><span class="mi">3</span><span class="p">]</span><span class="o">.</span><span class="n">detach</span><span class="p">()</span><span class="o">.</span><span class="n">squeeze</span><span class="p">()</span><span class="o">.</span><span class="n">cpu</span><span class="p">()</span><span class="o">.</span><span class="n">numpy</span><span class="p">()</span>
|
||
<span class="n">image</span> <span class="o">=</span> <span class="n">img_as_ubyte</span><span class="p">(</span><span class="n">image</span><span class="p">)</span>
|
||
<span class="n">writer</span><span class="o">.</span><span class="n">append_data</span><span class="p">(</span><span class="n">image</span><span class="p">)</span>
|
||
|
||
<span class="n">plt</span><span class="o">.</span><span class="n">figure</span><span class="p">()</span>
|
||
<span class="n">plt</span><span class="o">.</span><span class="n">imshow</span><span class="p">(</span><span class="n">image</span><span class="p">[</span><span class="o">...</span><span class="p">,</span> <span class="p">:</span><span class="mi">3</span><span class="p">])</span>
|
||
<span class="n">plt</span><span class="o">.</span><span class="n">title</span><span class="p">(</span><span class="s2">"iter: </span><span class="si">%d</span><span class="s2">, loss: </span><span class="si">%0.2f</span><span class="s2">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">loss</span><span class="o">.</span><span class="n">data</span><span class="p">))</span>
|
||
<span class="n">plt</span><span class="o">.</span><span class="n">axis</span><span class="p">(</span><span class="s2">"off"</span><span class="p">)</span>
|
||
|
||
<span class="n">writer</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
|
||
</div>
|
||
<div class="inner_cell">
|
||
<div class="text_cell_render border-box-sizing rendered_html">
|
||
<h2 id="5.-Conclusion">5. Conclusion<a class="anchor-link" href="#5.-Conclusion">¶</a></h2><p>In this tutorial we learnt how to <strong>load</strong> a mesh from an obj file, initialize a PyTorch3D datastructure called <strong>Meshes</strong>, set up an <strong>Renderer</strong> consisting of a <strong>Rasterizer</strong> and a <strong>Shader</strong>, set up an optimization loop including a <strong>Model</strong> and a <strong>loss function</strong>, and run the optimization.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div></div></div></div></div><footer class="nav-footer" id="footer"><section class="sitemap"><div class="footerSection"><div class="social"><a class="github-button" href="https://github.com/facebookresearch/pytorch3d" data-count-href="https://github.com/facebookresearch/pytorch3d/stargazers" data-show-count="true" data-count-aria-label="# stargazers on GitHub" aria-label="Star PyTorch3D on GitHub">pytorch3d</a></div></div></section><a href="https://opensource.facebook.com/" target="_blank" rel="noreferrer noopener" class="fbOpenSource"><img src="/img/oss_logo.png" alt="Facebook Open Source" width="170" height="45"/></a><section class="copyright">Copyright © 2023 Meta Platforms, Inc<br/>Legal:<a href="https://opensource.facebook.com/legal/privacy/" target="_blank" rel="noreferrer noopener">Privacy</a><a href="https://opensource.facebook.com/legal/terms/" target="_blank" rel="noreferrer noopener">Terms</a></section></footer></div></body></html> |