mirror of
https://github.com/facebookresearch/pytorch3d.git
synced 2025-08-02 03:42:50 +08:00
520 lines
44 KiB
HTML
520 lines
44 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"/><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 navListItemActive"><a class="navItem" href="/tutorials/render_textured_meshes">Render Textured Meshes</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"><a class="navItem" href="/tutorials/camera_position_optimization_with_differentiable_rendering">Camera Position Optimization</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></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/render_textured_meshes.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/render_textured_meshes.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/render_textured_meshes.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) Facebook, Inc. and its 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="Render-a-textured-mesh">Render a textured mesh<a class="anchor-link" href="#Render-a-textured-mesh">¶</a></h1><p>This tutorial shows how to:</p>
|
||
<ul>
|
||
<li>load a mesh and textures from an <code>.obj</code> file. </li>
|
||
<li>set up a renderer </li>
|
||
<li>render the mesh </li>
|
||
<li>vary the rendering settings such as lighting and camera position</li>
|
||
<li>use the batching features of the pytorch3d API to render the mesh from different viewpoints</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>If <code>torch</code>, <code>torchvision</code> and <code>pytorch3d</code> are not installed, run 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="o">!</span>pip install torch torchvision
|
||
<span class="kn">import</span> <span class="nn">sys</span>
|
||
<span class="kn">import</span> <span class="nn">torch</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="s1">'1.6.0+cu101'</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="s1">'linux'</span><span class="p">):</span>
|
||
<span class="o">!</span>pip install pytorch3d
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="o">!</span>pip install <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">matplotlib.pyplot</span> <span class="k">as</span> <span class="nn">plt</span>
|
||
<span class="kn">from</span> <span class="nn">skimage.io</span> <span class="k">import</span> <span class="n">imread</span>
|
||
|
||
<span class="c1"># Util function for loading meshes</span>
|
||
<span class="kn">from</span> <span class="nn">pytorch3d.io</span> <span class="k">import</span> <span class="n">load_objs_as_meshes</span><span class="p">,</span> <span class="n">load_obj</span>
|
||
|
||
<span class="c1"># Data structures and functions for rendering</span>
|
||
<span class="kn">from</span> <span class="nn">pytorch3d.structures</span> <span class="k">import</span> <span class="n">Meshes</span>
|
||
<span class="kn">from</span> <span class="nn">pytorch3d.renderer</span> <span class="k">import</span> <span class="p">(</span>
|
||
<span class="n">look_at_view_transform</span><span class="p">,</span>
|
||
<span class="n">FoVPerspectiveCameras</span><span class="p">,</span>
|
||
<span class="n">PointLights</span><span class="p">,</span>
|
||
<span class="n">DirectionalLights</span><span class="p">,</span>
|
||
<span class="n">Materials</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">SoftPhongShader</span><span class="p">,</span>
|
||
<span class="n">TexturesUV</span>
|
||
<span class="p">)</span>
|
||
|
||
<span class="c1"># add path for demo utils functions </span>
|
||
<span class="kn">import</span> <span class="nn">sys</span>
|
||
<span class="kn">import</span> <span class="nn">os</span>
|
||
<span class="n">sys</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">abspath</span><span class="p">(</span><span class="s1">''</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">
|
||
<p>If using <strong>Google Colab</strong>, fetch the utils file for plotting image grids:</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>wget https://raw.githubusercontent.com/facebookresearch/pytorch3d/master/docs/tutorials/utils/plot_image_grid.py
|
||
<span class="kn">from</span> <span class="nn">plot_image_grid</span> <span class="k">import</span> <span class="n">image_grid</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">
|
||
<p>OR if running <strong>locally</strong> uncomment and run 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="c1"># from utils import image_grid</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="1.-Load-a-mesh-and-texture-file">1. Load a mesh and texture file<a class="anchor-link" href="#1.-Load-a-mesh-and-texture-file">¶</a></h3><p>Load an <code>.obj</code> file and it's associated <code>.mtl</code> file and create a <strong>Textures</strong> and <strong>Meshes</strong> object.</p>
|
||
<p><strong>Meshes</strong> is a unique datastructure provided in PyTorch3D for working with batches of meshes of different sizes.</p>
|
||
<p><strong>TexturesUV</strong> is an auxillary datastructure for storing vertex uv and texture maps for meshes.</p>
|
||
<p><strong>Meshes</strong> has several class methods which are used throughout 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 running this notebook using <strong>Google Colab</strong>, run the following cell to fetch the mesh obj and texture files and save it at the path <code>data/cow_mesh</code>:
|
||
If running locally, the data is already available at the correct path.</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 -p data/cow_mesh
|
||
<span class="o">!</span>wget -P data/cow_mesh https://dl.fbaipublicfiles.com/pytorch3d/data/cow_mesh/cow.obj
|
||
<span class="o">!</span>wget -P data/cow_mesh https://dl.fbaipublicfiles.com/pytorch3d/data/cow_mesh/cow.mtl
|
||
<span class="o">!</span>wget -P data/cow_mesh https://dl.fbaipublicfiles.com/pytorch3d/data/cow_mesh/cow_texture.png
|
||
</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"># Setup</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"># Set paths</span>
|
||
<span class="n">DATA_DIR</span> <span class="o">=</span> <span class="s2">"./data"</span>
|
||
<span class="n">obj_filename</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">DATA_DIR</span><span class="p">,</span> <span class="s2">"cow_mesh/cow.obj"</span><span class="p">)</span>
|
||
|
||
<span class="c1"># Load obj file</span>
|
||
<span class="n">mesh</span> <span class="o">=</span> <span class="n">load_objs_as_meshes</span><span class="p">([</span><span class="n">obj_filename</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">texture_image</span><span class="o">=</span><span class="n">mesh</span><span class="o">.</span><span class="n">textures</span><span class="o">.</span><span class="n">maps_padded</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">
|
||
<h4 id="Let's-visualize-the-texture-map">Let's visualize the texture map<a class="anchor-link" href="#Let's-visualize-the-texture-map">¶</a></h4>
|
||
</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">7</span><span class="p">,</span><span class="mi">7</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">texture_image</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">plt</span><span class="o">.</span><span class="n">grid</span><span class="p">(</span><span class="s2">"off"</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="s1">'off'</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.-Create-a-renderer">2. Create a renderer<a class="anchor-link" href="#2.-Create-a-renderer">¶</a></h2><p>A renderer 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>In this example we will first create a <strong>renderer</strong> which uses a <strong>perspective camera</strong>, a <strong>point light</strong> and applies <strong>phong shading</strong>. Then we learn how to vary different components using the modular API.</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 camera.</span>
|
||
<span class="c1"># With world coordinates +Y up, +X left and +Z in, the front of the cow is facing the -Z direction. </span>
|
||
<span class="c1"># So we move the camera by 180 in the azimuth direction so it is facing the front of the cow. </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="mf">2.7</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">180</span><span class="p">)</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="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"># Define the settings for rasterization and shading. Here we set the output image to be of size</span>
|
||
<span class="c1"># 512x512. As we are rendering images for visualization purposes only we will set faces_per_pixel=1</span>
|
||
<span class="c1"># and blur_radius=0.0. 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">512</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"># Place a point light in front of the object. As mentioned above, the front of the cow is facing the </span>
|
||
<span class="c1"># -z direction. </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">0.0</span><span class="p">,</span> <span class="mf">0.0</span><span class="p">,</span> <span class="o">-</span><span class="mf">3.0</span><span class="p">]])</span>
|
||
|
||
<span class="c1"># Create a phong renderer by composing a rasterizer and a shader. The textured phong shader will </span>
|
||
<span class="c1"># interpolate the texture uv coordinates for each vertex, sample from a texture image and </span>
|
||
<span class="c1"># apply the Phong lighting model</span>
|
||
<span class="n">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">SoftPhongShader</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">
|
||
<h2 id="3.-Render-the-mesh">3. Render the mesh<a class="anchor-link" href="#3.-Render-the-mesh">¶</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>The light is in front of the object so it is bright and the image has specular highlights.</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">images</span> <span class="o">=</span> <span class="n">renderer</span><span class="p">(</span><span class="n">mesh</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">imshow</span><span class="p">(</span><span class="n">images</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">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">grid</span><span class="p">(</span><span class="s2">"off"</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>
|
||
</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.-Move-the-light-behind-the-object-and-re-render">4. Move the light behind the object and re-render<a class="anchor-link" href="#4.-Move-the-light-behind-the-object-and-re-render">¶</a></h2><p>We can pass arbirary keyword arguments to the <code>rasterizer</code>/<code>shader</code> via the call to the <code>renderer</code> so the renderer does not need to be reinitialized if any of the settings change/</p>
|
||
<p>In this case, we can simply update the location of the lights and pass them into the call to the renderer.</p>
|
||
<p>The image is now dark as there is only ambient lighting, and there are no specular highlights.</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"># Now move the light so it is on the +Z axis which will be behind the cow. </span>
|
||
<span class="n">lights</span><span class="o">.</span><span class="n">location</span> <span class="o">=</span> <span class="n">torch</span><span class="o">.</span><span class="n">tensor</span><span class="p">([</span><span class="mf">0.0</span><span class="p">,</span> <span class="mf">0.0</span><span class="p">,</span> <span class="o">+</span><span class="mf">1.0</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="kc">None</span><span class="p">]</span>
|
||
<span class="n">images</span> <span class="o">=</span> <span class="n">renderer</span><span class="p">(</span><span class="n">mesh</span><span class="p">,</span> <span class="n">lights</span><span class="o">=</span><span class="n">lights</span><span class="p">)</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="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">imshow</span><span class="p">(</span><span class="n">images</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">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">grid</span><span class="p">(</span><span class="s2">"off"</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>
|
||
</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.-Rotate-the-object,-modify-the-material-properties-or-light-properties">5. Rotate the object, modify the material properties or light properties<a class="anchor-link" href="#5.-Rotate-the-object,-modify-the-material-properties-or-light-properties">¶</a></h2><p>We can also change many other settings in the rendering pipeline. Here we:</p>
|
||
<ul>
|
||
<li>change the <strong>viewing angle</strong> of the camera</li>
|
||
<li>change the <strong>position</strong> of the point light</li>
|
||
<li>change the <strong>material reflectance</strong> properties of the mesh</li>
|
||
</ul>
|
||
</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"># Rotate the object by increasing the elevation and azimuth 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">dist</span><span class="o">=</span><span class="mf">2.7</span><span class="p">,</span> <span class="n">elev</span><span class="o">=</span><span class="mi">10</span><span class="p">,</span> <span class="n">azim</span><span class="o">=-</span><span class="mi">150</span><span class="p">)</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="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"># Move the light location so the light is shining on the cow's face. </span>
|
||
<span class="n">lights</span><span class="o">.</span><span class="n">location</span> <span class="o">=</span> <span class="n">torch</span><span class="o">.</span><span class="n">tensor</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">device</span><span class="o">=</span><span class="n">device</span><span class="p">)</span>
|
||
|
||
<span class="c1"># Change specular color to green and change material shininess </span>
|
||
<span class="n">materials</span> <span class="o">=</span> <span class="n">Materials</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">specular_color</span><span class="o">=</span><span class="p">[[</span><span class="mf">0.0</span><span class="p">,</span> <span class="mf">1.0</span><span class="p">,</span> <span class="mf">0.0</span><span class="p">]],</span>
|
||
<span class="n">shininess</span><span class="o">=</span><span class="mf">10.0</span>
|
||
<span class="p">)</span>
|
||
|
||
<span class="c1"># Re render the mesh, passing in keyword arguments for the modified components.</span>
|
||
<span class="n">images</span> <span class="o">=</span> <span class="n">renderer</span><span class="p">(</span><span class="n">mesh</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="n">materials</span><span class="o">=</span><span class="n">materials</span><span class="p">,</span> <span class="n">cameras</span><span class="o">=</span><span class="n">cameras</span><span class="p">)</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="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">imshow</span><span class="p">(</span><span class="n">images</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">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">grid</span><span class="p">(</span><span class="s2">"off"</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>
|
||
</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="6.-Batched-Rendering">6. Batched Rendering<a class="anchor-link" href="#6.-Batched-Rendering">¶</a></h2><p>One of the core design choices of the PyTorch3D API is to support <strong>batched inputs for all components</strong>.
|
||
The renderer and associated components can take batched inputs and <strong>render a batch of output images in one forward pass</strong>. We will now use this feature to render the mesh from many different viewpoints.</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"># Set batch size - this is the number of different viewpoints from which we want to render the mesh.</span>
|
||
<span class="n">batch_size</span> <span class="o">=</span> <span class="mi">20</span>
|
||
|
||
<span class="c1"># Create a batch of meshes by repeating the cow mesh and associated textures. </span>
|
||
<span class="c1"># Meshes has a useful `extend` method which allows us do this very easily. </span>
|
||
<span class="c1"># This also extends the textures. </span>
|
||
<span class="n">meshes</span> <span class="o">=</span> <span class="n">mesh</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">batch_size</span><span class="p">)</span>
|
||
|
||
<span class="c1"># Get a batch of viewing angles. </span>
|
||
<span class="n">elev</span> <span class="o">=</span> <span class="n">torch</span><span class="o">.</span><span class="n">linspace</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">180</span><span class="p">,</span> <span class="n">batch_size</span><span class="p">)</span>
|
||
<span class="n">azim</span> <span class="o">=</span> <span class="n">torch</span><span class="o">.</span><span class="n">linspace</span><span class="p">(</span><span class="o">-</span><span class="mi">180</span><span class="p">,</span> <span class="mi">180</span><span class="p">,</span> <span class="n">batch_size</span><span class="p">)</span>
|
||
|
||
<span class="c1"># All the cameras helper methods support mixed type inputs and broadcasting. So we can </span>
|
||
<span class="c1"># view the camera from the same distance and specify dist=2.7 as a float,</span>
|
||
<span class="c1"># and then specify elevation and azimuth angles for each viewpoint as tensors. </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">dist</span><span class="o">=</span><span class="mf">2.7</span><span class="p">,</span> <span class="n">elev</span><span class="o">=</span><span class="n">elev</span><span class="p">,</span> <span class="n">azim</span><span class="o">=</span><span class="n">azim</span><span class="p">)</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="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"># Move the light back in front of the cow which is facing the -z direction.</span>
|
||
<span class="n">lights</span><span class="o">.</span><span class="n">location</span> <span class="o">=</span> <span class="n">torch</span><span class="o">.</span><span class="n">tensor</span><span class="p">([[</span><span class="mf">0.0</span><span class="p">,</span> <span class="mf">0.0</span><span class="p">,</span> <span class="o">-</span><span class="mf">3.0</span><span class="p">]],</span> <span class="n">device</span><span class="o">=</span><span class="n">device</span><span class="p">)</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="c1"># We can pass arbirary keyword arguments to the rasterizer/shader via the renderer</span>
|
||
<span class="c1"># so the renderer does not need to be reinitialized if any of the settings change.</span>
|
||
<span class="n">images</span> <span class="o">=</span> <span class="n">renderer</span><span class="p">(</span><span class="n">meshes</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>
|
||
</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="n">image_grid</span><span class="p">(</span><span class="n">images</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">rows</span><span class="o">=</span><span class="mi">4</span><span class="p">,</span> <span class="n">cols</span><span class="o">=</span><span class="mi">5</span><span class="p">,</span> <span class="n">rgb</span><span class="o">=</span><span class="kc">True</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="7.-Conclusion">7. Conclusion<a class="anchor-link" href="#7.-Conclusion">¶</a></h2><p>In this tutorial we learnt how to <strong>load</strong> a textured 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>, and modify several components of the rendering pipeline.</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 © 2020 Facebook 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> |