├── LICENSE ├── README.md ├── dib-render ├── __init__.py ├── chamfer_dist │ ├── __init__.py │ ├── chamfer.cpp │ ├── chamfer.cu │ └── chamfer.py ├── check_chamfer.py ├── check_iou.py ├── config.py ├── cuda_dib_render │ ├── __init__.py │ ├── build.py │ ├── dr.cpp │ ├── dr_cuda_back.cu │ └── dr_cuda_for.cu ├── render_cuda │ ├── __init__.py │ ├── rendersettings.py │ └── utils_render_color2.py ├── sphere.obj ├── test-all.py └── voxelization.py ├── docs ├── .DS_Store ├── figures │ ├── .DS_Store │ ├── bird │ │ ├── .DS_Store │ │ ├── allsup.png │ │ └── car.png │ ├── car2.jpeg │ ├── car_1.jpeg │ ├── change-tex.png │ ├── combine_all_compare │ │ ├── 02691156_e2612c366bd11e305e9e2656aff7dd5b_19_blender_0.png │ │ ├── 02958343_cf3e2dd9595c223e82b157e7120744ea_4_blender_2.png │ │ ├── 02958343_d1dcddb5b1d7404dd9b0c189eb588ce6_4_blender_1.png │ │ ├── 02958343_d3869e2527ff032623276041d0efb3cb_3_blender_5.png │ │ ├── 02958343_e3c5a93775413a49ae3723ee0aa76826_6_blender_19.png │ │ ├── 03001627_d52e7e39bed3ed954f62c7a282978009_10_blender_23.png │ │ ├── 03001627_e3bc0a03103cf84e7a471a654ffbc436_8_blender_1.png │ │ ├── 03001627_eda8edcd64072b0db784faac204319d9_7_blender_8.png │ │ ├── 03211117_e1d73ee44f1d2422b5fb024f65f6da_4_blender_5.png │ │ ├── 03211117_e46e45f94470b45ad1924b802935a37a_17_blender_1.png │ │ ├── 03691459_cc88df1c3cfac12a99db62650613bd48_17_blender_14.png │ │ ├── 03691459_cc88df1c3cfac12a99db62650613bd48_17_blender_4.png │ │ ├── 03691459_cc88df1c3cfac12a99db62650613bd48_17_blender_5.png │ │ ├── 04090263_d945ecdf7613bfe0c7da109ecb5068a0_4_blender_17.png │ │ ├── 04256520_f05f6b3e7c0afdb352fc7e973ba7787_11_blender_15.png │ │ ├── 04256520_f43414acdca3878674c5bf7a74b1b6df_22_blender_16.png │ │ ├── 04256520_fcf30cec3180c05da5f9d52c12457194_22_blender_1.png │ │ ├── 04379243_cfa823ee81496f5912b57997414c1d71_4_blender_5.png │ │ ├── 04379243_e2571e4eba2d9f5eab610b0c94236463_20_blender_4.png │ │ ├── 04379243_e48675e37096a6898527e24d5de49fe6_1_blender_13.png │ │ ├── 04379243_ed8dd7ac0d865ac686f1a0f58f951001_15_blender_11.png │ │ ├── 04401088_e8d826158072a6bf1455397a420729a1_21_blender_20.png │ │ └── 04530566_f18739a47f1f08e08510ad9ae6ed36b6_22_blender_3.png │ ├── comp_nm3r_sup │ │ ├── db45ce3926c3ac69e8d8ad3bdef6aca2_8.png │ │ ├── dbded0816afdfcf776ad064d1c5fdd7c_14.png │ │ ├── dc8aef6a8c88997a582e5e3e7771ea25_19.png │ │ ├── df8000281bcfdf0754f3692df239bb9b_15.png │ │ ├── e00fde4225d166b1ce929ad7e848003e_2.png │ │ ├── e0b9bb886c578be86e9dcc2d1ea2784d_22.png │ │ ├── e625eb804f2fb6caa26598ab726b7540_23.png │ │ ├── eb27ff8c450c2c5f393cd3bb7e57a291_11.png │ │ ├── ef05b5fa8e2377f8fa7a46166f316347_10.png │ │ ├── efd87861810e35ca921cb81cb1632a5e_6.png │ │ └── fc85555afe23abcc5b716151669cefc7_16.png │ ├── gan_out.mp4 │ ├── model2a-2.png │ ├── texture_supp.pdf │ ├── update-out.mp4 │ └── w_wo.pdf ├── files │ ├── .DS_Store │ ├── bib.tex │ ├── diff_shader.pdf │ ├── paper.png │ └── supplement.pdf └── index.html ├── requirements.txt └── utils ├── __init__.py ├── dataloader ├── __init__.py └── dataloader_multiview_blender.py ├── model ├── __init__.py └── modelcolor.py ├── render └── renderfunc_cluster.py └── utils ├── __init__.py ├── utils_mesh.py └── utils_perspective.py /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a 6 | copy of this software and associated documentation files (the "Software"), 7 | to deal in the Software without restriction, including without limitation 8 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | and/or sell copies of the Software, and to permit persons to whom the 10 | Software is furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DIB-Render 2 | This is the official inference code for: 3 | 4 | #### Learning to Predict 3D Objects with an Interpolation-based Differentiable Renderer (NeurIPS 2019) 5 | 6 | [Wenzheng Chen](http://www.cs.toronto.edu/~wenzheng/), [Jun Gao\*](http://www.cs.toronto.edu/~jungao/), [Huan Ling\*](http://www.cs.toronto.edu/~linghuan/), [Edward J. Smith\*](), [Jaakko Lehtinen](https://users.aalto.fi/~lehtinj7/), [Alec Jacobson](https://www.cs.toronto.edu/~jacobson/), [Sanja Fidler](http://www.cs.toronto.edu/~fidler/) 7 | 8 | 9 | **[[Paper](https://arxiv.org/abs/1908.01210)] [[Project Page](https://nv-tlabs.github.io/DIB-R/)]** 10 | 11 | 12 | **Note**: key functions from this work have also been ported to [Kaolin Library](https://github.com/NVIDIAGameWorks/kaolin), where they continue to be maintained. See [this example repo](https://github.com/nv-tlabs/DIB-R-Single-Image-3D-Reconstruction), as well as [this tutorial](https://github.com/NVIDIAGameWorks/kaolin/blob/master/examples/tutorial/dibr_tutorial.ipynb). Please cite our paper regardless of the implementation you end up using for your research. 13 | 14 | ## Usage 15 | 16 | 17 | ### Install dependencies 18 | 19 | This code requires PyTorch 1.1.0 and python 3+. Please install dependencies by 20 | ```bash 21 | pip install -r requirments.txt 22 | ``` 23 | 24 | ### Compile the DIB-Render 25 | ```bash 26 | cd dib-render/cuda_dib_render 27 | python build.py install 28 | ``` 29 | 30 | 31 | ### Inference 32 | ``` bash 33 | python test-all.py \ 34 | --g_model_dir ./checkpoints/g_model.pth \ 35 | --svfolder ./prediction \ 36 | --data_folder ./dataset \ 37 | --filelist ./test_list.txt 38 | ``` 39 | 40 | To get the evaluation IOU, please first download the tool [Binvox](https://www.patrickmin.com/binvox/) and install it's dependencies, 41 | 42 | Voxelize the prediction using Binvox 43 | ```bash 44 | python voxelization.py --folder ./prediction 45 | ``` 46 | 47 | To evaluate the IOU, please first install binvox-rw-py following this [Link](https://github.com/dimatura/binvox-rw-py), then run the script 48 | ```bash 49 | python check_iou.py --folder ./prediction --gt_folder ./dataset 50 | ``` 51 | 52 | To get the boundary F-score, please run the following script 53 | ```bash 54 | python check_chamfer.py --folder ./prediction --gt_folder ./dataset 55 | ``` 56 | 57 | ### Ciatation 58 | If you use the code, please cite our paper: 59 | ``` 60 | @inproceedings{chen2019dibrender, 61 | title={Learning to Predict 3D Objects with an Interpolation-based Differentiable Renderer}, 62 | author={Wenzheng Chen and Jun Gao and Huan Ling and Edward Smith and Jaakko Lehtinen and Alec Jacobson and Sanja Fidler}, 63 | booktitle={Advances In Neural Information Processing Systems}, 64 | year={2019} 65 | } 66 | ``` -------------------------------------------------------------------------------- /dib-render/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in 11 | # all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | # DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /dib-render/chamfer_dist/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in 11 | # all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | # DEALINGS IN THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /dib-render/chamfer_dist/chamfer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #include 24 | #include 25 | using namespace std; 26 | 27 | void ChamferKernelLauncher( 28 | const float* xyz1, 29 | const float* xyz2, 30 | float* dist1, 31 | float* dist2, 32 | int* idx1, 33 | int* idx2, 34 | int b, int n, int m); 35 | 36 | void chamfer_forward_cuda( 37 | const at::Tensor xyz1, 38 | const at::Tensor xyz2, 39 | at::Tensor dist1, 40 | at::Tensor dist2, 41 | at::Tensor idx1, 42 | at::Tensor idx2) 43 | { 44 | int batch_size = xyz1.size(0); 45 | int n = xyz1.size(1); 46 | int m = xyz2.size(1); 47 | ChamferKernelLauncher(xyz1.data(), xyz2.data(), 48 | dist1.data(), dist2.data(), 49 | idx1.data(), idx2.data(), batch_size, n, m); 50 | } 51 | 52 | 53 | PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) { 54 | m.def("forward_cuda", &chamfer_forward_cuda, "Chamfer forward (CUDA)"); 55 | } 56 | -------------------------------------------------------------------------------- /dib-render/chamfer_dist/chamfer.cu: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #include 24 | #include 25 | using namespace std; 26 | #include 27 | #include 28 | 29 | __global__ void ChamferKernel( 30 | const float* xyz1, 31 | const float* xyz2, 32 | float* dist, 33 | int* idx, int batch_size, int n, int m) 34 | { 35 | // bidx * height + heiidx 36 | int presentthread = blockIdx.x * blockDim.x + threadIdx.x; 37 | int n_idx = presentthread % n; 38 | int b_idx = (presentthread - n_idx) / n; 39 | 40 | if (b_idx >= batch_size || n_idx >= n) { 41 | return; 42 | } 43 | int min_idx = 0; 44 | float min_dist = 10000.0; 45 | float cur_x = xyz1[b_idx * n * 3 + n_idx * 3]; 46 | float cur_y = xyz1[b_idx * n * 3 + n_idx * 3 + 1]; 47 | float cur_z = xyz1[b_idx * n * 3 + n_idx * 3 + 2]; 48 | float next_x, next_y, next_z; 49 | float diff_x, diff_y, diff_z; 50 | float tmp_dist; 51 | for (int i = 0; i < m; i++){ 52 | next_x = xyz2[b_idx * m * 3 + i * 3]; 53 | next_y = xyz2[b_idx * m * 3 + i * 3 + 1]; 54 | next_z = xyz2[b_idx * m * 3 + i * 3 + 2]; 55 | 56 | diff_x = cur_x - next_x; 57 | diff_y = cur_y - next_y; 58 | diff_z = cur_z - next_z; 59 | 60 | tmp_dist = diff_x * diff_x + diff_y * diff_y + diff_z * diff_z; 61 | tmp_dist = sqrt(tmp_dist); 62 | if (tmp_dist < min_dist){ 63 | min_dist = tmp_dist; 64 | min_idx = i; 65 | } 66 | } 67 | dist[b_idx * n + n_idx] = min_dist; 68 | idx[b_idx * n + n_idx] = min_idx; 69 | } 70 | 71 | void ChamferKernelLauncher( 72 | const float* xyz1, 73 | const float* xyz2, 74 | float* dist1, 75 | float* dist2, 76 | int* idx1, 77 | int* idx2, 78 | int batch_size, int n, int m){ 79 | 80 | const int threadnum = 1024; 81 | const int totalthread = batch_size * n; 82 | const int blocknum = totalthread / threadnum + 1; 83 | 84 | const dim3 threads(threadnum, 1, 1); 85 | const dim3 blocks(blocknum, 1, 1); 86 | 87 | ChamferKernel<<>>(xyz1, xyz2, dist1, idx1, batch_size, n, m); 88 | const int totalthread2 = batch_size * m; 89 | const int blocknum2 = totalthread2 / threadnum + 1; 90 | 91 | const dim3 threads2(threadnum, 1, 1); 92 | const dim3 blocks2(blocknum2, 1, 1); 93 | ChamferKernel<<>>(xyz2, xyz1, dist2, idx2, batch_size, m, n); 94 | 95 | cudaError_t err = cudaGetLastError(); 96 | } 97 | 98 | -------------------------------------------------------------------------------- /dib-render/chamfer_dist/chamfer.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in 11 | # all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | # DEALINGS IN THE SOFTWARE. 20 | 21 | import torch 22 | 23 | from torch.utils.cpp_extension import load 24 | cd = load(name="chamfer", 25 | sources=["chamfer_dist/chamfer.cpp", 26 | "chamfer_dist/chamfer.cu"]) 27 | 28 | class ChamferFunction(torch.autograd.Function): 29 | 30 | @staticmethod 31 | def forward(ctx, xyz1, xyz2): 32 | batchsize, n, _ = xyz1.size() 33 | _, m, _ = xyz2.size() 34 | 35 | dist1 = torch.zeros(batchsize, n).float().to(xyz1.device) 36 | dist2 = torch.zeros(batchsize, m).float().to(xyz1.device) 37 | 38 | idx1 = torch.zeros(batchsize, n).type(torch.IntTensor).to(xyz1.device) 39 | idx2 = torch.zeros(batchsize, m).type(torch.IntTensor).to(xyz1.device) 40 | 41 | cd.forward_cuda(xyz1, xyz2, dist1, dist2, idx1, idx2) 42 | return idx1, idx2, dist1, dist2 43 | 44 | @staticmethod 45 | def backward(ctx, graddist1, graddist2): 46 | ints = ctx.saved_tensors 47 | gradxyz1 = torch.zeros(ints.size()) 48 | return gradxyz1, gradxyz1 49 | 50 | class Chamfer(torch.nn.Module): 51 | def forward(self, points1, points2): 52 | return ChamferFunction.apply(points1, points2) -------------------------------------------------------------------------------- /dib-render/check_chamfer.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in 11 | # all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | # DEALINGS IN THE SOFTWARE. 20 | 21 | import glob 22 | import os 23 | import torch 24 | import argparse 25 | import sys 26 | sys.path.append('../utils/') 27 | from utils.utils_mesh import loadobjcolor, loadobj 28 | import numpy as np 29 | from chamfer_dist.chamfer import Chamfer 30 | torch.random.manual_seed(12345) 31 | np.random.seed(123456) 32 | import random 33 | random.seed(1234567) 34 | from collections import defaultdict 35 | 36 | def get_args(): 37 | parser = argparse.ArgumentParser(description='check chamfer-dist and F-score') 38 | parser.add_argument('--folder', type=str, default='debug', 39 | help='prediction folder') 40 | parser.add_argument('--gt_folder', type=str, default='debug', 41 | help='gt folder') 42 | args = parser.parse_args() 43 | return args 44 | 45 | def sample(verts, faces, num=10000, ret_choice = False): 46 | dist_uni = torch.distributions.Uniform(torch.tensor([0.0]).cuda(), torch.tensor([1.0]).cuda()) 47 | x1,x2,x3 = torch.split(torch.index_select(verts, 0, faces[:,0]) - torch.index_select(verts, 0, faces[:,1]), 1, dim = 1) 48 | y1,y2,y3 = torch.split(torch.index_select(verts, 0, faces[:,1]) - torch.index_select(verts, 0, faces[:,2]), 1, dim = 1) 49 | a = (x2*y3 - x3*y2)**2 50 | b = (x3*y1 - x1*y3)**2 51 | c = (x1*y2 - x2*y1)**2 52 | Areas = torch.sqrt(a+b+c)/2 53 | Areas = Areas / torch.sum(Areas) 54 | cat_dist = torch.distributions.Categorical(Areas.view(-1)) 55 | choices = cat_dist.sample_n(num) 56 | select_faces = faces[choices] 57 | xs = torch.index_select(verts, 0,select_faces[:,0]) 58 | ys = torch.index_select(verts, 0,select_faces[:,1]) 59 | zs = torch.index_select(verts, 0,select_faces[:,2]) 60 | u = torch.sqrt(dist_uni.sample_n(num)) 61 | v = dist_uni.sample_n(num) 62 | points = (1- u)*xs + (u*(1-v))*ys + u*v*zs 63 | if ret_choice: 64 | return points, choices 65 | else: 66 | return points 67 | 68 | def main() : 69 | args = get_args() 70 | folder = args.folder 71 | print('==> get all predictions') 72 | print(folder) 73 | meshfiles = glob.glob('%s/*/*/*.obj' % folder) 74 | print('Length mesh files: ', len(meshfiles)) 75 | gt_folder = args.gt_folder 76 | print ('==> starting ') 77 | chamfer = Chamfer() 78 | cates = '02691156,02828884,02933112,02958343,03001627,03211117,03636649,03691459,04090263,04256520,04379243,04401088,04530566' 79 | cates = cates.split(',') 80 | dist_cate = defaultdict(list) 81 | F_score = defaultdict(list) 82 | random.shuffle(meshfiles) 83 | toa = [0.01, 0.015, 0.02, 0.025, 0.03, 0.035, 0.04, 0.045, 0.05] 84 | for i, fl in enumerate(meshfiles): 85 | tmp_name = fl 86 | names = fl.split('/') 87 | cat = names[-3] 88 | md5 = names[-2] 89 | gt_name = os.path.join(gt_folder, cat, md5, 'model-0.45.obj') 90 | vertices, faces = loadobjcolor(tmp_name) 91 | if vertices.shape[0] == 0: 92 | print('Error in read shape') 93 | print(tmp_name) 94 | continue 95 | gt_vertices, gt_faces = loadobj(gt_name) 96 | if gt_vertices.shape[0] == 0: 97 | print('Error in read shape') 98 | print(tmp_name) 99 | continue 100 | gt_vertices = torch.from_numpy(gt_vertices).float().cuda() 101 | gt_faces = torch.from_numpy(gt_faces).cuda() 102 | try: 103 | sample_gt = sample(gt_vertices, gt_faces, num=2500) 104 | except: 105 | print('Error in sample:') 106 | print(fl) 107 | continue 108 | sample_gt = sample_gt.unsqueeze(0) 109 | 110 | vertices = torch.from_numpy(vertices).float().cuda() 111 | faces = torch.from_numpy(faces).cuda() 112 | try: 113 | sample_p = sample(vertices, faces, num=2500) 114 | except: 115 | print('Error in sample:') 116 | print(fl) 117 | continue 118 | sample_p = sample_p.unsqueeze(0) 119 | 120 | _, _, dist1, dist2 = chamfer(sample_p, sample_gt) 121 | 122 | cf = (dist1.mean() + dist2.mean()) / 2 123 | f_score_list = [] 124 | for t in toa: 125 | fp = (dist1 > t).float().sum() 126 | tp = (dist1 <= t).float().sum() 127 | precision = tp / (tp + fp) 128 | tp = (dist2 <= t).float().sum() 129 | fn = (dist2 > t).float().sum() 130 | recall = tp / (tp + fn) 131 | f_score = 2 * (precision * recall) / (precision + recall + 1e-8) 132 | f_score_list.append(f_score.item()) 133 | F_score[cat].append(f_score_list) 134 | dist_cate[cat].append(cf.item()) 135 | if i % 1000 == 999: 136 | print('-'*50) 137 | print('Step: ', i) 138 | print('==> chamfer') 139 | for c in cates: 140 | print('%s: %.10f' %(c, np.mean(dist_cate[c]))) 141 | print('Mean of ALL: %.10f'%(np.mean([np.mean(dist_cate[c]) for c in cates]))) 142 | print('==> F') 143 | mean_score_list = [] 144 | for c in cates: 145 | print(c, end='') 146 | s = F_score[c] 147 | s = np.asarray(s) 148 | mean_s = np.mean(s, axis=0) 149 | mean_score_list.append(mean_s) 150 | for i in range(len(toa)): 151 | print(' %.10f' % mean_s[i], end='') 152 | print('') 153 | all_mean = np.asarray(mean_score_list) 154 | all_mean = np.mean(all_mean, axis=0) 155 | print('ALL Mean:', end='') 156 | for i in range(len(toa)): 157 | print(' %.10f' % all_mean[i], end='') 158 | print('\n') 159 | 160 | if __name__ == '__main__': 161 | main() -------------------------------------------------------------------------------- /dib-render/check_iou.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in 11 | # all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | # DEALINGS IN THE SOFTWARE. 20 | 21 | from __future__ import print_function 22 | from __future__ import division 23 | 24 | import os 25 | import numpy as np 26 | import glob 27 | import binvox_rw 28 | import multiprocessing 29 | from functools import partial 30 | import argparse 31 | 32 | def get_args(): 33 | parser = argparse.ArgumentParser(description='check iou score') 34 | parser.add_argument('--folder', type=str, default='debug', 35 | help='prediction folder') 36 | parser.add_argument('--gt_folder', type=str, default='debug', 37 | help='gt folder') 38 | args = parser.parse_args() 39 | return args 40 | 41 | def evaluate_instance(file_name, gtfolder=None): 42 | if 'imview' in file_name or '_1' in file_name: 43 | return [0] 44 | 45 | prefl = file_name 46 | names = prefl.split('/') 47 | cat = names[-3] 48 | md5 = names[-2] 49 | 50 | gtfl = '%s/%s/%s/model-0.45.binvox' % (gtfolder, cat, md5) 51 | 52 | try: 53 | with open(prefl, 'rb') as f: 54 | data = binvox_rw.read_as_3d_array(f) 55 | with open(gtfl, 'rb') as f: 56 | data2 = binvox_rw.read_as_3d_array(f) 57 | except: 58 | print('Error in read data') 59 | print(prefl) 60 | print(gtfl) 61 | return [0] 62 | 63 | iouall = data.data | data2.data 64 | iouoverlap = data.data & data2.data 65 | iouthis = np.sum(iouoverlap) / (np.sum(iouall) + 1e-8) 66 | iouthisgt = np.sum(iouoverlap) / (np.sum(data2.data) + 1e-8) 67 | iouthispre = np.sum(iouoverlap) / (np.sum(data.data) + 1e-8) 68 | 69 | return [cat, iouthis, iouthisgt, iouthispre] 70 | 71 | 72 | def filter(file_list): 73 | new_list = [] 74 | for name in file_list: 75 | if '_1' in file_list: 76 | continue 77 | new_list.append(name) 78 | return new_list 79 | 80 | def main(): 81 | args = get_args() 82 | folder = args.folder 83 | print(folder) 84 | 85 | voxelfiles = glob.glob('%s/*/*/*.binvox' % folder) 86 | print('Length files: ', len(voxelfiles)) 87 | 88 | iou = {} 89 | iougt = {} 90 | ioupre = {} 91 | catenum = {} 92 | cates = '02691156,02828884,02933112,02958343,03001627,03211117,03636649,03691459,04090263,04256520,04379243,04401088,04530566' 93 | cates = cates.split(',') 94 | 95 | for ca in cates: 96 | iou[ca] = 0 97 | iougt[ca] = 0 98 | ioupre[ca] = 0 99 | catenum[ca] = 0 100 | 101 | gtfolder = args.gt_folder 102 | 103 | pool = multiprocessing.Pool(multiprocessing.cpu_count()) 104 | print("Using %i cpus" % multiprocessing.cpu_count()) 105 | 106 | results = [] 107 | 108 | for x in pool.imap_unordered(partial(evaluate_instance, gtfolder=gtfolder), voxelfiles): 109 | if x[0] != 0: 110 | results.append(x) 111 | 112 | pool.close() 113 | pool.join() 114 | 115 | for i in range(len(results)): 116 | result = results[i] 117 | if result[0] == 0: 118 | continue 119 | if len(result) == 1: 120 | continue 121 | cat, iouthis, iouthisgt, iouthispre = result 122 | iou[cat] += iouthis 123 | iougt[cat] += iouthisgt 124 | ioupre[cat] += iouthispre 125 | catenum[cat] += 1 126 | 127 | re = [] 128 | for ca in cates: 129 | iou[ca] /= catenum[ca] + 1e-8 130 | iougt[ca] /= catenum[ca] + 1e-8 131 | ioupre[ca] /= catenum[ca] + 1e-8 132 | print('{}, {} {} {}'.format(ca, iou[ca], ioupre[ca], iougt[ca], catenum[ca])) 133 | re.append([int(ca), iou[ca], ioupre[ca], iougt[ca], catenum[ca]]) 134 | 135 | re = np.array(re, dtype=np.float32) 136 | path = '%s-iou.npy' % folder 137 | np.save(file=path, arr=re) 138 | 139 | meanval = np.mean(re, axis=0) 140 | print('{}, {} {} {}'.format('mean', meanval[1], meanval[2], meanval[3])) 141 | iou_format = ['%.4f'%(t) for t in re[:,1]] 142 | print('&'.join(iou_format)) 143 | print('Category Num: ', re[:, -1]) 144 | 145 | if __name__ == '__main__': 146 | main() 147 | -------------------------------------------------------------------------------- /dib-render/config.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in 11 | # all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | # DEALINGS IN THE SOFTWARE. 20 | 21 | import argparse 22 | 23 | 24 | def get_args(): 25 | parser = argparse.ArgumentParser(description='dib-r') 26 | 27 | parser.add_argument('--filelist', type=str, default='train_list.txt', 28 | help='filelist name') 29 | parser.add_argument('--thread', type=int, default=8, 30 | help='num of workers') 31 | parser.add_argument('--svfolder', type=str, default='experiment', 32 | help='save folder for experiments ') 33 | parser.add_argument('--g_model_dir', type=str, default='pretrained_model', 34 | help='save path for pretrained model') 35 | parser.add_argument('--data_folder', type=str, default='data', 36 | help='data folder') 37 | parser.add_argument('--iter', type=int, default=-1, 38 | help='start iteration') 39 | 40 | parser.add_argument('--loss', type=str, default='iou', 41 | help='loss type') 42 | parser.add_argument('--camera', type=str, default='per', 43 | help='camera mode') 44 | parser.add_argument('--view', type=int, default=2, 45 | help='view number') 46 | 47 | parser.add_argument('--img_dim', type=int, default=64, 48 | help='dim of image') 49 | parser.add_argument('--img_channels', type=int, default=4, 50 | help='image channels') 51 | parser.add_argument('--batch_size', type=int, default=64, 52 | help='batch size') 53 | 54 | parser.add_argument('--epoch', type=int, default=1000, 55 | help='training epoch') 56 | parser.add_argument('--iter_log', type=int, default=50, 57 | help='iterations per log') 58 | parser.add_argument('--iter_sample', type=int, default=1000, 59 | help='iterations per sample') 60 | parser.add_argument('--iter_model', type=int, default=10000, 61 | help='iterations per model saving') 62 | 63 | parser.add_argument('--sil_lambda', type=float, default=1, 64 | help='hyperparamter for sil') 65 | 66 | args = parser.parse_args() 67 | 68 | return args 69 | 70 | -------------------------------------------------------------------------------- /dib-render/cuda_dib_render/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in 11 | # all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | # DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /dib-render/cuda_dib_render/build.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in 11 | # all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | # DEALINGS IN THE SOFTWARE. 20 | 21 | from setuptools import setup 22 | from torch.utils.cpp_extension import BuildExtension, CUDAExtension 23 | 24 | setup( 25 | name='dr_batch_dib_render', 26 | ext_modules=[ 27 | CUDAExtension('dr_batch_dib_render', [ 28 | 'dr.cpp', 29 | 'dr_cuda_for.cu', 30 | 'dr_cuda_back.cu' 31 | ]) 32 | ], 33 | cmdclass={ 34 | 'build_ext': BuildExtension 35 | }) 36 | 37 | -------------------------------------------------------------------------------- /dib-render/cuda_dib_render/dr.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #include 24 | 25 | // C++ interface 26 | #define CHECK_CUDA(x) AT_ASSERTM(x.type().is_cuda(), #x " must be a CUDA tensor") 27 | #define CHECK_CONTIGUOUS(x) AT_ASSERTM(x.is_contiguous(), #x " must be contiguous") 28 | #define CHECK_INPUT(x) CHECK_CUDA(x); CHECK_CONTIGUOUS(x) 29 | 30 | #define CHECK_DIM3(x, b, h, w, d) AT_ASSERTM((x.size(0) == b) && (x.size(1) == h) && (x.size(2) == w) && (x.size(3) == d), #x " must be same im size") 31 | #define CHECK_DIM2(x, b, f, d) AT_ASSERTM((x.size(0) == b) && (x.size(1) == f) && (x.size(2) == d), #x " must be same point size") 32 | 33 | //////////////////////////////////////////////////////////// 34 | // CUDA forward declarations 35 | void dr_cuda_forward_batch(at::Tensor points3d_bxfx9, at::Tensor points2d_bxfx6, 36 | at::Tensor pointsdirect_bxfx1, at::Tensor pointsbbox_bxfx4, 37 | at::Tensor pointsbbox2_bxfx4, at::Tensor pointsdep_bxfx1, 38 | at::Tensor colors_bxfx3d, at::Tensor imidx_bxhxwx1, 39 | at::Tensor imdep_bxhxwx1, at::Tensor imwei_bxhxwx3, 40 | at::Tensor probface_bxhxwxk, at::Tensor probcase_bxhxwxk, 41 | at::Tensor probdis_bxhxwxk, at::Tensor probdep_bxhxwxk, 42 | at::Tensor probacc_bxhxwxk, at::Tensor im_bxhxwxd, 43 | at::Tensor improb_bxhxwx1, int multiplier, int sigmainv); 44 | 45 | void dr_forward_batch(at::Tensor points3d_bxfx9, at::Tensor points2d_bxfx6, 46 | at::Tensor pointsdirect_bxfx1, at::Tensor pointsbbox_bxfx4, 47 | at::Tensor pointsbbox2_bxfx4, at::Tensor pointsdep_bxfx1, 48 | at::Tensor colors_bxfx3d, at::Tensor imidx_bxhxwx1, 49 | at::Tensor imdep_bxhxwx1, at::Tensor imwei_bxhxwx3, 50 | at::Tensor probface_bxhxwxk, at::Tensor probcase_bxhxwxk, 51 | at::Tensor probdis_bxhxwxk, at::Tensor probdep_bxhxwxk, 52 | at::Tensor probacc_bxhxwxk, at::Tensor im_bxhxwxd, 53 | at::Tensor improb_bxhxwx1, int multiplier, int sigmainv) { 54 | 55 | CHECK_INPUT(points3d_bxfx9); 56 | CHECK_INPUT(points2d_bxfx6); 57 | CHECK_INPUT(pointsdirect_bxfx1); 58 | CHECK_INPUT(pointsbbox_bxfx4); 59 | CHECK_INPUT(pointsbbox2_bxfx4); 60 | CHECK_INPUT(pointsdep_bxfx1); 61 | CHECK_INPUT(colors_bxfx3d); 62 | 63 | CHECK_INPUT(imidx_bxhxwx1); 64 | CHECK_INPUT(imdep_bxhxwx1); 65 | CHECK_INPUT(imwei_bxhxwx3); 66 | 67 | CHECK_INPUT(probface_bxhxwxk); 68 | CHECK_INPUT(probcase_bxhxwxk); 69 | CHECK_INPUT(probdis_bxhxwxk); 70 | CHECK_INPUT(probdep_bxhxwxk); 71 | CHECK_INPUT(probacc_bxhxwxk); 72 | 73 | CHECK_INPUT(im_bxhxwxd); 74 | CHECK_INPUT(improb_bxhxwx1); 75 | 76 | int bnum = points3d_bxfx9.size(0); 77 | int fnum = points3d_bxfx9.size(1); 78 | int height = im_bxhxwxd.size(1); 79 | int width = im_bxhxwxd.size(2); 80 | int dnum = im_bxhxwxd.size(3); 81 | 82 | int knum = probface_bxhxwxk.size(3); 83 | 84 | CHECK_DIM2(points3d_bxfx9, bnum, fnum, 9); 85 | CHECK_DIM2(points2d_bxfx6, bnum, fnum, 6); 86 | CHECK_DIM2(pointsdirect_bxfx1, bnum, fnum, 1); 87 | CHECK_DIM2(pointsbbox_bxfx4, bnum, fnum, 4); 88 | CHECK_DIM2(pointsbbox2_bxfx4, bnum, fnum, 4); 89 | CHECK_DIM2(pointsdep_bxfx1, bnum, fnum, 1); 90 | CHECK_DIM2(colors_bxfx3d, bnum, fnum, 3 * dnum); 91 | 92 | CHECK_DIM3(imidx_bxhxwx1, bnum, height, width, 1); 93 | CHECK_DIM3(imdep_bxhxwx1, bnum, height, width, 1); 94 | CHECK_DIM3(imwei_bxhxwx3, bnum, height, width, 3); 95 | 96 | CHECK_DIM3(probface_bxhxwxk, bnum, height, width, knum); 97 | CHECK_DIM3(probcase_bxhxwxk, bnum, height, width, knum); 98 | CHECK_DIM3(probdis_bxhxwxk, bnum, height, width, knum); 99 | CHECK_DIM3(probdep_bxhxwxk, bnum, height, width, knum); 100 | CHECK_DIM3(probacc_bxhxwxk, bnum, height, width, knum); 101 | 102 | CHECK_DIM3(im_bxhxwxd, bnum, height, width, dnum); 103 | CHECK_DIM3(improb_bxhxwx1, bnum, height, width, 1); 104 | 105 | dr_cuda_forward_batch(points3d_bxfx9, points2d_bxfx6, pointsdirect_bxfx1, 106 | pointsbbox_bxfx4, pointsbbox2_bxfx4, pointsdep_bxfx1, colors_bxfx3d, 107 | imidx_bxhxwx1, imdep_bxhxwx1, imwei_bxhxwx3, probface_bxhxwxk, 108 | probcase_bxhxwxk, probdis_bxhxwxk, probdep_bxhxwxk, probacc_bxhxwxk, 109 | im_bxhxwxd, improb_bxhxwx1, multiplier, sigmainv); 110 | 111 | return; 112 | } 113 | 114 | //////////////////////////////////////////////////////////// 115 | void dr_cuda_backward_batch(at::Tensor grad_image_bxhxwxd, 116 | at::Tensor grad_improb_bxhxwx1, at::Tensor image_bxhxwxd, 117 | at::Tensor improb_bxhxwx1, at::Tensor imidx_bxhxwx1, 118 | at::Tensor imwei_bxhxwx3, at::Tensor probface_bxhxwxk, 119 | at::Tensor probcase_bxhxwxk, at::Tensor probdis_bxhxwxk, 120 | at::Tensor probdep_bxhxwxk, at::Tensor probacc_bxhxwxk, 121 | at::Tensor points2d_bxfx6, at::Tensor colors_bxfx3d, 122 | at::Tensor grad_points2d_bxfx6, at::Tensor grad_colors_bxfx3d, 123 | at::Tensor grad_points2dprob_bxfx6, at::Tensor debug_im_bxhxwx3, 124 | int multiplier, int sigmainv); 125 | 126 | void dr_backward_batch(at::Tensor grad_image_bxhxwxd, 127 | at::Tensor grad_improb_bxhxwx1, at::Tensor image_bxhxwxd, 128 | at::Tensor improb_bxhxwx1, at::Tensor imidx_bxhxwx1, 129 | at::Tensor imwei_bxhxwx3, at::Tensor probface_bxhxwxk, 130 | at::Tensor probcase_bxhxwxk, at::Tensor probdis_bxhxwxk, 131 | at::Tensor probdep_bxhxwxk, at::Tensor probacc_bxhxwxk, 132 | at::Tensor points2d_bxfx6, at::Tensor colors_bxfx3d, 133 | at::Tensor grad_points2d_bxfx6, at::Tensor grad_colors_bxfx3d, 134 | at::Tensor grad_points2dprob_bxfx6, at::Tensor debug_im_bxhxwx3, 135 | int multiplier, int sigmainv) { 136 | 137 | CHECK_INPUT(grad_image_bxhxwxd); 138 | CHECK_INPUT(grad_improb_bxhxwx1); 139 | CHECK_INPUT(image_bxhxwxd); 140 | CHECK_INPUT(improb_bxhxwx1); 141 | CHECK_INPUT(imidx_bxhxwx1); 142 | CHECK_INPUT(imwei_bxhxwx3); 143 | 144 | CHECK_INPUT(probface_bxhxwxk); 145 | CHECK_INPUT(probcase_bxhxwxk); 146 | CHECK_INPUT(probdis_bxhxwxk); 147 | CHECK_INPUT(probdep_bxhxwxk); 148 | CHECK_INPUT(probacc_bxhxwxk); 149 | 150 | CHECK_INPUT(points2d_bxfx6); 151 | CHECK_INPUT(colors_bxfx3d); 152 | CHECK_INPUT(grad_points2d_bxfx6); 153 | CHECK_INPUT(grad_colors_bxfx3d); 154 | CHECK_INPUT(grad_points2dprob_bxfx6); 155 | CHECK_INPUT(debug_im_bxhxwx3); 156 | 157 | int bnum = grad_image_bxhxwxd.size(0); 158 | int height = grad_image_bxhxwxd.size(1); 159 | int width = grad_image_bxhxwxd.size(2); 160 | int dnum = grad_image_bxhxwxd.size(3); 161 | int fnum = grad_points2d_bxfx6.size(1); 162 | int knum = probface_bxhxwxk.size(3); 163 | 164 | CHECK_DIM3(grad_image_bxhxwxd, bnum, height, width, dnum); 165 | CHECK_DIM3(grad_improb_bxhxwx1, bnum, height, width, 1); 166 | 167 | CHECK_DIM3(image_bxhxwxd, bnum, height, width, dnum); 168 | CHECK_DIM3(improb_bxhxwx1, bnum, height, width, 1); 169 | 170 | CHECK_DIM3(imidx_bxhxwx1, bnum, height, width, 1); 171 | CHECK_DIM3(imwei_bxhxwx3, bnum, height, width, 3); 172 | 173 | CHECK_DIM3(probface_bxhxwxk, bnum, height, width, knum); 174 | CHECK_DIM3(probface_bxhxwxk, bnum, height, width, knum); 175 | CHECK_DIM3(probdis_bxhxwxk, bnum, height, width, knum); 176 | CHECK_DIM3(probdep_bxhxwxk, bnum, height, width, knum); 177 | CHECK_DIM3(probacc_bxhxwxk, bnum, height, width, knum); 178 | 179 | CHECK_DIM2(points2d_bxfx6, bnum, fnum, 6); 180 | CHECK_DIM2(colors_bxfx3d, bnum, fnum, 3 * dnum); 181 | CHECK_DIM2(grad_points2d_bxfx6, bnum, fnum, 6); 182 | CHECK_DIM2(grad_colors_bxfx3d, bnum, fnum, 3 * dnum); 183 | CHECK_DIM2(grad_points2dprob_bxfx6, bnum, fnum, 6); 184 | 185 | CHECK_DIM3(debug_im_bxhxwx3, bnum, height, width, 3); 186 | 187 | dr_cuda_backward_batch(grad_image_bxhxwxd, grad_improb_bxhxwx1, 188 | image_bxhxwxd, improb_bxhxwx1, imidx_bxhxwx1, imwei_bxhxwx3, 189 | probface_bxhxwxk, probcase_bxhxwxk, probdis_bxhxwxk, 190 | probdep_bxhxwxk, probacc_bxhxwxk, points2d_bxfx6, colors_bxfx3d, 191 | grad_points2d_bxfx6, grad_colors_bxfx3d, grad_points2dprob_bxfx6, 192 | debug_im_bxhxwx3, multiplier, sigmainv); 193 | 194 | return; 195 | } 196 | 197 | PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) { 198 | m.def("forward", &dr_forward_batch, "dr forward batch (CUDA)"); 199 | m.def("backward", &dr_backward_batch, "dr backward batch (CUDA)"); 200 | } 201 | 202 | -------------------------------------------------------------------------------- /dib-render/cuda_dib_render/dr_cuda_back.cu: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #include 24 | 25 | #include 26 | #include 27 | 28 | #define eps 1e-15 29 | 30 | // for the older gpus atomicAdd with double arguments does not exist 31 | #if __CUDA_ARCH__ < 600 and defined(__CUDA_ARCH__) 32 | static __inline__ __device__ double atomicAdd(double* address, double val) { 33 | unsigned long long int* address_as_ull = (unsigned long long int*)address; 34 | unsigned long long int old = *address_as_ull, assumed; 35 | do { 36 | assumed = old; 37 | old = atomicCAS(address_as_ull, assumed, 38 | __double_as_longlong(val + __longlong_as_double(assumed))); 39 | // Note: uses integer comparison to avoid hang in case of NaN (since NaN != NaN) } while (assumed != old); 40 | }while (assumed != old); 41 | return __longlong_as_double(old); 42 | } 43 | #endif 44 | 45 | template 46 | __global__ void dr_cuda_backword_color_batch( 47 | const scalar_t* __restrict__ grad_im_bxhxwxd, 48 | const scalar_t* __restrict__ im_bxhxwxd, 49 | const scalar_t* __restrict__ imidx_bxhxwx1, 50 | const scalar_t* __restrict__ imwei_bxhxwx3, 51 | const scalar_t* __restrict__ points2d_bxfx6, 52 | const scalar_t* __restrict__ features_bxfx3d, 53 | scalar_t* __restrict__ grad_points2d_bxfx6, 54 | scalar_t* __restrict__ grad_features_bxfx3d, 55 | scalar_t* __restrict__ debug_im_bxhxwx3, int bnum, int height, 56 | int width, int fnum, int dnum, int multiplier) { 57 | 58 | /* 59 | // thread index 60 | */ 61 | 62 | // bidx * height * width + heiidx * width + wididx 63 | int presentthread = blockIdx.x * blockDim.x + threadIdx.x; 64 | int wididx = presentthread % width; 65 | presentthread = (presentthread - wididx) / width; 66 | int heiidx = presentthread % height; 67 | int bidx = (presentthread - heiidx) / height; 68 | 69 | if (bidx >= bnum || heiidx >= height || wididx >= width) 70 | return; 71 | 72 | // which pixel it belongs to 73 | const int totalidx1 = bidx * height * width + heiidx * width + wididx; 74 | const int totalidx3 = totalidx1 * 3; 75 | const int totalidxd = totalidx1 * dnum; 76 | 77 | // coordinates 78 | scalar_t x0 = 1.0 * multiplier / width * (2 * wididx + 1 - width); 79 | scalar_t y0 = 1.0 * multiplier / height * (height - 2 * heiidx - 1); 80 | 81 | // which face it belongs to? 82 | scalar_t fidx = imidx_bxhxwx1[totalidx1]; 83 | 84 | // face begins from 1 85 | // convert it into int, use round! 86 | int fidxint = static_cast(fidx + 0.5) - 1; 87 | 88 | // visible faces 89 | if (fidxint >= 0) { 90 | const int shift1 = bidx * fnum + fidxint; 91 | const int shift6 = shift1 * 6; 92 | const int shift3d = shift1 * 3 * dnum; 93 | 94 | // the imaging model is: 95 | // I(x, y) = w0 * c0 + w1 * c1 + w2 * c2 96 | 97 | // gradient of colors 98 | // 3 points in one face 99 | for (int i = 0; i < 3; i++) { 100 | 101 | // directly use opengl weights 102 | scalar_t w = imwei_bxhxwx3[totalidx3 + i]; 103 | int pointshift = shift3d + i * dnum; 104 | 105 | // rgb value 106 | for (int rgb = 0; rgb < dnum; rgb++) { 107 | int colorshift = pointshift + rgb; 108 | 109 | // this should be atomic operation 110 | scalar_t * addr = grad_features_bxfx3d + colorshift; 111 | scalar_t val = grad_im_bxhxwxd[totalidxd + rgb] * w; 112 | atomicAdd(addr, val); 113 | } 114 | } 115 | 116 | // gradient of points 117 | // here, we calculate dl/dp 118 | // dl/dp = dldI * dI/dp 119 | // dI/dp = c0 * dw0 / dp + c1 * dw1 / dp + c2 * dw2 / dp 120 | // first 121 | // 4 coorinates 122 | scalar_t ax = points2d_bxfx6[shift6 + 0]; 123 | scalar_t ay = points2d_bxfx6[shift6 + 1]; 124 | scalar_t bx = points2d_bxfx6[shift6 + 2]; 125 | scalar_t by = points2d_bxfx6[shift6 + 3]; 126 | scalar_t cx = points2d_bxfx6[shift6 + 4]; 127 | scalar_t cy = points2d_bxfx6[shift6 + 5]; 128 | 129 | 130 | //////////////////////////////////////////////////////////////////////////////////// 131 | // replace with other variables 132 | scalar_t m = bx - ax; 133 | scalar_t p = by - ay; 134 | 135 | scalar_t n = cx - ax; 136 | scalar_t q = cy - ay; 137 | 138 | scalar_t s = x0 - ax; 139 | scalar_t t = y0 - ay; 140 | 141 | ////////////////////////////////////////////////////////////////////////////////////// 142 | 143 | scalar_t k1 = s * q - n * t; 144 | scalar_t k2 = m * t - s * p; 145 | scalar_t k3 = m * q - n * p; 146 | 147 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 148 | scalar_t dk1dm = 0; 149 | scalar_t dk1dn = -t; 150 | scalar_t dk1dp = 0; 151 | scalar_t dk1dq = s; 152 | scalar_t dk1ds = q; 153 | scalar_t dk1dt = -n; 154 | 155 | scalar_t dk2dm = t; 156 | scalar_t dk2dn = 0; 157 | scalar_t dk2dp = -s; 158 | scalar_t dk2dq = 0; 159 | scalar_t dk2ds = -p; 160 | scalar_t dk2dt = m; 161 | 162 | scalar_t dk3dm = q; 163 | scalar_t dk3dn = -p; 164 | scalar_t dk3dp = -n; 165 | scalar_t dk3dq = m; 166 | scalar_t dk3ds = 0; 167 | scalar_t dk3dt = 0; 168 | 169 | /////////////////////////////////////////////////////////////////////////////// 170 | // w1 = k1 / k3 171 | // w2 = k2 / k3 172 | // remember we need divide k3 ^ 2 173 | scalar_t dw1dm = dk1dm * k3 - dk3dm * k1; 174 | scalar_t dw1dn = dk1dn * k3 - dk3dn * k1; 175 | scalar_t dw1dp = dk1dp * k3 - dk3dp * k1; 176 | scalar_t dw1dq = dk1dq * k3 - dk3dq * k1; 177 | scalar_t dw1ds = dk1ds * k3 - dk3ds * k1; 178 | scalar_t dw1dt = dk1dt * k3 - dk3dt * k1; 179 | 180 | scalar_t dw2dm = dk2dm * k3 - dk3dm * k2; 181 | scalar_t dw2dn = dk2dn * k3 - dk3dn * k2; 182 | scalar_t dw2dp = dk2dp * k3 - dk3dp * k2; 183 | scalar_t dw2dq = dk2dq * k3 - dk3dq * k2; 184 | scalar_t dw2ds = dk2ds * k3 - dk3ds * k2; 185 | scalar_t dw2dt = dk2dt * k3 - dk3dt * k2; 186 | 187 | ////////////////////////////////////////////////////////////////////////////////////// 188 | scalar_t dw1dax = -(dw1dm + dw1dn + dw1ds); 189 | scalar_t dw1day = -(dw1dp + dw1dq + dw1dt); 190 | scalar_t dw1dbx = dw1dm; 191 | scalar_t dw1dby = dw1dp; 192 | scalar_t dw1dcx = dw1dn; 193 | scalar_t dw1dcy = dw1dq; 194 | 195 | scalar_t dw2dax = -(dw2dm + dw2dn + dw2ds); 196 | scalar_t dw2day = -(dw2dp + dw2dq + dw2dt); 197 | scalar_t dw2dbx = dw2dm; 198 | scalar_t dw2dby = dw2dp; 199 | scalar_t dw2dcx = dw2dn; 200 | scalar_t dw2dcy = dw2dq; 201 | 202 | for (int rgb = 0; rgb < dnum; rgb++) { 203 | 204 | // the same color for 3 points 205 | // thus we can simplify it 206 | scalar_t c0 = features_bxfx3d[shift3d + rgb]; 207 | scalar_t c1 = features_bxfx3d[shift3d + dnum + rgb]; 208 | scalar_t c2 = features_bxfx3d[shift3d + dnum + dnum + rgb]; 209 | 210 | scalar_t dIdax = (c1 - c0) * dw1dax + (c2 - c0) * dw2dax; 211 | scalar_t dIday = (c1 - c0) * dw1day + (c2 - c0) * dw2day; 212 | scalar_t dIdbx = (c1 - c0) * dw1dbx + (c2 - c0) * dw2dbx; 213 | scalar_t dIdby = (c1 - c0) * dw1dby + (c2 - c0) * dw2dby; 214 | scalar_t dIdcx = (c1 - c0) * dw1dcx + (c2 - c0) * dw2dcx; 215 | scalar_t dIdcy = (c1 - c0) * dw1dcy + (c2 - c0) * dw2dcy; 216 | 217 | scalar_t dldI = multiplier * grad_im_bxhxwxd[totalidxd + rgb] 218 | / (k3 * k3 + eps); 219 | 220 | atomicAdd(grad_points2d_bxfx6 + shift6 + 0, dldI * dIdax); 221 | atomicAdd(grad_points2d_bxfx6 + shift6 + 1, dldI * dIday); 222 | 223 | atomicAdd(grad_points2d_bxfx6 + shift6 + 2, dldI * dIdbx); 224 | atomicAdd(grad_points2d_bxfx6 + shift6 + 3, dldI * dIdby); 225 | 226 | atomicAdd(grad_points2d_bxfx6 + shift6 + 4, dldI * dIdcx); 227 | atomicAdd(grad_points2d_bxfx6 + shift6 + 5, dldI * dIdcy); 228 | 229 | 230 | } 231 | } 232 | } 233 | 234 | template 235 | __global__ void dr_cuda_backword_prob_batch( 236 | const scalar_t* __restrict__ grad_improb_bxhxwx1, 237 | const scalar_t* __restrict__ improb_bxhxwx1, 238 | const scalar_t* __restrict__ imidx_bxhxwx1, 239 | const scalar_t* __restrict__ probface_bxhxwxk, 240 | const scalar_t* __restrict__ probcase_bxhxwxk, 241 | const scalar_t* __restrict__ probdis_bxhxwxk, 242 | const scalar_t* __restrict__ probdep_bxhxwxk, 243 | const scalar_t* __restrict__ probacc_bxhxwxk, 244 | const scalar_t* __restrict__ points2d_bxfx6, 245 | scalar_t* __restrict__ grad_points2dprob_bxfx6, int bnum, int height, 246 | int width, int fnum, int knum, int multiplier, int sigmainv) { 247 | 248 | /* 249 | // thread index 250 | */ 251 | 252 | // bidx * height * width + heiidx * width + wididx 253 | int presentthread = blockIdx.x * blockDim.x + threadIdx.x; 254 | 255 | int wididx = presentthread % width; 256 | presentthread = (presentthread - wididx) / width; 257 | 258 | int heiidx = presentthread % height; 259 | int bidx = (presentthread - heiidx) / height; 260 | 261 | if (bidx >= bnum || heiidx >= height || wididx >= width) 262 | return; 263 | 264 | ////////////////////////////////////////////// 265 | // which pixel it belongs to 266 | const int totalidx1 = bidx * height * width + heiidx * width + wididx; 267 | const int totalidxk = totalidx1 * knum; 268 | 269 | ////////////////////////////////////////////// 270 | // coordinates 271 | scalar_t x0 = 1.0 * multiplier / width * (2 * wididx + 1 - width); 272 | scalar_t y0 = 1.0 * multiplier / height * (height - 2 * heiidx - 1); 273 | 274 | ///////////////////////////////////// 275 | // which face it belongs to? 276 | scalar_t fidx = imidx_bxhxwx1[totalidx1]; 277 | 278 | // face begins from 1 279 | // convert it into int, use round! 280 | int fidxint = static_cast(fidx + 0.5) - 1; 281 | 282 | ///////////////////////////////////// 283 | // not covered by any faces 284 | if (fidxint < 0) { 285 | 286 | int fidxcover = fidxint; 287 | 288 | scalar_t dLdp = grad_improb_bxhxwx1[totalidx1]; 289 | scalar_t allprob = improb_bxhxwx1[totalidx1]; 290 | 291 | for (int kid = 0; kid < knum; kid++) { 292 | 293 | scalar_t fidx = probface_bxhxwxk[totalidxk + kid]; 294 | 295 | // face begins from 1 296 | // convert it into int, use round! 297 | int fidxint = static_cast(fidx + 0.5) - 1; 298 | if (fidxint < 0) 299 | break; 300 | 301 | const int shift1 = bidx * fnum + fidxint; 302 | const int shift6 = shift1 * 6; 303 | 304 | /////////////////////////////////////////// 305 | scalar_t prob = probdis_bxhxwxk[totalidxk + kid]; 306 | 307 | scalar_t dLdz = -1.0 * sigmainv * dLdp * (1.0 - allprob) 308 | / (1.0 - prob + eps) * prob; 309 | 310 | /////////////////////////////////////////////////////////////////// 311 | scalar_t edgecase = probcase_bxhxwxk[totalidxk + kid]; 312 | int edgeid = static_cast(edgecase + 0.5) - 1; 313 | 314 | ///////////////////////////////////////////////////////////// 315 | if (edgeid >= 3) { 316 | 317 | // point distance 318 | int pshift = shift6 + (edgeid - 3) * 2; 319 | scalar_t x1 = points2d_bxfx6[pshift + 0]; 320 | scalar_t y1 = points2d_bxfx6[pshift + 1]; 321 | 322 | scalar_t dLdx1 = dLdz * 2 * (x1 - x0); 323 | scalar_t dLdy1 = dLdz * 2 * (y1 - y0); 324 | 325 | atomicAdd(grad_points2dprob_bxfx6 + pshift + 0, 326 | dLdx1 / multiplier); 327 | atomicAdd(grad_points2dprob_bxfx6 + pshift + 1, 328 | dLdy1 / multiplier); 329 | 330 | } else { 331 | 332 | // perpendicular distance 333 | 334 | int pshift = shift6 + edgeid * 2; 335 | scalar_t x1 = points2d_bxfx6[pshift + 0]; 336 | scalar_t y1 = points2d_bxfx6[pshift + 1]; 337 | 338 | int pshift2 = shift6 + ((edgeid + 1) % 3) * 2; 339 | scalar_t x2 = points2d_bxfx6[pshift2 + 0]; 340 | scalar_t y2 = points2d_bxfx6[pshift2 + 1]; 341 | 342 | // ax + by + c = 0 343 | scalar_t A = y2 - y1; 344 | scalar_t B = x1 - x2; 345 | scalar_t C = x2 * y1 - x1 * y2; 346 | 347 | // dissquare = d^2 = (ax+by+c)^2 / (a^2+b^2) 348 | // up = ax + by + c 349 | // down = a^2 + b^2 350 | // dissquare = up^2 / down 351 | scalar_t up = A * x0 + B * y0 + C; 352 | scalar_t down = A * A + B * B; 353 | scalar_t dissquare = up * up / (down + eps); 354 | 355 | ////////////////////////////////// 356 | scalar_t dzdA = 2 * (x0 * up - dissquare * A) / (down + eps); 357 | scalar_t dzdB = 2 * (y0 * up - dissquare * B) / (down + eps); 358 | scalar_t dzdC = 2 * up / (down + eps); 359 | 360 | scalar_t dLdx1 = dLdz * (dzdB - y2 * dzdC); 361 | scalar_t dLdy1 = dLdz * (x2 * dzdC - dzdA); 362 | 363 | scalar_t dLdx2 = dLdz * (y1 * dzdC - dzdB); 364 | scalar_t dLdy2 = dLdz * (dzdA - x1 * dzdC); 365 | 366 | atomicAdd(grad_points2dprob_bxfx6 + pshift + 0, 367 | dLdx1 / multiplier); 368 | atomicAdd(grad_points2dprob_bxfx6 + pshift + 1, 369 | dLdy1 / multiplier); 370 | 371 | atomicAdd(grad_points2dprob_bxfx6 + pshift2 + 0, 372 | dLdx2 / multiplier); 373 | atomicAdd(grad_points2dprob_bxfx6 + pshift2 + 1, 374 | dLdy2 / multiplier); 375 | } 376 | } 377 | } 378 | 379 | return; 380 | } 381 | 382 | void dr_cuda_backward_batch(at::Tensor grad_image_bxhxwxd, 383 | at::Tensor grad_improb_bxhxwx1, at::Tensor image_bxhxwxd, 384 | at::Tensor improb_bxhxwx1, at::Tensor imidx_bxhxwx1, 385 | at::Tensor imwei_bxhxwx3, at::Tensor probface_bxhxwxk, 386 | at::Tensor probcase_bxhxwxk, at::Tensor probdis_bxhxwxk, 387 | at::Tensor probdep_bxhxwxk, at::Tensor probacc_bxhxwxk, 388 | at::Tensor points2d_bxfx6, at::Tensor colors_bxfx3d, 389 | at::Tensor grad_points2d_bxfx6, at::Tensor grad_colors_bxfx3d, 390 | at::Tensor grad_points2dprob_bxfx6, at::Tensor debug_im_bxhxwx3, 391 | int multiplier, int sigmainv) { 392 | 393 | int bnum = grad_image_bxhxwxd.size(0); 394 | int height = grad_image_bxhxwxd.size(1); 395 | int width = grad_image_bxhxwxd.size(2); 396 | int dnum = grad_image_bxhxwxd.size(3); 397 | int fnum = grad_points2d_bxfx6.size(1); 398 | int knum = probface_bxhxwxk.size(3); 399 | 400 | // for bxhxw image size 401 | const int threadnum = 1024; 402 | const int totalthread = bnum * height * width; 403 | const int blocknum = totalthread / threadnum + 1; 404 | 405 | const dim3 threads(threadnum, 1, 1); 406 | const dim3 blocks(blocknum, 1, 1); 407 | 408 | // we exchange block and thread! 409 | AT_DISPATCH_FLOATING_TYPES(grad_image_bxhxwxd.type(), 410 | "dr_cuda_backward_color_batch", ([&] { 411 | dr_cuda_backword_color_batch<<>>( 412 | grad_image_bxhxwxd.data(), 413 | image_bxhxwxd.data(), 414 | imidx_bxhxwx1.data(), 415 | imwei_bxhxwx3.data(), 416 | points2d_bxfx6.data(), 417 | colors_bxfx3d.data(), 418 | grad_points2d_bxfx6.data(), 419 | grad_colors_bxfx3d.data(), 420 | debug_im_bxhxwx3.data(), 421 | bnum, height, width, fnum, dnum, multiplier); 422 | })); 423 | 424 | AT_DISPATCH_FLOATING_TYPES(grad_image_bxhxwxd.type(), 425 | "dr_cuda_backward_prob_batch", ([&] { 426 | dr_cuda_backword_prob_batch<<>>( 427 | grad_improb_bxhxwx1.data(), 428 | improb_bxhxwx1.data(), 429 | imidx_bxhxwx1.data(), 430 | probface_bxhxwxk.data(), 431 | probcase_bxhxwxk.data(), 432 | probdis_bxhxwxk.data(), 433 | probdep_bxhxwxk.data(), 434 | probacc_bxhxwxk.data(), 435 | points2d_bxfx6.data(), 436 | grad_points2dprob_bxfx6.data(), 437 | bnum, height, width, fnum, knum, multiplier, sigmainv); 438 | })); 439 | 440 | return; 441 | } 442 | 443 | -------------------------------------------------------------------------------- /dib-render/cuda_dib_render/dr_cuda_for.cu: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #include 24 | 25 | #include 26 | #include 27 | 28 | #define eps 1e-15 29 | 30 | template 31 | __global__ void dr_cuda_forward_render_batch( 32 | const scalar_t* __restrict__ points3d_bxfx9, 33 | const scalar_t* __restrict__ points2d_bxfx6, 34 | const scalar_t* __restrict__ pointsdirect_bxfx1, 35 | const scalar_t* __restrict__ pointsbbox_bxfx4, 36 | const scalar_t* __restrict__ features_bxfx3d, 37 | scalar_t* __restrict__ imidx_bxhxwx1, 38 | scalar_t* __restrict__ imdep_bxhxwx1, 39 | scalar_t* __restrict__ imwei_bxhxwx3, scalar_t* __restrict__ im_bxhxwxd, 40 | int bnum, int height, int width, int fnum, int dnum, int multiplier) { 41 | 42 | // bidx * height * width + heiidx * width + wididx 43 | int presentthread = blockIdx.x * blockDim.x + threadIdx.x; 44 | 45 | int wididx = presentthread % width; 46 | presentthread = (presentthread - wididx) / width; 47 | 48 | int heiidx = presentthread % height; 49 | int bidx = (presentthread - heiidx) / height; 50 | 51 | if (bidx >= bnum || heiidx >= height || wididx >= width) { 52 | return; 53 | } 54 | 55 | ///////////////////////////////////////////////////////////////// 56 | // which pixel it belongs to 57 | const int totalidx1 = bidx * height * width + heiidx * width + wididx; 58 | const int totalidx3 = totalidx1 * 3; 59 | const int totalidxd = totalidx1 * dnum; 60 | 61 | // pixel coordinate 62 | scalar_t x0 = 1.0 * multiplier / width * (2 * wididx + 1 - width); 63 | scalar_t y0 = 1.0 * multiplier / height * (height - 2 * heiidx - 1); 64 | 65 | //////////////////////////////////////////////////////////////////////// 66 | for (int fidxint = 0; fidxint < fnum; fidxint++) { 67 | 68 | // which face it belongs to 69 | const int shift1 = bidx * fnum + fidxint; 70 | const int shift4 = shift1 * 4; 71 | const int shift6 = shift1 * 6; 72 | const int shift9 = shift1 * 9; 73 | const int shift3d = shift1 * 3 * dnum; 74 | 75 | // is this face visible? 76 | scalar_t direction = pointsdirect_bxfx1[shift1]; 77 | if (direction < 0) { 78 | continue; 79 | } 80 | 81 | /////////////////////////////////////////////////////////////// 82 | // will this pixel is influenced by this face? 83 | scalar_t xmin = pointsbbox_bxfx4[shift4 + 0]; 84 | scalar_t ymin = pointsbbox_bxfx4[shift4 + 1]; 85 | scalar_t xmax = pointsbbox_bxfx4[shift4 + 2]; 86 | scalar_t ymax = pointsbbox_bxfx4[shift4 + 3]; 87 | 88 | // not covered by this face! 89 | if (x0 < xmin || x0 >= xmax || y0 < ymin || y0 >= ymax) { 90 | continue; 91 | } 92 | 93 | ////////////////////////////////////////////////////////// 94 | //////////////////////////////////////////////////////////////////////////////////// 95 | // if this pixel is covered by this face, then we check its depth and weights 96 | scalar_t ax = points2d_bxfx6[shift6 + 0]; 97 | scalar_t ay = points2d_bxfx6[shift6 + 1]; 98 | scalar_t bx = points2d_bxfx6[shift6 + 2]; 99 | scalar_t by = points2d_bxfx6[shift6 + 3]; 100 | scalar_t cx = points2d_bxfx6[shift6 + 4]; 101 | scalar_t cy = points2d_bxfx6[shift6 + 5]; 102 | 103 | // replace with other variables 104 | scalar_t m = bx - ax; 105 | scalar_t p = by - ay; 106 | 107 | scalar_t n = cx - ax; 108 | scalar_t q = cy - ay; 109 | 110 | scalar_t s = x0 - ax; 111 | scalar_t t = y0 - ay; 112 | 113 | 114 | scalar_t k1 = s * q - n * t; 115 | scalar_t k2 = m * t - s * p; 116 | scalar_t k3 = m * q - n * p; 117 | 118 | scalar_t w1 = k1 / (k3 + eps); 119 | scalar_t w2 = k2 / (k3 + eps); 120 | scalar_t w0 = 1 - w1 - w2; 121 | 122 | // not lie in the triangle 123 | if (w0 < 0 || w1 < 0 || w2 < 0) { 124 | continue; 125 | } 126 | 127 | 128 | 129 | 130 | ////////////////////////////////////////////////////////////////////////////////////// 131 | // if it is perspective, then this way has a little error 132 | // because face plane may not be parallel to the image plane 133 | // but let's ignore it first 134 | scalar_t az = points3d_bxfx9[shift9 + 2]; 135 | scalar_t bz = points3d_bxfx9[shift9 + 5]; 136 | scalar_t cz = points3d_bxfx9[shift9 + 8]; 137 | 138 | scalar_t z0 = w0 * az + w1 * bz + w2 * cz; 139 | scalar_t znow = imdep_bxhxwx1[totalidx1]; 140 | 141 | // it will be filled by a nearer face 142 | if (z0 <= znow) { 143 | continue; 144 | } 145 | 146 | /////////////////////////////////////////////////////////// 147 | // update it! 148 | // depth 149 | imdep_bxhxwx1[totalidx1] = z0; 150 | 151 | // index 152 | imidx_bxhxwx1[totalidx1] = fidxint + 1.0; 153 | 154 | // wei 155 | imwei_bxhxwx3[totalidx3 + 0] = w0; 156 | imwei_bxhxwx3[totalidx3 + 1] = w1; 157 | imwei_bxhxwx3[totalidx3 + 2] = w2; 158 | 159 | // color 160 | for (int d = 0; d < dnum; d++) { 161 | scalar_t r0 = features_bxfx3d[shift3d + d]; 162 | scalar_t r1 = features_bxfx3d[shift3d + dnum + d]; 163 | scalar_t r2 = features_bxfx3d[shift3d + dnum + dnum + d]; 164 | im_bxhxwxd[totalidxd + d] = w0 * r0 + w1 * r1 + w2 * r2; 165 | } 166 | 167 | // care about first triangle 168 | // break; 169 | // calculate all the faces!!! 170 | } 171 | } 172 | 173 | template 174 | __global__ void dr_cuda_forward_prob_batch( 175 | const scalar_t* __restrict__ points2d_bxfx6, 176 | const scalar_t* __restrict__ pointsbbox2_bxfx4, 177 | const scalar_t* __restrict__ pointsdep_bxfx1, 178 | const scalar_t* __restrict__ imidx_bxhxwx1, 179 | scalar_t* __restrict__ probface_bxhxwxk, 180 | scalar_t* __restrict__ probcase_bxhxwxk, 181 | scalar_t* __restrict__ probdis_bxhxwxk, 182 | scalar_t* __restrict__ probdep_bxhxwxk, 183 | scalar_t* __restrict__ probacc_bxhxwxk, 184 | scalar_t* __restrict__ improb_bxhxwx1, int bnum, int height, int width, 185 | int fnum, int knum, int multiplier, int sigmainv) { 186 | 187 | // bidx * height * width + heiidx * width + wididx 188 | int presentthread = blockIdx.x * blockDim.x + threadIdx.x; 189 | 190 | int wididx = presentthread % width; 191 | presentthread = (presentthread - wididx) / width; 192 | 193 | int heiidx = presentthread % height; 194 | int bidx = (presentthread - heiidx) / height; 195 | 196 | if (bidx >= bnum || heiidx >= height || wididx >= width) { 197 | return; 198 | } 199 | 200 | ///////////////////////////////////////////////////////////////// 201 | // which pixel it belongs to 202 | const int totalidx1 = bidx * height * width + heiidx * width + wididx; 203 | const int totalidxk = totalidx1 * knum; 204 | 205 | ///////////////////////////////////////////////////////// 206 | // which face it belongs to? 207 | scalar_t fidx = imidx_bxhxwx1[totalidx1]; 208 | 209 | // face begins from 1 210 | // convert it into int, use round! 211 | int fidxint = static_cast(fidx + 0.5) - 1; 212 | 213 | // not covered by any faces 214 | // maybe we can search its neighbour 215 | if (fidxint >= 0) { 216 | improb_bxhxwx1[totalidx1] = 1.0; 217 | } 218 | //////////////////////////////////////////////////////////////////////// 219 | // pixels not covered by any faces 220 | else { 221 | 222 | // pixel coordinate 223 | scalar_t x0 = 1.0 * multiplier / width * (2 * wididx + 1 - width); 224 | scalar_t y0 = 1.0 * multiplier / height * (height - 2 * heiidx - 1); 225 | 226 | int fidxcover = fidxint; 227 | 228 | int kid = 0; 229 | 230 | for (int fidxint = 0; fidxint < fnum; fidxint++) { 231 | 232 | // which face it belongs to 233 | const int shift1 = bidx * fnum + fidxint; 234 | const int shift4 = shift1 * 4; 235 | const int shift6 = shift1 * 6; 236 | 237 | /////////////////////////////////////////////////////////////// 238 | // will this pixel is influenced by this face? 239 | scalar_t xmin = pointsbbox2_bxfx4[shift4 + 0]; 240 | scalar_t ymin = pointsbbox2_bxfx4[shift4 + 1]; 241 | scalar_t xmax = pointsbbox2_bxfx4[shift4 + 2]; 242 | scalar_t ymax = pointsbbox2_bxfx4[shift4 + 3]; 243 | 244 | // not covered by this face! 245 | if (x0 < xmin || x0 >= xmax || y0 < ymin || y0 >= ymax) { 246 | continue; 247 | } 248 | 249 | ////////////////////////////////////////////////////////// 250 | scalar_t pdis[6]; 251 | 252 | // perdis 253 | for (int i = 0; i < 3; i++) { 254 | 255 | int pshift = shift6 + i * 2; 256 | scalar_t x1 = points2d_bxfx6[pshift + 0]; 257 | scalar_t y1 = points2d_bxfx6[pshift + 1]; 258 | 259 | int pshift2 = shift6 + ((i + 1) % 3) * 2; 260 | scalar_t x2 = points2d_bxfx6[pshift2 + 0]; 261 | scalar_t y2 = points2d_bxfx6[pshift2 + 1]; 262 | 263 | // ax + by + c = 0 264 | scalar_t A = y2 - y1; 265 | scalar_t B = x1 - x2; 266 | scalar_t C = x2 * y1 - x1 * y2; 267 | 268 | // dissquare = d^2 = (ax+by+c)^2 / (a^2+b^2) 269 | // up = ax + by + c 270 | // down = a^2 + b^2 271 | // dissquare = up^2 / down 272 | scalar_t up = A * x0 + B * y0 + C; 273 | scalar_t down = A * A + B * B; 274 | 275 | // is it a bad triangle? 276 | scalar_t x3 = B * B * x0 - A * B * y0 - A * C; 277 | scalar_t y3 = A * A * y0 - A * B * x0 - B * C; 278 | x3 = x3 / (down + eps); 279 | y3 = y3 / (down + eps); 280 | 281 | scalar_t direct = (x3 - x1) * (x3 - x2) + (y3 - y1) * (y3 - y2); 282 | 283 | if (direct > 0) { 284 | // bad triangle 285 | pdis[i] = 4 * multiplier * multiplier; 286 | } else { 287 | // perpendicular distance 288 | pdis[i] = up * up / (down + eps); 289 | } 290 | } 291 | 292 | //////////////////////////////////////////////////////////// 293 | // point distance 294 | for (int i = 0; i < 3; i++) { 295 | int pshift = shift6 + i * 2; 296 | scalar_t x1 = points2d_bxfx6[pshift + 0]; 297 | scalar_t y1 = points2d_bxfx6[pshift + 1]; 298 | pdis[i + 3] = (x0 - x1) * (x0 - x1) + (y0 - y1) * (y0 - y1); 299 | } 300 | 301 | /////////////////////////////////////////////////////////////// 302 | int edgeid = 0; 303 | scalar_t dissquare = pdis[0]; 304 | 305 | for (int i = 1; i < 6; i++) { 306 | if (dissquare > pdis[i]) { 307 | dissquare = pdis[i]; 308 | edgeid = i; 309 | } 310 | } 311 | 312 | ////////////////////////////////////////////////// 313 | scalar_t z = sigmainv * dissquare / multiplier / multiplier; 314 | 315 | scalar_t prob = exp(-z); 316 | 317 | ////////////////////////////////////////////////// 318 | probface_bxhxwxk[totalidxk + kid] = fidxint + 1.0; 319 | probcase_bxhxwxk[totalidxk + kid] = edgeid + 1.0; 320 | probdis_bxhxwxk[totalidxk + kid] = prob; 321 | probdep_bxhxwxk[totalidxk + kid] = probdep_bxhxwxk[shift1]; 322 | kid++; 323 | 324 | if (kid >= knum) 325 | break; 326 | } 327 | 328 | scalar_t allprob = 1.0; 329 | for (int i = 0; i < kid; i++) { 330 | scalar_t prob = probdis_bxhxwxk[totalidxk + i]; 331 | allprob *= (1.0 - prob); 332 | } 333 | 334 | // final result 335 | allprob = 1.0 - allprob; 336 | improb_bxhxwx1[totalidx1] = allprob; 337 | } 338 | } 339 | 340 | void dr_cuda_forward_batch(at::Tensor points3d_bxfx9, at::Tensor points2d_bxfx6, 341 | at::Tensor pointsdirect_bxfx1, at::Tensor pointsbbox_bxfx4, 342 | at::Tensor pointsbbox2_bxfx4, at::Tensor pointsdep_bxfx1, 343 | at::Tensor colors_bxfx3d, at::Tensor imidx_bxhxwx1, 344 | at::Tensor imdep_bxhxwx1, at::Tensor imwei_bxhxwx3, 345 | at::Tensor probface_bxhxwxk, at::Tensor probcase_bxhxwxk, 346 | at::Tensor probdis_bxhxwxk, at::Tensor probdep_bxhxwxk, 347 | at::Tensor probacc_bxhxwxk, at::Tensor im_bxhxwxd, 348 | at::Tensor improb_bxhxwx1, int multiplier, int sigmainv) { 349 | 350 | int bnum = points3d_bxfx9.size(0); 351 | int fnum = points3d_bxfx9.size(1); 352 | int height = im_bxhxwxd.size(1); 353 | int width = im_bxhxwxd.size(2); 354 | int dnum = im_bxhxwxd.size(3); 355 | 356 | int knum = probface_bxhxwxk.size(3); 357 | 358 | // for fxbxhxw image size 359 | const int threadnum = 1024; 360 | const int totalthread = bnum * height * width; 361 | const int blocknum = totalthread / threadnum + 1; 362 | 363 | const dim3 threads(threadnum, 1, 1); 364 | const dim3 blocks(blocknum, 1, 1); 365 | 366 | AT_DISPATCH_FLOATING_TYPES(points3d_bxfx9.type(), 367 | "dr_cuda_forward_render_batch", ([&] { 368 | dr_cuda_forward_render_batch<<>>( 369 | points3d_bxfx9.data(), 370 | points2d_bxfx6.data(), 371 | pointsdirect_bxfx1.data(), 372 | pointsbbox_bxfx4.data(), 373 | colors_bxfx3d.data(), 374 | imidx_bxhxwx1.data(), 375 | imdep_bxhxwx1.data(), 376 | imwei_bxhxwx3.data(), 377 | im_bxhxwxd.data(), 378 | bnum, height, width, fnum, dnum, multiplier); 379 | })); 380 | 381 | AT_DISPATCH_FLOATING_TYPES(points3d_bxfx9.type(), 382 | "dr_cuda_forward_prob_batch", ([&] { 383 | dr_cuda_forward_prob_batch<<>>( 384 | points2d_bxfx6.data(), 385 | pointsbbox2_bxfx4.data(), 386 | pointsdep_bxfx1.data(), 387 | imidx_bxhxwx1.data(), 388 | probface_bxhxwxk.data(), 389 | probcase_bxhxwxk.data(), 390 | probdis_bxhxwxk.data(), 391 | probdep_bxhxwxk.data(), 392 | probacc_bxhxwxk.data(), 393 | improb_bxhxwx1.data(), 394 | bnum, height, width, fnum, knum, multiplier, sigmainv); 395 | })); 396 | 397 | return; 398 | } 399 | 400 | -------------------------------------------------------------------------------- /dib-render/render_cuda/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in 11 | # all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | # DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /dib-render/render_cuda/rendersettings.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in 11 | # all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | # DEALINGS IN THE SOFTWARE. 20 | 21 | 22 | ############################################ 23 | height = 64 24 | width = 64 25 | 26 | multiplier = 1000 27 | 28 | expand = 0.02 29 | knum = 30 30 | 31 | eps = 1e-15 32 | debug = False 33 | 34 | -------------------------------------------------------------------------------- /dib-render/render_cuda/utils_render_color2.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in 11 | # all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | # DEALINGS IN THE SOFTWARE. 20 | 21 | import torch 22 | import torch.nn 23 | import torch.autograd 24 | from torch.autograd import Function 25 | 26 | import cv2 27 | import numpy as np 28 | import dr_batch_dib_render as dr_cuda_batch 29 | 30 | from rendersettings import height, width, \ 31 | expand, knum, \ 32 | multiplier, eps, debug 33 | 34 | ############################################ 35 | delta = 7000 # int(1.0 / (3e-3)) 36 | 37 | ############################################ 38 | # Inherit from Function 39 | class TriRender2D(Function): 40 | # Note that both forward and backward are @staticmethods 41 | @staticmethod 42 | def forward(ctx, tfpoints3d_bxfx9, tfpoints2d_bxfx6, \ 43 | tfnormalz_bxfx1, tffeatures_bxfx3d): 44 | 45 | bnum = tfpoints3d_bxfx9.shape[0] 46 | fnum = tfpoints3d_bxfx9.shape[1] 47 | 48 | 49 | # avoid numeric error 50 | tfpoints2dmul_bxfx6 = multiplier * tfpoints2d_bxfx6 51 | 52 | # bbox 53 | tfpoints2d_bxfx3x2 = tfpoints2dmul_bxfx6.view(bnum, fnum, 3, 2) 54 | tfpoints_min = torch.min(tfpoints2d_bxfx3x2, dim=2)[0] 55 | tfpoints_max = torch.max(tfpoints2d_bxfx3x2, dim=2)[0] 56 | tfpointsbbox_bxfx4 = torch.cat((tfpoints_min, tfpoints_max), dim=2) 57 | 58 | # bbox2 59 | tfpoints_min = tfpoints_min - expand * multiplier; 60 | tfpoints_max = tfpoints_max + expand * multiplier; 61 | tfpointsbbox2_bxfx4 = torch.cat((tfpoints_min, tfpoints_max), dim=2) 62 | 63 | # depth 64 | tfpointsdep_bxfx1 = (tfpoints3d_bxfx9[:, :, 2:3] \ 65 | +tfpoints3d_bxfx9[:, :, 5:6] \ 66 | +tfpoints3d_bxfx9[:, :, 8:9]) / 3.0 67 | 68 | tfimidxs_bxhxwx1 = torch.zeros(bnum, height, width, 1, dtype=torch.float32).to(tfpoints2d_bxfx3x2.device) 69 | tfimdeps_bxhxwx1 = -1000 * torch.ones(bnum, height, width, 1, dtype=torch.float32).to(tfpoints2d_bxfx3x2.device) 70 | tfimweis_bxhxwx3 = torch.zeros(bnum, height, width, 3, dtype=torch.float32).to(tfpoints2d_bxfx3x2.device) 71 | tfims_bxhxwxd = torch.zeros(bnum, height, width, 3, dtype=torch.float32).to(tfpoints2d_bxfx3x2.device) 72 | tfimprob_bxhxwx1 = torch.zeros(bnum, height, width, 1, dtype=torch.float32).to(tfpoints2d_bxfx3x2.device) 73 | 74 | # intermidiate varibales 75 | tfprobface = torch.zeros(bnum, height, width, knum, dtype=torch.float32).to(tfpoints2d_bxfx3x2.device) 76 | tfprobcase = torch.zeros(bnum, height, width, knum, dtype=torch.float32).to(tfpoints2d_bxfx3x2.device) 77 | tfprobdis = torch.zeros(bnum, height, width, knum, dtype=torch.float32).to(tfpoints2d_bxfx3x2.device) 78 | tfprobdep = torch.zeros(bnum, height, width, knum, dtype=torch.float32).to(tfpoints2d_bxfx3x2.device) 79 | tfprobacc = torch.zeros(bnum, height, width, knum, dtype=torch.float32).to(tfpoints2d_bxfx3x2.device) 80 | 81 | tfpointsdirect_bxfx1 = tfnormalz_bxfx1.contiguous() 82 | dr_cuda_batch.forward(tfpoints3d_bxfx9, tfpoints2dmul_bxfx6, \ 83 | tfpointsdirect_bxfx1, tfpointsbbox_bxfx4, \ 84 | tfpointsbbox2_bxfx4, tfpointsdep_bxfx1, \ 85 | tffeatures_bxfx3d, 86 | tfimidxs_bxhxwx1, tfimdeps_bxhxwx1, \ 87 | tfimweis_bxhxwx3, \ 88 | tfprobface, tfprobcase, tfprobdis, tfprobdep, tfprobacc, \ 89 | tfims_bxhxwxd, tfimprob_bxhxwx1, 90 | multiplier, delta) 91 | 92 | debug_im = torch.zeros(bnum, height, width, 3, dtype=torch.float32).to(tfpoints2d_bxfx3x2.device) 93 | ctx.save_for_backward(tfims_bxhxwxd, tfimprob_bxhxwx1, \ 94 | tfimidxs_bxhxwx1, tfimweis_bxhxwx3, \ 95 | tfpoints2dmul_bxfx6, tffeatures_bxfx3d, \ 96 | tfprobface, tfprobcase, tfprobdis, tfprobdep, tfprobacc, 97 | debug_im) 98 | 99 | tfims_bxhxwxd.requires_grad = True 100 | tfimprob_bxhxwx1.requires_grad = True 101 | return tfims_bxhxwxd, tfimprob_bxhxwx1 102 | 103 | # This function has only a single output, so it gets only one gradient 104 | @staticmethod 105 | def backward(ctx, dldI_bxhxwxd, dldp_bxhxwx1): 106 | 107 | tfims_bxhxwxd, tfimprob_bxhxwx1, \ 108 | tfimidxs_bxhxwx1, tfimweis_bxhxwx3, \ 109 | tfpoints2dmul_bxfx6, tfcolors_bxfx3d, \ 110 | tfprobface, tfprobcase, tfprobdis, tfprobdep, tfprobacc, \ 111 | debug_im = ctx.saved_tensors 112 | 113 | dldp2 = torch.zeros_like(tfpoints2dmul_bxfx6) 114 | dldp2_prob = torch.zeros_like(tfpoints2dmul_bxfx6) 115 | dldc = torch.zeros_like(tfcolors_bxfx3d) 116 | 117 | dr_cuda_batch.backward(dldI_bxhxwxd.contiguous(), \ 118 | dldp_bxhxwx1.contiguous(), \ 119 | tfims_bxhxwxd, tfimprob_bxhxwx1, \ 120 | tfimidxs_bxhxwx1, tfimweis_bxhxwx3, \ 121 | tfprobface, tfprobcase, tfprobdis, tfprobdep, tfprobacc, \ 122 | tfpoints2dmul_bxfx6, tfcolors_bxfx3d, \ 123 | dldp2, dldc, dldp2_prob, \ 124 | debug_im, multiplier, delta) 125 | 126 | return None, dldp2 + dldp2_prob, None, dldc 127 | 128 | 129 | ############################################################### 130 | linear = TriRender2D.apply 131 | 132 | ###################################################### 133 | -------------------------------------------------------------------------------- /dib-render/sphere.obj: -------------------------------------------------------------------------------- 1 | #### 2 | # 3 | # OBJ File Generated by Meshlab 4 | # 5 | #### 6 | # Object 2.obj 7 | # 8 | # Vertices: 642 9 | # Faces: 1280 10 | # 11 | #### 12 | v 0.000000 0.425325 0.262866 13 | v 0.000000 0.425325 -0.262866 14 | v 0.000000 -0.425325 0.262866 15 | v 0.000000 -0.425325 -0.262866 16 | v 0.425325 0.262866 0.000000 17 | v 0.425325 -0.262866 0.000000 18 | v -0.425325 0.262866 0.000000 19 | v -0.425325 -0.262866 0.000000 20 | v 0.262866 0.000000 0.425325 21 | v -0.262866 0.000000 0.425325 22 | v 0.262866 0.000000 -0.425325 23 | v -0.262866 0.000000 -0.425325 24 | v 0.000000 0.500000 0.000000 25 | v 0.250000 0.404509 0.154508 26 | v 0.250000 0.404509 -0.154508 27 | v -0.250000 0.404509 -0.154508 28 | v -0.250000 0.404509 0.154508 29 | v 0.000000 -0.500000 0.000000 30 | v 0.250000 -0.404509 -0.154508 31 | v 0.250000 -0.404509 0.154508 32 | v -0.250000 -0.404509 0.154508 33 | v -0.250000 -0.404509 -0.154508 34 | v 0.500000 0.000000 0.000000 35 | v 0.404509 -0.154508 -0.250000 36 | v 0.404509 0.154508 -0.250000 37 | v 0.404509 0.154508 0.250000 38 | v 0.404509 -0.154508 0.250000 39 | v -0.500000 0.000000 0.000000 40 | v -0.404509 -0.154508 0.250000 41 | v -0.404509 0.154508 0.250000 42 | v -0.404509 0.154508 -0.250000 43 | v -0.404509 -0.154508 -0.250000 44 | v 0.000000 0.000000 0.500000 45 | v -0.154508 -0.250000 0.404509 46 | v 0.154508 -0.250000 0.404509 47 | v 0.154508 0.250000 0.404509 48 | v -0.154508 0.250000 0.404509 49 | v 0.000000 0.000000 -0.500000 50 | v -0.154508 0.250000 -0.404509 51 | v 0.154508 0.250000 -0.404509 52 | v 0.154508 -0.250000 -0.404509 53 | v -0.154508 -0.250000 -0.404509 54 | v 0.131433 0.475528 0.081230 55 | v 0.262866 0.425325 0.000000 56 | v 0.131433 0.475528 -0.081230 57 | v -0.131433 0.475528 -0.081230 58 | v -0.262866 0.425325 0.000000 59 | v -0.131433 0.475528 0.081230 60 | v 0.131433 -0.475528 -0.081230 61 | v 0.262866 -0.425325 0.000000 62 | v 0.131433 -0.475528 0.081230 63 | v -0.131433 -0.475528 0.081230 64 | v -0.262866 -0.425325 0.000000 65 | v -0.131433 -0.475528 -0.081230 66 | v 0.475528 -0.081230 -0.131433 67 | v 0.425325 0.000000 -0.262866 68 | v 0.475528 0.081230 -0.131433 69 | v 0.475528 0.081230 0.131433 70 | v 0.425325 0.000000 0.262866 71 | v 0.475528 -0.081230 0.131433 72 | v -0.475528 -0.081230 0.131433 73 | v -0.425325 0.000000 0.262866 74 | v -0.475528 0.081230 0.131433 75 | v -0.475528 0.081230 -0.131433 76 | v -0.425325 0.000000 -0.262866 77 | v -0.475528 -0.081230 -0.131433 78 | v -0.081230 -0.131433 0.475528 79 | v 0.000000 -0.262866 0.425325 80 | v 0.081230 -0.131433 0.475528 81 | v 0.081230 0.131433 0.475528 82 | v 0.000000 0.262866 0.425325 83 | v -0.081230 0.131433 0.475528 84 | v -0.081230 0.131433 -0.475528 85 | v 0.000000 0.262866 -0.425325 86 | v 0.081230 0.131433 -0.475528 87 | v 0.081230 -0.131433 -0.475528 88 | v 0.000000 -0.262866 -0.425325 89 | v -0.081230 -0.131433 -0.475528 90 | v 0.293893 0.212663 0.344095 91 | v 0.344095 0.293893 0.212663 92 | v 0.212663 0.344095 0.293893 93 | v -0.344095 0.293893 0.212663 94 | v -0.293893 0.212663 0.344095 95 | v -0.212663 0.344095 0.293893 96 | v 0.344095 0.293893 -0.212663 97 | v 0.293893 0.212663 -0.344095 98 | v 0.212663 0.344095 -0.293893 99 | v -0.293893 0.212663 -0.344095 100 | v -0.344095 0.293893 -0.212663 101 | v -0.212663 0.344095 -0.293893 102 | v 0.344095 -0.293893 0.212663 103 | v 0.293893 -0.212663 0.344095 104 | v 0.212663 -0.344095 0.293893 105 | v -0.293893 -0.212663 0.344095 106 | v -0.344095 -0.293893 0.212663 107 | v -0.212663 -0.344095 0.293893 108 | v 0.293893 -0.212663 -0.344095 109 | v 0.344095 -0.293893 -0.212663 110 | v 0.212663 -0.344095 -0.293893 111 | v -0.344095 -0.293893 -0.212663 112 | v -0.293893 -0.212663 -0.344095 113 | v -0.212663 -0.344095 -0.293893 114 | v 0.000000 0.480969 -0.136633 115 | v 0.129946 0.431334 -0.216944 116 | v 0.000000 0.480969 0.136633 117 | v 0.129946 0.431334 0.216944 118 | v 0.351023 0.346890 0.080311 119 | v 0.351023 0.346890 -0.080311 120 | v -0.129946 0.431334 0.216944 121 | v -0.129946 0.431334 -0.216944 122 | v -0.351023 0.346890 -0.080311 123 | v -0.351023 0.346890 0.080311 124 | v 0.000000 -0.480969 0.136633 125 | v 0.129946 -0.431334 0.216944 126 | v 0.000000 -0.480969 -0.136633 127 | v 0.129946 -0.431334 -0.216944 128 | v 0.351023 -0.346890 -0.080311 129 | v 0.351023 -0.346890 0.080311 130 | v -0.129946 -0.431334 -0.216944 131 | v -0.129946 -0.431334 0.216944 132 | v -0.351023 -0.346890 0.080311 133 | v -0.351023 -0.346890 -0.080311 134 | v 0.480969 0.136633 0.000000 135 | v 0.431334 0.216944 -0.129946 136 | v 0.480969 -0.136633 0.000000 137 | v 0.431334 -0.216944 -0.129946 138 | v 0.346890 -0.080311 -0.351023 139 | v 0.346890 0.080311 -0.351023 140 | v 0.431334 -0.216944 0.129946 141 | v 0.431334 0.216944 0.129946 142 | v 0.346890 0.080311 0.351023 143 | v 0.346890 -0.080311 0.351023 144 | v -0.480969 0.136633 0.000000 145 | v -0.431334 0.216944 0.129946 146 | v -0.480969 -0.136633 0.000000 147 | v -0.431334 -0.216944 0.129946 148 | v -0.346890 -0.080311 0.351023 149 | v -0.346890 0.080311 0.351023 150 | v -0.431334 -0.216944 -0.129946 151 | v -0.431334 0.216944 -0.129946 152 | v -0.346890 0.080311 -0.351023 153 | v -0.346890 -0.080311 -0.351023 154 | v 0.136633 0.000000 0.480969 155 | v 0.216944 -0.129946 0.431334 156 | v -0.136633 0.000000 0.480969 157 | v -0.216944 -0.129946 0.431334 158 | v -0.080311 -0.351023 0.346890 159 | v 0.080311 -0.351023 0.346890 160 | v -0.216944 0.129946 0.431334 161 | v 0.216944 0.129946 0.431334 162 | v 0.080311 0.351023 0.346890 163 | v -0.080311 0.351023 0.346890 164 | v 0.136633 0.000000 -0.480969 165 | v 0.216944 0.129946 -0.431334 166 | v -0.136633 0.000000 -0.480969 167 | v -0.216944 0.129946 -0.431334 168 | v -0.080311 0.351023 -0.346890 169 | v 0.080311 0.351023 -0.346890 170 | v -0.216944 -0.129946 -0.431334 171 | v 0.216944 -0.129946 -0.431334 172 | v 0.080311 -0.351023 -0.346890 173 | v -0.080311 -0.351023 -0.346890 174 | v 0.199804 0.456491 0.041162 175 | v 0.199804 0.456491 -0.041162 176 | v 0.133202 0.481931 0.000000 177 | v -0.199804 0.456491 -0.041162 178 | v -0.199804 0.456491 0.041162 179 | v -0.133202 0.481931 0.000000 180 | v 0.199804 -0.456491 -0.041162 181 | v 0.199804 -0.456491 0.041162 182 | v 0.133202 -0.481931 0.000000 183 | v -0.199804 -0.456491 0.041162 184 | v -0.199804 -0.456491 -0.041162 185 | v -0.133202 -0.481931 0.000000 186 | v 0.456491 -0.041162 -0.199804 187 | v 0.456491 0.041162 -0.199804 188 | v 0.481931 0.000000 -0.133202 189 | v 0.456491 0.041162 0.199804 190 | v 0.456491 -0.041162 0.199804 191 | v 0.481931 0.000000 0.133202 192 | v -0.456491 -0.041162 0.199804 193 | v -0.456491 0.041162 0.199804 194 | v -0.481931 0.000000 0.133202 195 | v -0.456491 0.041162 -0.199804 196 | v -0.456491 -0.041162 -0.199804 197 | v -0.481931 0.000000 -0.133202 198 | v -0.041162 -0.199804 0.456491 199 | v 0.041162 -0.199804 0.456491 200 | v 0.000000 -0.133202 0.481931 201 | v 0.041162 0.199804 0.456491 202 | v -0.041162 0.199804 0.456491 203 | v 0.000000 0.133202 0.481931 204 | v -0.041162 0.199804 -0.456491 205 | v 0.041162 0.199804 -0.456491 206 | v 0.000000 0.133202 -0.481931 207 | v 0.041162 -0.199804 -0.456491 208 | v -0.041162 -0.199804 -0.456491 209 | v 0.000000 -0.133202 -0.481931 210 | v 0.323289 0.256688 0.282127 211 | v 0.282127 0.323289 0.256688 212 | v 0.256688 0.282127 0.323289 213 | v -0.323289 0.256688 0.282127 214 | v -0.256688 0.282127 0.323289 215 | v -0.282127 0.323289 0.256688 216 | v 0.323289 0.256688 -0.282127 217 | v 0.256688 0.282127 -0.323289 218 | v 0.282127 0.323289 -0.256688 219 | v -0.323289 0.256688 -0.282127 220 | v -0.282127 0.323289 -0.256688 221 | v -0.256688 0.282127 -0.323289 222 | v 0.323289 -0.256688 0.282127 223 | v 0.256688 -0.282127 0.323289 224 | v 0.282127 -0.323289 0.256688 225 | v -0.323289 -0.256688 0.282127 226 | v -0.282127 -0.323289 0.256688 227 | v -0.256688 -0.282127 0.323289 228 | v 0.323289 -0.256688 -0.282127 229 | v 0.282127 -0.323289 -0.256688 230 | v 0.256688 -0.282127 -0.323289 231 | v -0.323289 -0.256688 -0.282127 232 | v -0.256688 -0.282127 -0.323289 233 | v -0.282127 -0.323289 -0.256688 234 | v 0.066396 0.483196 -0.110059 235 | v 0.132041 0.458122 -0.150629 236 | v 0.065828 0.462152 -0.179114 237 | v 0.065828 0.462152 0.179114 238 | v 0.132041 0.458122 0.150629 239 | v 0.066396 0.483196 0.110059 240 | v 0.310120 0.390102 0.040571 241 | v 0.355641 0.351454 0.000000 242 | v 0.310120 0.390102 -0.040571 243 | v -0.066396 0.483196 0.110059 244 | v -0.132041 0.458122 0.150629 245 | v -0.065828 0.462152 0.179114 246 | v -0.065828 0.462152 -0.179114 247 | v -0.132041 0.458122 -0.150629 248 | v -0.066396 0.483196 -0.110059 249 | v -0.310120 0.390102 -0.040571 250 | v -0.355641 0.351454 0.000000 251 | v -0.310120 0.390102 0.040571 252 | v 0.066396 -0.483196 0.110059 253 | v 0.132041 -0.458122 0.150629 254 | v 0.065828 -0.462152 0.179114 255 | v 0.065828 -0.462152 -0.179114 256 | v 0.132041 -0.458122 -0.150629 257 | v 0.066396 -0.483196 -0.110059 258 | v 0.310120 -0.390102 -0.040571 259 | v 0.355641 -0.351454 0.000000 260 | v 0.310120 -0.390102 0.040571 261 | v -0.066396 -0.483196 -0.110059 262 | v -0.132041 -0.458122 -0.150629 263 | v -0.065828 -0.462152 -0.179114 264 | v -0.065828 -0.462152 0.179114 265 | v -0.132041 -0.458122 0.150629 266 | v -0.066396 -0.483196 0.110059 267 | v -0.310120 -0.390102 0.040571 268 | v -0.355641 -0.351454 0.000000 269 | v -0.310120 -0.390102 -0.040571 270 | v 0.483196 0.110059 -0.066396 271 | v 0.458122 0.150629 -0.132041 272 | v 0.462152 0.179114 -0.065828 273 | v 0.462152 -0.179114 -0.065828 274 | v 0.458122 -0.150629 -0.132041 275 | v 0.483196 -0.110059 -0.066396 276 | v 0.390102 -0.040571 -0.310120 277 | v 0.351454 0.000000 -0.355641 278 | v 0.390102 0.040571 -0.310120 279 | v 0.483196 -0.110059 0.066396 280 | v 0.458122 -0.150629 0.132041 281 | v 0.462152 -0.179114 0.065828 282 | v 0.462152 0.179114 0.065828 283 | v 0.458122 0.150629 0.132041 284 | v 0.483196 0.110059 0.066396 285 | v 0.390102 0.040571 0.310120 286 | v 0.351454 0.000000 0.355641 287 | v 0.390102 -0.040571 0.310120 288 | v -0.483196 0.110059 0.066396 289 | v -0.458122 0.150629 0.132041 290 | v -0.462152 0.179114 0.065828 291 | v -0.462152 -0.179114 0.065828 292 | v -0.458122 -0.150629 0.132041 293 | v -0.483196 -0.110059 0.066396 294 | v -0.390102 -0.040571 0.310120 295 | v -0.351454 0.000000 0.355641 296 | v -0.390102 0.040571 0.310120 297 | v -0.483196 -0.110059 -0.066396 298 | v -0.458122 -0.150629 -0.132041 299 | v -0.462152 -0.179114 -0.065828 300 | v -0.462152 0.179114 -0.065828 301 | v -0.458122 0.150629 -0.132041 302 | v -0.483196 0.110059 -0.066396 303 | v -0.390102 0.040571 -0.310120 304 | v -0.351454 0.000000 -0.355641 305 | v -0.390102 -0.040571 -0.310120 306 | v 0.110059 -0.066396 0.483196 307 | v 0.150629 -0.132041 0.458122 308 | v 0.179114 -0.065828 0.462152 309 | v -0.179114 -0.065828 0.462152 310 | v -0.150629 -0.132041 0.458122 311 | v -0.110059 -0.066396 0.483196 312 | v -0.040571 -0.310120 0.390102 313 | v 0.000000 -0.355641 0.351454 314 | v 0.040571 -0.310120 0.390102 315 | v -0.110059 0.066396 0.483196 316 | v -0.150629 0.132041 0.458122 317 | v -0.179114 0.065828 0.462152 318 | v 0.179114 0.065828 0.462152 319 | v 0.150629 0.132041 0.458122 320 | v 0.110059 0.066396 0.483196 321 | v 0.040571 0.310120 0.390102 322 | v 0.000000 0.355641 0.351454 323 | v -0.040571 0.310120 0.390102 324 | v 0.110059 0.066396 -0.483196 325 | v 0.150629 0.132041 -0.458122 326 | v 0.179114 0.065828 -0.462152 327 | v -0.179114 0.065828 -0.462152 328 | v -0.150629 0.132041 -0.458122 329 | v -0.110059 0.066396 -0.483196 330 | v -0.040571 0.310120 -0.390102 331 | v 0.000000 0.355641 -0.351454 332 | v 0.040571 0.310120 -0.390102 333 | v -0.110059 -0.066396 -0.483196 334 | v -0.150629 -0.132041 -0.458122 335 | v -0.179114 -0.065828 -0.462152 336 | v 0.179114 -0.065828 -0.462152 337 | v 0.150629 -0.132041 -0.458122 338 | v 0.110059 -0.066396 -0.483196 339 | v 0.040571 -0.310120 -0.390102 340 | v 0.000000 -0.355641 -0.351454 341 | v -0.040571 -0.310120 -0.390102 342 | v 0.148002 0.351155 0.323706 343 | v 0.173076 0.391726 0.258061 344 | v 0.106511 0.396325 0.285626 345 | v 0.285626 0.106511 0.396325 346 | v 0.323706 0.148002 0.351155 347 | v 0.258061 0.173076 0.391726 348 | v 0.391726 0.258061 0.173076 349 | v 0.396325 0.285626 0.106511 350 | v 0.351155 0.323706 0.148002 351 | v -0.173076 0.391726 0.258061 352 | v -0.148002 0.351155 0.323706 353 | v -0.106511 0.396325 0.285626 354 | v -0.396325 0.285626 0.106511 355 | v -0.391726 0.258061 0.173076 356 | v -0.351155 0.323706 0.148002 357 | v -0.323706 0.148002 0.351155 358 | v -0.285626 0.106511 0.396325 359 | v -0.258061 0.173076 0.391726 360 | v 0.173076 0.391726 -0.258061 361 | v 0.148002 0.351155 -0.323706 362 | v 0.106511 0.396325 -0.285626 363 | v 0.396325 0.285626 -0.106511 364 | v 0.391726 0.258061 -0.173076 365 | v 0.351155 0.323706 -0.148002 366 | v 0.323706 0.148002 -0.351155 367 | v 0.285626 0.106511 -0.396325 368 | v 0.258061 0.173076 -0.391726 369 | v -0.148002 0.351155 -0.323706 370 | v -0.173076 0.391726 -0.258061 371 | v -0.106511 0.396325 -0.285626 372 | v -0.285626 0.106511 -0.396325 373 | v -0.323706 0.148002 -0.351155 374 | v -0.258061 0.173076 -0.391726 375 | v -0.391726 0.258061 -0.173076 376 | v -0.396325 0.285626 -0.106511 377 | v -0.351155 0.323706 -0.148002 378 | v 0.173076 -0.391726 0.258061 379 | v 0.148002 -0.351155 0.323706 380 | v 0.106511 -0.396325 0.285626 381 | v 0.396325 -0.285626 0.106511 382 | v 0.391726 -0.258061 0.173076 383 | v 0.351155 -0.323706 0.148002 384 | v 0.323706 -0.148002 0.351155 385 | v 0.285626 -0.106511 0.396325 386 | v 0.258061 -0.173076 0.391726 387 | v -0.148002 -0.351155 0.323706 388 | v -0.173076 -0.391726 0.258061 389 | v -0.106511 -0.396325 0.285626 390 | v -0.285626 -0.106511 0.396325 391 | v -0.323706 -0.148002 0.351155 392 | v -0.258061 -0.173076 0.391726 393 | v -0.391726 -0.258061 0.173076 394 | v -0.396325 -0.285626 0.106511 395 | v -0.351155 -0.323706 0.148002 396 | v 0.148002 -0.351155 -0.323706 397 | v 0.173076 -0.391726 -0.258061 398 | v 0.106511 -0.396325 -0.285626 399 | v 0.285626 -0.106511 -0.396325 400 | v 0.323706 -0.148002 -0.351155 401 | v 0.258061 -0.173076 -0.391726 402 | v 0.391726 -0.258061 -0.173076 403 | v 0.396325 -0.285626 -0.106511 404 | v 0.351155 -0.323706 -0.148002 405 | v -0.173076 -0.391726 -0.258061 406 | v -0.148002 -0.351155 -0.323706 407 | v -0.106511 -0.396325 -0.285626 408 | v -0.396325 -0.285626 -0.106511 409 | v -0.391726 -0.258061 -0.173076 410 | v -0.351155 -0.323706 -0.148002 411 | v -0.323706 -0.148002 -0.351155 412 | v -0.285626 -0.106511 -0.396325 413 | v -0.258061 -0.173076 -0.391726 414 | v 0.066536 0.493844 0.041121 415 | v 0.066536 0.493844 -0.041121 416 | v 0.193094 0.445503 0.119338 417 | v 0.259629 0.420089 0.078217 418 | v 0.259629 0.420089 -0.078217 419 | v 0.193094 0.445503 -0.119338 420 | v -0.066536 0.493844 -0.041121 421 | v -0.066536 0.493844 0.041121 422 | v -0.193094 0.445503 -0.119338 423 | v -0.259629 0.420089 -0.078217 424 | v -0.259629 0.420089 0.078217 425 | v -0.193094 0.445503 0.119338 426 | v 0.066536 -0.493844 -0.041121 427 | v 0.066536 -0.493844 0.041121 428 | v 0.193094 -0.445503 -0.119338 429 | v 0.259629 -0.420089 -0.078217 430 | v 0.259629 -0.420089 0.078217 431 | v 0.193094 -0.445503 0.119338 432 | v -0.066536 -0.493844 0.041121 433 | v -0.066536 -0.493844 -0.041121 434 | v -0.193094 -0.445503 0.119338 435 | v -0.259629 -0.420089 0.078217 436 | v -0.259629 -0.420089 -0.078217 437 | v -0.193094 -0.445503 -0.119338 438 | v 0.493844 -0.041121 -0.066536 439 | v 0.493844 0.041121 -0.066536 440 | v 0.445503 -0.119338 -0.193094 441 | v 0.420089 -0.078217 -0.259629 442 | v 0.420089 0.078217 -0.259629 443 | v 0.445503 0.119338 -0.193094 444 | v 0.493844 0.041121 0.066536 445 | v 0.493844 -0.041121 0.066536 446 | v 0.445503 0.119338 0.193094 447 | v 0.420089 0.078217 0.259629 448 | v 0.420089 -0.078217 0.259629 449 | v 0.445503 -0.119338 0.193094 450 | v -0.493844 -0.041121 0.066536 451 | v -0.493844 0.041121 0.066536 452 | v -0.445503 -0.119338 0.193094 453 | v -0.420089 -0.078217 0.259629 454 | v -0.420089 0.078217 0.259629 455 | v -0.445503 0.119338 0.193094 456 | v -0.493844 0.041121 -0.066536 457 | v -0.493844 -0.041121 -0.066536 458 | v -0.445503 0.119338 -0.193094 459 | v -0.420089 0.078217 -0.259629 460 | v -0.420089 -0.078217 -0.259629 461 | v -0.445503 -0.119338 -0.193094 462 | v -0.041121 -0.066536 0.493844 463 | v 0.041121 -0.066536 0.493844 464 | v -0.119338 -0.193094 0.445503 465 | v -0.078217 -0.259629 0.420089 466 | v 0.078217 -0.259629 0.420089 467 | v 0.119338 -0.193094 0.445503 468 | v 0.041121 0.066536 0.493844 469 | v -0.041121 0.066536 0.493844 470 | v 0.119338 0.193094 0.445503 471 | v 0.078217 0.259629 0.420089 472 | v -0.078217 0.259629 0.420089 473 | v -0.119338 0.193094 0.445503 474 | v -0.041121 0.066536 -0.493844 475 | v 0.041121 0.066536 -0.493844 476 | v -0.119338 0.193094 -0.445503 477 | v -0.078217 0.259629 -0.420089 478 | v 0.078217 0.259629 -0.420089 479 | v 0.119338 0.193094 -0.445503 480 | v 0.041121 -0.066536 -0.493844 481 | v -0.041121 -0.066536 -0.493844 482 | v 0.119338 -0.193094 -0.445503 483 | v 0.078217 -0.259629 -0.420089 484 | v -0.078217 -0.259629 -0.420089 485 | v -0.119338 -0.193094 -0.445503 486 | v 0.226995 0.234215 0.378968 487 | v 0.185874 0.300750 0.353553 488 | v 0.353553 0.185874 0.300750 489 | v 0.378968 0.226995 0.234215 490 | v 0.300750 0.353553 0.185874 491 | v 0.234215 0.378968 0.226995 492 | v -0.300750 0.353553 0.185874 493 | v -0.234215 0.378968 0.226995 494 | v -0.378968 0.226995 0.234215 495 | v -0.353553 0.185874 0.300750 496 | v -0.226995 0.234215 0.378968 497 | v -0.185874 0.300750 0.353553 498 | v 0.300750 0.353553 -0.185874 499 | v 0.234215 0.378968 -0.226995 500 | v 0.378968 0.226995 -0.234215 501 | v 0.353553 0.185874 -0.300750 502 | v 0.226995 0.234215 -0.378968 503 | v 0.185874 0.300750 -0.353553 504 | v -0.226995 0.234215 -0.378968 505 | v -0.185874 0.300750 -0.353553 506 | v -0.353553 0.185874 -0.300750 507 | v -0.378968 0.226995 -0.234215 508 | v -0.300750 0.353553 -0.185874 509 | v -0.234215 0.378968 -0.226995 510 | v 0.300750 -0.353553 0.185874 511 | v 0.234215 -0.378968 0.226995 512 | v 0.378968 -0.226995 0.234215 513 | v 0.353553 -0.185874 0.300750 514 | v 0.226995 -0.234215 0.378968 515 | v 0.185874 -0.300750 0.353553 516 | v -0.226995 -0.234215 0.378968 517 | v -0.185874 -0.300750 0.353553 518 | v -0.353553 -0.185874 0.300750 519 | v -0.378968 -0.226995 0.234215 520 | v -0.300750 -0.353553 0.185874 521 | v -0.234215 -0.378968 0.226995 522 | v 0.226995 -0.234215 -0.378968 523 | v 0.185874 -0.300750 -0.353553 524 | v 0.353553 -0.185874 -0.300750 525 | v 0.378968 -0.226995 -0.234215 526 | v 0.300750 -0.353553 -0.185874 527 | v 0.234215 -0.378968 -0.226995 528 | v -0.300750 -0.353553 -0.185874 529 | v -0.234215 -0.378968 -0.226995 530 | v -0.378968 -0.226995 -0.234215 531 | v -0.353553 -0.185874 -0.300750 532 | v -0.226995 -0.234215 -0.378968 533 | v -0.185874 -0.300750 -0.353553 534 | v 0.000000 0.457522 -0.201678 535 | v 0.065600 0.432465 -0.242221 536 | v 0.000000 0.495219 -0.068976 537 | v 0.191807 0.421956 -0.187519 538 | v 0.000000 0.495219 0.068976 539 | v 0.000000 0.457522 0.201678 540 | v 0.065600 0.432465 0.242221 541 | v 0.191807 0.421956 0.187519 542 | v 0.303413 0.379326 -0.118543 543 | v 0.303413 0.379326 0.118543 544 | v 0.391921 0.307821 0.040543 545 | v 0.391921 0.307821 -0.040543 546 | v -0.065600 0.432465 0.242221 547 | v -0.191807 0.421956 0.187519 548 | v -0.065600 0.432465 -0.242221 549 | v -0.191807 0.421956 -0.187519 550 | v -0.303413 0.379326 0.118543 551 | v -0.303413 0.379326 -0.118543 552 | v -0.391921 0.307821 -0.040543 553 | v -0.391921 0.307821 0.040543 554 | v 0.000000 -0.457522 0.201678 555 | v 0.065600 -0.432465 0.242221 556 | v 0.000000 -0.495219 0.068976 557 | v 0.191807 -0.421956 0.187519 558 | v 0.000000 -0.495219 -0.068976 559 | v 0.000000 -0.457522 -0.201678 560 | v 0.065600 -0.432465 -0.242221 561 | v 0.191807 -0.421956 -0.187519 562 | v 0.303413 -0.379326 0.118543 563 | v 0.303413 -0.379326 -0.118543 564 | v 0.391921 -0.307821 -0.040543 565 | v 0.391921 -0.307821 0.040543 566 | v -0.065600 -0.432465 -0.242221 567 | v -0.191807 -0.421956 -0.187519 568 | v -0.065600 -0.432465 0.242221 569 | v -0.191807 -0.421956 0.187519 570 | v -0.303413 -0.379326 -0.118543 571 | v -0.303413 -0.379326 0.118543 572 | v -0.391921 -0.307821 0.040543 573 | v -0.391921 -0.307821 -0.040543 574 | v 0.457522 0.201678 0.000000 575 | v 0.432465 0.242221 -0.065600 576 | v 0.495219 0.068976 0.000000 577 | v 0.421956 0.187519 -0.191807 578 | v 0.495219 -0.068976 0.000000 579 | v 0.457522 -0.201678 0.000000 580 | v 0.432465 -0.242221 -0.065600 581 | v 0.421956 -0.187519 -0.191807 582 | v 0.379326 0.118543 -0.303413 583 | v 0.379326 -0.118543 -0.303413 584 | v 0.307821 -0.040543 -0.391921 585 | v 0.307821 0.040543 -0.391921 586 | v 0.432465 -0.242221 0.065600 587 | v 0.421956 -0.187519 0.191807 588 | v 0.432465 0.242221 0.065600 589 | v 0.421956 0.187519 0.191807 590 | v 0.379326 -0.118543 0.303413 591 | v 0.379326 0.118543 0.303413 592 | v 0.307821 0.040543 0.391921 593 | v 0.307821 -0.040543 0.391921 594 | v -0.457522 0.201678 0.000000 595 | v -0.432465 0.242221 0.065600 596 | v -0.495219 0.068976 0.000000 597 | v -0.421956 0.187519 0.191807 598 | v -0.495219 -0.068976 0.000000 599 | v -0.457522 -0.201678 0.000000 600 | v -0.432465 -0.242221 0.065600 601 | v -0.421956 -0.187519 0.191807 602 | v -0.379326 0.118543 0.303413 603 | v -0.379326 -0.118543 0.303413 604 | v -0.307821 -0.040543 0.391921 605 | v -0.307821 0.040543 0.391921 606 | v -0.432465 -0.242221 -0.065600 607 | v -0.421956 -0.187519 -0.191807 608 | v -0.432465 0.242221 -0.065600 609 | v -0.421956 0.187519 -0.191807 610 | v -0.379326 -0.118543 -0.303413 611 | v -0.379326 0.118543 -0.303413 612 | v -0.307821 0.040543 -0.391921 613 | v -0.307821 -0.040543 -0.391921 614 | v 0.201678 0.000000 0.457522 615 | v 0.242221 -0.065600 0.432465 616 | v 0.068976 0.000000 0.495219 617 | v 0.187519 -0.191807 0.421956 618 | v -0.068976 0.000000 0.495219 619 | v -0.201678 0.000000 0.457522 620 | v -0.242221 -0.065600 0.432465 621 | v -0.187519 -0.191807 0.421956 622 | v 0.118543 -0.303413 0.379326 623 | v -0.118543 -0.303413 0.379326 624 | v -0.040543 -0.391921 0.307821 625 | v 0.040543 -0.391921 0.307821 626 | v -0.242221 0.065600 0.432465 627 | v -0.187519 0.191807 0.421956 628 | v 0.242221 0.065600 0.432465 629 | v 0.187519 0.191807 0.421956 630 | v -0.118543 0.303413 0.379326 631 | v 0.118543 0.303413 0.379326 632 | v 0.040543 0.391921 0.307821 633 | v -0.040543 0.391921 0.307821 634 | v 0.201678 0.000000 -0.457522 635 | v 0.242221 0.065600 -0.432465 636 | v 0.068976 0.000000 -0.495219 637 | v 0.187519 0.191807 -0.421956 638 | v -0.068976 0.000000 -0.495219 639 | v -0.201678 0.000000 -0.457522 640 | v -0.242221 0.065600 -0.432465 641 | v -0.187519 0.191807 -0.421956 642 | v 0.118543 0.303413 -0.379326 643 | v -0.118543 0.303413 -0.379326 644 | v -0.040543 0.391921 -0.307821 645 | v 0.040543 0.391921 -0.307821 646 | v -0.242221 -0.065600 -0.432465 647 | v -0.187519 -0.191807 -0.421956 648 | v 0.242221 -0.065600 -0.432465 649 | v 0.187519 -0.191807 -0.421956 650 | v -0.118543 -0.303413 -0.379326 651 | v 0.118543 -0.303413 -0.379326 652 | v 0.040543 -0.391921 -0.307821 653 | v -0.040543 -0.391921 -0.307821 654 | # 642 vertices, 0 vertices normals 655 | 656 | f 163 164 165 657 | f 166 167 168 658 | f 169 170 171 659 | f 172 173 174 660 | f 175 176 177 661 | f 178 179 180 662 | f 181 182 183 663 | f 184 185 186 664 | f 187 188 189 665 | f 190 191 192 666 | f 193 194 195 667 | f 196 197 198 668 | f 199 200 201 669 | f 202 203 204 670 | f 205 206 207 671 | f 208 209 210 672 | f 211 212 213 673 | f 214 215 216 674 | f 217 218 219 675 | f 220 221 222 676 | f 223 224 225 677 | f 226 227 228 678 | f 229 230 231 679 | f 232 233 234 680 | f 235 236 237 681 | f 238 239 240 682 | f 241 242 243 683 | f 244 245 246 684 | f 247 248 249 685 | f 250 251 252 686 | f 253 254 255 687 | f 256 257 258 688 | f 259 260 261 689 | f 262 263 264 690 | f 265 266 267 691 | f 268 269 270 692 | f 271 272 273 693 | f 274 275 276 694 | f 277 278 279 695 | f 280 281 282 696 | f 283 284 285 697 | f 286 287 288 698 | f 289 290 291 699 | f 292 293 294 700 | f 295 296 297 701 | f 298 299 300 702 | f 301 302 303 703 | f 304 305 306 704 | f 307 308 309 705 | f 310 311 312 706 | f 313 314 315 707 | f 316 317 318 708 | f 319 320 321 709 | f 322 323 324 710 | f 325 326 327 711 | f 328 329 330 712 | f 331 332 333 713 | f 334 335 336 714 | f 337 338 339 715 | f 340 341 342 716 | f 343 344 345 717 | f 346 347 348 718 | f 349 350 351 719 | f 352 353 354 720 | f 355 356 357 721 | f 358 359 360 722 | f 361 362 363 723 | f 364 365 366 724 | f 367 368 369 725 | f 370 371 372 726 | f 373 374 375 727 | f 376 377 378 728 | f 379 380 381 729 | f 382 383 384 730 | f 385 386 387 731 | f 388 389 390 732 | f 391 392 393 733 | f 394 395 396 734 | f 397 398 399 735 | f 400 401 402 736 | f 403 165 404 737 | f 405 406 163 738 | f 164 407 408 739 | f 409 168 410 740 | f 411 412 166 741 | f 167 413 414 742 | f 415 171 416 743 | f 417 418 169 744 | f 170 419 420 745 | f 421 174 422 746 | f 423 424 172 747 | f 173 425 426 748 | f 427 177 428 749 | f 429 430 175 750 | f 176 431 432 751 | f 433 180 434 752 | f 435 436 178 753 | f 179 437 438 754 | f 439 183 440 755 | f 441 442 181 756 | f 182 443 444 757 | f 445 186 446 758 | f 447 448 184 759 | f 185 449 450 760 | f 451 189 452 761 | f 453 454 187 762 | f 188 455 456 763 | f 457 192 458 764 | f 459 460 190 765 | f 191 461 462 766 | f 463 195 464 767 | f 465 466 193 768 | f 194 467 468 769 | f 469 198 470 770 | f 471 472 196 771 | f 197 473 474 772 | f 475 201 476 773 | f 477 478 199 774 | f 200 479 480 775 | f 481 204 482 776 | f 483 484 202 777 | f 203 485 486 778 | f 487 207 488 779 | f 489 490 205 780 | f 206 491 492 781 | f 493 210 494 782 | f 495 496 208 783 | f 209 497 498 784 | f 499 213 500 785 | f 501 502 211 786 | f 212 503 504 787 | f 505 216 506 788 | f 507 508 214 789 | f 215 509 510 790 | f 511 219 512 791 | f 513 514 217 792 | f 218 515 516 793 | f 517 222 518 794 | f 519 520 220 795 | f 221 521 522 796 | f 523 225 524 797 | f 525 404 223 798 | f 224 408 526 799 | f 527 228 403 800 | f 528 529 226 801 | f 227 530 405 802 | f 407 231 531 803 | f 406 532 229 804 | f 230 533 534 805 | f 528 234 535 806 | f 527 410 232 807 | f 233 414 536 808 | f 525 237 409 809 | f 523 537 235 810 | f 236 538 411 811 | f 413 240 539 812 | f 412 540 238 813 | f 239 541 542 814 | f 543 243 544 815 | f 545 416 241 816 | f 242 420 546 817 | f 547 246 415 818 | f 548 549 244 819 | f 245 550 417 820 | f 419 249 551 821 | f 418 552 247 822 | f 248 553 554 823 | f 548 252 555 824 | f 547 422 250 825 | f 251 426 556 826 | f 545 255 421 827 | f 543 557 253 828 | f 254 558 423 829 | f 425 258 559 830 | f 424 560 256 831 | f 257 561 562 832 | f 563 261 564 833 | f 565 428 259 834 | f 260 432 566 835 | f 567 264 427 836 | f 568 569 262 837 | f 263 570 429 838 | f 431 267 571 839 | f 430 572 265 840 | f 266 573 574 841 | f 568 270 575 842 | f 567 434 268 843 | f 269 438 576 844 | f 565 273 433 845 | f 563 577 271 846 | f 272 578 435 847 | f 437 276 579 848 | f 436 580 274 849 | f 275 581 582 850 | f 583 279 584 851 | f 585 440 277 852 | f 278 444 586 853 | f 587 282 439 854 | f 588 589 280 855 | f 281 590 441 856 | f 443 285 591 857 | f 442 592 283 858 | f 284 593 594 859 | f 588 288 595 860 | f 587 446 286 861 | f 287 450 596 862 | f 585 291 445 863 | f 583 597 289 864 | f 290 598 447 865 | f 449 294 599 866 | f 448 600 292 867 | f 293 601 602 868 | f 603 297 604 869 | f 605 452 295 870 | f 296 456 606 871 | f 607 300 451 872 | f 608 609 298 873 | f 299 610 453 874 | f 455 303 611 875 | f 454 612 301 876 | f 302 613 614 877 | f 608 306 615 878 | f 607 458 304 879 | f 305 462 616 880 | f 605 309 457 881 | f 603 617 307 882 | f 308 618 459 883 | f 461 312 619 884 | f 460 620 310 885 | f 311 621 622 886 | f 623 315 624 887 | f 625 464 313 888 | f 314 468 626 889 | f 627 318 463 890 | f 628 629 316 891 | f 317 630 465 892 | f 467 321 631 893 | f 466 632 319 894 | f 320 633 634 895 | f 628 324 635 896 | f 627 470 322 897 | f 323 474 636 898 | f 625 327 469 899 | f 623 637 325 900 | f 326 638 471 901 | f 473 330 639 902 | f 472 640 328 903 | f 329 641 642 904 | f 621 333 529 905 | f 620 476 331 906 | f 332 480 530 907 | f 618 336 475 908 | f 617 581 334 909 | f 335 580 477 910 | f 479 339 532 911 | f 478 578 337 912 | f 338 577 533 913 | f 535 342 622 914 | f 536 482 340 915 | f 341 486 619 916 | f 539 345 481 917 | f 542 584 343 918 | f 344 586 483 919 | f 485 348 616 920 | f 484 591 346 921 | f 347 594 615 922 | f 524 351 634 923 | f 526 488 349 924 | f 350 492 631 925 | f 531 354 487 926 | f 534 564 352 927 | f 353 566 489 928 | f 491 357 626 929 | f 490 571 355 930 | f 356 574 624 931 | f 633 360 537 932 | f 632 494 358 933 | f 359 498 538 934 | f 630 363 493 935 | f 629 601 361 936 | f 362 600 495 937 | f 497 366 540 938 | f 496 598 364 939 | f 365 597 541 940 | f 544 369 614 941 | f 546 500 367 942 | f 368 504 611 943 | f 551 372 499 944 | f 554 575 370 945 | f 371 576 501 946 | f 503 375 606 947 | f 502 579 373 948 | f 374 582 604 949 | f 613 378 557 950 | f 612 506 376 951 | f 377 510 558 952 | f 610 381 505 953 | f 609 593 379 954 | f 380 592 507 955 | f 509 384 560 956 | f 508 590 382 957 | f 383 589 561 958 | f 641 387 549 959 | f 640 512 385 960 | f 386 516 550 961 | f 638 390 511 962 | f 637 573 388 963 | f 389 572 513 964 | f 515 393 552 965 | f 514 570 391 966 | f 392 569 553 967 | f 555 396 642 968 | f 556 518 394 969 | f 395 522 639 970 | f 559 399 517 971 | f 562 595 397 972 | f 398 596 519 973 | f 521 402 636 974 | f 520 599 400 975 | f 401 602 635 976 | f 43 163 165 977 | f 163 44 164 978 | f 165 164 45 979 | f 46 166 168 980 | f 166 47 167 981 | f 168 167 48 982 | f 49 169 171 983 | f 169 50 170 984 | f 171 170 51 985 | f 52 172 174 986 | f 172 53 173 987 | f 174 173 54 988 | f 55 175 177 989 | f 175 56 176 990 | f 177 176 57 991 | f 58 178 180 992 | f 178 59 179 993 | f 180 179 60 994 | f 61 181 183 995 | f 181 62 182 996 | f 183 182 63 997 | f 64 184 186 998 | f 184 65 185 999 | f 186 185 66 1000 | f 67 187 189 1001 | f 187 68 188 1002 | f 189 188 69 1003 | f 70 190 192 1004 | f 190 71 191 1005 | f 192 191 72 1006 | f 73 193 195 1007 | f 193 74 194 1008 | f 195 194 75 1009 | f 76 196 198 1010 | f 196 77 197 1011 | f 198 197 78 1012 | f 79 199 201 1013 | f 199 80 200 1014 | f 201 200 81 1015 | f 82 202 204 1016 | f 202 83 203 1017 | f 204 203 84 1018 | f 85 205 207 1019 | f 205 86 206 1020 | f 207 206 87 1021 | f 88 208 210 1022 | f 208 89 209 1023 | f 210 209 90 1024 | f 91 211 213 1025 | f 211 92 212 1026 | f 213 212 93 1027 | f 94 214 216 1028 | f 214 95 215 1029 | f 216 215 96 1030 | f 97 217 219 1031 | f 217 98 218 1032 | f 219 218 99 1033 | f 100 220 222 1034 | f 220 101 221 1035 | f 222 221 102 1036 | f 103 223 225 1037 | f 223 45 224 1038 | f 225 224 104 1039 | f 105 226 228 1040 | f 226 106 227 1041 | f 228 227 43 1042 | f 44 229 231 1043 | f 229 107 230 1044 | f 231 230 108 1045 | f 105 232 234 1046 | f 232 48 233 1047 | f 234 233 109 1048 | f 103 235 237 1049 | f 235 110 236 1050 | f 237 236 46 1051 | f 47 238 240 1052 | f 238 111 239 1053 | f 240 239 112 1054 | f 113 241 243 1055 | f 241 51 242 1056 | f 243 242 114 1057 | f 115 244 246 1058 | f 244 116 245 1059 | f 246 245 49 1060 | f 50 247 249 1061 | f 247 117 248 1062 | f 249 248 118 1063 | f 115 250 252 1064 | f 250 54 251 1065 | f 252 251 119 1066 | f 113 253 255 1067 | f 253 120 254 1068 | f 255 254 52 1069 | f 53 256 258 1070 | f 256 121 257 1071 | f 258 257 122 1072 | f 123 259 261 1073 | f 259 57 260 1074 | f 261 260 124 1075 | f 125 262 264 1076 | f 262 126 263 1077 | f 264 263 55 1078 | f 56 265 267 1079 | f 265 127 266 1080 | f 267 266 128 1081 | f 125 268 270 1082 | f 268 60 269 1083 | f 270 269 129 1084 | f 123 271 273 1085 | f 271 130 272 1086 | f 273 272 58 1087 | f 59 274 276 1088 | f 274 131 275 1089 | f 276 275 132 1090 | f 133 277 279 1091 | f 277 63 278 1092 | f 279 278 134 1093 | f 135 280 282 1094 | f 280 136 281 1095 | f 282 281 61 1096 | f 62 283 285 1097 | f 283 137 284 1098 | f 285 284 138 1099 | f 135 286 288 1100 | f 286 66 287 1101 | f 288 287 139 1102 | f 133 289 291 1103 | f 289 140 290 1104 | f 291 290 64 1105 | f 65 292 294 1106 | f 292 141 293 1107 | f 294 293 142 1108 | f 143 295 297 1109 | f 295 69 296 1110 | f 297 296 144 1111 | f 145 298 300 1112 | f 298 146 299 1113 | f 300 299 67 1114 | f 68 301 303 1115 | f 301 147 302 1116 | f 303 302 148 1117 | f 145 304 306 1118 | f 304 72 305 1119 | f 306 305 149 1120 | f 143 307 309 1121 | f 307 150 308 1122 | f 309 308 70 1123 | f 71 310 312 1124 | f 310 151 311 1125 | f 312 311 152 1126 | f 153 313 315 1127 | f 313 75 314 1128 | f 315 314 154 1129 | f 155 316 318 1130 | f 316 156 317 1131 | f 318 317 73 1132 | f 74 319 321 1133 | f 319 157 320 1134 | f 321 320 158 1135 | f 155 322 324 1136 | f 322 78 323 1137 | f 324 323 159 1138 | f 153 325 327 1139 | f 325 160 326 1140 | f 327 326 76 1141 | f 77 328 330 1142 | f 328 161 329 1143 | f 330 329 162 1144 | f 151 331 333 1145 | f 331 81 332 1146 | f 333 332 106 1147 | f 150 334 336 1148 | f 334 131 335 1149 | f 336 335 79 1150 | f 80 337 339 1151 | f 337 130 338 1152 | f 339 338 107 1153 | f 109 340 342 1154 | f 340 84 341 1155 | f 342 341 152 1156 | f 112 343 345 1157 | f 343 134 344 1158 | f 345 344 82 1159 | f 83 346 348 1160 | f 346 138 347 1161 | f 348 347 149 1162 | f 104 349 351 1163 | f 349 87 350 1164 | f 351 350 158 1165 | f 108 352 354 1166 | f 352 124 353 1167 | f 354 353 85 1168 | f 86 355 357 1169 | f 355 128 356 1170 | f 357 356 154 1171 | f 157 358 360 1172 | f 358 90 359 1173 | f 360 359 110 1174 | f 156 361 363 1175 | f 361 141 362 1176 | f 363 362 88 1177 | f 89 364 366 1178 | f 364 140 365 1179 | f 366 365 111 1180 | f 114 367 369 1181 | f 367 93 368 1182 | f 369 368 148 1183 | f 118 370 372 1184 | f 370 129 371 1185 | f 372 371 91 1186 | f 92 373 375 1187 | f 373 132 374 1188 | f 375 374 144 1189 | f 147 376 378 1190 | f 376 96 377 1191 | f 378 377 120 1192 | f 146 379 381 1193 | f 379 137 380 1194 | f 381 380 94 1195 | f 95 382 384 1196 | f 382 136 383 1197 | f 384 383 121 1198 | f 161 385 387 1199 | f 385 99 386 1200 | f 387 386 116 1201 | f 160 388 390 1202 | f 388 127 389 1203 | f 390 389 97 1204 | f 98 391 393 1205 | f 391 126 392 1206 | f 393 392 117 1207 | f 119 394 396 1208 | f 394 102 395 1209 | f 396 395 162 1210 | f 122 397 399 1211 | f 397 139 398 1212 | f 399 398 100 1213 | f 101 400 402 1214 | f 400 142 401 1215 | f 402 401 159 1216 | f 13 403 404 1217 | f 403 43 165 1218 | f 404 165 45 1219 | f 43 405 163 1220 | f 405 14 406 1221 | f 163 406 44 1222 | f 45 164 408 1223 | f 164 44 407 1224 | f 408 407 15 1225 | f 13 409 410 1226 | f 409 46 168 1227 | f 410 168 48 1228 | f 46 411 166 1229 | f 411 16 412 1230 | f 166 412 47 1231 | f 48 167 414 1232 | f 167 47 413 1233 | f 414 413 17 1234 | f 18 415 416 1235 | f 415 49 171 1236 | f 416 171 51 1237 | f 49 417 169 1238 | f 417 19 418 1239 | f 169 418 50 1240 | f 51 170 420 1241 | f 170 50 419 1242 | f 420 419 20 1243 | f 18 421 422 1244 | f 421 52 174 1245 | f 422 174 54 1246 | f 52 423 172 1247 | f 423 21 424 1248 | f 172 424 53 1249 | f 54 173 426 1250 | f 173 53 425 1251 | f 426 425 22 1252 | f 23 427 428 1253 | f 427 55 177 1254 | f 428 177 57 1255 | f 55 429 175 1256 | f 429 24 430 1257 | f 175 430 56 1258 | f 57 176 432 1259 | f 176 56 431 1260 | f 432 431 25 1261 | f 23 433 434 1262 | f 433 58 180 1263 | f 434 180 60 1264 | f 58 435 178 1265 | f 435 26 436 1266 | f 178 436 59 1267 | f 60 179 438 1268 | f 179 59 437 1269 | f 438 437 27 1270 | f 28 439 440 1271 | f 439 61 183 1272 | f 440 183 63 1273 | f 61 441 181 1274 | f 441 29 442 1275 | f 181 442 62 1276 | f 63 182 444 1277 | f 182 62 443 1278 | f 444 443 30 1279 | f 28 445 446 1280 | f 445 64 186 1281 | f 446 186 66 1282 | f 64 447 184 1283 | f 447 31 448 1284 | f 184 448 65 1285 | f 66 185 450 1286 | f 185 65 449 1287 | f 450 449 32 1288 | f 33 451 452 1289 | f 451 67 189 1290 | f 452 189 69 1291 | f 67 453 187 1292 | f 453 34 454 1293 | f 187 454 68 1294 | f 69 188 456 1295 | f 188 68 455 1296 | f 456 455 35 1297 | f 33 457 458 1298 | f 457 70 192 1299 | f 458 192 72 1300 | f 70 459 190 1301 | f 459 36 460 1302 | f 190 460 71 1303 | f 72 191 462 1304 | f 191 71 461 1305 | f 462 461 37 1306 | f 38 463 464 1307 | f 463 73 195 1308 | f 464 195 75 1309 | f 73 465 193 1310 | f 465 39 466 1311 | f 193 466 74 1312 | f 75 194 468 1313 | f 194 74 467 1314 | f 468 467 40 1315 | f 38 469 470 1316 | f 469 76 198 1317 | f 470 198 78 1318 | f 76 471 196 1319 | f 471 41 472 1320 | f 196 472 77 1321 | f 78 197 474 1322 | f 197 77 473 1323 | f 474 473 42 1324 | f 36 475 476 1325 | f 475 79 201 1326 | f 476 201 81 1327 | f 79 477 199 1328 | f 477 26 478 1329 | f 199 478 80 1330 | f 81 200 480 1331 | f 200 80 479 1332 | f 480 479 14 1333 | f 17 481 482 1334 | f 481 82 204 1335 | f 482 204 84 1336 | f 82 483 202 1337 | f 483 30 484 1338 | f 202 484 83 1339 | f 84 203 486 1340 | f 203 83 485 1341 | f 486 485 37 1342 | f 15 487 488 1343 | f 487 85 207 1344 | f 488 207 87 1345 | f 85 489 205 1346 | f 489 25 490 1347 | f 205 490 86 1348 | f 87 206 492 1349 | f 206 86 491 1350 | f 492 491 40 1351 | f 39 493 494 1352 | f 493 88 210 1353 | f 494 210 90 1354 | f 88 495 208 1355 | f 495 31 496 1356 | f 208 496 89 1357 | f 90 209 498 1358 | f 209 89 497 1359 | f 498 497 16 1360 | f 20 499 500 1361 | f 499 91 213 1362 | f 500 213 93 1363 | f 91 501 211 1364 | f 501 27 502 1365 | f 211 502 92 1366 | f 93 212 504 1367 | f 212 92 503 1368 | f 504 503 35 1369 | f 34 505 506 1370 | f 505 94 216 1371 | f 506 216 96 1372 | f 94 507 214 1373 | f 507 29 508 1374 | f 214 508 95 1375 | f 96 215 510 1376 | f 215 95 509 1377 | f 510 509 21 1378 | f 41 511 512 1379 | f 511 97 219 1380 | f 512 219 99 1381 | f 97 513 217 1382 | f 513 24 514 1383 | f 217 514 98 1384 | f 99 218 516 1385 | f 218 98 515 1386 | f 516 515 19 1387 | f 22 517 518 1388 | f 517 100 222 1389 | f 518 222 102 1390 | f 100 519 220 1391 | f 519 32 520 1392 | f 220 520 101 1393 | f 102 221 522 1394 | f 221 101 521 1395 | f 522 521 42 1396 | f 2 523 524 1397 | f 523 103 225 1398 | f 524 225 104 1399 | f 103 525 223 1400 | f 525 13 404 1401 | f 223 404 45 1402 | f 104 224 526 1403 | f 224 45 408 1404 | f 526 408 15 1405 | f 13 527 403 1406 | f 527 105 228 1407 | f 403 228 43 1408 | f 105 528 226 1409 | f 528 1 529 1410 | f 226 529 106 1411 | f 43 227 405 1412 | f 227 106 530 1413 | f 405 530 14 1414 | f 15 407 531 1415 | f 407 44 231 1416 | f 531 231 108 1417 | f 44 406 229 1418 | f 406 14 532 1419 | f 229 532 107 1420 | f 108 230 534 1421 | f 230 107 533 1422 | f 534 533 5 1423 | f 1 528 535 1424 | f 528 105 234 1425 | f 535 234 109 1426 | f 105 527 232 1427 | f 527 13 410 1428 | f 232 410 48 1429 | f 109 233 536 1430 | f 233 48 414 1431 | f 536 414 17 1432 | f 13 525 409 1433 | f 525 103 237 1434 | f 409 237 46 1435 | f 103 523 235 1436 | f 523 2 537 1437 | f 235 537 110 1438 | f 46 236 411 1439 | f 236 110 538 1440 | f 411 538 16 1441 | f 17 413 539 1442 | f 413 47 240 1443 | f 539 240 112 1444 | f 47 412 238 1445 | f 412 16 540 1446 | f 238 540 111 1447 | f 112 239 542 1448 | f 239 111 541 1449 | f 542 541 7 1450 | f 3 543 544 1451 | f 543 113 243 1452 | f 544 243 114 1453 | f 113 545 241 1454 | f 545 18 416 1455 | f 241 416 51 1456 | f 114 242 546 1457 | f 242 51 420 1458 | f 546 420 20 1459 | f 18 547 415 1460 | f 547 115 246 1461 | f 415 246 49 1462 | f 115 548 244 1463 | f 548 4 549 1464 | f 244 549 116 1465 | f 49 245 417 1466 | f 245 116 550 1467 | f 417 550 19 1468 | f 20 419 551 1469 | f 419 50 249 1470 | f 551 249 118 1471 | f 50 418 247 1472 | f 418 19 552 1473 | f 247 552 117 1474 | f 118 248 554 1475 | f 248 117 553 1476 | f 554 553 6 1477 | f 4 548 555 1478 | f 548 115 252 1479 | f 555 252 119 1480 | f 115 547 250 1481 | f 547 18 422 1482 | f 250 422 54 1483 | f 119 251 556 1484 | f 251 54 426 1485 | f 556 426 22 1486 | f 18 545 421 1487 | f 545 113 255 1488 | f 421 255 52 1489 | f 113 543 253 1490 | f 543 3 557 1491 | f 253 557 120 1492 | f 52 254 423 1493 | f 254 120 558 1494 | f 423 558 21 1495 | f 22 425 559 1496 | f 425 53 258 1497 | f 559 258 122 1498 | f 53 424 256 1499 | f 424 21 560 1500 | f 256 560 121 1501 | f 122 257 562 1502 | f 257 121 561 1503 | f 562 561 8 1504 | f 5 563 564 1505 | f 563 123 261 1506 | f 564 261 124 1507 | f 123 565 259 1508 | f 565 23 428 1509 | f 259 428 57 1510 | f 124 260 566 1511 | f 260 57 432 1512 | f 566 432 25 1513 | f 23 567 427 1514 | f 567 125 264 1515 | f 427 264 55 1516 | f 125 568 262 1517 | f 568 6 569 1518 | f 262 569 126 1519 | f 55 263 429 1520 | f 263 126 570 1521 | f 429 570 24 1522 | f 25 431 571 1523 | f 431 56 267 1524 | f 571 267 128 1525 | f 56 430 265 1526 | f 430 24 572 1527 | f 265 572 127 1528 | f 128 266 574 1529 | f 266 127 573 1530 | f 574 573 11 1531 | f 6 568 575 1532 | f 568 125 270 1533 | f 575 270 129 1534 | f 125 567 268 1535 | f 567 23 434 1536 | f 268 434 60 1537 | f 129 269 576 1538 | f 269 60 438 1539 | f 576 438 27 1540 | f 23 565 433 1541 | f 565 123 273 1542 | f 433 273 58 1543 | f 123 563 271 1544 | f 563 5 577 1545 | f 271 577 130 1546 | f 58 272 435 1547 | f 272 130 578 1548 | f 435 578 26 1549 | f 27 437 579 1550 | f 437 59 276 1551 | f 579 276 132 1552 | f 59 436 274 1553 | f 436 26 580 1554 | f 274 580 131 1555 | f 132 275 582 1556 | f 275 131 581 1557 | f 582 581 9 1558 | f 7 583 584 1559 | f 583 133 279 1560 | f 584 279 134 1561 | f 133 585 277 1562 | f 585 28 440 1563 | f 277 440 63 1564 | f 134 278 586 1565 | f 278 63 444 1566 | f 586 444 30 1567 | f 28 587 439 1568 | f 587 135 282 1569 | f 439 282 61 1570 | f 135 588 280 1571 | f 588 8 589 1572 | f 280 589 136 1573 | f 61 281 441 1574 | f 281 136 590 1575 | f 441 590 29 1576 | f 30 443 591 1577 | f 443 62 285 1578 | f 591 285 138 1579 | f 62 442 283 1580 | f 442 29 592 1581 | f 283 592 137 1582 | f 138 284 594 1583 | f 284 137 593 1584 | f 594 593 10 1585 | f 8 588 595 1586 | f 588 135 288 1587 | f 595 288 139 1588 | f 135 587 286 1589 | f 587 28 446 1590 | f 286 446 66 1591 | f 139 287 596 1592 | f 287 66 450 1593 | f 596 450 32 1594 | f 28 585 445 1595 | f 585 133 291 1596 | f 445 291 64 1597 | f 133 583 289 1598 | f 583 7 597 1599 | f 289 597 140 1600 | f 64 290 447 1601 | f 290 140 598 1602 | f 447 598 31 1603 | f 32 449 599 1604 | f 449 65 294 1605 | f 599 294 142 1606 | f 65 448 292 1607 | f 448 31 600 1608 | f 292 600 141 1609 | f 142 293 602 1610 | f 293 141 601 1611 | f 602 601 12 1612 | f 9 603 604 1613 | f 603 143 297 1614 | f 604 297 144 1615 | f 143 605 295 1616 | f 605 33 452 1617 | f 295 452 69 1618 | f 144 296 606 1619 | f 296 69 456 1620 | f 606 456 35 1621 | f 33 607 451 1622 | f 607 145 300 1623 | f 451 300 67 1624 | f 145 608 298 1625 | f 608 10 609 1626 | f 298 609 146 1627 | f 67 299 453 1628 | f 299 146 610 1629 | f 453 610 34 1630 | f 35 455 611 1631 | f 455 68 303 1632 | f 611 303 148 1633 | f 68 454 301 1634 | f 454 34 612 1635 | f 301 612 147 1636 | f 148 302 614 1637 | f 302 147 613 1638 | f 614 613 3 1639 | f 10 608 615 1640 | f 608 145 306 1641 | f 615 306 149 1642 | f 145 607 304 1643 | f 607 33 458 1644 | f 304 458 72 1645 | f 149 305 616 1646 | f 305 72 462 1647 | f 616 462 37 1648 | f 33 605 457 1649 | f 605 143 309 1650 | f 457 309 70 1651 | f 143 603 307 1652 | f 603 9 617 1653 | f 307 617 150 1654 | f 70 308 459 1655 | f 308 150 618 1656 | f 459 618 36 1657 | f 37 461 619 1658 | f 461 71 312 1659 | f 619 312 152 1660 | f 71 460 310 1661 | f 460 36 620 1662 | f 310 620 151 1663 | f 152 311 622 1664 | f 311 151 621 1665 | f 622 621 1 1666 | f 11 623 624 1667 | f 623 153 315 1668 | f 624 315 154 1669 | f 153 625 313 1670 | f 625 38 464 1671 | f 313 464 75 1672 | f 154 314 626 1673 | f 314 75 468 1674 | f 626 468 40 1675 | f 38 627 463 1676 | f 627 155 318 1677 | f 463 318 73 1678 | f 155 628 316 1679 | f 628 12 629 1680 | f 316 629 156 1681 | f 73 317 465 1682 | f 317 156 630 1683 | f 465 630 39 1684 | f 40 467 631 1685 | f 467 74 321 1686 | f 631 321 158 1687 | f 74 466 319 1688 | f 466 39 632 1689 | f 319 632 157 1690 | f 158 320 634 1691 | f 320 157 633 1692 | f 634 633 2 1693 | f 12 628 635 1694 | f 628 155 324 1695 | f 635 324 159 1696 | f 155 627 322 1697 | f 627 38 470 1698 | f 322 470 78 1699 | f 159 323 636 1700 | f 323 78 474 1701 | f 636 474 42 1702 | f 38 625 469 1703 | f 625 153 327 1704 | f 469 327 76 1705 | f 153 623 325 1706 | f 623 11 637 1707 | f 325 637 160 1708 | f 76 326 471 1709 | f 326 160 638 1710 | f 471 638 41 1711 | f 42 473 639 1712 | f 473 77 330 1713 | f 639 330 162 1714 | f 77 472 328 1715 | f 472 41 640 1716 | f 328 640 161 1717 | f 162 329 642 1718 | f 329 161 641 1719 | f 642 641 4 1720 | f 1 621 529 1721 | f 621 151 333 1722 | f 529 333 106 1723 | f 151 620 331 1724 | f 620 36 476 1725 | f 331 476 81 1726 | f 106 332 530 1727 | f 332 81 480 1728 | f 530 480 14 1729 | f 36 618 475 1730 | f 618 150 336 1731 | f 475 336 79 1732 | f 150 617 334 1733 | f 617 9 581 1734 | f 334 581 131 1735 | f 79 335 477 1736 | f 335 131 580 1737 | f 477 580 26 1738 | f 14 479 532 1739 | f 479 80 339 1740 | f 532 339 107 1741 | f 80 478 337 1742 | f 478 26 578 1743 | f 337 578 130 1744 | f 107 338 533 1745 | f 338 130 577 1746 | f 533 577 5 1747 | f 1 535 622 1748 | f 535 109 342 1749 | f 622 342 152 1750 | f 109 536 340 1751 | f 536 17 482 1752 | f 340 482 84 1753 | f 152 341 619 1754 | f 341 84 486 1755 | f 619 486 37 1756 | f 17 539 481 1757 | f 539 112 345 1758 | f 481 345 82 1759 | f 112 542 343 1760 | f 542 7 584 1761 | f 343 584 134 1762 | f 82 344 483 1763 | f 344 134 586 1764 | f 483 586 30 1765 | f 37 485 616 1766 | f 485 83 348 1767 | f 616 348 149 1768 | f 83 484 346 1769 | f 484 30 591 1770 | f 346 591 138 1771 | f 149 347 615 1772 | f 347 138 594 1773 | f 615 594 10 1774 | f 2 524 634 1775 | f 524 104 351 1776 | f 634 351 158 1777 | f 104 526 349 1778 | f 526 15 488 1779 | f 349 488 87 1780 | f 158 350 631 1781 | f 350 87 492 1782 | f 631 492 40 1783 | f 15 531 487 1784 | f 531 108 354 1785 | f 487 354 85 1786 | f 108 534 352 1787 | f 534 5 564 1788 | f 352 564 124 1789 | f 85 353 489 1790 | f 353 124 566 1791 | f 489 566 25 1792 | f 40 491 626 1793 | f 491 86 357 1794 | f 626 357 154 1795 | f 86 490 355 1796 | f 490 25 571 1797 | f 355 571 128 1798 | f 154 356 624 1799 | f 356 128 574 1800 | f 624 574 11 1801 | f 2 633 537 1802 | f 633 157 360 1803 | f 537 360 110 1804 | f 157 632 358 1805 | f 632 39 494 1806 | f 358 494 90 1807 | f 110 359 538 1808 | f 359 90 498 1809 | f 538 498 16 1810 | f 39 630 493 1811 | f 630 156 363 1812 | f 493 363 88 1813 | f 156 629 361 1814 | f 629 12 601 1815 | f 361 601 141 1816 | f 88 362 495 1817 | f 362 141 600 1818 | f 495 600 31 1819 | f 16 497 540 1820 | f 497 89 366 1821 | f 540 366 111 1822 | f 89 496 364 1823 | f 496 31 598 1824 | f 364 598 140 1825 | f 111 365 541 1826 | f 365 140 597 1827 | f 541 597 7 1828 | f 3 544 614 1829 | f 544 114 369 1830 | f 614 369 148 1831 | f 114 546 367 1832 | f 546 20 500 1833 | f 367 500 93 1834 | f 148 368 611 1835 | f 368 93 504 1836 | f 611 504 35 1837 | f 20 551 499 1838 | f 551 118 372 1839 | f 499 372 91 1840 | f 118 554 370 1841 | f 554 6 575 1842 | f 370 575 129 1843 | f 91 371 501 1844 | f 371 129 576 1845 | f 501 576 27 1846 | f 35 503 606 1847 | f 503 92 375 1848 | f 606 375 144 1849 | f 92 502 373 1850 | f 502 27 579 1851 | f 373 579 132 1852 | f 144 374 604 1853 | f 374 132 582 1854 | f 604 582 9 1855 | f 3 613 557 1856 | f 613 147 378 1857 | f 557 378 120 1858 | f 147 612 376 1859 | f 612 34 506 1860 | f 376 506 96 1861 | f 120 377 558 1862 | f 377 96 510 1863 | f 558 510 21 1864 | f 34 610 505 1865 | f 610 146 381 1866 | f 505 381 94 1867 | f 146 609 379 1868 | f 609 10 593 1869 | f 379 593 137 1870 | f 94 380 507 1871 | f 380 137 592 1872 | f 507 592 29 1873 | f 21 509 560 1874 | f 509 95 384 1875 | f 560 384 121 1876 | f 95 508 382 1877 | f 508 29 590 1878 | f 382 590 136 1879 | f 121 383 561 1880 | f 383 136 589 1881 | f 561 589 8 1882 | f 4 641 549 1883 | f 641 161 387 1884 | f 549 387 116 1885 | f 161 640 385 1886 | f 640 41 512 1887 | f 385 512 99 1888 | f 116 386 550 1889 | f 386 99 516 1890 | f 550 516 19 1891 | f 41 638 511 1892 | f 638 160 390 1893 | f 511 390 97 1894 | f 160 637 388 1895 | f 637 11 573 1896 | f 388 573 127 1897 | f 97 389 513 1898 | f 389 127 572 1899 | f 513 572 24 1900 | f 19 515 552 1901 | f 515 98 393 1902 | f 552 393 117 1903 | f 98 514 391 1904 | f 514 24 570 1905 | f 391 570 126 1906 | f 117 392 553 1907 | f 392 126 569 1908 | f 553 569 6 1909 | f 4 555 642 1910 | f 555 119 396 1911 | f 642 396 162 1912 | f 119 556 394 1913 | f 556 22 518 1914 | f 394 518 102 1915 | f 162 395 639 1916 | f 395 102 522 1917 | f 639 522 42 1918 | f 22 559 517 1919 | f 559 122 399 1920 | f 517 399 100 1921 | f 122 562 397 1922 | f 562 8 595 1923 | f 397 595 139 1924 | f 100 398 519 1925 | f 398 139 596 1926 | f 519 596 32 1927 | f 42 521 636 1928 | f 521 101 402 1929 | f 636 402 159 1930 | f 101 520 400 1931 | f 520 32 599 1932 | f 400 599 142 1933 | f 159 401 635 1934 | f 401 142 602 1935 | f 635 602 12 1936 | # 1280 faces, 0 coords texture 1937 | 1938 | # End of File -------------------------------------------------------------------------------- /dib-render/test-all.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in 11 | # all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | # DEALINGS IN THE SOFTWARE. 20 | 21 | from __future__ import print_function 22 | from __future__ import division 23 | 24 | import torch 25 | import torchvision.utils as vutils 26 | 27 | import os 28 | import numpy as np 29 | from config import get_args 30 | 31 | import sys 32 | sys.path.append('../utils/') 33 | sys.path.append('./render_cuda') 34 | 35 | from dataloader.dataloader_multiview_blender import get_data_loaders 36 | 37 | from utils.utils_mesh import loadobj, \ 38 | face2edge, edge2face, face2pneimtx, mtx2tfsparse, savemesh, savemeshcolor 39 | 40 | from utils.utils_perspective import camera_info_batch, perspectiveprojectionnp 41 | 42 | from model.modelcolor import Ecoder 43 | 44 | sys.path.append('../utils/render') 45 | from renderfunc_cluster import rendermeshcolor as rendermesh 46 | from render_cuda.utils_render_color2 import linear 47 | 48 | ############################################ 49 | # Make experiments reproducible 50 | torch.manual_seed(123456) 51 | np.random.seed(123456) 52 | eps = 1e-15 53 | 54 | #################### 55 | # Make directories # 56 | # - Samples # 57 | # - Checkpoints # 58 | #################### 59 | 60 | args = get_args() 61 | args.img_dim = 64 62 | args.batch_size = 64 63 | 64 | FILELIST = args.filelist 65 | IMG_DIM = args.img_dim 66 | N_CHANNELS = args.img_channels 67 | BATCH_SIZE = args.batch_size 68 | TOTAL_EPOCH = args.epoch 69 | ITERS_PER_LOG = args.iter_log 70 | ITERS_PER_SAMPLE = args.iter_sample 71 | ITERS_PER_MODEL = args.iter_model 72 | VERBOSE = True 73 | 74 | print('------------------') 75 | print('| Configurations |') 76 | print('------------------') 77 | print('') 78 | print('IMG_DIM: {}'.format(IMG_DIM)) 79 | print('N_CHANNELS: {}'.format(N_CHANNELS)) 80 | print('BATCH_SIZE: {}'.format(BATCH_SIZE)) 81 | print('FILELIST: {}'.format(FILELIST)) 82 | print('TOTAL_EPOCH: {}'.format(TOTAL_EPOCH)) 83 | print('ITERS_PER_LOG: {}'.format(ITERS_PER_LOG)) 84 | print('VERBOSE: {}'.format(VERBOSE)) 85 | print('') 86 | 87 | ########################################################## 88 | lossname = args.loss 89 | cameramode = args.camera 90 | viewnum = args.view 91 | 92 | test_iter_num = args.iter 93 | svfolder = args.svfolder 94 | g_model_dir = args.g_model_dir 95 | data_folder = args.data_folder 96 | 97 | #################### 98 | # Load the dataset # 99 | #################### 100 | 101 | # for test, only one view 102 | viewnum = 1 103 | 104 | filelist = FILELIST 105 | imsz = IMG_DIM 106 | numworkers = args.thread 107 | data = get_data_loaders(filelist, imsz, viewnum, mode='test', 108 | bs=BATCH_SIZE, numworkers=numworkers,data_folder=data_folder) 109 | 110 | ############################################ 111 | # load obj template, the sphere and blender camera 112 | # sphere.obj: A unit sphere with 642 vertices and 1280 faces 113 | pointnp_px3, facenp_fx3 = loadobj('sphere.obj') 114 | edge_ex2 = face2edge(facenp_fx3) 115 | edgef_ex2 = edge2face(facenp_fx3, edge_ex2) 116 | pneimtx = face2pneimtx(facenp_fx3) 117 | 118 | pnum = pointnp_px3.shape[0] 119 | fnum = facenp_fx3.shape[0] 120 | enum = edge_ex2.shape[0] 121 | 122 | camfovy = 49.13434207744484 / 180.0 * np.pi 123 | camprojmtx = perspectiveprojectionnp(camfovy, 1.0) 124 | 125 | ################################################ 126 | # Define device, neural nets, optimizers, etc. # 127 | ################################################ 128 | 129 | # Automatic GPU/CPU device placement 130 | device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu') 131 | 132 | # Create models 133 | g_model_im2mesh = Ecoder(N_CHANNELS, N_KERNELS=5, BATCH_SIZE=BATCH_SIZE, IMG_DIM=IMG_DIM, VERBOSE=VERBOSE).to(device) 134 | 135 | ############ 136 | # Training # 137 | ############ 138 | 139 | def test(iter_num=-1): 140 | print('Begin Testing!') 141 | # Try loading the latest existing checkpoints based on iter_num 142 | g_model_im2mesh.load_state_dict(torch.load(g_model_dir), strict=True) 143 | g_model_im2mesh.eval() 144 | print('Loaded the latest checkpoints from {}'.format(g_model_dir)) 145 | 146 | # Directory for test samples 147 | model_iter = iter_num 148 | if not os.path.exists(os.path.join(svfolder, 'test-%d' % model_iter)): 149 | print('Make Save Dir') 150 | os.makedirs(os.path.join(svfolder, 'test-%d' % model_iter)) 151 | 152 | global pointnp_px3, facenp_fx3, edgef_ex2, pneimtx 153 | global camprojmtx 154 | global cameramode, lossname 155 | 156 | p = pointnp_px3 157 | pmax = np.max(p, axis=0, keepdims=True) 158 | pmin = np.min(p, axis=0, keepdims=True) 159 | pmiddle = (pmax + pmin) / 2 160 | p = p - pmiddle 161 | 162 | assert cameramode == 'per', 'now we only support perspective' 163 | pointnp_px3 = p * 0.35 164 | 165 | tfp_1xpx3 = torch.from_numpy(pointnp_px3).to(device).view(1, pnum, 3) 166 | tff_fx3 = torch.from_numpy(facenp_fx3).to(device) 167 | 168 | tfcamproj = torch.from_numpy(camprojmtx).to(device) 169 | 170 | iou = {} 171 | catenum = {} 172 | cates = '02691156,02828884,02933112,02958343,03001627,03211117,03636649,03691459,04090263,04256520,04379243,04401088,04530566' 173 | cates = cates.split(',') 174 | for ca in cates: 175 | iou[ca] = 0 176 | catenum[ca] = 0 177 | 178 | iter_num = 0 179 | for i, da in enumerate(data): 180 | if da is None: 181 | continue 182 | iter_num += 1 183 | tfims = [] 184 | tfcams = [] 185 | 186 | for j in range(viewnum): 187 | imnp = da['view%d' % j]['im'] 188 | bs = imnp.shape[0] 189 | imnp_bxcxhxw = np.transpose(imnp, [0, 3, 1, 2]) 190 | tfim_bx4xhxw = torch.from_numpy(imnp_bxcxhxw).to(device) 191 | tfims.append(tfim_bx4xhxw) 192 | # camera 193 | camrot_bx3x3 = da['view%d' % j]['camrot'] 194 | campos_bx3 = da['view%d' % j]['campos'] 195 | tfcamrot = torch.from_numpy(camrot_bx3x3).to(device) 196 | tfcampos = torch.from_numpy(campos_bx3).to(device) 197 | tfcameras = [tfcamrot, tfcampos, tfcamproj] 198 | tfcams.append(tfcameras) 199 | 200 | ########################################3 201 | with torch.no_grad(): 202 | meshes = [] 203 | meshcolors = [] 204 | meshmovs = [] 205 | 206 | # generate j-th mesh 207 | for j in range(viewnum): 208 | meshmov_bxp3, mc_bxp3 = g_model_im2mesh(tfims[j][:, :args.img_channels,:,:]) 209 | meshmov_bxpx3 = meshmov_bxp3.view(bs, -1, 3) 210 | mesh_bxpx3 = meshmov_bxpx3 + tfp_1xpx3 211 | mc_bxpx3 = mc_bxp3.view(bs, -1, 3) 212 | 213 | # normalize 214 | mesh_max = torch.max(mesh_bxpx3, dim=1, keepdim=True)[0] 215 | mesh_min = torch.min(mesh_bxpx3, dim=1, keepdim=True)[0] 216 | mesh_middle = (mesh_min + mesh_max) / 2 217 | mesh_bxpx3 = mesh_bxpx3 - mesh_middle 218 | 219 | bs = mesh_bxpx3.shape[0] 220 | mesh_biggest = torch.max(mesh_bxpx3.view(bs, -1), dim=1)[0] 221 | mesh_bxpx3 = mesh_bxpx3 / mesh_biggest.view(bs, 1, 1) * 0.45 222 | 223 | meshes.append(mesh_bxpx3) 224 | meshcolors.append(mc_bxpx3) 225 | meshmovs.append(meshmov_bxpx3) 226 | 227 | meshesvv = [] 228 | mcvv = [] 229 | tfcamsvv = [[], [], tfcamproj] 230 | gtvv = [] 231 | 232 | # use j-th mesh 233 | for j in range(viewnum): 234 | # generate with k-th camera 235 | for k in range(viewnum): 236 | mesh_bxpx3 = meshes[j] 237 | mc_bxpx3 = meshcolors[j] 238 | meshesvv.append(mesh_bxpx3) 239 | mcvv.append(mc_bxpx3) 240 | tfcamrot_bx3x3, tfcampos_bx3, _ = tfcams[k] 241 | tfcamsvv[0].append(tfcamrot_bx3x3) 242 | tfcamsvv[1].append(tfcampos_bx3) 243 | # k-th camera, k-th image 244 | tfim_bx4xhxw = tfims[k] 245 | gtvv.append(tfim_bx4xhxw) 246 | 247 | mesh_vvbxpx3 = torch.cat(meshesvv) 248 | mc_vvbxpx3 = torch.cat(mcvv) 249 | tfcamsvv[0] = torch.cat(tfcamsvv[0]) 250 | tfcamsvv[1] = torch.cat(tfcamsvv[1]) 251 | tmp, _ = rendermesh(mesh_vvbxpx3, mc_vvbxpx3, tff_fx3, tfcamsvv, linear) 252 | impre_vvbxhxwx3, silpred_vvbxhxwx1 = tmp 253 | 254 | # Compute loss 255 | tfim_vvbx4xhxw = torch.cat(gtvv) 256 | 257 | impre_vvbx3xhxw = impre_vvbxhxwx3.permute(0, 3, 1, 2) 258 | imgt_vvbx3xhxw = tfim_vvbx4xhxw[:, :3, :, :] 259 | colloss = 3 * torch.mean(torch.abs(impre_vvbx3xhxw - imgt_vvbx3xhxw)) 260 | 261 | silpred_vvbx1xhxw = silpred_vvbxhxwx1.view(viewnum * viewnum * bs, 1, IMG_DIM, IMG_DIM) 262 | silgt = tfim_vvbx4xhxw[:, 3:4, :, :] 263 | 264 | silmul = silpred_vvbx1xhxw * silgt 265 | siladd = silpred_vvbx1xhxw + silgt 266 | silmul = silmul.view(bs, -1) 267 | siladd = siladd.view(bs, -1) 268 | iouup = torch.sum(silmul, dim=1) 269 | ioudown = torch.sum(siladd - silmul, dim=1) 270 | iouneg = iouup / (ioudown + eps) 271 | silloss = 1.0 - torch.mean(iouneg) 272 | 273 | iouneg = iouneg.detach().cpu().numpy() 274 | for cid, ca in enumerate(da['cate']): 275 | iou[ca] += iouneg[cid] 276 | catenum[ca] += 1 277 | 278 | if iter_num % 100 == 0: 279 | # Print statistics 280 | print('epo: {}, iter: {}, color_loss: {}, iou_loss: {}'. \ 281 | format(0, iter_num, colloss, silloss)) 282 | 283 | if iter_num % ITERS_PER_SAMPLE == ITERS_PER_SAMPLE - 1: 284 | silpred_vvbx3xhxw = silpred_vvbx1xhxw.repeat(1, 3, 1, 1) 285 | silgt_vvbx3xhxw = tfim_vvbx4xhxw[:, 3:4, :, :].repeat(1, 3, 1, 1) 286 | re = torch.cat((imgt_vvbx3xhxw, silgt_vvbx3xhxw, impre_vvbx3xhxw, silpred_vvbx3xhxw), dim=3) 287 | real_samples_dir = os.path.join(svfolder, 'test-%d' % model_iter, 'real_{:0>7d}.png'.format(iter_num)) 288 | vutils.save_image(re, real_samples_dir, normalize=False) 289 | 290 | meshnp_bxpx3 = mesh_vvbxpx3.detach().cpu().numpy() 291 | meshcolnp_bxpx3 = mc_vvbxpx3.detach().cpu().numpy() 292 | meshcolnp_bxpx3[meshcolnp_bxpx3 < 0] = 0 293 | meshcolnp_bxpx3[meshcolnp_bxpx3 > 1] = 1 294 | meshcolnp_bxpx3 = meshcolnp_bxpx3[..., ::-1] 295 | 296 | for j, meshnp_px3 in enumerate(meshnp_bxpx3): 297 | catname, md5name, numname = da['cate'][j], da['md5'][j], da['view0']['num'][j] 298 | mesh_dir = os.path.join(svfolder, 'test-%d' % model_iter, 299 | '{}/{}/{}.obj'.format(catname, md5name, numname)) 300 | if not os.path.exists(os.path.join(svfolder, 'test-%d' % model_iter, catname, md5name)): 301 | os.makedirs(os.path.join(svfolder, 'test-%d' % model_iter, catname, md5name)) 302 | tmo = meshnp_px3 303 | savemeshcolor(tmo, facenp_fx3, mesh_dir, meshcolnp_bxpx3[j]) 304 | 305 | re = [] 306 | for ca in cates: 307 | iou[ca] /= catenum[ca] 308 | print('{}, {}'.format(ca, iou[ca])) 309 | re.append([int(ca), iou[ca]]) 310 | re = np.array(re, dtype=np.float32) 311 | path = os.path.join(svfolder, 'test-%d.npy' % test_iter_num) 312 | np.save(file=path, arr=re) 313 | 314 | ############################################################### 315 | if __name__ == '__main__': 316 | test() -------------------------------------------------------------------------------- /dib-render/voxelization.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in 11 | # all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | # DEALINGS IN THE SOFTWARE. 20 | 21 | import threading 22 | import queue 23 | import glob 24 | import os 25 | import argparse 26 | 27 | def get_args(): 28 | parser = argparse.ArgumentParser(description='voxelize') 29 | parser.add_argument('--folder', type=str, default='debug', 30 | help='save folder') 31 | args = parser.parse_args() 32 | return args 33 | 34 | SHARE_Q = queue.Queue() 35 | _WORKER_THREAD_NUM = 80 36 | 37 | class MyThread(threading.Thread): 38 | def __init__(self, func): 39 | super(MyThread, self).__init__() 40 | self.func = func 41 | 42 | def run(self): 43 | self.func() 44 | 45 | def worker(): 46 | global SHARE_Q 47 | while not SHARE_Q.empty(): 48 | item = SHARE_Q.get() 49 | item2 = item.replace('.obj', '.binvox') 50 | io_redirect = ' > /dev/null 2>&1' 51 | if os.path.isfile(item) and (not os.path.isfile(item2)): 52 | cmd = "./binvox -d 32 -cb -dc -aw -pb -t binvox %s %s" % (item, io_redirect) 53 | os.system(cmd) 54 | 55 | def main(): 56 | global SHARE_Q 57 | threads = [] 58 | args = get_args() 59 | folder = args.folder 60 | 61 | print('==> get all predictions') 62 | print(folder) 63 | meshfiles = glob.glob('%s/*/*/*.obj' % folder) 64 | print('Length mesh files: ', len(meshfiles)) 65 | 66 | print ('==> starting ') 67 | for i, fl in enumerate(meshfiles): 68 | SHARE_Q.put(fl) 69 | 70 | for i in range(_WORKER_THREAD_NUM): 71 | thread = MyThread(worker) 72 | thread.start() 73 | threads.append(thread) 74 | 75 | for thread in threads: 76 | thread.join() 77 | 78 | if __name__ == '__main__': 79 | main() -------------------------------------------------------------------------------- /docs/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/.DS_Store -------------------------------------------------------------------------------- /docs/figures/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/figures/.DS_Store -------------------------------------------------------------------------------- /docs/figures/bird/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/figures/bird/.DS_Store -------------------------------------------------------------------------------- /docs/figures/bird/allsup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/figures/bird/allsup.png -------------------------------------------------------------------------------- /docs/figures/bird/car.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/figures/bird/car.png -------------------------------------------------------------------------------- /docs/figures/car2.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/figures/car2.jpeg -------------------------------------------------------------------------------- /docs/figures/car_1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/figures/car_1.jpeg -------------------------------------------------------------------------------- /docs/figures/change-tex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/figures/change-tex.png -------------------------------------------------------------------------------- /docs/figures/combine_all_compare/02691156_e2612c366bd11e305e9e2656aff7dd5b_19_blender_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/figures/combine_all_compare/02691156_e2612c366bd11e305e9e2656aff7dd5b_19_blender_0.png -------------------------------------------------------------------------------- /docs/figures/combine_all_compare/02958343_cf3e2dd9595c223e82b157e7120744ea_4_blender_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/figures/combine_all_compare/02958343_cf3e2dd9595c223e82b157e7120744ea_4_blender_2.png -------------------------------------------------------------------------------- /docs/figures/combine_all_compare/02958343_d1dcddb5b1d7404dd9b0c189eb588ce6_4_blender_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/figures/combine_all_compare/02958343_d1dcddb5b1d7404dd9b0c189eb588ce6_4_blender_1.png -------------------------------------------------------------------------------- /docs/figures/combine_all_compare/02958343_d3869e2527ff032623276041d0efb3cb_3_blender_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/figures/combine_all_compare/02958343_d3869e2527ff032623276041d0efb3cb_3_blender_5.png -------------------------------------------------------------------------------- /docs/figures/combine_all_compare/02958343_e3c5a93775413a49ae3723ee0aa76826_6_blender_19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/figures/combine_all_compare/02958343_e3c5a93775413a49ae3723ee0aa76826_6_blender_19.png -------------------------------------------------------------------------------- /docs/figures/combine_all_compare/03001627_d52e7e39bed3ed954f62c7a282978009_10_blender_23.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/figures/combine_all_compare/03001627_d52e7e39bed3ed954f62c7a282978009_10_blender_23.png -------------------------------------------------------------------------------- /docs/figures/combine_all_compare/03001627_e3bc0a03103cf84e7a471a654ffbc436_8_blender_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/figures/combine_all_compare/03001627_e3bc0a03103cf84e7a471a654ffbc436_8_blender_1.png -------------------------------------------------------------------------------- /docs/figures/combine_all_compare/03001627_eda8edcd64072b0db784faac204319d9_7_blender_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/figures/combine_all_compare/03001627_eda8edcd64072b0db784faac204319d9_7_blender_8.png -------------------------------------------------------------------------------- /docs/figures/combine_all_compare/03211117_e1d73ee44f1d2422b5fb024f65f6da_4_blender_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/figures/combine_all_compare/03211117_e1d73ee44f1d2422b5fb024f65f6da_4_blender_5.png -------------------------------------------------------------------------------- /docs/figures/combine_all_compare/03211117_e46e45f94470b45ad1924b802935a37a_17_blender_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/figures/combine_all_compare/03211117_e46e45f94470b45ad1924b802935a37a_17_blender_1.png -------------------------------------------------------------------------------- /docs/figures/combine_all_compare/03691459_cc88df1c3cfac12a99db62650613bd48_17_blender_14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/figures/combine_all_compare/03691459_cc88df1c3cfac12a99db62650613bd48_17_blender_14.png -------------------------------------------------------------------------------- /docs/figures/combine_all_compare/03691459_cc88df1c3cfac12a99db62650613bd48_17_blender_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/figures/combine_all_compare/03691459_cc88df1c3cfac12a99db62650613bd48_17_blender_4.png -------------------------------------------------------------------------------- /docs/figures/combine_all_compare/03691459_cc88df1c3cfac12a99db62650613bd48_17_blender_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/figures/combine_all_compare/03691459_cc88df1c3cfac12a99db62650613bd48_17_blender_5.png -------------------------------------------------------------------------------- /docs/figures/combine_all_compare/04090263_d945ecdf7613bfe0c7da109ecb5068a0_4_blender_17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/figures/combine_all_compare/04090263_d945ecdf7613bfe0c7da109ecb5068a0_4_blender_17.png -------------------------------------------------------------------------------- /docs/figures/combine_all_compare/04256520_f05f6b3e7c0afdb352fc7e973ba7787_11_blender_15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/figures/combine_all_compare/04256520_f05f6b3e7c0afdb352fc7e973ba7787_11_blender_15.png -------------------------------------------------------------------------------- /docs/figures/combine_all_compare/04256520_f43414acdca3878674c5bf7a74b1b6df_22_blender_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/figures/combine_all_compare/04256520_f43414acdca3878674c5bf7a74b1b6df_22_blender_16.png -------------------------------------------------------------------------------- /docs/figures/combine_all_compare/04256520_fcf30cec3180c05da5f9d52c12457194_22_blender_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/figures/combine_all_compare/04256520_fcf30cec3180c05da5f9d52c12457194_22_blender_1.png -------------------------------------------------------------------------------- /docs/figures/combine_all_compare/04379243_cfa823ee81496f5912b57997414c1d71_4_blender_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/figures/combine_all_compare/04379243_cfa823ee81496f5912b57997414c1d71_4_blender_5.png -------------------------------------------------------------------------------- /docs/figures/combine_all_compare/04379243_e2571e4eba2d9f5eab610b0c94236463_20_blender_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/figures/combine_all_compare/04379243_e2571e4eba2d9f5eab610b0c94236463_20_blender_4.png -------------------------------------------------------------------------------- /docs/figures/combine_all_compare/04379243_e48675e37096a6898527e24d5de49fe6_1_blender_13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/figures/combine_all_compare/04379243_e48675e37096a6898527e24d5de49fe6_1_blender_13.png -------------------------------------------------------------------------------- /docs/figures/combine_all_compare/04379243_ed8dd7ac0d865ac686f1a0f58f951001_15_blender_11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/figures/combine_all_compare/04379243_ed8dd7ac0d865ac686f1a0f58f951001_15_blender_11.png -------------------------------------------------------------------------------- /docs/figures/combine_all_compare/04401088_e8d826158072a6bf1455397a420729a1_21_blender_20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/figures/combine_all_compare/04401088_e8d826158072a6bf1455397a420729a1_21_blender_20.png -------------------------------------------------------------------------------- /docs/figures/combine_all_compare/04530566_f18739a47f1f08e08510ad9ae6ed36b6_22_blender_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/figures/combine_all_compare/04530566_f18739a47f1f08e08510ad9ae6ed36b6_22_blender_3.png -------------------------------------------------------------------------------- /docs/figures/comp_nm3r_sup/db45ce3926c3ac69e8d8ad3bdef6aca2_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/figures/comp_nm3r_sup/db45ce3926c3ac69e8d8ad3bdef6aca2_8.png -------------------------------------------------------------------------------- /docs/figures/comp_nm3r_sup/dbded0816afdfcf776ad064d1c5fdd7c_14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/figures/comp_nm3r_sup/dbded0816afdfcf776ad064d1c5fdd7c_14.png -------------------------------------------------------------------------------- /docs/figures/comp_nm3r_sup/dc8aef6a8c88997a582e5e3e7771ea25_19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/figures/comp_nm3r_sup/dc8aef6a8c88997a582e5e3e7771ea25_19.png -------------------------------------------------------------------------------- /docs/figures/comp_nm3r_sup/df8000281bcfdf0754f3692df239bb9b_15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/figures/comp_nm3r_sup/df8000281bcfdf0754f3692df239bb9b_15.png -------------------------------------------------------------------------------- /docs/figures/comp_nm3r_sup/e00fde4225d166b1ce929ad7e848003e_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/figures/comp_nm3r_sup/e00fde4225d166b1ce929ad7e848003e_2.png -------------------------------------------------------------------------------- /docs/figures/comp_nm3r_sup/e0b9bb886c578be86e9dcc2d1ea2784d_22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/figures/comp_nm3r_sup/e0b9bb886c578be86e9dcc2d1ea2784d_22.png -------------------------------------------------------------------------------- /docs/figures/comp_nm3r_sup/e625eb804f2fb6caa26598ab726b7540_23.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/figures/comp_nm3r_sup/e625eb804f2fb6caa26598ab726b7540_23.png -------------------------------------------------------------------------------- /docs/figures/comp_nm3r_sup/eb27ff8c450c2c5f393cd3bb7e57a291_11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/figures/comp_nm3r_sup/eb27ff8c450c2c5f393cd3bb7e57a291_11.png -------------------------------------------------------------------------------- /docs/figures/comp_nm3r_sup/ef05b5fa8e2377f8fa7a46166f316347_10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/figures/comp_nm3r_sup/ef05b5fa8e2377f8fa7a46166f316347_10.png -------------------------------------------------------------------------------- /docs/figures/comp_nm3r_sup/efd87861810e35ca921cb81cb1632a5e_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/figures/comp_nm3r_sup/efd87861810e35ca921cb81cb1632a5e_6.png -------------------------------------------------------------------------------- /docs/figures/comp_nm3r_sup/fc85555afe23abcc5b716151669cefc7_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/figures/comp_nm3r_sup/fc85555afe23abcc5b716151669cefc7_16.png -------------------------------------------------------------------------------- /docs/figures/gan_out.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/figures/gan_out.mp4 -------------------------------------------------------------------------------- /docs/figures/model2a-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/figures/model2a-2.png -------------------------------------------------------------------------------- /docs/figures/texture_supp.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/figures/texture_supp.pdf -------------------------------------------------------------------------------- /docs/figures/update-out.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/figures/update-out.mp4 -------------------------------------------------------------------------------- /docs/figures/w_wo.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/figures/w_wo.pdf -------------------------------------------------------------------------------- /docs/files/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/files/.DS_Store -------------------------------------------------------------------------------- /docs/files/bib.tex: -------------------------------------------------------------------------------- 1 | @article{chen2019learning, 2 | title={Learning to Predict 3D Objects with an Interpolation-based Differentiable Renderer}, 3 | author={Chen, Wenzheng and Gao, Jun and Ling, Huan and Smith, Edward and Lehtinen, Jaakko and Jacobson, Alec and Fidler, Sanja}, 4 | journal={arXiv preprint arXiv:1908.01210}, 5 | year={2019} 6 | } -------------------------------------------------------------------------------- /docs/files/diff_shader.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/files/diff_shader.pdf -------------------------------------------------------------------------------- /docs/files/paper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/files/paper.png -------------------------------------------------------------------------------- /docs/files/supplement.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nv-tlabs/DIB-R/602f6d620d6c919a1a4892504112b971299b86dd/docs/files/supplement.pdf -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Redirecting to https://research.nvidia.com/labs/toronto-ai/DIB-R/ 4 | 5 | 6 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | numpy==1.16.2 2 | tensorboardX==1.6 3 | torch==1.1.0 4 | torchvision==0.2.1 -------------------------------------------------------------------------------- /utils/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in 11 | # all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | # DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /utils/dataloader/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in 11 | # all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | # DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /utils/dataloader/dataloader_multiview_blender.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in 11 | # all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | # DEALINGS IN THE SOFTWARE. 20 | 21 | from __future__ import print_function 22 | from __future__ import division 23 | 24 | import os 25 | import numpy as np 26 | import cv2 27 | 28 | from torch.utils.data import Dataset, DataLoader 29 | 30 | ####################################################### 31 | class DataProvider(Dataset): 32 | def __init__(self, file_list, 33 | imsz=-1, 34 | viewnum=1, 35 | mode='train', 36 | datadebug=False, 37 | classes=None, 38 | data_folder=None): 39 | 40 | self.mode = mode 41 | self.datadebug = datadebug 42 | 43 | self.imsz = imsz 44 | self.viewum = viewnum 45 | 46 | assert self.viewum >= 1 47 | 48 | self.folder = data_folder 49 | self.camfolder = data_folder 50 | print(self.folder) 51 | 52 | self.pkl_list = [] 53 | with open(file_list, 'r') as f: 54 | while True: 55 | line = f.readline().strip() 56 | if not line: 57 | break 58 | self.pkl_list.append(line) 59 | 60 | if not classes is None: 61 | self.filter_class(classes) 62 | self.imnum = len(self.pkl_list) 63 | print('imnum {}'.format(self.imnum)) 64 | 65 | self.imnum = len(self.pkl_list) 66 | print(self.pkl_list[0]) 67 | print(self.pkl_list[-1]) 68 | print('imnum {}'.format(self.imnum)) 69 | 70 | def __len__(self): 71 | return self.imnum 72 | 73 | def __getitem__(self, idx): 74 | return self.prepare_instance(idx) 75 | 76 | def filter_class(self, classes): 77 | new_pkl_list = [] 78 | for pkl in self.pkl_list: 79 | for cls in classes: 80 | if cls in pkl: 81 | new_pkl_list.append(pkl) 82 | break 83 | self.pkl_list = new_pkl_list 84 | 85 | def load_im_cam(self, pkl_path, catagory, md5name, num): 86 | imname = '%s/%s/%s/%d.png' % (self.folder, catagory, md5name, num) 87 | img = cv2.imread(imname, cv2.IMREAD_UNCHANGED) 88 | img = cv2.resize(img, (self.imsz, self.imsz)) 89 | im_hxwx4 = img.astype('float32') / 255.0 90 | 91 | rotntxname = '%s/%s/%s/%d.npy' % (self.camfolder, catagory, md5name, num) 92 | rotmtx_4x4 = np.load(rotntxname).astype(np.float32) 93 | rotmx = rotmtx_4x4[:3, :3] 94 | transmtx = rotmtx_4x4[:3, 3:4] 95 | transmtx = -np.matmul(rotmx.T, transmtx) 96 | renderparam = (rotmx, transmtx) 97 | 98 | return im_hxwx4, renderparam 99 | 100 | def prepare_instance(self, idx): 101 | re = {} 102 | re['valid'] = True 103 | 104 | pkl_path = self.pkl_list[idx] 105 | _, fname = os.path.split(pkl_path) 106 | fname, _ = os.path.splitext(fname) 107 | catagory, md5name, numname = fname.split('_') 108 | re['cate'] = catagory 109 | re['md5'] = md5name 110 | 111 | try: 112 | if self.viewum == 1: 113 | num = int(numname) 114 | im_hxwx4, renderparam = self.load_im_cam(pkl_path, catagory, md5name, num) 115 | 116 | i = 0 117 | re['view%d' % i] = {} 118 | re['view%d' % i]['camrot'] = renderparam[0] 119 | re['view%d' % i]['campos'] = renderparam[1] 120 | re['view%d' % i]['im'] = im_hxwx4 121 | re['view%d' % i]['ori_im'] = np.copy(im_hxwx4) 122 | re['view%d' % i]['num'] = num 123 | else: 124 | for i in range(self.viewum): 125 | # 24 views in total 126 | num = np.random.randint(24) 127 | im_hxwx4, renderparam = self.load_im_cam(pkl_path, catagory, md5name, num) 128 | re['view%d' % i] = {} 129 | re['view%d' % i]['camrot'] = renderparam[0] 130 | re['view%d' % i]['campos'] = renderparam[1][:, 0] 131 | re['view%d' % i]['im'] = im_hxwx4 132 | re['view%d' % i]['ori_im'] = np.copy(im_hxwx4) 133 | re['view%d' % i]['num'] = num 134 | except: 135 | re['valid'] = False 136 | return re 137 | 138 | return re 139 | 140 | 141 | def collate_fn(batch_list): 142 | collated = {} 143 | batch_list = [data for data in batch_list if data['valid']] 144 | if len(batch_list) == 0: 145 | return None 146 | 147 | keys = ['cate', 'md5'] 148 | for key in keys: 149 | val = [item[key] for item in batch_list] 150 | collated[key] = val 151 | 152 | viewnum = len(batch_list[0].keys()) - 3 153 | keys = ['im', 'camrot', 'campos', 'num'] 154 | for i in range(viewnum): 155 | collated['view%d' % i] = {} 156 | for key in keys: 157 | val = [item['view%d' % i][key] for item in batch_list] 158 | val = np.stack(val, axis=0) 159 | collated['view%d' % i][key] = val 160 | 161 | return collated 162 | 163 | 164 | def get_data_loaders(filelist, imsz, viewnum, mode, bs, numworkers, classes=None, data_folder=None): 165 | print('Building dataloaders') 166 | dataset_train = DataProvider(filelist, imsz, viewnum, 167 | mode=mode, datadebug=False, classes=classes, data_folder=data_folder) 168 | 169 | if mode == 'test': 170 | shuffle = False 171 | else: 172 | shuffle = True 173 | 174 | train_loader = DataLoader(dataset_train, batch_size=bs, 175 | shuffle=shuffle, num_workers=numworkers, collate_fn=collate_fn) 176 | 177 | print('train num {}'.format(len(dataset_train))) 178 | print('train iter'.format(len(train_loader))) 179 | 180 | return train_loader -------------------------------------------------------------------------------- /utils/model/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in 11 | # all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | # DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /utils/model/modelcolor.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in 11 | # all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | # DEALINGS IN THE SOFTWARE. 20 | 21 | from __future__ import print_function 22 | from __future__ import division 23 | 24 | import torch 25 | import torch.nn as nn 26 | import torch.nn.functional as TorchF 27 | 28 | 29 | ################################# 30 | class Ecoder(nn.Module): 31 | def __init__(self, N_CHANNELS, N_KERNELS, \ 32 | BATCH_SIZE, IMG_DIM, VERBOSE=False, pred_cam=False): 33 | super(Ecoder, self).__init__() 34 | block1 = self.convblock(N_CHANNELS, 64, N_KERNELS, stride=2, pad=2) 35 | block2 = self.convblock(64, 128, N_KERNELS, stride=2, pad=2) 36 | block3 = self.convblock(128, 256, N_KERNELS, stride=2, pad=2) 37 | 38 | linear1 = self.linearblock(16384, 1024) 39 | linear2 = self.linearblock(1024, 1024) 40 | self.linear3 = nn.Linear(1024, 1024) 41 | self.pred_cam = pred_cam 42 | if self.pred_cam: 43 | self.pred_cam_linear_1 = nn.Linear(1024, 128) 44 | self.pred_cam_linear_2 = nn.Linear(128, 9 + 3) 45 | 46 | linear4 = self.linearblock(1024, 1024) 47 | linear5 = self.linearblock(1024, 2048) 48 | self.linear6 = nn.Linear(2048, 1926) 49 | 50 | linear42 = self.linearblock(1024, 1024) 51 | linear52 = self.linearblock(1024, 2048) 52 | self.linear62 = nn.Linear(2048, 1926) 53 | 54 | ################################################# 55 | all_blocks = block1 + block2 + block3 56 | self.encoder1 = nn.Sequential(*all_blocks) 57 | 58 | all_blocks = linear1 + linear2 59 | self.encoder2 = nn.Sequential(*all_blocks) 60 | 61 | all_blocks = linear4 + linear5 62 | self.decoder = nn.Sequential(*all_blocks) 63 | 64 | all_blocks = linear42 + linear52 65 | self.decoder2 = nn.Sequential(*all_blocks) 66 | 67 | # Initialize with Xavier Glorot 68 | for m in self.modules(): 69 | if isinstance(m, nn.ConvTranspose2d) \ 70 | or isinstance(m, nn.Linear) \ 71 | or isinstance(object, nn.Conv2d): 72 | nn.init.xavier_uniform_(m.weight) 73 | nn.init.normal_(m.weight, mean=0, std=0.001) 74 | 75 | # Free some memory 76 | del all_blocks, block1, block2, block3, \ 77 | linear1, linear2, linear4, linear5, \ 78 | linear42, linear52 79 | 80 | # Print summary 81 | if VERBOSE: 82 | self.summary(BATCH_SIZE, N_CHANNELS, IMG_DIM) 83 | 84 | def convblock(self, indim, outdim, ker, stride, pad): 85 | block2 = [ 86 | nn.Conv2d(indim, outdim, ker, stride, pad), 87 | nn.BatchNorm2d(outdim), 88 | nn.ReLU() 89 | ] 90 | return block2 91 | 92 | def linearblock(self, indim, outdim): 93 | block2 = [ 94 | nn.Linear(indim, outdim), 95 | nn.BatchNorm1d(outdim), 96 | nn.ReLU() 97 | ] 98 | return block2 99 | 100 | def forward(self, x): 101 | 102 | for layer in self.encoder1: 103 | x = layer(x) 104 | 105 | bnum = x.shape[0] 106 | x = x.view(bnum, -1) # flatten the encoder1 output 107 | for layer in self.encoder2: 108 | x = layer(x) 109 | x = self.linear3(x) 110 | if self.pred_cam: 111 | cam_x = TorchF.relu(self.pred_cam_linear_1(x)) 112 | pred_cam = self.pred_cam_linear_2(cam_x) 113 | x1 = x 114 | for layer in self.decoder: 115 | x1 = layer(x1) 116 | x1 = self.linear6(x1) 117 | 118 | x2 = x 119 | for layer in self.decoder2: 120 | x2 = layer(x2) 121 | x2 = self.linear62(x2) 122 | if self.pred_cam: 123 | return x1, x2, pred_cam 124 | return x1, x2 125 | 126 | def summary(self, BATCH_SIZE, N_CHANNELS, IMG_DIM): 127 | 128 | x = torch.zeros(BATCH_SIZE, N_CHANNELS, IMG_DIM, IMG_DIM) 129 | 130 | # Print the title in a good design 131 | # for easy recognition. 132 | print() 133 | summary_title = '| {} Summary |'.format(self.__class__.__name__) 134 | for _ in range(len(summary_title)): 135 | print('-', end='') 136 | print() 137 | print(summary_title) 138 | for _ in range(len(summary_title)): 139 | print('-', end='') 140 | print('\n') 141 | 142 | # Run forward pass while not tracking history on 143 | # tape using `torch.no_grad()` for printing the 144 | # output shape of each neural layer operation. 145 | print('Input: {}'.format(x.size())) 146 | with torch.no_grad(): 147 | 148 | for layer in self.encoder1: 149 | x = layer(x) 150 | print('Out: {} \tLayer: {}'.format(x.size(), layer)) 151 | 152 | bnum = x.shape[0] 153 | x = x.view(bnum, -1) # flatten the encoder1 output 154 | print('Out: {} \tlayer: {}'.format(x.size(), 'Reshape: Flatten')) 155 | 156 | for layer in self.encoder2: 157 | x = layer(x) 158 | print('Out: {} \tLayer: {}'.format(x.size(), layer)) 159 | 160 | x = self.linear3(x) 161 | print('Out: {} \tLayer: {}'.format(x.size(), self.linear3)) 162 | 163 | for layer in self.decoder: 164 | x = layer(x) 165 | print('Out: {} \tLayer: {}'.format(x.size(), layer)) 166 | 167 | x = self.linear6(x) 168 | print('Out: {} \tLayer: {}'.format(x.size(), self.linear6)) 169 | 170 | 171 | if __name__ == '__main__': 172 | 173 | ################################### 174 | BATCH_SIZE = 64 175 | IMG_DIM = 64 176 | N_CHANNELS = 4 177 | N_KERNELS = 5 178 | VERBOSE = True 179 | 180 | model = Ecoder(N_CHANNELS, N_KERNELS, BATCH_SIZE, IMG_DIM, VERBOSE) 181 | -------------------------------------------------------------------------------- /utils/render/renderfunc_cluster.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in 11 | # all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | # DEALINGS IN THE SOFTWARE. 20 | 21 | from __future__ import print_function 22 | from __future__ import division 23 | 24 | import torch 25 | import torch.nn 26 | import torch.autograd 27 | import torch.nn as nn 28 | from torch.autograd import Function 29 | 30 | 31 | ################################################################ 32 | def p2f(points_bxpx3, faces_fx3, cameras): 33 | # perspective, use just one camera 34 | camera_rot_bx3x3, camera_pos_bx3, camera_proj_3x1 = cameras 35 | cameratrans_rot_bx3x3 = camera_rot_bx3x3.permute(0, 2, 1) 36 | 37 | # follow pixel2mesh!!! 38 | # new_p = cam_mat * (old_p - cam_pos) 39 | points_bxpx3 = points_bxpx3 - camera_pos_bx3.view(-1, 1, 3) 40 | points_bxpx3 = torch.matmul(points_bxpx3, cameratrans_rot_bx3x3) 41 | 42 | camera_proj_bx1x3 = camera_proj_3x1.view(-1, 1, 3) 43 | xy_bxpx3 = points_bxpx3 * camera_proj_bx1x3 44 | xy_bxpx2 = xy_bxpx3[:, :, :2] / xy_bxpx3[:, :, 2:3] 45 | 46 | ########################################################## 47 | # 1 points 48 | pf0_bxfx3 = points_bxpx3[:, faces_fx3[:, 0], :] 49 | pf1_bxfx3 = points_bxpx3[:, faces_fx3[:, 1], :] 50 | pf2_bxfx3 = points_bxpx3[:, faces_fx3[:, 2], :] 51 | points3d_bxfx9 = torch.cat((pf0_bxfx3, pf1_bxfx3, pf2_bxfx3), dim=2) 52 | 53 | xy_f0 = xy_bxpx2[:, faces_fx3[:, 0], :] 54 | xy_f1 = xy_bxpx2[:, faces_fx3[:, 1], :] 55 | xy_f2 = xy_bxpx2[:, faces_fx3[:, 2], :] 56 | points2d_bxfx6 = torch.cat((xy_f0, xy_f1, xy_f2), dim=2) 57 | 58 | ###################################################### 59 | # 2 normals 60 | v01_bxfx3 = pf1_bxfx3 - pf0_bxfx3 61 | v02_bxfx3 = pf2_bxfx3 - pf0_bxfx3 62 | 63 | # bs cannot be 3, if it is 3, we must specify dim 64 | normal_bxfx3 = torch.cross(v01_bxfx3, v02_bxfx3, dim=2) 65 | normalz_bxfx1 = normal_bxfx3[:, :, 2:3] 66 | # normalz_bxfx1 = torch.abs(normalz_bxfx1) 67 | 68 | normallen_bxfx1 = torch.sqrt(torch.sum(normal_bxfx3 ** 2, dim=2, keepdim=True)) 69 | normal1_bxfx3 = normal_bxfx3 / (normallen_bxfx1 + 1e-15) 70 | 71 | return points3d_bxfx9, points2d_bxfx6, normalz_bxfx1, normal1_bxfx3 72 | 73 | 74 | ################################################################### 75 | 76 | def rendermeshcolor(points_bxpx3, tfcolor_bxpx3, faces_fx3, cameras, func): 77 | 78 | points3d_bxfx9, points2d_bxfx6, normalz_bxfx1, normal1_bxfx3 = p2f(points_bxpx3, faces_fx3, cameras) 79 | 80 | ###################################################### 81 | # 3 colors 82 | c0 = tfcolor_bxpx3[:, faces_fx3[:, 0], :] 83 | c1 = tfcolor_bxpx3[:, faces_fx3[:, 1], :] 84 | c2 = tfcolor_bxpx3[:, faces_fx3[:, 2], :] 85 | 86 | tfcolor_bxfx9 = torch.cat((c0, c1, c2), dim=2) 87 | 88 | return func(points3d_bxfx9, points2d_bxfx6, normalz_bxfx1, tfcolor_bxfx9), normal1_bxfx3 89 | 90 | 91 | class RenderMeshColor(nn.Module): 92 | def __init__(self, func): 93 | super(RenderMeshColor, self).__init__() 94 | self.func = func 95 | 96 | def forward(self, points_bxpx3, tfcolor_bxpx3, faces_fx3, cameras_1, cameras_2, cameras_3): 97 | faces_fx3 = faces_fx3.squeeze(0) 98 | cameras = [cameras_1, cameras_2, cameras_3.squeeze(0)] 99 | points3d_bxfx9, points2d_bxfx6, normalz_bxfx1, normal1_bxfx3 = p2f(points_bxpx3, faces_fx3, cameras) 100 | 101 | ###################################################### 102 | # 3 colors 103 | c0 = tfcolor_bxpx3[:, faces_fx3[:, 0], :] 104 | c1 = tfcolor_bxpx3[:, faces_fx3[:, 1], :] 105 | c2 = tfcolor_bxpx3[:, faces_fx3[:, 2], :] 106 | tfcolor_bxfx9 = torch.cat((c0, c1, c2), dim=2) 107 | 108 | return self.func(points3d_bxfx9, points2d_bxfx6, normalz_bxfx1, tfcolor_bxfx9), normal1_bxfx3 -------------------------------------------------------------------------------- /utils/utils/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in 11 | # all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | # DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /utils/utils/utils_mesh.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in 11 | # all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | # DEALINGS IN THE SOFTWARE. 20 | 21 | import os 22 | import torch 23 | import numpy as np 24 | 25 | ################################################################## 26 | # faces begin from 0!!! 27 | def face2edge(facenp_fx3): 28 | ''' 29 | facenp_fx3, int32 30 | return edgenp_ex2, int32 31 | ''' 32 | f1 = facenp_fx3[:, 0:1] 33 | f2 = facenp_fx3[:, 1:2] 34 | f3 = facenp_fx3[:, 2:3] 35 | e1 = np.concatenate((f1, f1, f2), axis=0) 36 | e2 = np.concatenate((f2, f3, f3), axis=0) 37 | edgenp_ex2 = np.concatenate((e1, e2), axis=1) 38 | # sort & unique 39 | edgenp_ex2 = np.sort(edgenp_ex2, axis=1) 40 | edgenp_ex2 = np.unique(edgenp_ex2, axis=0) 41 | return edgenp_ex2 42 | 43 | 44 | def edge2face(facenp_fx3, edgenp_ex2): 45 | ''' 46 | facenp_fx3, int32 47 | edgenp_ex2, int32 48 | return edgenp_ex2, int32 49 | this edge is indexed by face 50 | ''' 51 | fnum = facenp_fx3.shape[0] 52 | enum = edgenp_ex2.shape[0] 53 | 54 | facesort = np.sort(facenp_fx3, axis=1) 55 | edgesort = np.sort(edgenp_ex2, axis=1) 56 | edgere_ex2 = np.zeros_like(edgesort) 57 | for i in range(enum): 58 | pbe, pen = edgesort[i] 59 | eid = 0 60 | for j in range(fnum): 61 | f1, f2, f3 = facesort[j] 62 | cond1 = f1 == pbe and f2 == pen 63 | cond2 = f1 == pbe and f3 == pen 64 | cond3 = f2 == pbe and f3 == pen 65 | if cond1 or cond2 or cond3: 66 | edgere_ex2[i, eid] = j 67 | eid += 1 68 | 69 | return edgere_ex2 70 | 71 | 72 | def face2pneimtx(facenp_fx3): 73 | ''' 74 | facenp_fx3, int32 75 | return pointneighbourmtx, pxp, float32 76 | will normalize! 77 | assume it is a good mesh 78 | every point has more than one neighbour 79 | ''' 80 | pnum = np.max(facenp_fx3) + 1 81 | pointneighbourmtx = np.zeros(shape=(pnum, pnum), dtype=np.float32) 82 | for i in range(3): 83 | be = i 84 | en = (i + 1) % 3 85 | idx1 = facenp_fx3[:, be] 86 | idx2 = facenp_fx3[:, en] 87 | pointneighbourmtx[idx1, idx2] = 1 88 | pointneighbourmtx[idx2, idx1] = 1 89 | pointneicount = np.sum(pointneighbourmtx, axis=1, keepdims=True) 90 | assert np.all(pointneicount > 0) 91 | pointneighbourmtx /= pointneicount 92 | return pointneighbourmtx 93 | 94 | 95 | def face2pfmtx(facenp_fx3): 96 | ''' 97 | facenp_fx3, int32 98 | reutrn pfmtx, pxf, float32 99 | ''' 100 | pnum = np.max(facenp_fx3) + 1 101 | fnum = facenp_fx3.shape[0] 102 | pfmtx = np.zeros(shape=(pnum, fnum), dtype=np.float32) 103 | for i, f in enumerate(facenp_fx3): 104 | pfmtx[f[0], i] = 1 105 | pfmtx[f[1], i] = 1 106 | pfmtx[f[2], i] = 1 107 | return pfmtx 108 | 109 | 110 | # upsample new points 111 | def meshresample(pointnp_px3, facenp_fx3, edgenp_ex2): 112 | p1 = pointnp_px3[edgenp_ex2[:, 0], :] 113 | p2 = pointnp_px3[edgenp_ex2[:, 1], :] 114 | pmid = (p1 + p2) / 2 115 | point2np_px3 = np.concatenate((pointnp_px3, pmid), axis=0) 116 | 117 | # delete f 118 | # add 4 new faces 119 | face2np_fx3 = [] 120 | pnum = np.max(facenp_fx3) + 1 121 | for f in facenp_fx3: 122 | p1, p2, p3 = f 123 | p12 = (edgenp_ex2 == (min(p1, p2), max(p1, p2))).all(axis=1).nonzero()[0] + pnum 124 | p23 = (edgenp_ex2 == (min(p2, p3), max(p2, p3))).all(axis=1).nonzero()[0] + pnum 125 | p31 = (edgenp_ex2 == (min(p3, p1), max(p3, p1))).all(axis=1).nonzero()[0] + pnum 126 | face2np_fx3.append([p1, p12, p31]) 127 | face2np_fx3.append([p12, p2, p23]) 128 | face2np_fx3.append([p31, p23, p3]) 129 | face2np_fx3.append([p12, p23, p31]) 130 | face2np_fx3 = np.array(face2np_fx3, dtype=np.int64) 131 | return point2np_px3, face2np_fx3 132 | 133 | 134 | def mtx2tfsparse(mtx): 135 | m, n = mtx.shape 136 | rows, cols = np.nonzero(mtx) 137 | # N = rows.shape[0] 138 | # value = np.ones(shape=(N,), dtype=np.float32) 139 | value = mtx[rows, cols] 140 | v = torch.FloatTensor(value) 141 | i = torch.LongTensor(np.stack((rows, cols), axis=0)) 142 | tfspmtx = torch.sparse.FloatTensor(i, v, torch.Size([m, n])) 143 | return tfspmtx 144 | 145 | 146 | ################################################################ 147 | def loadobj(meshfile): 148 | 149 | v = [] 150 | f = [] 151 | meshfp = open(meshfile, 'r') 152 | for line in meshfp.readlines(): 153 | data = line.strip().split(' ') 154 | data = [da for da in data if len(da) > 0] 155 | if len(data) != 4: 156 | continue 157 | if data[0] == 'v': 158 | v.append([float(d) for d in data[1:]]) 159 | if data[0] == 'f': 160 | data = [da.split('/')[0] for da in data] 161 | f.append([int(d) for d in data[1:]]) 162 | meshfp.close() 163 | 164 | # torch need int64 165 | facenp_fx3 = np.array(f, dtype=np.int64) - 1 166 | pointnp_px3 = np.array(v, dtype=np.float32) 167 | return pointnp_px3, facenp_fx3 168 | 169 | 170 | def loadobjcolor(meshfile): 171 | v = [] 172 | f = [] 173 | meshfp = open(meshfile, 'r') 174 | for line in meshfp.readlines(): 175 | data = line.strip().split(' ') 176 | data = [da for da in data if len(da) > 0] 177 | if len(data) != 4 and len(data) != 7: 178 | continue 179 | if data[0] == 'v': 180 | v.append([float(d) for d in data[1:4]]) 181 | if data[0] == 'f': 182 | data = [da.split('/')[0] for da in data] 183 | f.append([int(d) for d in data[1:]]) 184 | meshfp.close() 185 | 186 | # torch need int64 187 | facenp_fx3 = np.array(f, dtype=np.int64) - 1 188 | pointnp_px3 = np.array(v, dtype=np.float32) 189 | return pointnp_px3, facenp_fx3 190 | 191 | 192 | def loadobjtex(meshfile): 193 | 194 | v = [] 195 | vt = [] 196 | f = [] 197 | ft = [] 198 | meshfp = open(meshfile, 'r') 199 | for line in meshfp.readlines(): 200 | data = line.strip().split(' ') 201 | data = [da for da in data if len(da) > 0] 202 | if len(data) != 4: 203 | continue 204 | if data[0] == 'v': 205 | v.append([float(d) for d in data[1:]]) 206 | if data[0] == 'vt': 207 | vt.append([float(d) for d in data[1:]]) 208 | if data[0] == 'f': 209 | data = [da.split('/') for da in data] 210 | f.append([int(d[0]) for d in data[1:]]) 211 | ft.append([int(d[1]) for d in data[1:]]) 212 | meshfp.close() 213 | 214 | # torch need int64 215 | facenp_fx3 = np.array(f, dtype=np.int64) - 1 216 | ftnp_fx3 = np.array(ft, dtype=np.int64) - 1 217 | pointnp_px3 = np.array(v, dtype=np.float32) 218 | uvs = np.array(vt, dtype=np.float32)[:, :2] 219 | return pointnp_px3, facenp_fx3, uvs, ftnp_fx3 220 | 221 | 222 | def savemesh(pointnp_px3, facenp_fx3, fname, partinfo=None): 223 | 224 | if partinfo is None: 225 | fid = open(fname, 'w') 226 | for pidx, p in enumerate(pointnp_px3): 227 | pp = p 228 | fid.write('v %f %f %f\n' % (pp[0], pp[1], pp[2])) 229 | for f in facenp_fx3: 230 | f1 = f + 1 231 | fid.write('f %d %d %d\n' % (f1[0], f1[1], f1[2])) 232 | fid.close() 233 | else: 234 | fid = open(fname, 'w') 235 | for pidx, p in enumerate(pointnp_px3): 236 | if partinfo[pidx, -1] == 0: 237 | pp = p 238 | color = [1, 0, 0] 239 | else: 240 | pp = p 241 | color = [0, 0, 1] 242 | fid.write('v %f %f %f %f %f %f\n' % (pp[0], pp[1], pp[2], color[0], color[1], color[2])) 243 | for f in facenp_fx3: 244 | f1 = f + 1 245 | fid.write('f %d %d %d\n' % (f1[0], f1[1], f1[2])) 246 | fid.close() 247 | return 248 | 249 | 250 | def savemeshcolor(pointnp_px3, facenp_fx3, fname, color_px3=None): 251 | 252 | if color_px3 is None: 253 | fid = open(fname, 'w') 254 | for pidx, p in enumerate(pointnp_px3): 255 | pp = p 256 | fid.write('v %f %f %f\n' % (pp[0], pp[1], pp[2])) 257 | for f in facenp_fx3: 258 | f1 = f + 1 259 | fid.write('f %d %d %d\n' % (f1[0], f1[1], f1[2])) 260 | fid.close() 261 | else: 262 | fid = open(fname, 'w') 263 | for pidx, p in enumerate(pointnp_px3): 264 | pp = p 265 | color = color_px3[pidx] 266 | fid.write('v %f %f %f %f %f %f\n' % (pp[0], pp[1], pp[2], color[0], color[1], color[2])) 267 | for f in facenp_fx3: 268 | f1 = f + 1 269 | fid.write('f %d %d %d\n' % (f1[0], f1[1], f1[2])) 270 | fid.close() 271 | return 272 | 273 | 274 | def p2f(points_px3, faces_fx3): 275 | 276 | ########################################################## 277 | # 1 points 278 | pf0_bxfx3 = points_px3[faces_fx3[:, 0], :] 279 | pf1_bxfx3 = points_px3[faces_fx3[:, 1], :] 280 | pf2_bxfx3 = points_px3[faces_fx3[:, 2], :] 281 | # import ipdb 282 | # ipdb.set_trace() 283 | points3d_bxfx9 = np.concatenate((pf0_bxfx3, pf1_bxfx3, pf2_bxfx3), axis= -1) 284 | 285 | return points3d_bxfx9 286 | 287 | 288 | def savemesh_facecolor(pointnp_px3, facenp_fx3, fname, color_px9=None): 289 | pointnp_px9 = p2f(pointnp_px3, facenp_fx3) 290 | # import ipdb 291 | # ipdb.set_trace() 292 | 293 | fid = open(fname, 'w') 294 | for pidx, p in enumerate(pointnp_px9): 295 | pp = p 296 | color = color_px9[pidx] 297 | for i_point in range(3): 298 | fid.write('v %f %f %f %f %f %f\n' % (pp[i_point * 3 + 0], pp[i_point * 3 + 1], pp[i_point * 3 + 2], 299 | color[i_point * 3], color[i_point * 3 + 1], color[i_point * 3 + 2])) 300 | for f_idx in range(pointnp_px9.shape[0]): 301 | fid.write('f %d %d %d\n' % (f_idx * 3 + 1, f_idx * 3 + 2, f_idx * 3 + 3)) 302 | 303 | fid.close() 304 | def saveobjscale(meshfile, scale, maxratio, shift=None): 305 | 306 | mname, prefix = os.path.splitext(meshfile) 307 | mnamenew = '%s-%.2f%s' % (mname, maxratio, prefix) 308 | 309 | meshfp = open(meshfile, 'r') 310 | meshfp2 = open(mnamenew, 'w') 311 | for line in meshfp.readlines(): 312 | data = line.strip().split(' ') 313 | data = [da for da in data if len(da) > 0] 314 | if len(data) != 4: 315 | meshfp2.write(line) 316 | continue 317 | else: 318 | if data[0] == 'v': 319 | p = [scale * float(d) for d in data[1:]] 320 | meshfp2.write('v %f %f %f\n' % (p[0], p[1], p[2])) 321 | else: 322 | meshfp2.write(line) 323 | continue 324 | 325 | meshfp.close() 326 | meshfp2.close() 327 | 328 | return 329 | 330 | -------------------------------------------------------------------------------- /utils/utils/utils_perspective.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in 11 | # all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | # DEALINGS IN THE SOFTWARE. 20 | 21 | import numpy as np 22 | 23 | 24 | def unit(v): 25 | norm = np.linalg.norm(v) 26 | if norm == 0: 27 | return v 28 | return v / norm 29 | 30 | 31 | def lookatnp(eye_3x1, center_3x1, up_3x1): 32 | # 3 variables should be length 1 33 | camz = center_3x1 - eye_3x1 34 | camz /= np.sqrt(np.sum(camz ** 2)) 35 | camx = np.cross(camz[:, 0], up_3x1[:, 0]).reshape(3, 1) 36 | camy = np.cross(camx[:, 0], camz[:, 0]).reshape(3, 1) 37 | 38 | # they are not guaranteed to be 1!!! 39 | mtx = np.concatenate([unit(camx), unit(camy), -camz], axis=1).transpose() 40 | shift = -np.matmul(mtx, eye_3x1) 41 | return mtx, shift 42 | 43 | 44 | def camera_info(param): 45 | theta = np.deg2rad(param[0]) 46 | phi = np.deg2rad(param[1]) 47 | 48 | camY = param[3] * np.sin(phi) 49 | temp = param[3] * np.cos(phi) 50 | camX = temp * np.cos(theta) 51 | camZ = temp * np.sin(theta) 52 | cam_pos = np.array([camX, camY, camZ]) 53 | 54 | axisZ = cam_pos.copy() 55 | axisY = np.array([0, 1, 0], dtype=np.float32) 56 | axisX = np.cross(axisY, axisZ) 57 | axisY = np.cross(axisZ, axisX) 58 | 59 | # cam_mat = np.array([axisX, axisY, axisZ]) 60 | cam_mat = np.array([unit(axisX), unit(axisY), unit(axisZ)]) 61 | 62 | return cam_mat, cam_pos 63 | 64 | 65 | ##################################################### 66 | def perspectiveprojectionnp(fovy, ratio=1.0, near=0.01, far=10.0): 67 | 68 | tanfov = np.tan(fovy / 2.0) 69 | # top = near * tanfov 70 | # right = ratio * top 71 | # mtx = [near / right, 0, 0, 0, \ 72 | # 0, near / top, 0, 0, \ 73 | # 0, 0, -(far+near)/(far-near), -2*far*near/(far-near), \ 74 | # 0, 0, -1, 0] 75 | mtx = [[1.0 / (ratio * tanfov), 0, 0, 0], \ 76 | [0, 1.0 / tanfov, 0, 0], \ 77 | [0, 0, -(far + near) / (far - near), -2 * far * near / (far - near)], \ 78 | [0, 0, -1.0, 0]] 79 | # return np.array(mtx, dtype=np.float32) 80 | return np.array([[1.0 / (ratio * tanfov)], [1.0 / tanfov], [-1]], dtype=np.float32) 81 | 82 | 83 | ##################################################### 84 | def camera_info_batch(param_bx4): 85 | 86 | bnum = param_bx4.shape[0] 87 | cam_mat_bx3x3 = [] 88 | cam_pos_bx3 = [] 89 | 90 | for i in range(bnum): 91 | param = param_bx4[i] 92 | cam_mat, cam_pos = camera_info(param) 93 | cam_mat_bx3x3.append(cam_mat) 94 | cam_pos_bx3.append(cam_pos) 95 | 96 | cam_mat_bx3x3 = np.stack(cam_mat_bx3x3, axis=0) 97 | cam_pos_bx3 = np.stack(cam_pos_bx3, axis=0) 98 | 99 | return cam_mat_bx3x3, cam_pos_bx3 100 | 101 | --------------------------------------------------------------------------------