Showing preview only (572K chars total). Download the full file or copy to clipboard to get everything.
Repository: chrischoy/DeepGlobalRegistration
Branch: master
Commit: 1f4871d4c616
Files: 51
Total size: 550.5 KB
Directory structure:
gitextract_yw16jmpj/
├── .gitignore
├── LICENSE
├── README.md
├── assets/
│ └── results.npz
├── config.py
├── core/
│ ├── __init__.py
│ ├── correspondence.py
│ ├── deep_global_registration.py
│ ├── knn.py
│ ├── loss.py
│ ├── metrics.py
│ ├── registration.py
│ └── trainer.py
├── dataloader/
│ ├── base_loader.py
│ ├── data_loaders.py
│ ├── inf_sampler.py
│ ├── kitti_loader.py
│ ├── split/
│ │ ├── test_3dmatch.txt
│ │ ├── test_kitti.txt
│ │ ├── test_modelnet40.txt
│ │ ├── test_scan2cad.txt
│ │ ├── train_3dmatch.txt
│ │ ├── train_kitti.txt
│ │ ├── train_modelnet40.txt
│ │ ├── train_scan2cad.txt
│ │ ├── val_3dmatch.txt
│ │ ├── val_kitti.txt
│ │ ├── val_modelnet40.txt
│ │ └── val_scan2cad.txt
│ ├── threedmatch_loader.py
│ └── transforms.py
├── demo.py
├── model/
│ ├── __init__.py
│ ├── common.py
│ ├── pyramidnet.py
│ ├── residual_block.py
│ ├── resunet.py
│ └── simpleunet.py
├── requirements.txt
├── scripts/
│ ├── analyze_stats.py
│ ├── download_3dmatch.sh
│ ├── test_3dmatch.py
│ ├── test_kitti.py
│ ├── train_3dmatch.sh
│ └── train_kitti.sh
├── train.py
└── util/
├── __init__.py
├── file.py
├── integration.py
├── pointcloud.py
└── timer.py
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
# Temp files
.DS_Store
__pycache__
*.swp
*.swo
*.orig
.idea
outputs/
*.pyc
*.npy
*.pdf
util/*.sh
checkpoints
# *.npz
3dmatch/
tmp.txt
output.ply
bunny.ply
test.sh
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2020 Chris Choy (chrischoy@ai.stanford.edu), Wei Dong (weidong@andrew.cmu.edu)
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Please cite the following papers if you use any part of the code.
```
@inproceedings{choy2020deep,
title={Deep Global Registration},
author={Choy, Christopher and Dong, Wei and Koltun, Vladlen},
booktitle={Proceedings of the IEEE Conference on Computer Vision and Pattern Recognition},
year={2020}
}
@inproceedings{choy2019fully,
author = {Choy, Christopher and Park, Jaesik and Koltun, Vladlen},
title = {Fully Convolutional Geometric Features},
booktitle = {ICCV},
year = {2019},
}
@inproceedings{choy20194d,
title={4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural Networks},
author={Choy, Christopher and Gwak, JunYoung and Savarese, Silvio},
booktitle={Proceedings of the IEEE Conference on Computer Vision and Pattern Recognition},
year={2019}
}
```
================================================
FILE: README.md
================================================
# Deep Global Registration
## Introduction
This repository contains python scripts for training and testing [Deep Global Registration, CVPR 2020 Oral](https://node1.chrischoy.org/data/publications/dgr/DGR.pdf).
Deep Global Registration (DGR) proposes a differentiable framework for pairwise registration of real-world 3D scans. DGR consists of the following three modules:
- a 6-dimensional convolutional network for correspondence confidence prediction
- a differentiable Weighted Procrustes algorithm for closed-form pose estimation
- a robust gradient-based SE(3) optimizer for pose refinement.
For more details, please check out
- [CVPR 2020 oral paper](https://node1.chrischoy.org/data/publications/dgr/DGR.pdf)
- [1min oral video](https://youtu.be/stzgn6DkozA)
- [Full CVPR oral presentation](https://youtu.be/Iy17wvo07BU)
[](https://youtu.be/stzgn6DkozA)
## Quick Pipleine Visualization
| Indoor 3DMatch Registration | Outdoor KITTI Lidar Registration |
|:---------------------------:|:---------------------------:|
|  |  |
## Related Works
Recent end-to-end frameworks combine feature learning and pose optimization. PointNetLK combines PointNet global features with an iterative pose optimization method. Wang et al. in Deep Closest Point train graph neural network features by backpropagating through pose optimization.
We further advance this line of work. In particular, our Weighted Procrustes method reduces the complexity of optimization from quadratic to linear and enables the use of dense correspondences for highly accurate registration of real-world scans.
## Deep Global Registration
The first component is a 6-dimensional convolutional network that analyzes the geometry of 3D correspondences and estimates their accuracy. Please refer to [High-dim ConvNets, CVPR'20](https://github.com/chrischoy/HighDimConvNets) for more details.
The second component we develop is a differentiable Weighted Procrustes solver. The Procrustes method provides a closed-form solution for rigid registration in SE(3). A differentiable version of the Procrustes method used for end-to-end registration passes gradients through coordinates, which requires O(N^2) time and memory for N keypoints. Instead, the Weighted Procrustes method passes gradients through the weights associated with correspondences rather than correspondence coordinates.
The computational complexity of the Weighted Procrustes method is linear to the number of correspondences, allowing the registration pipeline to use dense correspondence sets rather than sparse keypoints. This substantially increases registration accuracy.
Our third component is a robust optimization module that fine-tunes the alignment produced by the Weighted Procrustes solver and the failure detection module.
This optimization module minimizes a differentiable loss via gradient descent on the continuous SE(3) representation space. The optimization is fast since it does not require neighbor search in the inner loop such as ICP.
## Configuration
Our network is built on the [MinkowskiEngine](https://github.com/StanfordVL/MinkowskiEngine) and the system requirements are:
- Ubuntu 14.04 or higher
- <b>CUDA 10.1.243 or higher</b>
- pytorch 1.5 or higher
- python 3.6 or higher
- GCC 7
You can install the MinkowskiEngine and the python requirements on your system with:
```shell
# Install MinkowskiEngine
sudo apt install libopenblas-dev g++-7
pip install torch
export CXX=g++-7; pip install -U MinkowskiEngine --install-option="--blas=openblas" -v
# Download and setup DeepGlobalRegistration
git clone https://github.com/chrischoy/DeepGlobalRegistration.git
cd DeepGlobalRegistration
pip install -r requirements.txt
```
## Demo
You may register your own data with relevant pretrained DGR models. 3DMatch is suitable for indoor RGB-D scans; KITTI is for outdoor LiDAR scans.
| Inlier Model | FCGF model | Dataset | Voxel Size | Feature Dimension | Performance | Link |
|:------------:|:-----------:|:-------:|:-------------:|:-----------------:|:--------------------------:|:------:|
| ResUNetBN2C | ResUNetBN2C | 3DMatch | 5cm (0.05) | 32 | TE: 7.34cm, RE: 2.43deg | [weights](http://node2.chrischoy.org/data/projects/DGR/ResUNetBN2C-feat32-3dmatch-v0.05.pth) |
| ResUNetBN2C | ResUNetBN2C | KITTI | 30cm (0.3) | 32 | TE: 3.14cm, RE: 0.14deg | [weights](http://node2.chrischoy.org/data/projects/DGR/ResUNetBN2C-feat32-kitti-v0.3.pth) |
```shell
python demo.py
```
| Input PointClouds | Output Prediction |
|:---------------------------:|:---------------------------:|
|  |  |
## Experiments
| Comparison | Speed vs. Recall Pareto Frontier |
| ------- | --------------- |
|  |  |
## Training
The entire network depends on pretrained [FCGF models](https://github.com/chrischoy/FCGF#model-zoo). Please download corresponding models before training.
| Model | Normalized Feature | Dataset | Voxel Size | Feature Dimension | Link |
|:-----------:|:-------------------:|:-------:|:-------------:|:-----------------:|:------:|
| ResUNetBN2C | True | 3DMatch | 5cm (0.05) | 32 | [download](https://node1.chrischoy.org/data/publications/fcgf/2019-08-16_19-21-47.pth) |
| ResUNetBN2C | True | KITTI | 30cm (0.3) | 32 | [download](https://node1.chrischoy.org/data/publications/fcgf/KITTI-v0.3-ResUNetBN2C-conv1-5-nout32.pth) |
### 3DMatch
You may download preprocessed data and train via these commands:
```shell
./scripts/download_3dmatch.sh /path/to/3dmatch
export THREED_MATCH_DIR=/path/to/3dmatch; FCGF_WEIGHTS=/path/to/fcgf_3dmatch.pth ./scripts/train_3dmatch.sh
```
### KITTI
Follow the instruction on [KITTI Odometry website](http://www.cvlibs.net/datasets/kitti/eval_odometry.php) to download the KITTI odometry train set. Then train with
```shell
export KITTI_PATH=/path/to/kitti; FCGF_WEIGHTS=/path/to/fcgf_kitti.pth ./scripts/train_kitti.sh
```
## Testing
3DMatch test set is different from train set and is available at the [download section](http://3dmatch.cs.princeton.edu/) of the official website. You may download and decompress these scenes to a new folder.
To evaluate trained model on 3DMatch or KITTI, you may use
```shell
python -m scripts.test_3dmatch --threed_match_dir /path/to/3dmatch_test/ --weights /path/to/dgr_3dmatch.pth
```
and
```shell
python -m scripts.test_kitti --kitti_dir /path/to/kitti/ --weights /path/to/dgr_kitti.pth
```
## Generate figures
We also provide experimental results of 3DMatch comparisons in `results.npz`. To reproduce figures we presented in the paper, you may use
```shell
python scripts/analyze_stats.py assets/results.npz
```
## Citing our work
Please cite the following papers if you use our code:
```latex
@inproceedings{choy2020deep,
title={Deep Global Registration},
author={Choy, Christopher and Dong, Wei and Koltun, Vladlen},
booktitle={CVPR},
year={2020}
}
@inproceedings{choy2019fully,
title = {Fully Convolutional Geometric Features},
author = {Choy, Christopher and Park, Jaesik and Koltun, Vladlen},
booktitle = {ICCV},
year = {2019}
}
@inproceedings{choy20194d,
title={4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural Networks},
author={Choy, Christopher and Gwak, JunYoung and Savarese, Silvio},
booktitle={CVPR},
year={2019}
}
```
## Concurrent Works
There have a number of 3D registration works published concurrently.
- Gojcic et al., [Learning Multiview 3D Point Cloud Registration, CVPR'20](https://github.com/zgojcic/3D_multiview_reg)
- Wang et al., [PRNet: Self-Supervised Learning for Partial-to-Partial Registration, NeurIPS'19](https://github.com/WangYueFt/prnet)
- Yang et al., [TEASER: Fast and Certifiable Point Cloud Registration, arXiv'20](https://github.com/MIT-SPARK/TEASER-plusplus)
================================================
FILE: config.py
================================================
# Copyright (c) Chris Choy (chrischoy@ai.stanford.edu) and Wei Dong (weidong@andrew.cmu.edu)
#
# Please cite the following papers if you use any part of the code.
# - Christopher Choy, Wei Dong, Vladlen Koltun, Deep Global Registration, CVPR 2020
# - Christopher Choy, Jaesik Park, Vladlen Koltun, Fully Convolutional Geometric Features, ICCV 2019
# - Christopher Choy, JunYoung Gwak, Silvio Savarese, 4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural Networks, CVPR 2019
import argparse
arg_lists = []
parser = argparse.ArgumentParser()
def add_argument_group(name):
arg = parser.add_argument_group(name)
arg_lists.append(arg)
return arg
def str2bool(v):
return v.lower() in ('true', '1')
# yapf: disable
logging_arg = add_argument_group('Logging')
logging_arg.add_argument('--out_dir', type=str, default='outputs')
trainer_arg = add_argument_group('Trainer')
trainer_arg.add_argument('--trainer', type=str, default='WeightedProcrustesTrainer')
# Batch setting
trainer_arg.add_argument('--batch_size', type=int, default=4)
trainer_arg.add_argument('--val_batch_size', type=int, default=1)
# Data loader configs
trainer_arg.add_argument('--train_phase', type=str, default="train")
trainer_arg.add_argument('--val_phase', type=str, default="val")
trainer_arg.add_argument('--test_phase', type=str, default="test")
# Data augmentation
trainer_arg.add_argument('--use_random_scale', type=str2bool, default=False)
trainer_arg.add_argument('--min_scale', type=float, default=0.8)
trainer_arg.add_argument('--max_scale', type=float, default=1.2)
trainer_arg.add_argument('--use_random_rotation', type=str2bool, default=True)
trainer_arg.add_argument('--rotation_range', type=float, default=360)
trainer_arg.add_argument(
'--positive_pair_search_voxel_size_multiplier', type=float, default=1.5)
trainer_arg.add_argument('--save_epoch_freq', type=int, default=1)
trainer_arg.add_argument('--val_epoch_freq', type=int, default=1)
trainer_arg.add_argument('--stat_freq', type=int, default=40, help='Frequency for writing stats to log')
trainer_arg.add_argument('--test_valid', type=str2bool, default=True)
trainer_arg.add_argument('--val_max_iter', type=int, default=400)
trainer_arg.add_argument('--use_balanced_loss', type=str2bool, default=False)
trainer_arg.add_argument('--inlier_direct_loss_weight', type=float, default=1.)
trainer_arg.add_argument('--procrustes_loss_weight', type=float, default=1.)
trainer_arg.add_argument('--trans_weight', type=float, default=1)
trainer_arg.add_argument('--eval_registration', type=str2bool, default=True)
trainer_arg.add_argument('--clip_weight_thresh', type=float, default=0.05, help='Weight threshold for detecting inliers')
trainer_arg.add_argument('--best_val_metric', type=str, default='succ_rate')
# Inlier detection trainer
inlier_arg = add_argument_group('Inlier')
inlier_arg.add_argument('--inlier_model', type=str, default='ResUNetBN2C')
inlier_arg.add_argument('--inlier_feature_type', type=str, default='ones')
inlier_arg.add_argument('--inlier_conv1_kernel_size', type=int, default=3)
inlier_arg.add_argument('--inlier_knn', type=int, default=1)
inlier_arg.add_argument('--knn_search_method', type=str, default='gpu')
inlier_arg.add_argument('--inlier_use_direct_loss', type=str2bool, default=True)
# Feature specific configurations
feat_arg = add_argument_group('feat')
feat_arg.add_argument('--feat_model', type=str, default='SimpleNetBN2C')
feat_arg.add_argument('--feat_model_n_out', type=int, default=16, help='Feature dimension')
feat_arg.add_argument('--feat_conv1_kernel_size', type=int, default=3)
feat_arg.add_argument('--normalize_feature', type=str2bool, default=True)
feat_arg.add_argument('--use_xyz_feature', type=str2bool, default=False)
feat_arg.add_argument('--dist_type', type=str, default='L2')
# Optimizer arguments
opt_arg = add_argument_group('Optimizer')
opt_arg.add_argument('--optimizer', type=str, default='SGD')
opt_arg.add_argument('--max_epoch', type=int, default=100)
opt_arg.add_argument('--lr', type=float, default=1e-1)
opt_arg.add_argument('--momentum', type=float, default=0.8)
opt_arg.add_argument('--sgd_momentum', type=float, default=0.9)
opt_arg.add_argument('--sgd_dampening', type=float, default=0.1)
opt_arg.add_argument('--adam_beta1', type=float, default=0.9)
opt_arg.add_argument('--adam_beta2', type=float, default=0.999)
opt_arg.add_argument('--weight_decay', type=float, default=1e-4)
opt_arg.add_argument('--iter_size', type=int, default=1, help='accumulate gradient')
opt_arg.add_argument('--bn_momentum', type=float, default=0.05)
opt_arg.add_argument('--exp_gamma', type=float, default=0.99)
opt_arg.add_argument('--scheduler', type=str, default='ExpLR')
opt_arg.add_argument('--num_train_iter', type=int, default=-1, help='train N iter if positive')
opt_arg.add_argument('--icp_cache_path', type=str, default="icp")
# Misc
misc_arg = add_argument_group('Misc')
misc_arg.add_argument('--use_gpu', type=str2bool, default=True)
misc_arg.add_argument('--weights', type=str, default=None)
misc_arg.add_argument('--weights_dir', type=str, default=None)
misc_arg.add_argument('--resume', type=str, default=None)
misc_arg.add_argument('--resume_dir', type=str, default=None)
misc_arg.add_argument('--train_num_workers', type=int, default=2)
misc_arg.add_argument('--val_num_workers', type=int, default=1)
misc_arg.add_argument('--test_num_workers', type=int, default=2)
misc_arg.add_argument('--fast_validation', type=str2bool, default=False)
misc_arg.add_argument('--nn_max_n', type=int, default=250, help='The maximum number of features to find nearest neighbors in batch')
# Dataset specific configurations
data_arg = add_argument_group('Data')
data_arg.add_argument('--dataset', type=str, default='ThreeDMatchPairDataset03')
data_arg.add_argument('--voxel_size', type=float, default=0.025)
data_arg.add_argument('--threed_match_dir', type=str, default='.')
data_arg.add_argument('--kitti_dir', type=str, default=None, help="Path to the KITTI odometry dataset. This path should contain <kitti_dir>/dataset/sequences.")
data_arg.add_argument('--kitti_max_time_diff', type=int, default=3, help='max time difference between pairs (non inclusive)')
data_arg.add_argument('--kitti_date', type=str, default='2011_09_26')
# Evaluation
eval_arg = add_argument_group('Data')
eval_arg.add_argument('--hit_ratio_thresh', type=float, default=0.1)
eval_arg.add_argument('--success_rte_thresh', type=float, default=0.3, help='Success if the RTE below this (m)')
eval_arg.add_argument('--success_rre_thresh', type=float, default=15, help='Success if the RTE below this (degree)')
eval_arg.add_argument('--test_random_crop', action='store_true')
eval_arg.add_argument('--test_random_rotation', type=str2bool, default=False)
# Demo
demo_arg = add_argument_group('demo')
demo_arg.add_argument('--pcd0', default="redkitchen_000.ply", type=str)
demo_arg.add_argument('--pcd1', default="redkitchen_010.ply", type=str)
# yapf: enable
def get_config():
args = parser.parse_args()
return args
================================================
FILE: core/__init__.py
================================================
# Copyright (c) Chris Choy (chrischoy@ai.stanford.edu) and Wei Dong (weidong@andrew.cmu.edu)
#
# Please cite the following papers if you use any part of the code.
# - Christopher Choy, Wei Dong, Vladlen Koltun, Deep Global Registration, CVPR 2020
# - Christopher Choy, Jaesik Park, Vladlen Koltun, Fully Convolutional Geometric Features, ICCV 2019
# - Christopher Choy, JunYoung Gwak, Silvio Savarese, 4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural Networks, CVPR 2019
================================================
FILE: core/correspondence.py
================================================
# Copyright (c) Chris Choy (chrischoy@ai.stanford.edu) and Wei Dong (weidong@andrew.cmu.edu)
#
# Please cite the following papers if you use any part of the code.
# - Christopher Choy, Wei Dong, Vladlen Koltun, Deep Global Registration, CVPR 2020
# - Christopher Choy, Jaesik Park, Vladlen Koltun, Fully Convolutional Geometric Features, ICCV 2019
# - Christopher Choy, JunYoung Gwak, Silvio Savarese, 4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural Networks, CVPR 2019
import copy
import numpy as np
import open3d as o3d
import torch
def _hash(arr, M=None):
if isinstance(arr, np.ndarray):
N, D = arr.shape
else:
N, D = len(arr[0]), len(arr)
hash_vec = np.zeros(N, dtype=np.int64)
for d in range(D):
if isinstance(arr, np.ndarray):
hash_vec += arr[:, d] * M**d
else:
hash_vec += arr[d] * M**d
return hash_vec
def find_correct_correspondence(pos_pairs, pred_pairs, hash_seed=None, len_batch=None):
assert len(pos_pairs) == len(pred_pairs)
if hash_seed is None:
assert len(len_batch) == len(pos_pairs)
corrects = []
for i, pos_pred in enumerate(zip(pos_pairs, pred_pairs)):
pos_pair, pred_pair = pos_pred
if isinstance(pos_pair, torch.Tensor):
pos_pair = pos_pair.numpy()
if isinstance(pred_pair, torch.Tensor):
pred_pair = pred_pair.numpy()
if hash_seed is None:
N0, N1 = len_batch[i]
_hash_seed = max(N0, N1)
else:
_hash_seed = hash_seed
pos_keys = _hash(pos_pair, _hash_seed)
pred_keys = _hash(pred_pair, _hash_seed)
corrects.append(np.isin(pred_keys, pos_keys, assume_unique=False))
return np.hstack(corrects)
================================================
FILE: core/deep_global_registration.py
================================================
# Copyright (c) Chris Choy (chrischoy@ai.stanford.edu) and Wei Dong (weidong@andrew.cmu.edu)
#
# Please cite the following papers if you use any part of the code.
# - Christopher Choy, Wei Dong, Vladlen Koltun, Deep Global Registration, CVPR 2020
# - Christopher Choy, Jaesik Park, Vladlen Koltun, Fully Convolutional Geometric Features, ICCV 2019
# - Christopher Choy, JunYoung Gwak, Silvio Savarese, 4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural Networks, CVPR 2019
import os
import sys
import math
import logging
import open3d as o3d
import numpy as np
import time
import torch
import copy
import MinkowskiEngine as ME
sys.path.append('.')
from model import load_model
from core.registration import GlobalRegistration
from core.knn import find_knn_gpu
from util.timer import Timer
from util.pointcloud import make_open3d_point_cloud
# Feature-based registrations in Open3D
def registration_ransac_based_on_feature_matching(pcd0, pcd1, feats0, feats1,
distance_threshold, num_iterations):
assert feats0.shape[1] == feats1.shape[1]
source_feat = o3d.registration.Feature()
source_feat.resize(feats0.shape[1], len(feats0))
source_feat.data = feats0.astype('d').transpose()
target_feat = o3d.registration.Feature()
target_feat.resize(feats1.shape[1], len(feats1))
target_feat.data = feats1.astype('d').transpose()
result = o3d.registration.registration_ransac_based_on_feature_matching(
pcd0, pcd1, source_feat, target_feat, distance_threshold,
o3d.registration.TransformationEstimationPointToPoint(False), 4,
[o3d.registration.CorrespondenceCheckerBasedOnDistance(distance_threshold)],
o3d.registration.RANSACConvergenceCriteria(num_iterations, 1000))
return result.transformation
def registration_ransac_based_on_correspondence(pcd0, pcd1, idx0, idx1,
distance_threshold, num_iterations):
corres = np.stack((idx0, idx1), axis=1)
corres = o3d.utility.Vector2iVector(corres)
result = o3d.pipelines.registration.registration_ransac_based_on_correspondence(
source = pcd0,
target = pcd1,
corres = corres,
max_correspondence_distance = distance_threshold,
estimation_method = o3d.pipelines.registration.TransformationEstimationPointToPoint(False),
ransac_n = 4,
criteria = o3d.pipelines.registration.RANSACConvergenceCriteria(4000000, num_iterations))
return result.transformation
class DeepGlobalRegistration:
def __init__(self, config, device=torch.device('cuda')):
# Basic config
self.config = config
self.clip_weight_thresh = self.config.clip_weight_thresh
self.device = device
# Safeguard
self.safeguard_method = 'correspondence' # correspondence, feature_matching
# Final tuning
self.use_icp = True
# Misc
self.feat_timer = Timer()
self.reg_timer = Timer()
# Model config loading
print("=> loading checkpoint '{}'".format(config.weights))
assert os.path.exists(config.weights)
state = torch.load(config.weights)
network_config = state['config']
self.network_config = network_config
self.config.inlier_feature_type = network_config.inlier_feature_type
self.voxel_size = network_config.voxel_size
print(f'=> Setting voxel size to {self.voxel_size}')
# FCGF network initialization
num_feats = 1
try:
FCGFModel = load_model(network_config['feat_model'])
self.fcgf_model = FCGFModel(
num_feats,
network_config['feat_model_n_out'],
bn_momentum=network_config['bn_momentum'],
conv1_kernel_size=network_config['feat_conv1_kernel_size'],
normalize_feature=network_config['normalize_feature'])
except KeyError: # legacy pretrained models
FCGFModel = load_model(network_config['model'])
self.fcgf_model = FCGFModel(num_feats,
network_config['model_n_out'],
bn_momentum=network_config['bn_momentum'],
conv1_kernel_size=network_config['conv1_kernel_size'],
normalize_feature=network_config['normalize_feature'])
self.fcgf_model.load_state_dict(state['state_dict'])
self.fcgf_model = self.fcgf_model.to(device)
self.fcgf_model.eval()
# Inlier network initialization
num_feats = 6 if network_config.inlier_feature_type == 'coords' else 1
InlierModel = load_model(network_config['inlier_model'])
self.inlier_model = InlierModel(
num_feats,
1,
bn_momentum=network_config['bn_momentum'],
conv1_kernel_size=network_config['inlier_conv1_kernel_size'],
normalize_feature=False,
D=6)
self.inlier_model.load_state_dict(state['state_dict_inlier'])
self.inlier_model = self.inlier_model.to(self.device)
self.inlier_model.eval()
print("=> loading finished")
def preprocess(self, pcd):
'''
Stage 0: preprocess raw input point cloud
Input: raw point cloud
Output: voxelized point cloud with
- xyz: unique point cloud with one point per voxel
- coords: coords after voxelization
- feats: dummy feature placeholder for general sparse convolution
'''
if isinstance(pcd, o3d.geometry.PointCloud):
xyz = np.array(pcd.points)
elif isinstance(pcd, np.ndarray):
xyz = pcd
else:
raise Exception('Unrecognized pcd type')
# Voxelization:
# Maintain double type for xyz to improve numerical accuracy in quantization
_, sel = ME.utils.sparse_quantize(xyz / self.voxel_size, return_index=True)
npts = len(sel)
xyz = torch.from_numpy(xyz[sel]).to(self.device)
# ME standard batch coordinates
coords = ME.utils.batched_coordinates([torch.floor(xyz / self.voxel_size).int()], device=self.device)
feats = torch.ones(npts, 1)
return xyz.float(), coords, feats
def fcgf_feature_extraction(self, feats, coords):
'''
Step 1: extract fast and accurate FCGF feature per point
'''
sinput = ME.SparseTensor(feats, coordinates=coords, device=self.device)
return self.fcgf_model(sinput).F
def fcgf_feature_matching(self, feats0, feats1):
'''
Step 2: coarsely match FCGF features to generate initial correspondences
'''
nns = find_knn_gpu(feats0,
feats1,
nn_max_n=self.network_config.nn_max_n,
knn=1,
return_distance=False)
corres_idx0 = torch.arange(len(nns)).long().squeeze().to(self.device)
corres_idx1 = nns.long().squeeze()
return corres_idx0, corres_idx1
def inlier_feature_generation(self, xyz0, xyz1, coords0, coords1, fcgf_feats0,
fcgf_feats1, corres_idx0, corres_idx1):
'''
Step 3: generate features for inlier prediction
'''
assert len(corres_idx0) == len(corres_idx1)
feat_type = self.config.inlier_feature_type
assert feat_type in ['ones', 'feats', 'coords']
corres_idx0 = corres_idx0.to(self.device)
corres_idx1 = corres_idx1.to(self.device)
if feat_type == 'ones':
feat = torch.ones((len(corres_idx0), 1)).float()
elif feat_type == 'feats':
feat = torch.cat((fcgf_feats0[corres_idx0], fcgf_feats1[corres_idx1]), dim=1)
elif feat_type == 'coords':
feat = torch.cat((torch.cos(xyz0[corres_idx0]), torch.cos(xyz1[corres_idx1])),
dim=1)
else: # should never reach here
raise TypeError('Undefined feature type')
return feat
def inlier_prediction(self, inlier_feats, coords):
'''
Step 4: predict inlier likelihood
'''
sinput = ME.SparseTensor(inlier_feats, coordinates=coords, device=self.device)
soutput = self.inlier_model(sinput)
return soutput.F
def safeguard_registration(self, pcd0, pcd1, idx0, idx1, feats0, feats1,
distance_threshold, num_iterations):
if self.safeguard_method == 'correspondence':
T = registration_ransac_based_on_correspondence(pcd0,
pcd1,
idx0.cpu().numpy(),
idx1.cpu().numpy(),
distance_threshold,
num_iterations=num_iterations)
elif self.safeguard_method == 'fcgf_feature_matching':
T = registration_ransac_based_on_fcgf_feature_matching(pcd0, pcd1,
feats0.cpu().numpy(),
feats1.cpu().numpy(),
distance_threshold,
num_iterations)
else:
raise ValueError('Undefined')
return T
def register(self, xyz0, xyz1, inlier_thr=0.00):
'''
Main algorithm of DeepGlobalRegistration
'''
self.reg_timer.tic()
with torch.no_grad():
# Step 0: voxelize and generate sparse input
xyz0, coords0, feats0 = self.preprocess(xyz0)
xyz1, coords1, feats1 = self.preprocess(xyz1)
# Step 1: Feature extraction
self.feat_timer.tic()
fcgf_feats0 = self.fcgf_feature_extraction(feats0, coords0)
fcgf_feats1 = self.fcgf_feature_extraction(feats1, coords1)
self.feat_timer.toc()
# Step 2: Coarse correspondences
corres_idx0, corres_idx1 = self.fcgf_feature_matching(fcgf_feats0, fcgf_feats1)
# Step 3: Inlier feature generation
# coords[corres_idx0]: 1D temporal + 3D spatial coord
# coords[corres_idx1, 1:]: 3D spatial coord
# => 1D temporal + 6D spatial coord
inlier_coords = torch.cat((coords0[corres_idx0], coords1[corres_idx1, 1:]),
dim=1).int()
inlier_feats = self.inlier_feature_generation(xyz0, xyz1, coords0, coords1,
fcgf_feats0, fcgf_feats1,
corres_idx0, corres_idx1)
# Step 4: Inlier likelihood estimation and truncation
logit = self.inlier_prediction(inlier_feats.contiguous(), coords=inlier_coords)
weights = logit.sigmoid()
if self.clip_weight_thresh > 0:
weights[weights < self.clip_weight_thresh] = 0
wsum = weights.sum().item()
# Step 5: Registration. Note: torch's gradient may be required at this stage
# > Case 0: Weighted Procrustes + Robust Refinement
wsum_threshold = max(200, len(weights) * 0.05)
sign = '>=' if wsum >= wsum_threshold else '<'
print(f'=> Weighted sum {wsum:.2f} {sign} threshold {wsum_threshold}')
T = np.identity(4)
if wsum >= wsum_threshold:
try:
rot, trans, opt_output = GlobalRegistration(xyz0[corres_idx0],
xyz1[corres_idx1],
weights=weights.detach(),
break_threshold_ratio=1e-4,
quantization_size=2 *
self.voxel_size,
verbose=False)
T[0:3, 0:3] = rot.detach().cpu().numpy()
T[0:3, 3] = trans.detach().cpu().numpy()
dgr_time = self.reg_timer.toc()
print(f'=> DGR takes {dgr_time:.2} s')
except RuntimeError:
# Will directly go to Safeguard
print('###############################################')
print('# WARNING: SVD failed, weights sum: ', wsum)
print('# Falling back to Safeguard')
print('###############################################')
else:
# > Case 1: Safeguard RANSAC + (Optional) ICP
pcd0 = make_open3d_point_cloud(xyz0)
pcd1 = make_open3d_point_cloud(xyz1)
T = self.safeguard_registration(pcd0,
pcd1,
corres_idx0,
corres_idx1,
feats0,
feats1,
2 * self.voxel_size,
num_iterations=80000)
safeguard_time = self.reg_timer.toc()
print(f'=> Safeguard takes {safeguard_time:.2} s')
if self.use_icp:
T = o3d.pipelines.registration.registration_icp(
source=make_open3d_point_cloud(xyz0),
target=make_open3d_point_cloud(xyz1),
max_correspondence_distance=self.voxel_size * 2,
init=T).transformation
return T
================================================
FILE: core/knn.py
================================================
# Copyright (c) Chris Choy (chrischoy@ai.stanford.edu) and Wei Dong (weidong@andrew.cmu.edu)
#
# Please cite the following papers if you use any part of the code.
# - Christopher Choy, Wei Dong, Vladlen Koltun, Deep Global Registration, CVPR 2020
# - Christopher Choy, Jaesik Park, Vladlen Koltun, Fully Convolutional Geometric Features, ICCV 2019
# - Christopher Choy, JunYoung Gwak, Silvio Savarese, 4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural Networks, CVPR 2019
import torch
import numpy as np
from scipy.spatial import cKDTree
from core.metrics import pdist
def find_knn_cpu(feat0, feat1, knn=1, return_distance=False):
feat1tree = cKDTree(feat1)
dists, nn_inds = feat1tree.query(feat0, k=knn, n_jobs=-1)
if return_distance:
return nn_inds, dists
else:
return nn_inds
def find_knn_gpu(F0, F1, nn_max_n=-1, knn=1, return_distance=False):
def knn_dist(f0, f1, knn=1, dist_type='L2'):
knn_dists, knn_inds = [], []
with torch.no_grad():
dist = pdist(f0, f1, dist_type=dist_type)
min_dist, ind = dist.min(dim=1, keepdim=True)
knn_dists.append(min_dist)
knn_inds.append(ind)
if knn > 1:
for k in range(knn - 1):
NR, NC = dist.shape
flat_ind = (torch.arange(NR) * NC).type_as(ind) + ind.squeeze()
dist.view(-1)[flat_ind] = np.inf
min_dist, ind = dist.min(dim=1, keepdim=True)
knn_dists.append(min_dist)
knn_inds.append(ind)
min_dist = torch.cat(knn_dists, 1)
ind = torch.cat(knn_inds, 1)
return min_dist, ind
# Too much memory if F0 or F1 large. Divide the F0
if nn_max_n > 1:
N = len(F0)
C = int(np.ceil(N / nn_max_n))
stride = nn_max_n
dists, inds = [], []
for i in range(C):
with torch.no_grad():
dist, ind = knn_dist(F0[i * stride:(i + 1) * stride], F1, knn=knn, dist_type='L2')
dists.append(dist)
inds.append(ind)
dists = torch.cat(dists)
inds = torch.cat(inds)
assert len(inds) == N
else:
dist = pdist(F0, F1, dist_type='SquareL2')
min_dist, inds = dist.min(dim=1)
dists = min_dist.detach().unsqueeze(1) #.cpu()
# inds = inds.cpu()
if return_distance:
return inds, dists
else:
return inds
def find_knn_batch(F0,
F1,
len_batch,
return_distance=False,
nn_max_n=-1,
knn=1,
search_method=None,
concat_results=False):
if search_method is None or search_method == 'gpu':
return find_knn_gpu_batch(
F0,
F1,
len_batch=len_batch,
nn_max_n=nn_max_n,
knn=knn,
return_distance=return_distance,
concat_results=concat_results)
elif search_method == 'cpu':
return find_knn_cpu_batch(
F0,
F1,
len_batch=len_batch,
knn=knn,
return_distance=return_distance,
concat_results=concat_results)
else:
raise ValueError(f'Search method {search_method} not defined')
def find_knn_gpu_batch(F0,
F1,
len_batch,
nn_max_n=-1,
knn=1,
return_distance=False,
concat_results=False):
dists, nns = [], []
start0, start1 = 0, 0
for N0, N1 in len_batch:
nn = find_knn_gpu(
F0[start0:start0 + N0],
F1[start1:start1 + N1],
nn_max_n=nn_max_n,
knn=knn,
return_distance=return_distance)
if return_distance:
nn, dist = nn
dists.append(dist)
if concat_results:
nns.append(nn + start1)
else:
nns.append(nn)
start0 += N0
start1 += N1
if concat_results:
nns = torch.cat(nns)
if return_distance:
dists = torch.cat(dists)
if return_distance:
return nns, dists
else:
return nns
def find_knn_cpu_batch(F0,
F1,
len_batch,
knn=1,
return_distance=False,
concat_results=False):
if not isinstance(F0, np.ndarray):
F0 = F0.detach().cpu().numpy()
F1 = F1.detach().cpu().numpy()
dists, nns = [], []
start0, start1 = 0, 0
for N0, N1 in len_batch:
nn = find_knn_cpu(
F0[start0:start0 + N0], F1[start1:start1 + N1], return_distance=return_distance)
if return_distance:
nn, dist = nn
dists.append(dist)
if concat_results:
nns.append(nn + start1)
else:
nns.append(nn + start1)
start0 += N0
start1 += N1
if concat_results:
nns = np.hstack(nns)
if return_distance:
dists = np.hstack(dists)
if return_distance:
return torch.from_numpy(nns), torch.from_numpy(dists)
else:
return torch.from_numpy(nns)
================================================
FILE: core/loss.py
================================================
# Copyright (c) Chris Choy (chrischoy@ai.stanford.edu) and Wei Dong (weidong@andrew.cmu.edu)
#
# Please cite the following papers if you use any part of the code.
# - Christopher Choy, Wei Dong, Vladlen Koltun, Deep Global Registration, CVPR 2020
# - Christopher Choy, Jaesik Park, Vladlen Koltun, Fully Convolutional Geometric Features, ICCV 2019
# - Christopher Choy, JunYoung Gwak, Silvio Savarese, 4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural Networks, CVPR 2019
import torch
import torch.nn as nn
import numpy as np
class UnbalancedLoss(nn.Module):
NUM_LABELS = 2
def __init__(self):
super().__init__()
self.crit = nn.BCEWithLogitsLoss()
def forward(self, logits, label):
return self.crit(logits, label.to(torch.float))
class BalancedLoss(nn.Module):
NUM_LABELS = 2
def __init__(self):
super().__init__()
self.crit = nn.BCEWithLogitsLoss()
def forward(self, logits, label):
assert torch.all(label < self.NUM_LABELS)
loss = torch.scalar_tensor(0.).to(logits)
for i in range(self.NUM_LABELS):
target_mask = label == i
if torch.any(target_mask):
loss += self.crit(logits[target_mask], label[target_mask].to(
torch.float)) / self.NUM_LABELS
return loss
class HighDimSmoothL1Loss:
def __init__(self, weights, quantization_size=1, eps=np.finfo(np.float32).eps):
self.eps = eps
self.quantization_size = quantization_size
self.weights = weights
if self.weights is not None:
self.w1 = weights.sum()
def __call__(self, X, Y):
sq_dist = torch.sum(((X - Y) / self.quantization_size)**2, axis=1, keepdim=True)
use_sq_half = 0.5 * (sq_dist < 1).float()
loss = (0.5 - use_sq_half) * (torch.sqrt(sq_dist + self.eps) -
0.5) + use_sq_half * sq_dist
if self.weights is None:
return loss.mean()
else:
return (loss * self.weights).sum() / self.w1
================================================
FILE: core/metrics.py
================================================
# Copyright (c) Chris Choy (chrischoy@ai.stanford.edu) and Wei Dong (weidong@andrew.cmu.edu)
#
# Please cite the following papers if you use any part of the code.
# - Christopher Choy, Wei Dong, Vladlen Koltun, Deep Global Registration, CVPR 2020
# - Christopher Choy, Jaesik Park, Vladlen Koltun, Fully Convolutional Geometric Features, ICCV 2019
# - Christopher Choy, JunYoung Gwak, Silvio Savarese, 4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural Networks, CVPR 2019
import torch
import torch.functional as F
def rotation_mat2angle(R):
return torch.acos(torch.clamp((torch.trace(R) - 1) / 2, -0.9999, 0.9999))
def rotation_error(R1, R2):
assert R1.shape == R2.shape
return torch.acos(torch.clamp((torch.trace(torch.mm(R1.t(), R2)) - 1) / 2, -0.9999, 0.9999))
def translation_error(t1, t2):
assert t1.shape == t2.shape
return torch.sqrt(((t1 - t2)**2).sum())
def batch_rotation_error(rots1, rots2):
r"""
arccos( (tr(R_1^T R_2) - 1) / 2 )
rots1: B x 3 x 3 or B x 9
rots1: B x 3 x 3 or B x 9
"""
assert len(rots1) == len(rots2)
trace_r1Tr2 = (rots1.reshape(-1, 9) * rots2.reshape(-1, 9)).sum(1)
side = (trace_r1Tr2 - 1) / 2
return torch.acos(torch.clamp(side, min=-0.999, max=0.999))
def batch_translation_error(trans1, trans2):
r"""
trans1: B x 3
trans2: B x 3
"""
assert len(trans1) == len(trans2)
return torch.norm(trans1 - trans2, p=2, dim=1, keepdim=False)
def eval_metrics(output, target):
output = (F.sigmoid(output) > 0.5)
target = target
return torch.norm(output - target)
def corr_dist(est, gth, xyz0, xyz1, weight=None, max_dist=1):
xyz0_est = xyz0 @ est[:3, :3].t() + est[:3, 3]
xyz0_gth = xyz0 @ gth[:3, :3].t() + gth[:3, 3]
dists = torch.clamp(torch.sqrt(((xyz0_est - xyz0_gth).pow(2)).sum(1)), max=max_dist)
if weight is not None:
dists = weight * dists
return dists.mean()
def pdist(A, B, dist_type='L2'):
if dist_type == 'L2':
D2 = torch.sum((A.unsqueeze(1) - B.unsqueeze(0)).pow(2), 2)
return torch.sqrt(D2 + 1e-7)
elif dist_type == 'SquareL2':
return torch.sum((A.unsqueeze(1) - B.unsqueeze(0)).pow(2), 2)
else:
raise NotImplementedError('Not implemented')
def get_loss_fn(loss):
if loss == 'corr_dist':
return corr_dist
else:
raise ValueError(f'Loss {loss}, not defined')
================================================
FILE: core/registration.py
================================================
# Copyright (c) Chris Choy (chrischoy@ai.stanford.edu) and Wei Dong (weidong@andrew.cmu.edu)
#
# Please cite the following papers if you use any part of the code.
# - Christopher Choy, Wei Dong, Vladlen Koltun, Deep Global Registration, CVPR 2020
# - Christopher Choy, Jaesik Park, Vladlen Koltun, Fully Convolutional Geometric Features, ICCV 2019
# - Christopher Choy, JunYoung Gwak, Silvio Savarese, 4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural Networks, CVPR 2019
import numpy as np
import torch
import torch.optim as optim
from core.knn import pdist
from core.loss import HighDimSmoothL1Loss
def ortho2rotation(poses):
r"""
poses: batch x 6
"""
def normalize_vector(v):
r"""
Batch x 3
"""
v_mag = torch.sqrt((v**2).sum(1, keepdim=True))
v_mag = torch.clamp(v_mag, min=1e-8)
v = v / v_mag
return v
def cross_product(u, v):
r"""
u: batch x 3
v: batch x 3
"""
i = u[:, 1] * v[:, 2] - u[:, 2] * v[:, 1]
j = u[:, 2] * v[:, 0] - u[:, 0] * v[:, 2]
k = u[:, 0] * v[:, 1] - u[:, 1] * v[:, 0]
i = i[:, None]
j = j[:, None]
k = k[:, None]
return torch.cat((i, j, k), 1)
def proj_u2a(u, a):
r"""
u: batch x 3
a: batch x 3
"""
inner_prod = (u * a).sum(1, keepdim=True)
norm2 = (u**2).sum(1, keepdim=True)
norm2 = torch.clamp(norm2, min=1e-8)
factor = inner_prod / norm2
return factor * u
x_raw = poses[:, 0:3]
y_raw = poses[:, 3:6]
x = normalize_vector(x_raw)
y = normalize_vector(y_raw - proj_u2a(x, y_raw))
z = cross_product(x, y)
x = x[:, :, None]
y = y[:, :, None]
z = z[:, :, None]
return torch.cat((x, y, z), 2)
def argmin_se3_squared_dist(X, Y):
"""
X: torch tensor N x 3
Y: torch tensor N x 3
"""
# https://ieeexplore.ieee.org/document/88573
assert len(X) == len(Y)
mux = X.mean(0, keepdim=True)
muy = Y.mean(0, keepdim=True)
Sxy = (Y - muy).t().mm(X - mux) / len(X)
U, D, V = Sxy.svd()
# svd = gesvd.GESVDFunction()
# U, S, V = svd.apply(Sxy)
# S[-1, -1] = U.det() * V.det()
S = torch.eye(3)
if U.det() * V.det() < 0:
S[-1, -1] = -1
R = U.mm(S.mm(V.t()))
t = muy.squeeze() - R.mm(mux.t()).squeeze()
return R, t
def weighted_procrustes(X, Y, w, eps):
"""
X: torch tensor N x 3
Y: torch tensor N x 3
w: torch tensor N
"""
# https://ieeexplore.ieee.org/document/88573
assert len(X) == len(Y)
W1 = torch.abs(w).sum()
w_norm = w / (W1 + eps)
mux = (w_norm * X).sum(0, keepdim=True)
muy = (w_norm * Y).sum(0, keepdim=True)
# Use CPU for small arrays
Sxy = (Y - muy).t().mm(w_norm * (X - mux)).cpu().double()
U, D, V = Sxy.svd()
S = torch.eye(3).double()
if U.det() * V.det() < 0:
S[-1, -1] = -1
R = U.mm(S.mm(V.t())).float()
t = (muy.cpu().squeeze() - R.mm(mux.cpu().t()).squeeze()).float()
return R, t
class Transformation(torch.nn.Module):
def __init__(self, R_init=None, t_init=None):
torch.nn.Module.__init__(self)
rot_init = torch.rand(1, 6)
trans_init = torch.zeros(1, 3)
if R_init is not None:
rot_init[0, :3] = R_init[:, 0]
rot_init[0, 3:] = R_init[:, 1]
if t_init is not None:
trans_init[0] = t_init
self.rot6d = torch.nn.Parameter(rot_init)
self.trans = torch.nn.Parameter(trans_init)
def forward(self, points):
rot_mat = ortho2rotation(self.rot6d)
return points @ rot_mat[0].t() + self.trans
def GlobalRegistration(points,
trans_points,
weights=None,
max_iter=1000,
verbose=False,
stat_freq=20,
max_break_count=20,
break_threshold_ratio=1e-5,
loss_fn=None,
quantization_size=1):
if isinstance(points, np.ndarray):
points = torch.from_numpy(points).float()
if isinstance(trans_points, np.ndarray):
trans_points = torch.from_numpy(trans_points).float()
if loss_fn is None:
if weights is not None:
weights.requires_grad = False
loss_fn = HighDimSmoothL1Loss(weights, quantization_size)
if weights is None:
# Get the initialization using https://ieeexplore.ieee.org/document/88573
R, t = argmin_se3_squared_dist(points, trans_points)
else:
R, t = weighted_procrustes(points, trans_points, weights, loss_fn.eps)
transformation = Transformation(R, t).to(points.device)
optimizer = optim.Adam(transformation.parameters(), lr=1e-1)
scheduler = optim.lr_scheduler.ExponentialLR(optimizer, gamma=0.999)
loss_prev = loss_fn(transformation(points), trans_points).item()
break_counter = 0
# Transform points
for i in range(max_iter):
new_points = transformation(points)
loss = loss_fn(new_points, trans_points)
if loss.item() < 1e-7:
break
optimizer.zero_grad()
loss.backward()
optimizer.step()
scheduler.step()
if i % stat_freq == 0 and verbose:
print(i, scheduler.get_lr(), loss.item())
if abs(loss_prev - loss.item()) < loss_prev * break_threshold_ratio:
break_counter += 1
if break_counter >= max_break_count:
break
loss_prev = loss.item()
rot6d = transformation.rot6d.detach()
trans = transformation.trans.detach()
opt_result = {'iterations': i, 'loss': loss.item(), 'break_count': break_counter}
return ortho2rotation(rot6d)[0], trans, opt_result
================================================
FILE: core/trainer.py
================================================
# Copyright (c) Chris Choy (chrischoy@ai.stanford.edu) and Wei Dong (weidong@andrew.cmu.edu)
#
# Please cite the following papers if you use any part of the code.
# - Christopher Choy, Wei Dong, Vladlen Koltun, Deep Global Registration, CVPR 2020
# - Christopher Choy, Jaesik Park, Vladlen Koltun, Fully Convolutional Geometric Features, ICCV 2019
# - Christopher Choy, JunYoung Gwak, Silvio Savarese, 4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural Networks, CVPR 2019
# Written by Chris Choy <chrischoy@ai.stanford.edu>
# Distributed under MIT License
import time
import os
import os.path as osp
import gc
import logging
import numpy as np
import json
import torch
import torch.optim as optim
import torch.nn.functional as F
from tensorboardX import SummaryWriter
from model import load_model
from core.knn import find_knn_batch
from core.correspondence import find_correct_correspondence
from core.loss import UnbalancedLoss, BalancedLoss
from core.metrics import batch_rotation_error, batch_translation_error
import core.registration as GlobalRegistration
from util.timer import Timer, AverageMeter
from util.file import ensure_dir
import MinkowskiEngine as ME
eps = np.finfo(float).eps
np2th = torch.from_numpy
class WeightedProcrustesTrainer:
def __init__(self, config, data_loader, val_data_loader=None):
# occupancy only for 3D Match dataset. For ScanNet, use RGB 3 channels.
num_feats = 3 if config.use_xyz_feature else 1
# Feature model initialization
if config.use_gpu and not torch.cuda.is_available():
logging.warning('Warning: There\'s no CUDA support on this machine, '
'training is performed on CPU.')
raise ValueError('GPU not available, but cuda flag set')
self.device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
self.config = config
# Training config
self.max_epoch = config.max_epoch
self.start_epoch = 1
self.checkpoint_dir = config.out_dir
self.data_loader = data_loader
self.train_data_loader_iter = self.data_loader.__iter__()
self.iter_size = config.iter_size
self.batch_size = data_loader.batch_size
# Validation config
self.val_max_iter = config.val_max_iter
self.val_epoch_freq = config.val_epoch_freq
self.best_val_metric = config.best_val_metric
self.best_val_epoch = -np.inf
self.best_val = -np.inf
self.val_data_loader = val_data_loader
self.test_valid = True if self.val_data_loader is not None else False
# Logging
self.log_step = int(np.sqrt(self.config.batch_size))
self.writer = SummaryWriter(config.out_dir)
# Model
FeatModel = load_model(config.feat_model)
InlierModel = load_model(config.inlier_model)
num_feats = 6 if self.config.inlier_feature_type == 'coords' else 1
self.feat_model = FeatModel(num_feats,
config.feat_model_n_out,
bn_momentum=config.bn_momentum,
conv1_kernel_size=config.feat_conv1_kernel_size,
normalize_feature=config.normalize_feature).to(
self.device)
logging.info(self.feat_model)
self.inlier_model = InlierModel(num_feats,
1,
bn_momentum=config.bn_momentum,
conv1_kernel_size=config.inlier_conv1_kernel_size,
normalize_feature=False,
D=6).to(self.device)
logging.info(self.inlier_model)
# Loss and optimizer
self.clip_weight_thresh = self.config.clip_weight_thresh
if self.config.use_balanced_loss:
self.crit = BalancedLoss()
else:
self.crit = UnbalancedLoss()
self.optimizer = getattr(optim, config.optimizer)(self.inlier_model.parameters(),
lr=config.lr,
momentum=config.momentum,
weight_decay=config.weight_decay)
self.scheduler = optim.lr_scheduler.ExponentialLR(self.optimizer, config.exp_gamma)
# Output preparation
ensure_dir(self.checkpoint_dir)
json.dump(config,
open(os.path.join(self.checkpoint_dir, 'config.json'), 'w'),
indent=4,
sort_keys=False)
self._load_weights(config)
def train(self):
"""
Major interface
Full training logic: train, valid, and save
"""
# Baseline random feature performance
if self.test_valid:
val_dict = self._valid_epoch()
for k, v in val_dict.items():
self.writer.add_scalar(f'val/{k}', v, 0)
# Train and valid
for epoch in range(self.start_epoch, self.max_epoch + 1):
lr = self.scheduler.get_lr()
logging.info(f" Epoch: {epoch}, LR: {lr}")
self._train_epoch(epoch)
self._save_checkpoint(epoch)
self.scheduler.step()
if self.test_valid and epoch % self.val_epoch_freq == 0:
val_dict = self._valid_epoch()
for k, v in val_dict.items():
self.writer.add_scalar(f'val/{k}', v, epoch)
if self.best_val < val_dict[self.best_val_metric]:
logging.info(
f'Saving the best val model with {self.best_val_metric}: {val_dict[self.best_val_metric]}'
)
self.best_val = val_dict[self.best_val_metric]
self.best_val_epoch = epoch
self._save_checkpoint(epoch, 'best_val_checkpoint')
else:
logging.info(
f'Current best val model with {self.best_val_metric}: {self.best_val} at epoch {self.best_val_epoch}'
)
def _train_epoch(self, epoch):
gc.collect()
# Fix the feature model and train the inlier model
self.feat_model.eval()
self.inlier_model.train()
# Epoch starts from 1
total_loss, total_num = 0, 0.0
data_loader = self.data_loader
iter_size = self.iter_size
# Meters for statistics
average_valid_meter = AverageMeter()
loss_meter = AverageMeter()
data_meter = AverageMeter()
regist_succ_meter = AverageMeter()
regist_rte_meter = AverageMeter()
regist_rre_meter = AverageMeter()
# Timers for profiling
data_timer = Timer()
nn_timer = Timer()
inlier_timer = Timer()
total_timer = Timer()
if self.config.num_train_iter > 0:
num_train_iter = self.config.num_train_iter
else:
num_train_iter = len(data_loader) // iter_size
start_iter = (epoch - 1) * num_train_iter
tp, fp, tn, fn = 0, 0, 0, 0
# Iterate over batches
for curr_iter in range(num_train_iter):
self.optimizer.zero_grad()
batch_loss, data_time = 0, 0
total_timer.tic()
for iter_idx in range(iter_size):
data_timer.tic()
input_dict = self.get_data(self.train_data_loader_iter)
data_time += data_timer.toc(average=False)
# Initial inlier prediction with FCGF and KNN matching
reg_coords, reg_feats, pred_pairs, is_correct, feat_time, nn_time = self.generate_inlier_input(
xyz0=input_dict['pcd0'],
xyz1=input_dict['pcd1'],
iC0=input_dict['sinput0_C'],
iC1=input_dict['sinput1_C'],
iF0=input_dict['sinput0_F'],
iF1=input_dict['sinput1_F'],
len_batch=input_dict['len_batch'],
pos_pairs=input_dict['correspondences'])
nn_timer.update(nn_time)
# Inlier prediction with 6D ConvNet
inlier_timer.tic()
reg_sinput = ME.SparseTensor(reg_feats.contiguous(),
coords=reg_coords.int()).to(self.device)
reg_soutput = self.inlier_model(reg_sinput)
inlier_timer.toc()
logits = reg_soutput.F
weights = logits.sigmoid()
# Truncate weights too low
# For training, inplace modification is prohibited for backward
if self.clip_weight_thresh > 0:
weights_tmp = torch.zeros_like(weights)
valid_mask = weights > self.clip_weight_thresh
weights_tmp[valid_mask] = weights[valid_mask]
weights = weights_tmp
# Weighted Procrustes
pred_rots, pred_trans, ws = self.weighted_procrustes(xyz0s=input_dict['pcd0'],
xyz1s=input_dict['pcd1'],
pred_pairs=pred_pairs,
weights=weights)
# Get batch registration loss
gt_rots, gt_trans = self.decompose_rotation_translation(input_dict['T_gt'])
rot_error = batch_rotation_error(pred_rots, gt_rots)
trans_error = batch_translation_error(pred_trans, gt_trans)
individual_loss = rot_error + self.config.trans_weight * trans_error
# Select batches with at least 10 valid correspondences
valid_mask = ws > 10
num_valid = valid_mask.sum().item()
average_valid_meter.update(num_valid)
# Registration loss against registration GT
loss = self.config.procrustes_loss_weight * individual_loss[valid_mask].mean()
if not np.isfinite(loss.item()):
max_val = loss.item()
logging.info('Loss is infinite, abort ')
continue
# Direct inlier loss against nearest neighbor searched GT
target = torch.from_numpy(is_correct).squeeze()
if self.config.inlier_use_direct_loss:
inlier_loss = self.config.inlier_direct_loss_weight * self.crit(
logits.cpu().squeeze(), target.to(torch.float)) / iter_size
loss += inlier_loss
loss.backward()
# Update statistics before backprop
with torch.no_grad():
regist_rre_meter.update(rot_error.squeeze() * 180 / np.pi)
regist_rte_meter.update(trans_error.squeeze())
success = (trans_error.squeeze() < self.config.success_rte_thresh) * (
rot_error.squeeze() * 180 / np.pi < self.config.success_rre_thresh)
regist_succ_meter.update(success.float())
batch_loss += loss.mean().item()
neg_target = (~target).to(torch.bool)
pred = logits > 0 # todo thresh
pred_on_pos, pred_on_neg = pred[target], pred[neg_target]
tp += pred_on_pos.sum().item()
fp += pred_on_neg.sum().item()
tn += (~pred_on_neg).sum().item()
fn += (~pred_on_pos).sum().item()
# Check gradient and avoid backprop of inf values
max_grad = torch.abs(self.inlier_model.final.kernel.grad).max().cpu().item()
# Backprop only if gradient is finite
if not np.isfinite(max_grad):
self.optimizer.zero_grad()
logging.info(f'Clearing the NaN gradient at iter {curr_iter}')
else:
self.optimizer.step()
gc.collect()
torch.cuda.empty_cache()
total_loss += batch_loss
total_num += 1.0
total_timer.toc()
data_meter.update(data_time)
loss_meter.update(batch_loss)
# Output to logs
if curr_iter % self.config.stat_freq == 0:
precision = tp / (tp + fp + eps)
recall = tp / (tp + fn + eps)
f1 = 2 * (precision * recall) / (precision + recall + eps)
tpr = tp / (tp + fn + eps)
tnr = tn / (tn + fp + eps)
balanced_accuracy = (tpr + tnr) / 2
correspondence_accuracy = is_correct.sum() / len(is_correct)
stat = {
'loss': loss_meter.avg,
'precision': precision,
'recall': recall,
'tpr': tpr,
'tnr': tnr,
'balanced_accuracy': balanced_accuracy,
'f1': f1,
'num_valid': average_valid_meter.avg,
}
for k, v in stat.items():
self.writer.add_scalar(f'train/{k}', v, start_iter + curr_iter)
logging.info(' '.join([
f"Train Epoch: {epoch} [{curr_iter}/{num_train_iter}],",
f"Current Loss: {loss_meter.avg:.3e},",
f"Correspondence acc: {correspondence_accuracy:.3e}",
f", Precision: {precision:.4f}, Recall: {recall:.4f}, F1: {f1:.4f},",
f"TPR: {tpr:.4f}, TNR: {tnr:.4f}, BAcc: {balanced_accuracy:.4f}",
f"RTE: {regist_rte_meter.avg:.3e}, RRE: {regist_rre_meter.avg:.3e},",
f"Succ rate: {regist_succ_meter.avg:3e}",
f"Avg num valid: {average_valid_meter.avg:3e}",
f"\tData time: {data_meter.avg:.4f}, Train time: {total_timer.avg - data_meter.avg:.4f},",
f"NN search time: {nn_timer.avg:.3e}, Total time: {total_timer.avg:.4f}"
]))
loss_meter.reset()
regist_rte_meter.reset()
regist_rre_meter.reset()
regist_succ_meter.reset()
average_valid_meter.reset()
data_meter.reset()
total_timer.reset()
tp, fp, tn, fn = 0, 0, 0, 0
def _valid_epoch(self):
# Change the network to evaluation mode
self.feat_model.eval()
self.inlier_model.eval()
self.val_data_loader.dataset.reset_seed(0)
num_data = 0
loss_meter = AverageMeter()
hit_ratio_meter = AverageMeter()
regist_succ_meter = AverageMeter()
regist_rte_meter = AverageMeter()
regist_rre_meter = AverageMeter()
data_timer = Timer()
feat_timer = Timer()
inlier_timer = Timer()
nn_timer = Timer()
dgr_timer = Timer()
tot_num_data = len(self.val_data_loader.dataset)
if self.val_max_iter > 0:
tot_num_data = min(self.val_max_iter, tot_num_data)
tot_num_data = int(tot_num_data / self.val_data_loader.batch_size)
data_loader_iter = self.val_data_loader.__iter__()
tp, fp, tn, fn = 0, 0, 0, 0
for batch_idx in range(tot_num_data):
data_timer.tic()
input_dict = self.get_data(data_loader_iter)
data_timer.toc()
reg_coords, reg_feats, pred_pairs, is_correct, feat_time, nn_time = self.generate_inlier_input(
xyz0=input_dict['pcd0'],
xyz1=input_dict['pcd1'],
iC0=input_dict['sinput0_C'],
iC1=input_dict['sinput1_C'],
iF0=input_dict['sinput0_F'],
iF1=input_dict['sinput1_F'],
len_batch=input_dict['len_batch'],
pos_pairs=input_dict['correspondences'])
feat_timer.update(feat_time)
nn_timer.update(nn_time)
hit_ratio_meter.update(is_correct.sum().item() / len(is_correct))
inlier_timer.tic()
reg_sinput = ME.SparseTensor(reg_feats.contiguous(),
coords=reg_coords.int()).to(self.device)
reg_soutput = self.inlier_model(reg_sinput)
inlier_timer.toc()
dgr_timer.tic()
logits = reg_soutput.F
weights = logits.sigmoid()
if self.clip_weight_thresh > 0:
weights[weights < self.clip_weight_thresh] = 0
# Weighted Procrustes
pred_rots, pred_trans, ws = self.weighted_procrustes(xyz0s=input_dict['pcd0'],
xyz1s=input_dict['pcd1'],
pred_pairs=pred_pairs,
weights=weights)
dgr_timer.toc()
valid_mask = ws > 10
gt_rots, gt_trans = self.decompose_rotation_translation(input_dict['T_gt'])
rot_error = batch_rotation_error(pred_rots, gt_rots) * 180 / np.pi
trans_error = batch_translation_error(pred_trans, gt_trans)
regist_rre_meter.update(rot_error.squeeze())
regist_rte_meter.update(trans_error.squeeze())
# Compute success
success = (trans_error < self.config.success_rte_thresh) * (
rot_error < self.config.success_rre_thresh) * valid_mask
regist_succ_meter.update(success.float())
target = torch.from_numpy(is_correct).squeeze()
neg_target = (~target).to(torch.bool)
pred = weights > 0.5 # TODO thresh
pred_on_pos, pred_on_neg = pred[target], pred[neg_target]
tp += pred_on_pos.sum().item()
fp += pred_on_neg.sum().item()
tn += (~pred_on_neg).sum().item()
fn += (~pred_on_pos).sum().item()
num_data += 1
torch.cuda.empty_cache()
if batch_idx % self.config.stat_freq == 0:
precision = tp / (tp + fp + eps)
recall = tp / (tp + fn + eps)
f1 = 2 * (precision * recall) / (precision + recall + eps)
tpr = tp / (tp + fn + eps)
tnr = tn / (tn + fp + eps)
balanced_accuracy = (tpr + tnr) / 2
logging.info(' '.join([
f"Validation iter {num_data} / {tot_num_data} : Data Loading Time: {data_timer.avg:.3e},",
f"NN search time: {nn_timer.avg:.3e}",
f"Feature Extraction Time: {feat_timer.avg:.3e}, Inlier Time: {inlier_timer.avg:.3e},",
f"Loss: {loss_meter.avg:.4f}, Hit Ratio: {hit_ratio_meter.avg:.4f}, Precision: {precision:.4f}, Recall: {recall:.4f}, F1: {f1:.4f}, ",
f"TPR: {tpr:.4f}, TNR: {tnr:.4f}, BAcc: {balanced_accuracy:.4f}, ",
f"DGR RTE: {regist_rte_meter.avg:.3e}, DGR RRE: {regist_rre_meter.avg:.3e}, DGR Time: {dgr_timer.avg:.3e}",
f"DGR Succ rate: {regist_succ_meter.avg:3e}",
]))
data_timer.reset()
precision = tp / (tp + fp + eps)
recall = tp / (tp + fn + eps)
f1 = 2 * (precision * recall) / (precision + recall + eps)
tpr = tp / (tp + fn + eps)
tnr = tn / (tn + fp + eps)
balanced_accuracy = (tpr + tnr) / 2
logging.info(' '.join([
f"Feature Extraction Time: {feat_timer.avg:.3e}, NN search time: {nn_timer.avg:.3e}",
f"Inlier Time: {inlier_timer.avg:.3e}, Final Loss: {loss_meter.avg}, ",
f"Loss: {loss_meter.avg}, Hit Ratio: {hit_ratio_meter.avg:.4f}, Precision: {precision}, Recall: {recall}, F1: {f1}, ",
f"TPR: {tpr}, TNR: {tnr}, BAcc: {balanced_accuracy}, ",
f"RTE: {regist_rte_meter.avg:.3e}, RRE: {regist_rre_meter.avg:.3e}, DGR Time: {dgr_timer.avg:.3e}",
f"DGR Succ rate: {regist_succ_meter.avg:3e}",
]))
stat = {
'loss': loss_meter.avg,
'precision': precision,
'recall': recall,
'tpr': tpr,
'tnr': tnr,
'balanced_accuracy': balanced_accuracy,
'f1': f1,
'regist_rte': regist_rte_meter.avg,
'regist_rre': regist_rre_meter.avg,
'succ_rate': regist_succ_meter.avg
}
return stat
def _load_weights(self, config):
if config.resume is None and config.weights:
logging.info("=> loading weights for inlier model '{}'".format(config.weights))
checkpoint = torch.load(config.weights)
self.feat_model.load_state_dict(checkpoint['state_dict'])
logging.info("=> Loaded base model weights from '{}'".format(config.weights))
if 'state_dict_inlier' in checkpoint:
self.inlier_model.load_state_dict(checkpoint['state_dict_inlier'])
logging.info("=> Loaded inlier weights from '{}'".format(config.weights))
else:
logging.warn("Inlier weight not found in '{}'".format(config.weights))
if config.resume is not None:
if osp.isfile(config.resume):
logging.info("=> loading checkpoint '{}'".format(config.resume))
state = torch.load(config.resume)
self.start_epoch = state['epoch']
self.feat_model.load_state_dict(state['state_dict'])
self.feat_model = self.feat_model.to(self.device)
self.scheduler.load_state_dict(state['scheduler'])
self.optimizer.load_state_dict(state['optimizer'])
if 'best_val' in state.keys():
self.best_val = state['best_val']
self.best_val_epoch = state['best_val_epoch']
self.best_val_metric = state['best_val_metric']
if 'state_dict_inlier' in state:
self.inlier_model.load_state_dict(state['state_dict_inlier'])
self.inlier_model = self.inlier_model.to(self.device)
else:
logging.warn("Inlier weights not found in '{}'".format(config.resume))
else:
logging.warn("Inlier weights does not exist at '{}'".format(config.resume))
def _save_checkpoint(self, epoch, filename='checkpoint'):
"""
Saving checkpoints
:param epoch: current epoch number
:param log: logging information of the epoch
:param save_best: if True, rename the saved checkpoint to 'model_best.pth'
"""
print('_save_checkpoint from inlier_trainer')
state = {
'epoch': epoch,
'state_dict': self.feat_model.state_dict(),
'state_dict_inlier': self.inlier_model.state_dict(),
'optimizer': self.optimizer.state_dict(),
'scheduler': self.scheduler.state_dict(),
'config': self.config,
'best_val': self.best_val,
'best_val_epoch': self.best_val_epoch,
'best_val_metric': self.best_val_metric
}
filename = os.path.join(self.checkpoint_dir, f'{filename}.pth')
logging.info("Saving checkpoint: {} ...".format(filename))
torch.save(state, filename)
def get_data(self, iterator):
while True:
try:
input_data = iterator.next()
except ValueError as e:
logging.info('Skipping an empty batch')
continue
return input_data
def decompose_by_length(self, tensor, reference_tensors):
decomposed_tensors = []
start_ind = 0
for r in reference_tensors:
N = len(r)
decomposed_tensors.append(tensor[start_ind:start_ind + N])
start_ind += N
return decomposed_tensors
def decompose_rotation_translation(self, Ts):
Ts = Ts.float()
Rs = Ts[:, :3, :3]
ts = Ts[:, :3, 3]
Rs.require_grad = False
ts.require_grad = False
return Rs, ts
def weighted_procrustes(self, xyz0s, xyz1s, pred_pairs, weights):
decomposed_weights = self.decompose_by_length(weights, pred_pairs)
RT = []
ws = []
for xyz0, xyz1, pred_pair, w in zip(xyz0s, xyz1s, pred_pairs, decomposed_weights):
xyz0.requires_grad = False
xyz1.requires_grad = False
ws.append(w.sum().item())
predT = GlobalRegistration.weighted_procrustes(
X=xyz0[pred_pair[:, 0]].to(self.device),
Y=xyz1[pred_pair[:, 1]].to(self.device),
w=w,
eps=np.finfo(np.float32).eps)
RT.append(predT)
Rs, ts = list(zip(*RT))
Rs = torch.stack(Rs, 0)
ts = torch.stack(ts, 0)
ws = torch.Tensor(ws)
return Rs, ts, ws
def generate_inlier_features(self, xyz0, xyz1, C0, C1, F0, F1, pair_ind0, pair_ind1):
"""
Assume that the indices 0 and indices 1 gives the pairs in the
(downsampled) correspondences.
"""
assert len(pair_ind0) == len(pair_ind1)
reg_feat_type = self.config.inlier_feature_type
assert reg_feat_type in ['ones', 'coords', 'counts', 'feats']
# Move coordinates and indices to the device
if 'coords' in reg_feat_type:
C0 = C0.to(self.device)
C1 = C1.to(self.device)
# TODO: change it to append the features and then concat at last
if reg_feat_type == 'ones':
reg_feat = torch.ones((len(pair_ind0), 1)).to(torch.float32)
elif reg_feat_type == 'feats':
reg_feat = torch.cat((F0[pair_ind0], F1[pair_ind1]), dim=1)
elif reg_feat_type == 'coords':
reg_feat = torch.cat((torch.cos(torch.cat(
xyz0, 0)[pair_ind0]), torch.cos(torch.cat(xyz1, 0)[pair_ind1])),
dim=1)
else:
raise ValueError('Inlier feature type not defined')
return reg_feat
def generate_inlier_input(self, xyz0, xyz1, iC0, iC1, iF0, iF1, len_batch, pos_pairs):
# pairs consist of (xyz1 index, xyz0 index)
stime = time.time()
sinput0 = ME.SparseTensor(iF0, coords=iC0).to(self.device)
oF0 = self.feat_model(sinput0).F
sinput1 = ME.SparseTensor(iF1, coords=iC1).to(self.device)
oF1 = self.feat_model(sinput1).F
feat_time = time.time() - stime
stime = time.time()
pred_pairs = self.find_pairs(oF0, oF1, len_batch)
nn_time = time.time() - stime
is_correct = find_correct_correspondence(pos_pairs, pred_pairs, len_batch=len_batch)
cat_pred_pairs = []
start_inds = torch.zeros((1, 2)).long()
for lens, pred_pair in zip(len_batch, pred_pairs):
cat_pred_pairs.append(pred_pair + start_inds)
start_inds += torch.LongTensor(lens)
cat_pred_pairs = torch.cat(cat_pred_pairs, 0)
pred_pair_inds0, pred_pair_inds1 = cat_pred_pairs.t()
reg_coords = torch.cat((iC0[pred_pair_inds0], iC1[pred_pair_inds1, 1:]), 1)
reg_feats = self.generate_inlier_features(xyz0, xyz1, iC0, iC1, oF0, oF1,
pred_pair_inds0, pred_pair_inds1).float()
return reg_coords, reg_feats, pred_pairs, is_correct, feat_time, nn_time
def find_pairs(self, F0, F1, len_batch):
nn_batch = find_knn_batch(F0,
F1,
len_batch,
nn_max_n=self.config.nn_max_n,
knn=self.config.inlier_knn,
return_distance=False,
search_method=self.config.knn_search_method)
pred_pairs = []
for nns, lens in zip(nn_batch, len_batch):
pred_pair_ind0, pred_pair_ind1 = torch.arange(
len(nns)).long()[:, None], nns.long().cpu()
nn_pairs = []
for j in range(nns.shape[1]):
nn_pairs.append(
torch.cat((pred_pair_ind0.cpu(), pred_pair_ind1[:, j].unsqueeze(1)), 1))
pred_pairs.append(torch.cat(nn_pairs, 0))
return pred_pairs
================================================
FILE: dataloader/base_loader.py
================================================
# Copyright (c) Chris Choy (chrischoy@ai.stanford.edu) and Wei Dong (weidong@andrew.cmu.edu)
#
# Please cite the following papers if you use any part of the code.
# - Christopher Choy, Wei Dong, Vladlen Koltun, Deep Global Registration, CVPR 2020
# - Christopher Choy, Jaesik Park, Vladlen Koltun, Fully Convolutional Geometric Features, ICCV 2019
# - Christopher Choy, JunYoung Gwak, Silvio Savarese, 4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural Networks, CVPR 2019
#
# Written by Chris Choy <chrischoy@ai.stanford.edu>
# Distributed under MIT License
import os
import logging
import random
import torch
import torch.utils.data
import numpy as np
import dataloader.transforms as t
from dataloader.inf_sampler import InfSampler
import MinkowskiEngine as ME
import open3d as o3d
class CollationFunctionFactory:
def __init__(self, concat_correspondences=True, collation_type='default'):
self.concat_correspondences = concat_correspondences
if collation_type == 'default':
self.collation_fn = self.collate_default
elif collation_type == 'collate_pair':
self.collation_fn = self.collate_pair_fn
else:
raise ValueError(f'collation_type {collation_type} not found')
def __call__(self, list_data):
return self.collation_fn(list_data)
def collate_default(self, list_data):
return list_data
def collate_pair_fn(self, list_data):
N = len(list_data)
list_data = [data for data in list_data if data is not None]
if N != len(list_data):
logging.info(f"Retain {len(list_data)} from {N} data.")
if len(list_data) == 0:
raise ValueError('No data in the batch')
xyz0, xyz1, coords0, coords1, feats0, feats1, matching_inds, trans, extra_packages = list(
zip(*list_data))
matching_inds_batch, trans_batch, len_batch = [], [], []
coords_batch0 = ME.utils.batched_coordinates(coords0)
coords_batch1 = ME.utils.batched_coordinates(coords1)
trans_batch = torch.from_numpy(np.stack(trans)).float()
curr_start_inds = torch.zeros((1, 2), dtype=torch.int32)
for batch_id, _ in enumerate(coords0):
# For scan2cad there will be empty matching_inds even after filtering
# This check will skip these pairs while not affecting other datasets
if (len(matching_inds[batch_id]) == 0):
continue
N0 = coords0[batch_id].shape[0]
N1 = coords1[batch_id].shape[0]
if self.concat_correspondences:
matching_inds_batch.append(
torch.IntTensor(matching_inds[batch_id]) + curr_start_inds)
else:
matching_inds_batch.append(torch.IntTensor(matching_inds[batch_id]))
len_batch.append([N0, N1])
# Move the head
curr_start_inds[0, 0] += N0
curr_start_inds[0, 1] += N1
# Concatenate all lists
feats_batch0 = torch.cat(feats0, 0).float()
feats_batch1 = torch.cat(feats1, 0).float()
# xyz_batch0 = torch.cat(xyz0, 0).float()
# xyz_batch1 = torch.cat(xyz1, 0).float()
# trans_batch = torch.cat(trans_batch, 0).float()
if self.concat_correspondences:
matching_inds_batch = torch.cat(matching_inds_batch, 0).int()
return {
'pcd0': xyz0,
'pcd1': xyz1,
'sinput0_C': coords_batch0,
'sinput0_F': feats_batch0,
'sinput1_C': coords_batch1,
'sinput1_F': feats_batch1,
'correspondences': matching_inds_batch,
'T_gt': trans_batch,
'len_batch': len_batch,
'extra_packages': extra_packages,
}
class PairDataset(torch.utils.data.Dataset):
AUGMENT = None
def __init__(self,
phase,
transform=None,
random_rotation=True,
random_scale=True,
manual_seed=False,
config=None):
self.phase = phase
self.files = []
self.data_objects = []
self.transform = transform
self.voxel_size = config.voxel_size
self.matching_search_voxel_size = \
config.voxel_size * config.positive_pair_search_voxel_size_multiplier
self.random_scale = random_scale
self.min_scale = config.min_scale
self.max_scale = config.max_scale
self.random_rotation = random_rotation
self.rotation_range = config.rotation_range
self.randg = np.random.RandomState()
if manual_seed:
self.reset_seed()
def reset_seed(self, seed=0):
logging.info(f"Resetting the data loader seed to {seed}")
self.randg.seed(seed)
def apply_transform(self, pts, trans):
R = trans[:3, :3]
T = trans[:3, 3]
pts = pts @ R.T + T
return pts
def __len__(self):
return len(self.files)
================================================
FILE: dataloader/data_loaders.py
================================================
# Copyright (c) Chris Choy (chrischoy@ai.stanford.edu) and Wei Dong (weidong@andrew.cmu.edu)
#
# Please cite the following papers if you use any part of the code.
# - Christopher Choy, Wei Dong, Vladlen Koltun, Deep Global Registration, CVPR 2020
# - Christopher Choy, Jaesik Park, Vladlen Koltun, Fully Convolutional Geometric Features, ICCV 2019
# - Christopher Choy, JunYoung Gwak, Silvio Savarese, 4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural Networks, CVPR 2019
from dataloader.threedmatch_loader import *
from dataloader.kitti_loader import *
ALL_DATASETS = [
ThreeDMatchPairDataset07, ThreeDMatchPairDataset05, ThreeDMatchPairDataset03,
ThreeDMatchTrajectoryDataset, KITTIPairDataset, KITTINMPairDataset
]
dataset_str_mapping = {d.__name__: d for d in ALL_DATASETS}
def make_data_loader(config, phase, batch_size, num_workers=0, shuffle=None):
assert phase in ['train', 'trainval', 'val', 'test']
if shuffle is None:
shuffle = phase != 'test'
if config.dataset not in dataset_str_mapping.keys():
logging.error(f'Dataset {config.dataset}, does not exists in ' +
', '.join(dataset_str_mapping.keys()))
Dataset = dataset_str_mapping[config.dataset]
use_random_scale = False
use_random_rotation = False
transforms = []
if phase in ['train', 'trainval']:
use_random_rotation = config.use_random_rotation
use_random_scale = config.use_random_scale
transforms += [t.Jitter()]
if phase in ['val', 'test']:
use_random_rotation = config.test_random_rotation
dset = Dataset(phase,
transform=t.Compose(transforms),
random_scale=use_random_scale,
random_rotation=use_random_rotation,
config=config)
collation_fn = CollationFunctionFactory(concat_correspondences=False,
collation_type='collate_pair')
loader = torch.utils.data.DataLoader(dset,
batch_size=batch_size,
collate_fn=collation_fn,
num_workers=num_workers,
sampler=InfSampler(dset, shuffle))
return loader
================================================
FILE: dataloader/inf_sampler.py
================================================
# Copyright (c) Chris Choy (chrischoy@ai.stanford.edu) and Wei Dong (weidong@andrew.cmu.edu)
#
# Please cite the following papers if you use any part of the code.
# - Christopher Choy, Wei Dong, Vladlen Koltun, Deep Global Registration, CVPR 2020
# - Christopher Choy, Jaesik Park, Vladlen Koltun, Fully Convolutional Geometric Features, ICCV 2019
# - Christopher Choy, JunYoung Gwak, Silvio Savarese, 4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural Networks, CVPR 2019
import torch
from torch.utils.data.sampler import Sampler
class InfSampler(Sampler):
"""Samples elements randomly, without replacement.
Arguments:
data_source (Dataset): dataset to sample from
"""
def __init__(self, data_source, shuffle=False):
self.data_source = data_source
self.shuffle = shuffle
self.reset_permutation()
def reset_permutation(self):
perm = len(self.data_source)
if self.shuffle:
perm = torch.randperm(perm)
self._perm = perm.tolist()
def __iter__(self):
return self
def __next__(self):
if len(self._perm) == 0:
self.reset_permutation()
return self._perm.pop()
def __len__(self):
return len(self.data_source)
================================================
FILE: dataloader/kitti_loader.py
================================================
# Copyright (c) Chris Choy (chrischoy@ai.stanford.edu) and Wei Dong (weidong@andrew.cmu.edu)
#
# Please cite the following papers if you use any part of the code.
# - Christopher Choy, Wei Dong, Vladlen Koltun, Deep Global Registration, CVPR 2020
# - Christopher Choy, Jaesik Park, Vladlen Koltun, Fully Convolutional Geometric Features, ICCV 2019
# - Christopher Choy, JunYoung Gwak, Silvio Savarese, 4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural Networks, CVPR 2019
import os
import glob
from dataloader.base_loader import *
from dataloader.transforms import *
from util.pointcloud import get_matching_indices, make_open3d_point_cloud
kitti_cache = {}
kitti_icp_cache = {}
class KITTIPairDataset(PairDataset):
AUGMENT = None
DATA_FILES = {
'train': './dataloader/split/train_kitti.txt',
'val': './dataloader/split/val_kitti.txt',
'test': './dataloader/split/test_kitti.txt'
}
TEST_RANDOM_ROTATION = False
IS_ODOMETRY = True
def __init__(self,
phase,
transform=None,
random_rotation=True,
random_scale=True,
manual_seed=False,
config=None):
# For evaluation, use the odometry dataset training following the 3DFeat eval method
self.root = root = config.kitti_dir + '/dataset'
random_rotation = self.TEST_RANDOM_ROTATION
self.icp_path = config.icp_cache_path
try:
os.mkdir(self.icp_path)
except OSError as error:
pass
PairDataset.__init__(self, phase, transform, random_rotation, random_scale,
manual_seed, config)
logging.info(f"Loading the subset {phase} from {root}")
# Use the kitti root
self.max_time_diff = max_time_diff = config.kitti_max_time_diff
subset_names = open(self.DATA_FILES[phase]).read().split()
for dirname in subset_names:
drive_id = int(dirname)
inames = self.get_all_scan_ids(drive_id)
for start_time in inames:
for time_diff in range(2, max_time_diff):
pair_time = time_diff + start_time
if pair_time in inames:
self.files.append((drive_id, start_time, pair_time))
def get_all_scan_ids(self, drive_id):
fnames = glob.glob(self.root + '/sequences/%02d/velodyne/*.bin' % drive_id)
assert len(
fnames) > 0, f"Make sure that the path {self.root} has drive id: {drive_id}"
inames = [int(os.path.split(fname)[-1][:-4]) for fname in fnames]
return inames
@property
def velo2cam(self):
try:
velo2cam = self._velo2cam
except AttributeError:
R = np.array([
7.533745e-03, -9.999714e-01, -6.166020e-04, 1.480249e-02, 7.280733e-04,
-9.998902e-01, 9.998621e-01, 7.523790e-03, 1.480755e-02
]).reshape(3, 3)
T = np.array([-4.069766e-03, -7.631618e-02, -2.717806e-01]).reshape(3, 1)
velo2cam = np.hstack([R, T])
self._velo2cam = np.vstack((velo2cam, [0, 0, 0, 1])).T
return self._velo2cam
def get_video_odometry(self, drive, indices=None, ext='.txt', return_all=False):
data_path = self.root + '/poses/%02d.txt' % drive
if data_path not in kitti_cache:
kitti_cache[data_path] = np.genfromtxt(data_path)
if return_all:
return kitti_cache[data_path]
else:
return kitti_cache[data_path][indices]
def odometry_to_positions(self, odometry):
T_w_cam0 = odometry.reshape(3, 4)
T_w_cam0 = np.vstack((T_w_cam0, [0, 0, 0, 1]))
return T_w_cam0
def rot3d(self, axis, angle):
ei = np.ones(3, dtype='bool')
ei[axis] = 0
i = np.nonzero(ei)[0]
m = np.eye(3)
c, s = np.cos(angle), np.sin(angle)
m[i[0], i[0]] = c
m[i[0], i[1]] = -s
m[i[1], i[0]] = s
m[i[1], i[1]] = c
return m
def pos_transform(self, pos):
x, y, z, rx, ry, rz, _ = pos[0]
RT = np.eye(4)
RT[:3, :3] = np.dot(np.dot(self.rot3d(0, rx), self.rot3d(1, ry)), self.rot3d(2, rz))
RT[:3, 3] = [x, y, z]
return RT
def get_position_transform(self, pos0, pos1, invert=False):
T0 = self.pos_transform(pos0)
T1 = self.pos_transform(pos1)
return (np.dot(T1, np.linalg.inv(T0)).T if not invert else np.dot(
np.linalg.inv(T1), T0).T)
def _get_velodyne_fn(self, drive, t):
fname = self.root + '/sequences/%02d/velodyne/%06d.bin' % (drive, t)
return fname
def __getitem__(self, idx):
drive = self.files[idx][0]
t0, t1 = self.files[idx][1], self.files[idx][2]
all_odometry = self.get_video_odometry(drive, [t0, t1])
positions = [self.odometry_to_positions(odometry) for odometry in all_odometry]
fname0 = self._get_velodyne_fn(drive, t0)
fname1 = self._get_velodyne_fn(drive, t1)
# XYZ and reflectance
xyzr0 = np.fromfile(fname0, dtype=np.float32).reshape(-1, 4)
xyzr1 = np.fromfile(fname1, dtype=np.float32).reshape(-1, 4)
xyz0 = xyzr0[:, :3]
xyz1 = xyzr1[:, :3]
key = '%d_%d_%d' % (drive, t0, t1)
filename = self.icp_path + '/' + key + '.npy'
if key not in kitti_icp_cache:
if not os.path.exists(filename):
# work on the downsampled xyzs, 0.05m == 5cm
sel0 = ME.utils.sparse_quantize(xyz0 / 0.05, return_index=True)
sel1 = ME.utils.sparse_quantize(xyz1 / 0.05, return_index=True)
M = (self.velo2cam @ positions[0].T @ np.linalg.inv(positions[1].T)
@ np.linalg.inv(self.velo2cam)).T
xyz0_t = self.apply_transform(xyz0[sel0], M)
pcd0 = make_open3d_point_cloud(xyz0_t)
pcd1 = make_open3d_point_cloud(xyz1[sel1])
reg = o3d.registration.registration_icp(pcd0, pcd1, 0.2, np.eye(4),
o3d.registration.TransformationEstimationPointToPoint(),
o3d.registration.ICPConvergenceCriteria(max_iteration=200))
pcd0.transform(reg.transformation)
# pcd0.transform(M2) or self.apply_transform(xyz0, M2)
M2 = M @ reg.transformation
# o3d.draw_geometries([pcd0, pcd1])
# write to a file
np.save(filename, M2)
else:
M2 = np.load(filename)
kitti_icp_cache[key] = M2
else:
M2 = kitti_icp_cache[key]
if self.random_rotation:
T0 = sample_random_trans(xyz0, self.randg, np.pi / 4)
T1 = sample_random_trans(xyz1, self.randg, np.pi / 4)
trans = T1 @ M2 @ np.linalg.inv(T0)
xyz0 = self.apply_transform(xyz0, T0)
xyz1 = self.apply_transform(xyz1, T1)
else:
trans = M2
matching_search_voxel_size = self.matching_search_voxel_size
if self.random_scale and random.random() < 0.95:
scale = self.min_scale + \
(self.max_scale - self.min_scale) * random.random()
matching_search_voxel_size *= scale
xyz0 = scale * xyz0
xyz1 = scale * xyz1
# Voxelization
xyz0_th = torch.from_numpy(xyz0)
xyz1_th = torch.from_numpy(xyz1)
sel0 = ME.utils.sparse_quantize(xyz0_th / self.voxel_size, return_index=True)
sel1 = ME.utils.sparse_quantize(xyz1_th / self.voxel_size, return_index=True)
# Make point clouds using voxelized points
pcd0 = make_open3d_point_cloud(xyz0[sel0])
pcd1 = make_open3d_point_cloud(xyz1[sel1])
# Get matches
matches = get_matching_indices(pcd0, pcd1, trans, matching_search_voxel_size)
if len(matches) < 1000:
raise ValueError(f"Insufficient matches in {drive}, {t0}, {t1}")
# Get features
npts0 = len(sel0)
npts1 = len(sel1)
feats_train0, feats_train1 = [], []
unique_xyz0_th = xyz0_th[sel0]
unique_xyz1_th = xyz1_th[sel1]
feats_train0.append(torch.ones((npts0, 1)))
feats_train1.append(torch.ones((npts1, 1)))
feats0 = torch.cat(feats_train0, 1)
feats1 = torch.cat(feats_train1, 1)
coords0 = torch.floor(unique_xyz0_th / self.voxel_size)
coords1 = torch.floor(unique_xyz1_th / self.voxel_size)
if self.transform:
coords0, feats0 = self.transform(coords0, feats0)
coords1, feats1 = self.transform(coords1, feats1)
extra_package = {'drive': drive, 't0': t0, 't1': t1}
return (unique_xyz0_th.float(),
unique_xyz1_th.float(), coords0.int(), coords1.int(), feats0.float(),
feats1.float(), matches, trans, extra_package)
class KITTINMPairDataset(KITTIPairDataset):
r"""
Generate KITTI pairs within N meter distance
"""
MIN_DIST = 10
def __init__(self,
phase,
transform=None,
random_rotation=True,
random_scale=True,
manual_seed=False,
config=None):
self.root = root = os.path.join(config.kitti_dir, 'dataset')
self.icp_path = os.path.join(config.kitti_dir, config.icp_cache_path)
try:
os.mkdir(self.icp_path)
except OSError as error:
pass
random_rotation = self.TEST_RANDOM_ROTATION
PairDataset.__init__(self, phase, transform, random_rotation, random_scale,
manual_seed, config)
logging.info(f"Loading the subset {phase} from {root}")
subset_names = open(self.DATA_FILES[phase]).read().split()
for dirname in subset_names:
drive_id = int(dirname)
fnames = glob.glob(root + '/sequences/%02d/velodyne/*.bin' % drive_id)
assert len(fnames) > 0, f"Make sure that the path {root} has data {dirname}"
inames = sorted([int(os.path.split(fname)[-1][:-4]) for fname in fnames])
all_odo = self.get_video_odometry(drive_id, return_all=True)
all_pos = np.array([self.odometry_to_positions(odo) for odo in all_odo])
Ts = all_pos[:, :3, 3]
pdist = (Ts.reshape(1, -1, 3) - Ts.reshape(-1, 1, 3))**2
pdist = np.sqrt(pdist.sum(-1))
more_than_10 = pdist > self.MIN_DIST
curr_time = inames[0]
while curr_time in inames:
# Find the min index
next_time = np.where(more_than_10[curr_time][curr_time:curr_time + 100])[0]
if len(next_time) == 0:
curr_time += 1
else:
# Follow https://github.com/yewzijian/3DFeatNet/blob/master/scripts_data_processing/kitti/process_kitti_data.m#L44
next_time = next_time[0] + curr_time - 1
if next_time in inames:
self.files.append((drive_id, curr_time, next_time))
curr_time = next_time + 1
# Remove problematic sequence
for item in [
(8, 15, 58),
]:
if item in self.files:
self.files.pop(self.files.index(item))
================================================
FILE: dataloader/split/test_3dmatch.txt
================================================
7-scenes-redkitchen
sun3d-home_at-home_at_scan1_2013_jan_1
sun3d-home_md-home_md_scan9_2012_sep_30
sun3d-hotel_uc-scan3
sun3d-hotel_umd-maryland_hotel1
sun3d-hotel_umd-maryland_hotel3
sun3d-mit_76_studyroom-76-1studyroom2
sun3d-mit_lab_hj-lab_hj_tea_nov_2_2012_scan1_erika
================================================
FILE: dataloader/split/test_kitti.txt
================================================
8
9
10
================================================
FILE: dataloader/split/test_modelnet40.txt
================================================
glass_box/test/glass_box_0172.off
glass_box/test/glass_box_0173.off
glass_box/test/glass_box_0174.off
glass_box/test/glass_box_0175.off
glass_box/test/glass_box_0176.off
glass_box/test/glass_box_0177.off
glass_box/test/glass_box_0178.off
glass_box/test/glass_box_0179.off
glass_box/test/glass_box_0180.off
glass_box/test/glass_box_0181.off
glass_box/test/glass_box_0182.off
glass_box/test/glass_box_0183.off
glass_box/test/glass_box_0184.off
glass_box/test/glass_box_0185.off
glass_box/test/glass_box_0186.off
glass_box/test/glass_box_0187.off
glass_box/test/glass_box_0188.off
glass_box/test/glass_box_0189.off
glass_box/test/glass_box_0190.off
glass_box/test/glass_box_0191.off
glass_box/test/glass_box_0192.off
glass_box/test/glass_box_0193.off
glass_box/test/glass_box_0194.off
glass_box/test/glass_box_0195.off
glass_box/test/glass_box_0196.off
glass_box/test/glass_box_0197.off
glass_box/test/glass_box_0198.off
glass_box/test/glass_box_0199.off
glass_box/test/glass_box_0200.off
glass_box/test/glass_box_0201.off
glass_box/test/glass_box_0202.off
glass_box/test/glass_box_0203.off
glass_box/test/glass_box_0204.off
glass_box/test/glass_box_0205.off
glass_box/test/glass_box_0206.off
glass_box/test/glass_box_0207.off
glass_box/test/glass_box_0208.off
glass_box/test/glass_box_0209.off
glass_box/test/glass_box_0210.off
glass_box/test/glass_box_0211.off
glass_box/test/glass_box_0212.off
glass_box/test/glass_box_0213.off
glass_box/test/glass_box_0214.off
glass_box/test/glass_box_0215.off
glass_box/test/glass_box_0216.off
glass_box/test/glass_box_0217.off
glass_box/test/glass_box_0218.off
glass_box/test/glass_box_0219.off
glass_box/test/glass_box_0220.off
glass_box/test/glass_box_0221.off
glass_box/test/glass_box_0222.off
glass_box/test/glass_box_0223.off
glass_box/test/glass_box_0224.off
glass_box/test/glass_box_0225.off
glass_box/test/glass_box_0226.off
glass_box/test/glass_box_0227.off
glass_box/test/glass_box_0228.off
glass_box/test/glass_box_0229.off
glass_box/test/glass_box_0230.off
glass_box/test/glass_box_0231.off
glass_box/test/glass_box_0232.off
glass_box/test/glass_box_0233.off
glass_box/test/glass_box_0234.off
glass_box/test/glass_box_0235.off
glass_box/test/glass_box_0236.off
glass_box/test/glass_box_0237.off
glass_box/test/glass_box_0238.off
glass_box/test/glass_box_0239.off
glass_box/test/glass_box_0240.off
glass_box/test/glass_box_0241.off
glass_box/test/glass_box_0242.off
glass_box/test/glass_box_0243.off
glass_box/test/glass_box_0244.off
glass_box/test/glass_box_0245.off
glass_box/test/glass_box_0246.off
glass_box/test/glass_box_0247.off
glass_box/test/glass_box_0248.off
glass_box/test/glass_box_0249.off
glass_box/test/glass_box_0250.off
glass_box/test/glass_box_0251.off
glass_box/test/glass_box_0252.off
glass_box/test/glass_box_0253.off
glass_box/test/glass_box_0254.off
glass_box/test/glass_box_0255.off
glass_box/test/glass_box_0256.off
glass_box/test/glass_box_0257.off
glass_box/test/glass_box_0258.off
glass_box/test/glass_box_0259.off
glass_box/test/glass_box_0260.off
glass_box/test/glass_box_0261.off
glass_box/test/glass_box_0262.off
glass_box/test/glass_box_0263.off
glass_box/test/glass_box_0264.off
glass_box/test/glass_box_0265.off
glass_box/test/glass_box_0266.off
glass_box/test/glass_box_0267.off
glass_box/test/glass_box_0268.off
glass_box/test/glass_box_0269.off
glass_box/test/glass_box_0270.off
glass_box/test/glass_box_0271.off
laptop/test/laptop_0150.off
laptop/test/laptop_0151.off
laptop/test/laptop_0152.off
laptop/test/laptop_0153.off
laptop/test/laptop_0154.off
laptop/test/laptop_0155.off
laptop/test/laptop_0156.off
laptop/test/laptop_0157.off
laptop/test/laptop_0158.off
laptop/test/laptop_0159.off
laptop/test/laptop_0160.off
laptop/test/laptop_0161.off
laptop/test/laptop_0162.off
laptop/test/laptop_0163.off
laptop/test/laptop_0164.off
laptop/test/laptop_0165.off
laptop/test/laptop_0166.off
laptop/test/laptop_0167.off
laptop/test/laptop_0168.off
laptop/test/laptop_0169.off
sink/test/sink_0129.off
sink/test/sink_0130.off
sink/test/sink_0131.off
sink/test/sink_0132.off
sink/test/sink_0133.off
sink/test/sink_0134.off
sink/test/sink_0135.off
sink/test/sink_0136.off
sink/test/sink_0137.off
sink/test/sink_0138.off
sink/test/sink_0139.off
sink/test/sink_0140.off
sink/test/sink_0141.off
sink/test/sink_0142.off
sink/test/sink_0143.off
sink/test/sink_0144.off
sink/test/sink_0145.off
sink/test/sink_0146.off
sink/test/sink_0147.off
sink/test/sink_0148.off
night_stand/test/night_stand_0201.off
night_stand/test/night_stand_0202.off
night_stand/test/night_stand_0203.off
night_stand/test/night_stand_0204.off
night_stand/test/night_stand_0205.off
night_stand/test/night_stand_0206.off
night_stand/test/night_stand_0207.off
night_stand/test/night_stand_0208.off
night_stand/test/night_stand_0209.off
night_stand/test/night_stand_0210.off
night_stand/test/night_stand_0211.off
night_stand/test/night_stand_0212.off
night_stand/test/night_stand_0213.off
night_stand/test/night_stand_0214.off
night_stand/test/night_stand_0215.off
night_stand/test/night_stand_0216.off
night_stand/test/night_stand_0217.off
night_stand/test/night_stand_0218.off
night_stand/test/night_stand_0219.off
night_stand/test/night_stand_0220.off
night_stand/test/night_stand_0221.off
night_stand/test/night_stand_0222.off
night_stand/test/night_stand_0223.off
night_stand/test/night_stand_0224.off
night_stand/test/night_stand_0225.off
night_stand/test/night_stand_0226.off
night_stand/test/night_stand_0227.off
night_stand/test/night_stand_0228.off
night_stand/test/night_stand_0229.off
night_stand/test/night_stand_0230.off
night_stand/test/night_stand_0231.off
night_stand/test/night_stand_0232.off
night_stand/test/night_stand_0233.off
night_stand/test/night_stand_0234.off
night_stand/test/night_stand_0235.off
night_stand/test/night_stand_0236.off
night_stand/test/night_stand_0237.off
night_stand/test/night_stand_0238.off
night_stand/test/night_stand_0239.off
night_stand/test/night_stand_0240.off
night_stand/test/night_stand_0241.off
night_stand/test/night_stand_0242.off
night_stand/test/night_stand_0243.off
night_stand/test/night_stand_0244.off
night_stand/test/night_stand_0245.off
night_stand/test/night_stand_0246.off
night_stand/test/night_stand_0247.off
night_stand/test/night_stand_0248.off
night_stand/test/night_stand_0249.off
night_stand/test/night_stand_0250.off
night_stand/test/night_stand_0251.off
night_stand/test/night_stand_0252.off
night_stand/test/night_stand_0253.off
night_stand/test/night_stand_0254.off
night_stand/test/night_stand_0255.off
night_stand/test/night_stand_0256.off
night_stand/test/night_stand_0257.off
night_stand/test/night_stand_0258.off
night_stand/test/night_stand_0259.off
night_stand/test/night_stand_0260.off
night_stand/test/night_stand_0261.off
night_stand/test/night_stand_0262.off
night_stand/test/night_stand_0263.off
night_stand/test/night_stand_0264.off
night_stand/test/night_stand_0265.off
night_stand/test/night_stand_0266.off
night_stand/test/night_stand_0267.off
night_stand/test/night_stand_0268.off
night_stand/test/night_stand_0269.off
night_stand/test/night_stand_0270.off
night_stand/test/night_stand_0271.off
night_stand/test/night_stand_0272.off
night_stand/test/night_stand_0273.off
night_stand/test/night_stand_0274.off
night_stand/test/night_stand_0275.off
night_stand/test/night_stand_0276.off
night_stand/test/night_stand_0277.off
night_stand/test/night_stand_0278.off
night_stand/test/night_stand_0279.off
night_stand/test/night_stand_0280.off
night_stand/test/night_stand_0281.off
night_stand/test/night_stand_0282.off
night_stand/test/night_stand_0283.off
night_stand/test/night_stand_0284.off
night_stand/test/night_stand_0285.off
night_stand/test/night_stand_0286.off
car/test/car_0198.off
car/test/car_0199.off
car/test/car_0200.off
car/test/car_0201.off
car/test/car_0202.off
car/test/car_0203.off
car/test/car_0204.off
car/test/car_0205.off
car/test/car_0206.off
car/test/car_0207.off
car/test/car_0208.off
car/test/car_0209.off
car/test/car_0210.off
car/test/car_0211.off
car/test/car_0212.off
car/test/car_0213.off
car/test/car_0214.off
car/test/car_0215.off
car/test/car_0216.off
car/test/car_0217.off
car/test/car_0218.off
car/test/car_0219.off
car/test/car_0220.off
car/test/car_0221.off
car/test/car_0222.off
car/test/car_0223.off
car/test/car_0224.off
car/test/car_0225.off
car/test/car_0226.off
car/test/car_0227.off
car/test/car_0228.off
car/test/car_0229.off
car/test/car_0230.off
car/test/car_0231.off
car/test/car_0232.off
car/test/car_0233.off
car/test/car_0234.off
car/test/car_0235.off
car/test/car_0236.off
car/test/car_0237.off
car/test/car_0238.off
car/test/car_0239.off
car/test/car_0240.off
car/test/car_0241.off
car/test/car_0242.off
car/test/car_0243.off
car/test/car_0244.off
car/test/car_0245.off
car/test/car_0246.off
car/test/car_0247.off
car/test/car_0248.off
car/test/car_0249.off
car/test/car_0250.off
car/test/car_0251.off
car/test/car_0252.off
car/test/car_0253.off
car/test/car_0254.off
car/test/car_0255.off
car/test/car_0256.off
car/test/car_0257.off
car/test/car_0258.off
car/test/car_0259.off
car/test/car_0260.off
car/test/car_0261.off
car/test/car_0262.off
car/test/car_0263.off
car/test/car_0264.off
car/test/car_0265.off
car/test/car_0266.off
car/test/car_0267.off
car/test/car_0268.off
car/test/car_0269.off
car/test/car_0270.off
car/test/car_0271.off
car/test/car_0272.off
car/test/car_0273.off
car/test/car_0274.off
car/test/car_0275.off
car/test/car_0276.off
car/test/car_0277.off
car/test/car_0278.off
car/test/car_0279.off
car/test/car_0280.off
car/test/car_0281.off
car/test/car_0282.off
car/test/car_0283.off
car/test/car_0284.off
car/test/car_0285.off
car/test/car_0286.off
car/test/car_0287.off
car/test/car_0288.off
car/test/car_0289.off
car/test/car_0290.off
car/test/car_0291.off
car/test/car_0292.off
car/test/car_0293.off
car/test/car_0294.off
car/test/car_0295.off
car/test/car_0296.off
car/test/car_0297.off
dresser/test/dresser_0201.off
dresser/test/dresser_0202.off
dresser/test/dresser_0203.off
dresser/test/dresser_0204.off
dresser/test/dresser_0205.off
dresser/test/dresser_0206.off
dresser/test/dresser_0207.off
dresser/test/dresser_0208.off
dresser/test/dresser_0209.off
dresser/test/dresser_0210.off
dresser/test/dresser_0211.off
dresser/test/dresser_0212.off
dresser/test/dresser_0213.off
dresser/test/dresser_0214.off
dresser/test/dresser_0215.off
dresser/test/dresser_0216.off
dresser/test/dresser_0217.off
dresser/test/dresser_0218.off
dresser/test/dresser_0219.off
dresser/test/dresser_0220.off
dresser/test/dresser_0221.off
dresser/test/dresser_0222.off
dresser/test/dresser_0223.off
dresser/test/dresser_0224.off
dresser/test/dresser_0225.off
dresser/test/dresser_0226.off
dresser/test/dresser_0227.off
dresser/test/dresser_0228.off
dresser/test/dresser_0229.off
dresser/test/dresser_0230.off
dresser/test/dresser_0231.off
dresser/test/dresser_0232.off
dresser/test/dresser_0233.off
dresser/test/dresser_0234.off
dresser/test/dresser_0235.off
dresser/test/dresser_0236.off
dresser/test/dresser_0237.off
dresser/test/dresser_0238.off
dresser/test/dresser_0239.off
dresser/test/dresser_0240.off
dresser/test/dresser_0241.off
dresser/test/dresser_0242.off
dresser/test/dresser_0243.off
dresser/test/dresser_0244.off
dresser/test/dresser_0245.off
dresser/test/dresser_0246.off
dresser/test/dresser_0247.off
dresser/test/dresser_0248.off
dresser/test/dresser_0249.off
dresser/test/dresser_0250.off
dresser/test/dresser_0251.off
dresser/test/dresser_0252.off
dresser/test/dresser_0253.off
dresser/test/dresser_0254.off
dresser/test/dresser_0255.off
dresser/test/dresser_0256.off
dresser/test/dresser_0257.off
dresser/test/dresser_0258.off
dresser/test/dresser_0259.off
dresser/test/dresser_0260.off
dresser/test/dresser_0261.off
dresser/test/dresser_0262.off
dresser/test/dresser_0263.off
dresser/test/dresser_0264.off
dresser/test/dresser_0265.off
dresser/test/dresser_0266.off
dresser/test/dresser_0267.off
dresser/test/dresser_0268.off
dresser/test/dresser_0269.off
dresser/test/dresser_0270.off
dresser/test/dresser_0271.off
dresser/test/dresser_0272.off
dresser/test/dresser_0273.off
dresser/test/dresser_0274.off
dresser/test/dresser_0275.off
dresser/test/dresser_0276.off
dresser/test/dresser_0277.off
dresser/test/dresser_0278.off
dresser/test/dresser_0279.off
dresser/test/dresser_0280.off
dresser/test/dresser_0281.off
dresser/test/dresser_0282.off
dresser/test/dresser_0283.off
dresser/test/dresser_0284.off
dresser/test/dresser_0285.off
dresser/test/dresser_0286.off
toilet/test/toilet_0345.off
toilet/test/toilet_0346.off
toilet/test/toilet_0347.off
toilet/test/toilet_0348.off
toilet/test/toilet_0349.off
toilet/test/toilet_0350.off
toilet/test/toilet_0351.off
toilet/test/toilet_0352.off
toilet/test/toilet_0353.off
toilet/test/toilet_0354.off
toilet/test/toilet_0355.off
toilet/test/toilet_0356.off
toilet/test/toilet_0357.off
toilet/test/toilet_0358.off
toilet/test/toilet_0359.off
toilet/test/toilet_0360.off
toilet/test/toilet_0361.off
toilet/test/toilet_0362.off
toilet/test/toilet_0363.off
toilet/test/toilet_0364.off
toilet/test/toilet_0365.off
toilet/test/toilet_0366.off
toilet/test/toilet_0367.off
toilet/test/toilet_0368.off
toilet/test/toilet_0369.off
toilet/test/toilet_0370.off
toilet/test/toilet_0371.off
toilet/test/toilet_0372.off
toilet/test/toilet_0373.off
toilet/test/toilet_0374.off
toilet/test/toilet_0375.off
toilet/test/toilet_0376.off
toilet/test/toilet_0377.off
toilet/test/toilet_0378.off
toilet/test/toilet_0379.off
toilet/test/toilet_0380.off
toilet/test/toilet_0381.off
toilet/test/toilet_0382.off
toilet/test/toilet_0383.off
toilet/test/toilet_0384.off
toilet/test/toilet_0385.off
toilet/test/toilet_0386.off
toilet/test/toilet_0387.off
toilet/test/toilet_0388.off
toilet/test/toilet_0389.off
toilet/test/toilet_0390.off
toilet/test/toilet_0391.off
toilet/test/toilet_0392.off
toilet/test/toilet_0393.off
toilet/test/toilet_0394.off
toilet/test/toilet_0395.off
toilet/test/toilet_0396.off
toilet/test/toilet_0397.off
toilet/test/toilet_0398.off
toilet/test/toilet_0399.off
toilet/test/toilet_0400.off
toilet/test/toilet_0401.off
toilet/test/toilet_0402.off
toilet/test/toilet_0403.off
toilet/test/toilet_0404.off
toilet/test/toilet_0405.off
toilet/test/toilet_0406.off
toilet/test/toilet_0407.off
toilet/test/toilet_0408.off
toilet/test/toilet_0409.off
toilet/test/toilet_0410.off
toilet/test/toilet_0411.off
toilet/test/toilet_0412.off
toilet/test/toilet_0413.off
toilet/test/toilet_0414.off
toilet/test/toilet_0415.off
toilet/test/toilet_0416.off
toilet/test/toilet_0417.off
toilet/test/toilet_0418.off
toilet/test/toilet_0419.off
toilet/test/toilet_0420.off
toilet/test/toilet_0421.off
toilet/test/toilet_0422.off
toilet/test/toilet_0423.off
toilet/test/toilet_0424.off
toilet/test/toilet_0425.off
toilet/test/toilet_0426.off
toilet/test/toilet_0427.off
toilet/test/toilet_0428.off
toilet/test/toilet_0429.off
toilet/test/toilet_0430.off
toilet/test/toilet_0431.off
toilet/test/toilet_0432.off
toilet/test/toilet_0433.off
toilet/test/toilet_0434.off
toilet/test/toilet_0435.off
toilet/test/toilet_0436.off
toilet/test/toilet_0437.off
toilet/test/toilet_0438.off
toilet/test/toilet_0439.off
toilet/test/toilet_0440.off
toilet/test/toilet_0441.off
toilet/test/toilet_0442.off
toilet/test/toilet_0443.off
toilet/test/toilet_0444.off
curtain/test/curtain_0139.off
curtain/test/curtain_0140.off
curtain/test/curtain_0141.off
curtain/test/curtain_0142.off
curtain/test/curtain_0143.off
curtain/test/curtain_0144.off
curtain/test/curtain_0145.off
curtain/test/curtain_0146.off
curtain/test/curtain_0147.off
curtain/test/curtain_0148.off
curtain/test/curtain_0149.off
curtain/test/curtain_0150.off
curtain/test/curtain_0151.off
curtain/test/curtain_0152.off
curtain/test/curtain_0153.off
curtain/test/curtain_0154.off
curtain/test/curtain_0155.off
curtain/test/curtain_0156.off
curtain/test/curtain_0157.off
curtain/test/curtain_0158.off
wardrobe/test/wardrobe_0088.off
wardrobe/test/wardrobe_0089.off
wardrobe/test/wardrobe_0090.off
wardrobe/test/wardrobe_0091.off
wardrobe/test/wardrobe_0092.off
wardrobe/test/wardrobe_0093.off
wardrobe/test/wardrobe_0094.off
wardrobe/test/wardrobe_0095.off
wardrobe/test/wardrobe_0096.off
wardrobe/test/wardrobe_0097.off
wardrobe/test/wardrobe_0098.off
wardrobe/test/wardrobe_0099.off
wardrobe/test/wardrobe_0100.off
wardrobe/test/wardrobe_0101.off
wardrobe/test/wardrobe_0102.off
wardrobe/test/wardrobe_0103.off
wardrobe/test/wardrobe_0104.off
wardrobe/test/wardrobe_0105.off
wardrobe/test/wardrobe_0106.off
wardrobe/test/wardrobe_0107.off
stool/test/stool_0091.off
stool/test/stool_0092.off
stool/test/stool_0093.off
stool/test/stool_0094.off
stool/test/stool_0095.off
stool/test/stool_0096.off
stool/test/stool_0097.off
stool/test/stool_0098.off
stool/test/stool_0099.off
stool/test/stool_0100.off
stool/test/stool_0101.off
stool/test/stool_0102.off
stool/test/stool_0103.off
stool/test/stool_0104.off
stool/test/stool_0105.off
stool/test/stool_0106.off
stool/test/stool_0107.off
stool/test/stool_0108.off
stool/test/stool_0109.off
stool/test/stool_0110.off
mantel/test/mantel_0285.off
mantel/test/mantel_0286.off
mantel/test/mantel_0287.off
mantel/test/mantel_0288.off
mantel/test/mantel_0289.off
mantel/test/mantel_0290.off
mantel/test/mantel_0291.off
mantel/test/mantel_0292.off
mantel/test/mantel_0293.off
mantel/test/mantel_0294.off
mantel/test/mantel_0295.off
mantel/test/mantel_0296.off
mantel/test/mantel_0297.off
mantel/test/mantel_0298.off
mantel/test/mantel_0299.off
mantel/test/mantel_0300.off
mantel/test/mantel_0301.off
mantel/test/mantel_0302.off
mantel/test/mantel_0303.off
mantel/test/mantel_0304.off
mantel/test/mantel_0305.off
mantel/test/mantel_0306.off
mantel/test/mantel_0307.off
mantel/test/mantel_0308.off
mantel/test/mantel_0309.off
mantel/test/mantel_0310.off
mantel/test/mantel_0311.off
mantel/test/mantel_0312.off
mantel/test/mantel_0313.off
mantel/test/mantel_0314.off
mantel/test/mantel_0315.off
mantel/test/mantel_0316.off
mantel/test/mantel_0317.off
mantel/test/mantel_0318.off
mantel/test/mantel_0319.off
mantel/test/mantel_0320.off
mantel/test/mantel_0321.off
mantel/test/mantel_0322.off
mantel/test/mantel_0323.off
mantel/test/mantel_0324.off
mantel/test/mantel_0325.off
mantel/test/mantel_0326.off
mantel/test/mantel_0327.off
mantel/test/mantel_0328.off
mantel/test/mantel_0329.off
mantel/test/mantel_0330.off
mantel/test/mantel_0331.off
mantel/test/mantel_0332.off
mantel/test/mantel_0333.off
mantel/test/mantel_0334.off
mantel/test/mantel_0335.off
mantel/test/mantel_0336.off
mantel/test/mantel_0337.off
mantel/test/mantel_0338.off
mantel/test/mantel_0339.off
mantel/test/mantel_0340.off
mantel/test/mantel_0341.off
mantel/test/mantel_0342.off
mantel/test/mantel_0343.off
mantel/test/mantel_0344.off
mantel/test/mantel_0345.off
mantel/test/mantel_0346.off
mantel/test/mantel_0347.off
mantel/test/mantel_0348.off
mantel/test/mantel_0349.off
mantel/test/mantel_0350.off
mantel/test/mantel_0351.off
mantel/test/mantel_0352.off
mantel/test/mantel_0353.off
mantel/test/mantel_0354.off
mantel/test/mantel_0355.off
mantel/test/mantel_0356.off
mantel/test/mantel_0357.off
mantel/test/mantel_0358.off
mantel/test/mantel_0359.off
mantel/test/mantel_0360.off
mantel/test/mantel_0361.off
mantel/test/mantel_0362.off
mantel/test/mantel_0363.off
mantel/test/mantel_0364.off
mantel/test/mantel_0365.off
mantel/test/mantel_0366.off
mantel/test/mantel_0367.off
mantel/test/mantel_0368.off
mantel/test/mantel_0369.off
mantel/test/mantel_0370.off
mantel/test/mantel_0371.off
mantel/test/mantel_0372.off
mantel/test/mantel_0373.off
mantel/test/mantel_0374.off
mantel/test/mantel_0375.off
mantel/test/mantel_0376.off
mantel/test/mantel_0377.off
mantel/test/mantel_0378.off
mantel/test/mantel_0379.off
mantel/test/mantel_0380.off
mantel/test/mantel_0381.off
mantel/test/mantel_0382.off
mantel/test/mantel_0383.off
mantel/test/mantel_0384.off
cup/test/cup_0080.off
cup/test/cup_0081.off
cup/test/cup_0082.off
cup/test/cup_0083.off
cup/test/cup_0084.off
cup/test/cup_0085.off
cup/test/cup_0086.off
cup/test/cup_0087.off
cup/test/cup_0088.off
cup/test/cup_0089.off
cup/test/cup_0090.off
cup/test/cup_0091.off
cup/test/cup_0092.off
cup/test/cup_0093.off
cup/test/cup_0094.off
cup/test/cup_0095.off
cup/test/cup_0096.off
cup/test/cup_0097.off
cup/test/cup_0098.off
cup/test/cup_0099.off
radio/test/radio_0105.off
radio/test/radio_0106.off
radio/test/radio_0107.off
radio/test/radio_0108.off
radio/test/radio_0109.off
radio/test/radio_0110.off
radio/test/radio_0111.off
radio/test/radio_0112.off
radio/test/radio_0113.off
radio/test/radio_0114.off
radio/test/radio_0115.off
radio/test/radio_0116.off
radio/test/radio_0117.off
radio/test/radio_0118.off
radio/test/radio_0119.off
radio/test/radio_0120.off
radio/test/radio_0121.off
radio/test/radio_0122.off
radio/test/radio_0123.off
radio/test/radio_0124.off
airplane/test/airplane_0627.off
airplane/test/airplane_0628.off
airplane/test/airplane_0629.off
airplane/test/airplane_0630.off
airplane/test/airplane_0631.off
airplane/test/airplane_0632.off
airplane/test/airplane_0633.off
airplane/test/airplane_0634.off
airplane/test/airplane_0635.off
airplane/test/airplane_0636.off
airplane/test/airplane_0637.off
airplane/test/airplane_0638.off
airplane/test/airplane_0639.off
airplane/test/airplane_0640.off
airplane/test/airplane_0641.off
airplane/test/airplane_0642.off
airplane/test/airplane_0643.off
airplane/test/airplane_0644.off
airplane/test/airplane_0645.off
airplane/test/airplane_0646.off
airplane/test/airplane_0647.off
airplane/test/airplane_0648.off
airplane/test/airplane_0649.off
airplane/test/airplane_0650.off
airplane/test/airplane_0651.off
airplane/test/airplane_0652.off
airplane/test/airplane_0653.off
airplane/test/airplane_0654.off
airplane/test/airplane_0655.off
airplane/test/airplane_0656.off
airplane/test/airplane_0657.off
airplane/test/airplane_0658.off
airplane/test/airplane_0659.off
airplane/test/airplane_0660.off
airplane/test/airplane_0661.off
airplane/test/airplane_0662.off
airplane/test/airplane_0663.off
airplane/test/airplane_0664.off
airplane/test/airplane_0665.off
airplane/test/airplane_0666.off
airplane/test/airplane_0667.off
airplane/test/airplane_0668.off
airplane/test/airplane_0669.off
airplane/test/airplane_0670.off
airplane/test/airplane_0671.off
airplane/test/airplane_0672.off
airplane/test/airplane_0673.off
airplane/test/airplane_0674.off
airplane/test/airplane_0675.off
airplane/test/airplane_0676.off
airplane/test/airplane_0677.off
airplane/test/airplane_0678.off
airplane/test/airplane_0679.off
airplane/test/airplane_0680.off
airplane/test/airplane_0681.off
airplane/test/airplane_0682.off
airplane/test/airplane_0683.off
airplane/test/airplane_0684.off
airplane/test/airplane_0685.off
airplane/test/airplane_0686.off
airplane/test/airplane_0687.off
airplane/test/airplane_0688.off
airplane/test/airplane_0689.off
airplane/test/airplane_0690.off
airplane/test/airplane_0691.off
airplane/test/airplane_0692.off
airplane/test/airplane_0693.off
airplane/test/airplane_0694.off
airplane/test/airplane_0695.off
airplane/test/airplane_0696.off
airplane/test/airplane_0697.off
airplane/test/airplane_0698.off
airplane/test/airplane_0699.off
airplane/test/airplane_0700.off
airplane/test/airplane_0701.off
airplane/test/airplane_0702.off
airplane/test/airplane_0703.off
airplane/test/airplane_0704.off
airplane/test/airplane_0705.off
airplane/test/airplane_0706.off
airplane/test/airplane_0707.off
airplane/test/airplane_0708.off
airplane/test/airplane_0709.off
airplane/test/airplane_0710.off
airplane/test/airplane_0711.off
airplane/test/airplane_0712.off
airplane/test/airplane_0713.off
airplane/test/airplane_0714.off
airplane/test/airplane_0715.off
airplane/test/airplane_0716.off
airplane/test/airplane_0717.off
airplane/test/airplane_0718.off
airplane/test/airplane_0719.off
airplane/test/airplane_0720.off
airplane/test/airplane_0721.off
airplane/test/airplane_0722.off
airplane/test/airplane_0723.off
airplane/test/airplane_0724.off
airplane/test/airplane_0725.off
airplane/test/airplane_0726.off
table/test/table_0393.off
table/test/table_0394.off
table/test/table_0395.off
table/test/table_0396.off
table/test/table_0397.off
table/test/table_0398.off
table/test/table_0399.off
table/test/table_0400.off
table/test/table_0401.off
table/test/table_0402.off
table/test/table_0403.off
table/test/table_0404.off
table/test/table_0405.off
table/test/table_0406.off
table/test/table_0407.off
table/test/table_0408.off
table/test/table_0409.off
table/test/table_0410.off
table/test/table_0411.off
table/test/table_0412.off
table/test/table_0413.off
table/test/table_0414.off
table/test/table_0415.off
table/test/table_0416.off
table/test/table_0417.off
table/test/table_0418.off
table/test/table_0419.off
table/test/table_0420.off
table/test/table_0421.off
table/test/table_0422.off
table/test/table_0423.off
table/test/table_0424.off
table/test/table_0425.off
table/test/table_0426.off
table/test/table_0427.off
table/test/table_0428.off
table/test/table_0429.off
table/test/table_0430.off
table/test/table_0431.off
table/test/table_0432.off
table/test/table_0433.off
table/test/table_0434.off
table/test/table_0435.off
table/test/table_0436.off
table/test/table_0437.off
table/test/table_0438.off
table/test/table_0439.off
table/test/table_0440.off
table/test/table_0441.off
table/test/table_0442.off
table/test/table_0443.off
table/test/table_0444.off
table/test/table_0445.off
table/test/table_0446.off
table/test/table_0447.off
table/test/table_0448.off
table/test/table_0449.off
table/test/table_0450.off
table/test/table_0451.off
table/test/table_0452.off
table/test/table_0453.off
table/test/table_0454.off
table/test/table_0455.off
table/test/table_0456.off
table/test/table_0457.off
table/test/table_0458.off
table/test/table_0459.off
table/test/table_0460.off
table/test/table_0461.off
table/test/table_0462.off
table/test/table_0463.off
table/test/table_0464.off
table/test/table_0465.off
table/test/table_0466.off
table/test/table_0467.off
table/test/table_0468.off
table/test/table_0469.off
table/test/table_0470.off
table/test/table_0471.off
table/test/table_0472.off
table/test/table_0473.off
table/test/table_0474.off
table/test/table_0475.off
table/test/table_0476.off
table/test/table_0477.off
table/test/table_0478.off
table/test/table_0479.off
table/test/table_0480.off
table/test/table_0481.off
table/test/table_0482.off
table/test/table_0483.off
table/test/table_0484.off
table/test/table_0485.off
table/test/table_0486.off
table/test/table_0487.off
table/test/table_0488.off
table/test/table_0489.off
table/test/table_0490.off
table/test/table_0491.off
table/test/table_0492.off
bench/test/bench_0174.off
bench/test/bench_0175.off
bench/test/bench_0176.off
bench/test/bench_0177.off
bench/test/bench_0178.off
bench/test/bench_0179.off
bench/test/bench_0180.off
bench/test/bench_0181.off
bench/test/bench_0182.off
bench/test/bench_0183.off
bench/test/bench_0184.off
bench/test/bench_0185.off
bench/test/bench_0186.off
bench/test/bench_0187.off
bench/test/bench_0188.off
bench/test/bench_0189.off
bench/test/bench_0190.off
bench/test/bench_0191.off
bench/test/bench_0192.off
bench/test/bench_0193.off
plant/test/plant_0241.off
plant/test/plant_0242.off
plant/test/plant_0243.off
plant/test/plant_0244.off
plant/test/plant_0245.off
plant/test/plant_0246.off
plant/test/plant_0247.off
plant/test/plant_0248.off
plant/test/plant_0249.off
plant/test/plant_0250.off
plant/test/plant_0251.off
plant/test/plant_0252.off
plant/test/plant_0253.off
plant/test/plant_0254.off
plant/test/plant_0255.off
plant/test/plant_0256.off
plant/test/plant_0257.off
plant/test/plant_0258.off
plant/test/plant_0259.off
plant/test/plant_0260.off
plant/test/plant_0261.off
plant/test/plant_0262.off
plant/test/plant_0263.off
plant/test/plant_0264.off
plant/test/plant_0265.off
plant/test/plant_0266.off
plant/test/plant_0267.off
plant/test/plant_0268.off
plant/test/plant_0269.off
plant/test/plant_0270.off
plant/test/plant_0271.off
plant/test/plant_0272.off
plant/test/plant_0273.off
plant/test/plant_0274.off
plant/test/plant_0275.off
plant/test/plant_0276.off
plant/test/plant_0277.off
plant/test/plant_0278.off
plant/test/plant_0279.off
plant/test/plant_0280.off
plant/test/plant_0281.off
plant/test/plant_0282.off
plant/test/plant_0283.off
plant/test/plant_0284.off
plant/test/plant_0285.off
plant/test/plant_0286.off
plant/test/plant_0287.off
plant/test/plant_0288.off
plant/test/plant_0289.off
plant/test/plant_0290.off
plant/test/plant_0291.off
plant/test/plant_0292.off
plant/test/plant_0293.off
plant/test/plant_0294.off
plant/test/plant_0295.off
plant/test/plant_0296.off
plant/test/plant_0297.off
plant/test/plant_0298.off
plant/test/plant_0299.off
plant/test/plant_0300.off
plant/test/plant_0301.off
plant/test/plant_0302.off
plant/test/plant_0303.off
plant/test/plant_0304.off
plant/test/plant_0305.off
plant/test/plant_0306.off
plant/test/plant_0307.off
plant/test/plant_0308.off
plant/test/plant_0309.off
plant/test/plant_0310.off
plant/test/plant_0311.off
plant/test/plant_0312.off
plant/test/plant_0313.off
plant/test/plant_0314.off
plant/test/plant_0315.off
plant/test/plant_0316.off
plant/test/plant_0317.off
plant/test/plant_0318.off
plant/test/plant_0319.off
plant/test/plant_0320.off
plant/test/plant_0321.off
plant/test/plant_0322.off
plant/test/plant_0323.off
plant/test/plant_0324.off
plant/test/plant_0325.off
plant/test/plant_0326.off
plant/test/plant_0327.off
plant/test/plant_0328.off
plant/test/plant_0329.off
plant/test/plant_0330.off
plant/test/plant_0331.off
plant/test/plant_0332.off
plant/test/plant_0333.off
plant/test/plant_0334.off
plant/test/plant_0335.off
plant/test/plant_0336.off
plant/test/plant_0337.off
plant/test/plant_0338.off
plant/test/plant_0339.off
plant/test/plant_0340.off
chair/test/chair_0890.off
chair/test/chair_0891.off
chair/test/chair_0892.off
chair/test/chair_0893.off
chair/test/chair_0894.off
chair/test/chair_0895.off
chair/test/chair_0896.off
chair/test/chair_0897.off
chair/test/chair_0898.off
chair/test/chair_0899.off
chair/test/chair_0900.off
chair/test/chair_0901.off
chair/test/chair_0902.off
chair/test/chair_0903.off
chair/test/chair_0904.off
chair/test/chair_0905.off
chair/test/chair_0906.off
chair/test/chair_0907.off
chair/test/chair_0908.off
chair/test/chair_0909.off
chair/test/chair_0910.off
chair/test/chair_0911.off
chair/test/chair_0912.off
chair/test/chair_0913.off
chair/test/chair_0914.off
chair/test/chair_0915.off
chair/test/chair_0916.off
chair/test/chair_0917.off
chair/test/chair_0918.off
chair/test/chair_0919.off
chair/test/chair_0920.off
chair/test/chair_0921.off
chair/test/chair_0922.off
chair/test/chair_0923.off
chair/test/chair_0924.off
chair/test/chair_0925.off
chair/test/chair_0926.off
chair/test/chair_0927.off
chair/test/chair_0928.off
chair/test/chair_0929.off
chair/test/chair_0930.off
chair/test/chair_0931.off
chair/test/chair_0932.off
chair/test/chair_0933.off
chair/test/chair_0934.off
chair/test/chair_0935.off
chair/test/chair_0936.off
chair/test/chair_0937.off
chair/test/chair_0938.off
chair/test/chair_0939.off
chair/test/chair_0940.off
chair/test/chair_0941.off
chair/test/chair_0942.off
chair/test/chair_0943.off
chair/test/chair_0944.off
chair/test/chair_0945.off
chair/test/chair_0946.off
chair/test/chair_0947.off
chair/test/chair_0948.off
chair/test/chair_0949.off
chair/test/chair_0950.off
chair/test/chair_0951.off
chair/test/chair_0952.off
chair/test/chair_0953.off
chair/test/chair_0954.off
chair/test/chair_0955.off
chair/test/chair_0956.off
chair/test/chair_0957.off
chair/test/chair_0958.off
chair/test/chair_0959.off
chair/test/chair_0960.off
chair/test/chair_0961.off
chair/test/chair_0962.off
chair/test/chair_0963.off
chair/test/chair_0964.off
chair/test/chair_0965.off
chair/test/chair_0966.off
chair/test/chair_0967.off
chair/test/chair_0968.off
chair/test/chair_0969.off
chair/test/chair_0970.off
chair/test/chair_0971.off
chair/test/chair_0972.off
chair/test/chair_0973.off
chair/test/chair_0974.off
chair/test/chair_0975.off
chair/test/chair_0976.off
chair/test/chair_0977.off
chair/test/chair_0978.off
chair/test/chair_0979.off
chair/test/chair_0980.off
chair/test/chair_0981.off
chair/test/chair_0982.off
chair/test/chair_0983.off
chair/test/chair_0984.off
chair/test/chair_0985.off
chair/test/chair_0986.off
chair/test/chair_0987.off
chair/test/chair_0988.off
chair/test/chair_0989.off
vase/test/vase_0476.off
vase/test/vase_0477.off
vase/test/vase_0478.off
vase/test/vase_0479.off
vase/test/vase_0480.off
vase/test/vase_0481.off
vase/test/vase_0482.off
vase/test/vase_0483.off
vase/test/vase_0484.off
vase/test/vase_0485.off
vase/test/vase_0486.off
vase/test/vase_0487.off
vase/test/vase_0488.off
vase/test/vase_0489.off
vase/test/vase_0490.off
vase/test/vase_0491.off
vase/test/vase_0492.off
vase/test/vase_0493.off
vase/test/vase_0494.off
vase/test/vase_0495.off
vase/test/vase_0496.off
vase/test/vase_0497.off
vase/test/vase_0498.off
vase/test/vase_0499.off
vase/test/vase_0500.off
vase/test/vase_0501.off
vase/test/vase_0502.off
vase/test/vase_0503.off
vase/test/vase_0504.off
vase/test/vase_0505.off
vase/test/vase_0506.off
vase/test/vase_0507.off
vase/test/vase_0508.off
vase/test/vase_0509.off
vase/test/vase_0510.off
vase/test/vase_0511.off
vase/test/vase_0512.off
vase/test/vase_0513.off
vase/test/vase_0514.off
vase/test/vase_0515.off
vase/test/vase_0516.off
vase/test/vase_0517.off
vase/test/vase_0518.off
vase/test/vase_0519.off
vase/test/vase_0520.off
vase/test/vase_0521.off
vase/test/vase_0522.off
vase/test/vase_0523.off
vase/test/vase_0524.off
vase/test/vase_0525.off
vase/test/vase_0526.off
vase/test/vase_0527.off
vase/test/vase_0528.off
vase/test/vase_0529.off
vase/test/vase_0530.off
vase/test/vase_0531.off
vase/test/vase_0532.off
vase/test/vase_0533.off
vase/test/vase_0534.off
vase/test/vase_0535.off
vase/test/vase_0536.off
vase/test/vase_0537.off
vase/test/vase_0538.off
vase/test/vase_0539.off
vase/test/vase_0540.off
vase/test/vase_0541.off
vase/test/vase_0542.off
vase/test/vase_0543.off
vase/test/vase_0544.off
vase/test/vase_0545.off
vase/test/vase_0546.off
vase/test/vase_0547.off
vase/test/vase_0548.off
vase/test/vase_0549.off
vase/test/vase_0550.off
vase/test/vase_0551.off
vase/test/vase_0552.off
vase/test/vase_0553.off
vase/test/vase_0554.off
vase/test/vase_0555.off
vase/test/vase_0556.off
vase/test/vase_0557.off
vase/test/vase_0558.off
vase/test/vase_0559.off
vase/test/vase_0560.off
vase/test/vase_0561.off
vase/test/vase_0562.off
vase/test/vase_0563.off
vase/test/vase_0564.off
vase/test/vase_0565.off
vase/test/vase_0566.off
vase/test/vase_0567.off
vase/test/vase_0568.off
vase/test/vase_0569.off
vase/test/vase_0570.off
vase/test/vase_0571.off
vase/test/vase_0572.off
vase/test/vase_0573.off
vase/test/vase_0574.off
vase/test/vase_0575.off
bookshelf/test/bookshelf_0573.off
bookshelf/test/bookshelf_0574.off
bookshelf/test/bookshelf_0575.off
bookshelf/test/bookshelf_0576.off
bookshelf/test/bookshelf_0577.off
bookshelf/test/bookshelf_0578.off
bookshelf/test/bookshelf_0579.off
bookshelf/test/bookshelf_0580.off
bookshelf/test/bookshelf_0581.off
bookshelf/test/bookshelf_0582.off
bookshelf/test/bookshelf_0583.off
bookshelf/test/bookshelf_0584.off
bookshelf/test/bookshelf_0585.off
bookshelf/test/bookshelf_0586.off
bookshelf/test/bookshelf_0587.off
bookshelf/test/bookshelf_0588.off
bookshelf/test/bookshelf_0589.off
bookshelf/test/bookshelf_0590.off
bookshelf/test/bookshelf_0591.off
bookshelf/test/bookshelf_0592.off
bookshelf/test/bookshelf_0593.off
bookshelf/test/bookshelf_0594.off
bookshelf/test/bookshelf_0595.off
bookshelf/test/bookshelf_0596.off
bookshelf/test/bookshelf_0597.off
bookshelf/test/bookshelf_0598.off
bookshelf/test/bookshelf_0599.off
bookshelf/test/bookshelf_0600.off
bookshelf/test/bookshelf_0601.off
bookshelf/test/bookshelf_0602.off
bookshelf/test/bookshelf_0603.off
bookshelf/test/bookshelf_0604.off
bookshelf/test/bookshelf_0605.off
bookshelf/test/bookshelf_0606.off
bookshelf/test/bookshelf_0607.off
bookshelf/test/bookshelf_0608.off
bookshelf/test/bookshelf_0609.off
bookshelf/test/bookshelf_0610.off
bookshelf/test/bookshelf_0611.off
bookshelf/test/bookshelf_0612.off
bookshelf/test/bookshelf_0613.off
bookshelf/test/bookshelf_0614.off
bookshelf/test/bookshelf_0615.off
bookshelf/test/bookshelf_0616.off
bookshelf/test/bookshelf_0617.off
bookshelf/test/bookshelf_0618.off
bookshelf/test/bookshelf_0619.off
bookshelf/test/bookshelf_0620.off
bookshelf/test/bookshelf_0621.off
bookshelf/test/bookshelf_0622.off
bookshelf/test/bookshelf_0623.off
bookshelf/test/bookshelf_0624.off
bookshelf/test/bookshelf_0625.off
bookshelf/test/bookshelf_0626.off
bookshelf/test/bookshelf_0627.off
bookshelf/test/bookshelf_0628.off
bookshelf/test/bookshelf_0629.off
bookshelf/test/bookshelf_0630.off
bookshelf/test/bookshelf_0631.off
bookshelf/test/bookshelf_0632.off
bookshelf/test/bookshelf_0633.off
bookshelf/test/bookshelf_0634.off
bookshelf/test/bookshelf_0635.off
bookshelf/test/bookshelf_0636.off
bookshelf/test/bookshelf_0637.off
bookshelf/test/bookshelf_0638.off
bookshelf/test/bookshelf_0639.off
bookshelf/test/bookshelf_0640.off
bookshelf/test/bookshelf_0641.off
bookshelf/test/bookshelf_0642.off
bookshelf/test/bookshelf_0643.off
bookshelf/test/bookshelf_0644.off
bookshelf/test/bookshelf_0645.off
bookshelf/test/bookshelf_0646.off
bookshelf/test/bookshelf_0647.off
bookshelf/test/bookshelf_0648.off
bookshelf/test/bookshelf_0649.off
bookshelf/test/bookshelf_0650.off
bookshelf/test/bookshelf_0651.off
bookshelf/test/bookshelf_0652.off
bookshelf/test/bookshelf_0653.off
bookshelf/test/bookshelf_0654.off
bookshelf/test/bookshelf_0655.off
bookshelf/test/bookshelf_0656.off
bookshelf/test/bookshelf_0657.off
bookshelf/test/bookshelf_0658.off
bookshelf/test/bookshelf_0659.off
bookshelf/test/bookshelf_0660.off
bookshelf/test/bookshelf_0661.off
bookshelf/test/bookshelf_0662.off
bookshelf/test/bookshelf_0663.off
bookshelf/test/bookshelf_0664.off
bookshelf/test/bookshelf_0665.off
bookshelf/test/bookshelf_0666.off
bookshelf/test/bookshelf_0667.off
bookshelf/test/bookshelf_0668.off
bookshelf/test/bookshelf_0669.off
bookshelf/test/bookshelf_0670.off
bookshelf/test/bookshelf_0671.off
bookshelf/test/bookshelf_0672.off
guitar/test/guitar_0156.off
guitar/test/guitar_0157.off
guitar/test/guitar_0158.off
guitar/test/guitar_0159.off
guitar/test/guitar_0160.off
guitar/test/guitar_0161.off
guitar/test/guitar_0162.off
guitar/test/guitar_0163.off
guitar/test/guitar_0164.off
guitar/test/guitar_0165.off
guitar/test/guitar_0166.off
guitar/test/guitar_0167.off
guitar/test/guitar_0168.off
guitar/test/guitar_0169.off
guitar/test/guitar_0170.off
guitar/test/guitar_0171.off
guitar/test/guitar_0172.off
guitar/test/guitar_0173.off
guitar/test/guitar_0174.off
guitar/test/guitar_0175.off
guitar/test/guitar_0176.off
guitar/test/guitar_0177.off
guitar/test/guitar_0178.off
guitar/test/guitar_0179.off
guitar/test/guitar_0180.off
guitar/test/guitar_0181.off
guitar/test/guitar_0182.off
guitar/test/guitar_0183.off
guitar/test/guitar_0184.off
guitar/test/guitar_0185.off
guitar/test/guitar_0186.off
guitar/test/guitar_0187.off
guitar/test/guitar_0188.off
guitar/test/guitar_0189.off
guitar/test/guitar_0190.off
guitar/test/guitar_0191.off
guitar/test/guitar_0192.off
guitar/test/guitar_0193.off
guitar/test/guitar_0194.off
guitar/test/guitar_0195.off
guitar/test/guitar_0196.off
guitar/test/guitar_0197.off
guitar/test/guitar_0198.off
guitar/test/guitar_0199.off
guitar/test/guitar_0200.off
guitar/test/guitar_0201.off
guitar/test/guitar_0202.off
guitar/test/guitar_0203.off
guitar/test/guitar_0204.off
guitar/test/guitar_0205.off
guitar/test/guitar_0206.off
guitar/test/guitar_0207.off
guitar/test/guitar_0208.off
guitar/test/guitar_0209.off
guitar/test/guitar_0210.off
guitar/test/guitar_0211.off
guitar/test/guitar_0212.off
guitar/test/guitar_0213.off
guitar/test/guitar_0214.off
guitar/test/guitar_0215.off
guitar/test/guitar_0216.off
guitar/test/guitar_0217.off
guitar/test/guitar_0218.off
guitar/test/guitar_0219.off
guitar/test/guitar_0220.off
guitar/test/guitar_0221.off
guitar/test/guitar_0222.off
guitar/test/guitar_0223.off
guitar/test/guitar_0224.off
guitar/test/guitar_0225.off
guitar/test/guitar_0226.off
guitar/test/guitar_0227.off
guitar/test/guitar_0228.off
guitar/test/guitar_0229.off
guitar/test/guitar_0230.off
guitar/test/guitar_0231.off
guitar/test/guitar_0232.off
guitar/test/guitar_0233.off
guitar/test/guitar_0234.off
guitar/test/guitar_0235.off
guitar/test/guitar_0236.off
guitar/test/guitar_0237.off
guitar/test/guitar_0238.off
guitar/test/guitar_0239.off
guitar/test/guitar_0240.off
guitar/test/guitar_0241.off
guitar/test/guitar_0242.off
guitar/test/guitar_0243.off
guitar/test/guitar_0244.off
guitar/test/guitar_0245.off
guitar/test/guitar_0246.off
guitar/test/guitar_0247.off
guitar/test/guitar_0248.off
guitar/test/guitar_0249.off
guitar/test/guitar_0250.off
guitar/test/guitar_0251.off
guitar/test/guitar_0252.off
guitar/test/guitar_0253.off
guitar/test/guitar_0254.off
guitar/test/guitar_0255.off
tv_stand/test/tv_stand_0268.off
tv_stand/test/tv_stand_0269.off
tv_stand/test/tv_stand_0270.off
tv_stand/test/tv_stand_0271.off
tv_stand/test/tv_stand_0272.off
tv_stand/test/tv_stand_0273.off
tv_stand/test/tv_stand_0274.off
tv_stand/test/tv_stand_0275.off
tv_stand/test/tv_stand_0276.off
tv_stand/test/tv_stand_0277.off
tv_stand/test/tv_stand_0278.off
tv_stand/test/tv_stand_0279.off
tv_stand/test/tv_stand_0280.off
tv_stand/test/tv_stand_0281.off
tv_stand/test/tv_stand_0282.off
tv_stand/test/tv_stand_0283.off
tv_stand/test/tv_stand_0284.off
tv_stand/test/tv_stand_0285.off
tv_stand/test/tv_stand_0286.off
tv_stand/test/tv_stand_0287.off
tv_stand/test/tv_stand_0288.off
tv_stand/test/tv_stand_0289.off
tv_stand/test/tv_stand_0290.off
tv_stand/test/tv_stand_0291.off
tv_stand/test/tv_stand_0292.off
tv_stand/test/tv_stand_0293.off
tv_stand/test/tv_stand_0294.off
tv_stand/test/tv_stand_0295.off
tv_stand/test/tv_stand_0296.off
tv_stand/test/tv_stand_0297.off
tv_stand/test/tv_stand_0298.off
tv_stand/test/tv_stand_0299.off
tv_stand/test/tv_stand_0300.off
tv_stand/test/tv_stand_0301.off
tv_stand/test/tv_stand_0302.off
tv_stand/test/tv_stand_0303.off
tv_stand/test/tv_stand_0304.off
tv_stand/test/tv_stand_0305.off
tv_stand/test/tv_stand_0306.off
tv_stand/test/tv_stand_0307.off
tv_stand/test/tv_stand_0308.off
tv_stand/test/tv_stand_0309.off
tv_stand/test/tv_stand_0310.off
tv_stand/test/tv_stand_0311.off
tv_stand/test/tv_stand_0312.off
tv_stand/test/tv_stand_0313.off
tv_stand/test/tv_stand_0314.off
tv_stand/test/tv_stand_0315.off
tv_stand/test/tv_stand_0316.off
tv_stand/test/tv_stand_0317.off
tv_stand/test/tv_stand_0318.off
tv_stand/test/tv_stand_0319.off
tv_stand/test/tv_stand_0320.off
tv_stand/test/tv_stand_0321.off
tv_stand/test/tv_stand_0322.off
tv_stand/test/tv_stand_0323.off
tv_stand/test/tv_stand_0324.off
tv_stand/test/tv_stand_0325.off
tv_stand/test/tv_stand_0326.off
tv_stand/test/tv_stand_0327.off
tv_stand/test/tv_stand_0328.off
tv_stand/test/tv_stand_0329.off
tv_stand/test/tv_stand_0330.off
tv_stand/test/tv_stand_0331.off
tv_stand/test/tv_stand_0332.off
tv_stand/test/tv_stand_0333.off
tv_stand/test/tv_stand_0334.off
tv_stand/test/tv_stand_0335.off
tv_stand/test/tv_stand_0336.off
tv_stand/test/tv_stand_0337.off
tv_stand/test/tv_stand_0338.off
tv_stand/test/tv_stand_0339.off
tv_stand/test/tv_stand_0340.off
tv_stand/test/tv_stand_0341.off
tv_stand/test/tv_stand_0342.off
tv_stand/test/tv_stand_0343.off
tv_stand/test/tv_stand_0344.off
tv_stand/test/tv_stand_0345.off
tv_stand/test/tv_stand_0346.off
tv_stand/test/tv_stand_0347.off
tv_stand/test/tv_stand_0348.off
tv_stand/test/tv_stand_0349.off
tv_stand/test/tv_stand_0350.off
tv_stand/test/tv_stand_0351.off
tv_stand/test/tv_stand_0352.off
tv_stand/test/tv_stand_0353.off
tv_stand/test/tv_stand_0354.off
tv_stand/test/tv_stand_0355.off
tv_stand/test/tv_stand_0356.off
tv_stand/test/tv_stand_0357.off
tv_stand/test/tv_stand_0358.off
tv_stand/test/tv_stand_0359.off
tv_stand/test/tv_stand_0360.off
tv_stand/test/tv_stand_0361.off
tv_stand/test/tv_stand_0362.off
tv_stand/test/tv_stand_0363.off
tv_stand/test/tv_stand_0364.off
tv_stand/test/tv_stand_0365.off
tv_stand/test/tv_stand_0366.off
tv_stand/test/tv_stand_0367.off
bathtub/test/bathtub_0107.off
bathtub/test/bathtub_0108.off
bathtub/test/bathtub_0109.off
bathtub/test/bathtub_0110.off
bathtub/test/bathtub_0111.off
bathtub/test/bathtub_0112.off
bathtub/test/bathtub_0113.off
bathtub/test/bathtub_0114.off
bathtub/test/bathtub_0115.off
bathtub/test/bathtub_0116.off
bathtub/test/bathtub_0117.off
bathtub/test/bathtub_0118.off
bathtub/test/bathtub_0119.off
bathtub/test/bathtub_0120.off
bathtub/test/bathtub_0121.off
bathtub/test/bathtub_0122.off
bathtub/test/bathtub_0123.off
bathtub/test/bathtub_0124.off
bathtub/test/bathtub_0125.off
bathtub/test/bathtub_0126.off
bathtub/test/bathtub_0127.off
bathtub/test/bathtub_0128.off
bathtub/test/bathtub_0129.off
bathtub/test/bathtub_0130.off
bathtub/test/bathtub_0131.off
bathtub/test/bathtub_0132.off
bathtub/test/bathtub_0133.off
bathtub/test/bathtub_0134.off
bathtub/test/bathtub_0135.off
bathtub/test/bathtub_0136.off
bathtub/test/bathtub_0137.off
bathtub/test/bathtub_0138.off
bathtub/test/bathtub_0139.off
bathtub/test/bathtub_0140.off
bathtub/test/bathtub_0141.off
bathtub/test/bathtub_0142.off
bathtub/test/bathtub_0143.off
bathtub/test/bathtub_0144.off
bathtub/test/bathtub_0145.off
bathtub/test/bathtub_0146.off
bathtub/test/bathtub_0147.off
bathtub/test/bathtub_0148.off
bathtub/test/bathtub_0149.off
bathtub/test/bathtub_0150.off
bathtub/test/bathtub_0151.off
bathtub/test/bathtub_0152.off
bathtub/test/bathtub_0153.off
bathtub/test/bathtub_0154.off
bathtub/test/bathtub_0155.off
bathtub/test/bathtub_0156.off
monitor/test/monitor_0466.off
monitor/test/monitor_0467.off
monitor/test/monitor_0468.off
monitor/test/monitor_0469.off
monitor/test/monitor_0470.off
monitor/test/monitor_0471.off
monitor/test/monitor_0472.off
monitor/test/monitor_0473.off
monitor/test/monitor_0474.off
monitor/test/monitor_0475.off
monitor/test/monitor_0476.off
monitor/test/monitor_0477.off
monitor/test/monitor_0478.off
monitor/test/monitor_0479.off
monitor/test/monitor_0480.off
monitor/test/monitor_0481.off
monitor/test/monitor_0482.off
monitor/test/monitor_0483.off
monitor/test/monitor_0484.off
monitor/test/monitor_0485.off
monitor/test/monitor_0486.off
monitor/test/monitor_0487.off
monitor/test/monitor_0488.off
monitor/test/monitor_0489.off
monitor/test/monitor_0490.off
monitor/test/monitor_0491.off
monitor/test/monitor_0492.off
monitor/test/monitor_0493.off
monitor/test/monitor_0494.off
monitor/test/monitor_0495.off
monitor/test/monitor_0496.off
monitor/test/monitor_0497.off
monitor/test/monitor_0498.off
monitor/test/monitor_0499.off
monitor/test/monitor_0500.off
monitor/test/monitor_0501.off
monitor/test/monitor_0502.off
monitor/test/monitor_0503.off
monitor/test/monitor_0504.off
monitor/test/monitor_0505.off
monitor/test/monitor_0506.off
monitor/test/monitor_0507.off
monitor/test/monitor_0508.off
monitor/test/monitor_0509.off
monitor/test/monitor_0510.off
monitor/test/monitor_0511.off
monitor/test/monitor_0512.off
monitor/test/monitor_0513.off
monitor/test/monitor_0514.off
monitor/test/monitor_0515.off
monitor/test/monitor_0516.off
monitor/test/monitor_0517.off
monitor/test/monitor_0518.off
monitor/test/monitor_0519.off
monitor/test/monitor_0520.off
monitor/test/monitor_0521.off
monitor/test/monitor_0522.off
monitor/test/monitor_0523.off
monitor/test/monitor_0524.off
monitor/test/monitor_0525.off
monitor/test/monitor_0526.off
monitor/test/monitor_0527.off
monitor/test/monitor_0528.off
monitor/test/monitor_0529.off
monitor/test/monitor_0530.off
monitor/test/monitor_0531.off
monitor/test/monitor_0532.off
monitor/test/monitor_0533.off
monitor/test/monitor_0534.off
monitor/test/monitor_0535.off
monitor/test/monitor_0536.off
monitor/test/monitor_0537.off
monitor/test/monitor_0538.off
monitor/test/monitor_0539.off
monitor/test/monitor_0540.off
monitor/test/monitor_0541.off
monitor/test/monitor_0542.off
monitor/test/monitor_0543.off
monitor/test/monitor_0544.off
monitor/test/monitor_0545.off
monitor/test/monitor_0546.off
monitor/test/monitor_0547.off
monitor/test/monitor_0548.off
monitor/test/monitor_0549.off
monitor/test/monitor_0550.off
monitor/test/monitor_0551.off
monitor/test/monitor_0552.off
monitor/test/monitor_0553.off
monitor/test/monitor_0554.off
monitor/test/monitor_0555.off
monitor/test/monitor_0556.off
monitor/test/monitor_0557.off
monitor/test/monitor_0558.off
monitor/test/monitor_0559.off
monitor/test/monitor_0560.off
monitor/test/monitor_0561.off
monitor/test/monitor_0562.off
monitor/test/monitor_0563.off
monitor/test/monitor_0564.off
monitor/test/monitor_0565.off
bottle/test/bottle_0336.off
bottle/test/bottle_0337.off
bottle/test/bottle_0338.off
bottle/test/bottle_0339.off
bottle/test/bottle_0340.off
bottle/test/bottle_0341.off
bottle/test/bottle_0342.off
bottle/test/bottle_0343.off
bottle/test/bottle_0344.off
bottle/test/bottle_0345.off
bottle/test/bottle_0346.off
bottle/test/bottle_0347.off
bottle/test/bottle_0348.off
bottle/test/bottle_0349.off
bottle/test/bottle_0350.off
bottle/test/bottle_0351.off
bottle/test/bottle_0352.off
bottle/test/bottle_0353.off
bottle/test/bottle_0354.off
bottle/test/bottle_0355.off
bottle/test/bottle_0356.off
bottle/test/bottle_0357.off
bottle/test/bottle_0358.off
bottle/test/bottle_0359.off
bottle/test/bottle_0360.off
bottle/test/bottle_0361.off
bottle/test/bottle_0362.off
bottle/test/bottle_0363.off
bottle/test/bottle_0364.off
bottle/test/bottle_0365.off
bottle/test/bottle_0366.off
bottle/test/bottle_0367.off
bottle/test/bottle_0368.off
bottle/test/bottle_0369.off
bottle/test/bottle_0370.off
bottle/test/bottle_0371.off
bottle/test/bottle_0372.off
bottle/test/bottle_0373.off
bottle/test/bottle_0374.off
bottle/test/bottle_0375.off
bottle/test/bottle_0376.off
bottle/test/bottle_0377.off
bottle/test/bottle_0378.off
bottle/test/bottle_0379.off
bottle/test/bottle_0380.off
bottle/test/bottle_0381.off
bottle/test/bottle_0382.off
bottle/test/bottle_0383.off
bottle/test/bottle_0384.off
bottle/test/bottle_0385.off
bottle/test/bottle_0386.off
bottle/test/bottle_0387.off
bottle/test/bottle_0388.off
bottle/test/bottle_0389.off
bottle/test/bottle_0390.off
bottle/test/bottle_0391.off
bottle/test/bottle_0392.off
bottle/test/bottle_0393.off
bottle/test/bottle_0394.off
bottle/test/bottle_0395.off
bottle/test/bottle_0396.off
bottle/test/bottle_0397.off
bottle/test/bottle_0398.off
bottle/test/bottle_0399.off
bottle/test/bottle_0400.off
bottle/test/bottle_0401.off
bottle/test/bottle_0402.off
bottle/test/bottle_0403.off
bottle/test/bottle_0404.off
bottle/test/bottle_0405.off
bottle/test/bottle_0406.off
bottle/test/bottle_0407.off
bottle/test/bottle_0408.off
bottle/test/bottle_0409.off
bottle/test/bottle_0410.off
bottle/test/bottle_0411.off
bottle/test/bottle_0412.off
bottle/test/bottle_0413.off
bottle/test/bottle_0414.off
bottle/test/bottle_0415.off
bottle/test/bottle_0416.off
bottle/test/bottle_0417.off
bottle/test/bottle_0418.off
bottle/test/bottle_0419.off
bottle/test/bottle_0420.off
bottle/test/bottle_0421.off
bottle/test/bottle_0422.off
bottle/test/bottle_0423.off
bottle/test/bottle_0424.off
bottle/test/bottle_0425.off
bottle/test/bottle_0426.off
bottle/test/bottle_0427.off
bottle/test/bottle_0428.off
bottle/test/bottle_0429.off
bottle/test/bottle_0430.off
bottle/test/bottle_0431.off
bottle/test/bottle_0432.off
bottle/test/bottle_0433.off
bottle/test/bottle_0434.off
bottle/test/bottle_0435.off
bowl/test/bowl_0065.off
bowl/test/bowl_0066.off
bowl/test/bowl_0067.off
bowl/test/bowl_0068.off
bowl/test/bowl_0069.off
bowl/test/bowl_0070.off
bowl/test/bowl_0071.off
bowl/test/bowl_0072.off
bowl/test/bowl_0073.off
bowl/test/bowl_0074.off
bowl/test/bowl_0075.off
bowl/test/bowl_0076.off
bowl/test/bowl_0077.off
bowl/test/bowl_0078.off
bowl/test/bowl_0079.off
bowl/test/bowl_0080.off
bowl/test/bowl_0081.off
bowl/test/bowl_0082.off
bowl/test/bowl_0083.off
bowl/test/bowl_0084.off
keyboard/test/keyboard_0146.off
keyboard/test/keyboard_0147.off
keyboard/test/keyboard_0148.off
keyboard/test/keyboard_0149.off
keyboard/test/keyboard_0150.off
keyboard/test/keyboard_0151.off
keyboard/test/keyboard_0152.off
keyboard/test/keyboard_0153.off
keyboard/test/keyboard_0154.off
keyboard/test/keyboard_0155.off
keyboard/test/keyboard_0156.off
keyboard/test/keyboard_0157.off
keyboard/test/keyboard_0158.off
keyboard/test/keyboard_0159.off
keyboard/test/keyboard_0160.off
keyboard/test/keyboard_0161.off
keyboard/test/keyboard_0162.off
keyboard/test/keyboard_0163.off
keyboard/test/keyboard_0164.off
keyboard/test/keyboard_0165.off
desk/test/desk_0201.off
desk/test/desk_0202.off
desk/test/desk_0203.off
desk/test/desk_0204.off
desk/test/desk_0205.off
desk/test/desk_0206.off
desk/test/desk_0207.off
desk/test/desk_0208.off
desk/test/desk_0209.off
desk/test/desk_0210.off
desk/test/desk_0211.off
desk/test/desk_0212.off
desk/test/desk_0213.off
desk/test/desk_0214.off
desk/test/desk_0215.off
desk/test/desk_0216.off
desk/test/desk_0217.off
desk/test/desk_0218.off
desk/test/desk_0219.off
desk/test/desk_0220.off
desk/test/desk_0221.off
desk/test/desk_0222.off
desk/test/desk_0223.off
desk/test/desk_0224.off
desk/test/desk_0225.off
desk/test/desk_0226.off
desk/test/desk_0227.off
desk/test/desk_0228.off
desk/test/desk_0229.off
desk/test/desk_0230.off
desk/test/desk_0231.off
desk/test/desk_0232.off
desk/test/desk_0233.off
desk/test/desk_0234.off
desk/test/desk_0235.off
desk/test/desk_0236.off
desk/test/desk_0237.off
desk/test/desk_0238.off
desk/test/desk_0239.off
desk/test/desk_0240.off
desk/test/desk_0241.off
desk/test/desk_0242.off
desk/test/desk_0243.off
desk/test/desk_0244.off
desk/test/desk_0245.off
desk/test/desk_0246.off
desk/test/desk_0247.off
desk/test/desk_0248.off
desk/test/desk_0249.off
desk/test/desk_0250.off
desk/test/desk_0251.off
desk/test/desk_0252.off
desk/test/desk_0253.off
desk/test/desk_0254.off
desk/test/desk_0255.off
desk/test/desk_0256.off
desk/test/desk_0257.off
desk/test/desk_0258.off
desk/test/desk_0259.off
desk/test/desk_0260.off
desk/test/desk_0261.off
desk/test/desk_0262.off
desk/test/desk_0263.off
desk/test/desk_0264.off
desk/test/desk_0265.off
desk/test/desk_0266.off
desk/test/desk_0267.off
desk/test/desk_0268.off
desk/test/desk_0269.off
desk/test/desk_0270.off
desk/test/desk_0271.off
desk/test/desk_0272.off
desk/test/desk_0273.off
desk/test/desk_0274.off
desk/test/desk_0275.off
desk/test/desk_0276.off
desk/test/desk_0277.off
desk/test/desk_0278.off
desk/test/desk_0279.off
desk/test/desk_0280.off
desk/test/desk_0281.off
desk/test/desk_0282.off
desk/test/desk_0283.off
desk/test/desk_0284.off
desk/test/desk_0285.off
desk/test/desk_0286.off
bed/test/bed_0516.off
bed/test/bed_0517.off
bed/test/bed_0518.off
bed/test/bed_0519.off
bed/test/bed_0520.off
bed/test/bed_0521.off
bed/test/bed_0522.off
bed/test/bed_0523.off
bed/test/bed_0524.off
bed/test/bed_0525.off
bed/test/bed_0526.off
bed/test/bed_0527.off
bed/test/bed_0528.off
bed/test/bed_0529.off
bed/test/bed_0530.off
bed/test/bed_0531.off
bed/test/bed_0532.off
bed/test/bed_0533.off
bed/test/bed_0534.off
bed/test/bed_0535.off
bed/test/bed_0536.off
bed/test/bed_0537.off
bed/test/bed_0538.off
bed/test/bed_0539.off
bed/test/bed_0540.off
bed/test/bed_0541.off
bed/test/bed_0542.off
bed/test/bed_0543.off
bed/test/bed_0544.off
bed/test/bed_0545.off
bed/test/bed_0546.off
bed/test/bed_0547.off
bed/test/bed_0548.off
bed/test/bed_0549.off
bed/test/bed_0550.off
bed/test/bed_0551.off
bed/test/bed_0552.off
bed/test/bed_0553.off
bed/test/bed_0554.off
bed/test/bed_0555.off
bed/test/bed_0556.off
bed/test/bed_0557.off
bed/test/bed_0558.off
bed/test/bed_0559.off
bed/test/bed_0560.off
bed/test/bed_0561.off
bed/test/bed_0562.off
bed/test/bed_0563.off
bed/test/bed_0564.off
bed/test/bed_0565.off
bed/test/bed_0566.off
bed/test/bed_0567.off
bed/test/bed_0568.off
bed/test/bed_0569.off
bed/test/bed_0570.off
bed/test/bed_0571.off
bed/test/bed_0572.off
bed/test/bed_0573.off
bed/test/bed_0574.off
bed/test/bed_0575.off
bed/test/bed_0576.off
bed/test/bed_0577.off
bed/test/bed_0578.off
bed/test/bed_0579.off
bed/test/bed_0580.off
bed/test/bed_0581.off
bed/test/bed_0582.off
bed/test/bed_0583.off
bed/test/bed_0584.off
bed/test/bed_0585.off
bed/test/bed_0586.off
bed/test/bed_0587.off
bed/test/bed_0588.off
bed/test/bed_0589.off
bed/test/bed_0590.off
bed/test/bed_0591.off
bed/test/bed_0592.off
bed/test/bed_0593.off
bed/test/bed_0594.off
bed/test/bed_0595.off
bed/test/bed_0596.off
bed/test/bed_0597.off
bed/test/bed_0598.off
bed/test/bed_0599.off
bed/test/bed_0600.off
bed/test/bed_0601.off
bed/test/bed_0602.off
bed/test/bed_0603.off
bed/test/bed_0604.off
bed/test/bed_0605.off
bed/test/bed_0606.off
bed/test/bed_0607.off
bed/test/bed_0608.off
bed/test/bed_0609.off
bed/test/bed_0610.off
bed/test/bed_0611.off
bed/test/bed_0612.off
bed/test/bed_0613.off
bed/test/bed_0614.off
bed/test/bed_0615.off
tent/test/tent_0164.off
tent/test/tent_0165.off
tent/test/tent_0166.off
tent/test/tent_0167.off
tent/test/tent_0168.off
tent/test/tent_0169.off
tent/test/tent_0170.off
tent/test/tent_0171.off
tent/test/tent_0172.off
tent/test/tent_0173.off
tent/test/tent_0174.off
tent/test/tent_0175.off
tent/test/tent_0176.off
tent/test/tent_0177.off
tent/test/tent_0178.off
tent/test/tent_0179.off
tent/test/tent_0180.off
tent/test/tent_0181.off
tent/test/tent_0182.off
tent/test/tent_0183.off
piano/test/piano_0232.off
piano/test/piano_0233.off
piano/test/piano_0234.off
piano/test/piano_0235.off
piano/test/piano_0236.off
piano/test/piano_0237.off
piano/test/piano_0238.off
piano/test/piano_0239.off
piano/test/piano_0240.off
piano/test/piano_0241.off
piano/test/piano_0242.off
piano/test/piano_0243.off
piano/test/piano_0244.off
piano/test/piano_0245.off
piano/test/piano_0246.off
piano/test/piano_0247.off
piano/test/piano_0248.off
piano/test/piano_0249.off
piano/test/piano_0250.off
piano/test/piano_0251.off
piano/test/piano_0252.off
piano/test/piano_0253.off
piano/test/piano_0254.off
piano/test/piano_0255.off
piano/test/piano_0256.off
piano/test/piano_0257.off
piano/test/piano_0258.off
piano/test/piano_0259.off
piano/test/piano_0260.off
piano/test/piano_0261.off
piano/test/piano_0262.off
piano/test/piano_0263.off
piano/test/piano_0264.off
piano/test/piano_0265.off
piano/test/piano_0266.off
piano/test/piano_0267.off
piano/test/piano_0268.off
piano/test/piano_0269.off
piano/test/piano_0270.off
piano/test/piano_0271.off
piano/test/piano_0272.off
piano/test/piano_0273.off
piano/test/piano_0274.off
piano/test/piano_0275.off
piano/test/piano_0276.off
piano/test/piano_0277.off
piano/test/piano_0278.off
piano/test/piano_0279.off
piano/test/piano_0280.off
piano/test/piano_0281.off
piano/test/piano_0282.off
piano/test/piano_0283.off
piano/test/piano_0284.off
piano/test/piano_0285.off
piano/test/piano_0286.off
piano/test/piano_0287.off
piano/test/piano_0288.off
piano/test/piano_0289.off
piano/test/piano_0290.off
piano/test/piano_0291.off
piano/test/piano_0292.off
piano/test/piano_0293.off
piano/test/piano_0294.off
piano/test/piano_0295.off
piano/test/piano_0296.off
piano/test/piano_0297.off
piano/test/piano_0298.off
piano/test/piano_0299.off
piano/test/piano_0300.off
piano/test/piano_0301.off
piano/test/piano_0302.off
piano/test/piano_0303.off
piano/test/piano_0304.off
piano/test/piano_0305.off
piano/test/piano_0306.off
piano/test/piano_0307.off
piano/test/piano_0308.off
piano/test/piano_0309.off
piano/test/piano_0310.off
piano/test/piano_0311.off
piano/test/piano_0312.off
piano/test/piano_0313.off
piano/test/piano_0314.off
piano/test/piano_0315.off
piano/test/piano_0316.off
piano/test/piano_0317.off
piano/test/piano_0318.off
piano/test/piano_0319.off
piano/test/piano_0320.off
piano/test/piano_0321.off
piano/test/piano_0322.off
piano/test/piano_0323.off
piano/test/piano_0324.off
piano/test/piano_0325.off
piano/test/piano_0326.off
piano/test/piano_0327.off
piano/test/piano_0328.off
piano/test/piano_0329.off
piano/test/piano_0330.off
piano/test/piano_0331.off
sofa/test/sofa_0681.off
sofa/test/sofa_0682.off
sofa/test/sofa_0683.off
sofa/test/sofa_0684.off
sofa/test/sofa_0685.off
sofa/test/sofa_0686.off
sofa/test/sofa_0687.off
sofa/test/sofa_0688.off
sofa/test/sofa_0689.off
sofa/test/sofa_0690.off
sofa/test/sofa_0691.off
sofa/test/sofa_0692.off
sofa/test/sofa_0693.off
sofa/test/sofa_0694.off
sofa/test/sofa_0695.off
sofa/test/sofa_0696.off
sofa/test/sofa_0697.off
sofa/test/sofa_0698.off
sofa/test/sofa_0699.off
sofa/test/sofa_0700.off
sofa/test/sofa_0701.off
sofa/test/sofa_0702.off
sofa/test/sofa_0703.off
sofa/test/sofa_0704.off
sofa/test/sofa_0705.off
sofa/test/sofa_0706.off
sofa/test/sofa_0707.off
sofa/test/sofa_0708.off
sofa/test/sofa_0709.off
sofa/test/sofa_0710.off
sofa/test/sofa_0711.off
sofa/test/sofa_0712.off
sofa/test/sofa_0713.off
sofa/test/sofa_0714.off
sofa/test/sofa_0715.off
sofa/test/sofa_0716.off
sofa/test/sofa_0717.off
sofa/test/sofa_0718.off
sofa/test/sofa_0719.off
sofa/test/sofa_0720.off
sofa/test/sofa_0721.off
sofa/test/sofa_0722.off
sofa/test/sofa_0723.off
sofa/test/sofa_0724.off
sofa/test/sofa_0725.off
sofa/test/sofa_0726.off
sofa/test/sofa_0727.off
sofa/test/sofa_0728.off
sofa/test/sofa_0729.off
sofa/test/sofa_0730.off
sofa/test/sofa_0731.off
sofa/test/sofa_0732.off
sofa/test/sofa_0733.off
sofa/test/sofa_0734.off
sofa/test/sofa_0735.off
sofa/test/sofa_0736.off
sofa/test/sofa_0737.off
sofa/test/sofa_0738.off
sofa/test/sofa_0739.off
sofa/test/sofa_0740.off
sofa/test/sofa_0741.off
sofa/test/sofa_0742.off
sofa/test/sofa_0743.off
sofa/test/sofa_0744.off
sofa/test/sofa_0745.off
sofa/test/sofa_0746.off
sofa/test/sofa_0747.off
sofa/test/sofa_0748.off
sofa/test/sofa_0749.off
sofa/test/sofa_0750.off
sofa/test/sofa_0751.off
sofa/test/sofa_0752.off
sofa/test/sofa_0753.off
sofa/test/sofa_0754.off
sofa/test/sofa_0755.off
sofa/test/sofa_0756.off
sofa/test/sofa_0757.off
sofa/test/sofa_0758.off
sofa/test/sofa_0759.off
sofa/test/sofa_0760.off
sofa/test/sofa_0761.off
sofa/test/sofa_0762.off
sofa/test/sofa_0763.off
sofa/test/sofa_0764.off
sofa/test/sofa_0765.off
sofa/test/sofa_0766.off
sofa/test/sofa_0767.off
sofa/test/sofa_0768.off
sofa/test/sofa_0769.off
sofa/test/sofa_0770.off
sofa/test/sofa_0771.off
sofa/test/sofa_0772.off
sofa/test/sofa_0773.off
sofa/test/sofa_0774.off
sofa/test/sofa_0775.off
sofa/test/sofa_0776.off
sofa/test/sofa_0777.off
sofa/test/sofa_0778.off
sofa/test/sofa_0779.off
sofa/test/sofa_0780.off
person/test/person_0089.off
person/test/person_0090.off
person/test/person_0091.off
person/test/person_0092.off
person/test/person_0093.off
person/test/person_0094.off
person/test/person_0095.off
person/test/person_0096.off
person/test/person_0097.off
person/test/person_0098.off
person/test/person_0099.off
person/test/person_0100.off
person/test/person_0101.off
person/test/person_0102.off
person/test/person_0103.off
person/test/person_0104.off
person/test/person_0105.off
person/test/person_0106.off
person/test/person_0107.off
person/test/person_0108.off
xbox/test/xbox_0104.off
xbox/test/xbox_0105.off
xbox/test/xbox_0106.off
xbox/test/xbox_0107.off
xbox/test/xbox_0108.off
xbox/test/xbox_0109.off
xbox/test/xbox_0110.off
xbox/test/xbox_0111.off
xbox/test/xbox_0112.off
xbox/test/xbox_0113.off
xbox/test/xbox_0114.off
xbox/test/xbox_0115.off
xbox/test/xbox_0116.off
xbox/test/xbox_0117.off
xbox/test/xbox_0118.off
xbox/test/xbox_0119.off
xbox/test/xbox_0120.off
xbox/test/xbox_0121.off
xbox/test/xbox_0122.off
xbox/test/xbox_0123.off
stairs/test/stairs_0125.off
stairs/test/stairs_0126.off
stairs/test/stairs_0127.off
stairs/test/stairs_0128.off
stairs/test/stairs_0129.off
stairs/test/stairs_0130.off
stairs/test/stairs_0131.off
stairs/test/stairs_0132.off
stairs/test/stairs_0133.off
stairs/test/stairs_0134.off
stairs/test/stairs_0135.off
stairs/test/stairs_0136.off
stairs/test/stairs_0137.off
stairs/test/stairs_0138.off
stairs/test/stairs_0139.off
stairs/test/stairs_0140.off
stairs/test/stairs_0141.off
stairs/test/stairs_0142.off
stairs/test/stairs_0143.off
stairs/test/stairs_0144.off
cone/test/cone_0168.off
cone/test/cone_0169.off
cone/test/cone_0170.off
cone/test/cone_0171.off
cone/test/cone_0172.off
cone/test/cone_0173.off
cone/test/cone_0174.off
cone/test/cone_0175.off
cone/test/cone_0176.off
cone/test/cone_0177.off
cone/test/cone_0178.off
cone/test/cone_0179.off
cone/test/cone_0180.off
cone/test/cone_0181.off
cone/test/cone_0182.off
cone/test/cone_0183.off
cone/test/cone_0184.off
cone/test/cone_0185.off
cone/test/cone_0186.off
cone/test/cone_0187.off
lamp/test/lamp_0125.off
lamp/test/lamp_0126.off
lamp/test/lamp_0127.off
lamp/test/lamp_0128.off
lamp/test/lamp_0129.off
lamp/test/lamp_0130.off
lamp/test/lamp_0131.off
lamp/test/lamp_0132.off
lamp/test/lamp_0133.off
lamp/test/lamp_0134.off
lamp/test/lamp_0135.off
lamp/test/lamp_0136.off
lamp/test/lamp_0137.off
lamp/test/lamp_0138.off
lamp/test/lamp_0139.off
lamp/test/lamp_0140.off
lamp/test/lamp_0141.off
lamp/test/lamp_0142.off
lamp/test/lamp_0143.off
lamp/test/lamp_0144.off
door/test/door_0110.off
door/test/door_0111.off
door/test/door_0112.off
door/test/door_0113.off
door/test/door_0114.off
door/test/door_0115.off
door/test/door_0116.off
door/test/door_0117.off
door/test/door_0118.off
door/test/door_0119.off
door/test/door_0120.off
door/test/door_0121.off
door/test/door_0122.off
door/test/door_0123.off
door/test/door_0124.off
door/test/door_0125.off
door/test/door_0126.off
door/test/door_0127.off
door/test/door_0128.off
door/test/door_0129.off
range_hood/test/range_hood_0116.off
range_hood/test/range_hood_0117.off
range_hood/test/range_hood_0118.off
range_hood/test/range_hood_0119.off
range_hood/test/range_hood_0120.off
range_hood/test/range_hood_0121.off
range_hood/test/range_hood_0122.off
range_hood/test/range_hood_0123.off
range_hood/test/range_hood_0124.off
range_hood/test/range_hood_0125.off
range_hood/test/range_hood_0126.off
range_hood/test/range_hood_0127.off
range_hood/test/range_hood_0128.off
range_hood/test/range_hood_0129.off
range_hood/test/range_hood_0130.off
range_hood/test/range_hood_0131.off
range_hood/test/range_hood_0132.off
range_hood/test/range_hood_0133.off
range_hood/test/range_hood_0134.off
range_hood/test/range_hood_0135.off
range_hood/test/range_hood_0136.off
range_hood/test/range_hood_0137.off
range_hood/test/range_hood_0138.off
range_hood/test/range_hood_0139.off
range_hood/test/range_hood_0140.off
range_hood/test/range_hood_0141.off
range_hood/test/range_hood_0142.off
range_hood/test/range_hood_0143.off
range_hood/test/range_hood_0144.off
range_hood/test/range_hood_0145.off
range_hood/test/range_hood_0146.off
range_hood/test/range_hood_0147.off
range_hood/test/range_hood_0148.off
range_hood/test/range_hood_0149.off
range_hood/test/range_hood_0150.off
range_hood/test/range_hood_0151.off
range_hood/test/range_hood_0152.off
range_hood/test/range_hood_0153.off
range_hood/test/range_hood_0154.off
range_hood/test/range_hood_0155.off
range_hood/test/range_hood_0156.off
range_hood/test/range_hood_0157.off
range_hood/test/range_hood_0158.off
range_hood/test/range_hood_0159.off
range_hood/test/range_hood_0160.off
range_hood/test/range_hood_0161.off
range_hood/test/range_hood_0162.off
range_hood/test/range_hood_0163.off
range_hood/test/range_hood_0164.off
range_hood/test/range_hood_0165.off
range_hood/test/range_hood_0166.off
range_hood/test/range_hood_0167.off
range_hood/test/range_hood_0168.off
range_hood/test/range_hood_0169.off
range_hood/test/range_hood_0170.off
range_hood/test/range_hood_0171.off
range_hood/test/range_hood_0172.off
range_hood/test/range_hood_0173.off
range_hood/test/range_hood_0174.off
range_hood/test/range_hood_0175.off
range_hood/test/range_hood_0176.off
range_hood/test/range_hood_0177.off
range_hood/test/range_hood_0178.off
range_hood/test/range_hood_0179.off
range_hood/test/range_hood_0180.off
range_hood/test/range_hood_0181.off
range_hood/test/range_hood_0182.off
range_hood/test/range_hood_0183.off
range_hood/test/range_hood_0184.off
range_hood/test/range_hood_0185.off
range_hood/test/range_hood_0186.off
range_hood/test/range_hood_0187.off
range_hood/test/range_hood_0188.off
range_hood/test/range_hood_0189.off
range_hood/test/range_hood_0190.off
range_hood/test/range_hood_0191.off
range_hood/test/range_hood_0192.off
range_hood/test/range_hood_0193.off
range_hood/test/range_hood_0194.off
range_hood/test/range_hood_0195.off
range_hood/test/range_hood_0196.off
range_hood/test/range_hood_0197.off
range_hood/test/range_hood_0198.off
range_hood/test/range_hood_0199.off
range_hood/test/range_hood_0200.off
range_hood/test/range_hood_0201.off
range_hood/test/range_hood_0202.off
range_hood/test/range_hood_0203.off
range_hood/test/range_hood_0204.off
range_hood/test/range_hood_0205.off
range_hood/test/range_hood_0206.off
range_hood/test/range_hood_0207.off
range_hood/test/range_hood_0208.off
range_hood/test/range_hood_0209.off
range_hood/test/range_hood_0210.off
range_hood/test/range_hood_0211.off
range_hood/test/range_hood_0212.off
range_hood/test/range_hood_0213.off
range_hood/test/range_hood_0214.off
range_hood/test/range_hood_0215.off
flower_pot/test/flower_pot_0150.off
flower_pot/test/flower_pot_0151.off
flower_pot/test/flower_pot_0152.off
flower_pot/test/flower_pot_0153.off
flower_pot/test/flower_pot_0154.off
flower_pot/test/flower_pot_0155.off
flower_pot/test/flower_pot_0156.off
flower_pot/test/flower_pot_0157.off
flower_pot/test/flower_pot_0158.off
flower_pot/test/flower_pot_0159.off
flower_pot/test/flower_pot_0160.off
flower_pot/test/flower_pot_0161.off
flower_pot/test/flower_pot_0162.off
flower_pot/test/flower_pot_0163.off
flower_pot/test/flower_pot_0164.off
flower_pot/test/flower_pot_0165.off
flower_pot/test/flower_pot_0166.off
flower_pot/test/flower_pot_0167.off
flower_pot/test/flower_pot_0168.off
flower_pot/test/flower_pot_0169.off
================================================
FILE: dataloader/split/test_scan2cad.txt
================================================
full_annotations_clean_test.json
================================================
FILE: dataloader/split/train_3dmatch.txt
================================================
sun3d-brown_bm_1-brown_bm_1
sun3d-brown_cogsci_1-brown_cogsci_1
sun3d-brown_cs_2-brown_cs2
sun3d-brown_cs_3-brown_cs3
sun3d-harvard_c3-hv_c3_1
sun3d-harvard_c5-hv_c5_1
sun3d-harvard_c6-hv_c6_1
sun3d-harvard_c8-hv_c8_3
sun3d-home_bksh-home_bksh_oct_30_2012_scan2_erika
sun3d-hotel_nips2012-nips_4
sun3d-hotel_sf-scan1
sun3d-mit_32_d507-d507_2
sun3d-mit_46_ted_lab1-ted_lab_2
sun3d-mit_76_417-76-417b
sun3d-mit_dorm_next_sj-dorm_next_sj_oct_30_2012_scan1_erika
sun3d-mit_w20_athena-sc_athena_oct_29_2012_scan1_erika
7-scenes-chess
7-scenes-fire
7-scenes-office
7-scenes-pumpkin
7-scenes-stairs
rgbd-scenes-v2-scene_01
rgbd-scenes-v2-scene_02
rgbd-scenes-v2-scene_03
rgbd-scenes-v2-scene_04
rgbd-scenes-v2-scene_05
rgbd-scenes-v2-scene_06
rgbd-scenes-v2-scene_07
rgbd-scenes-v2-scene_08
rgbd-scenes-v2-scene_09
rgbd-scenes-v2-scene_11
rgbd-scenes-v2-scene_12
rgbd-scenes-v2-scene_13
rgbd-scenes-v2-scene_14
bundlefusion-apt0
bundlefusion-apt1
bundlefusion-apt2
bundlefusion-copyroom
bundlefusion-office1
bundlefusion-office2
bundlefusion-office3
analysis-by-synthesis-apt1-kitchen
analysis-by-synthesis-apt1-living
analysis-by-synthesis-apt2-bed
analysis-by-synthesis-apt2-living
analysis-by-synthesis-apt2-luke
analysis-by-synthesis-office2-5a
analysis-by-synthesis-office2-5b
================================================
FILE: dataloader/split/train_kitti.txt
================================================
0
1
2
3
4
5
================================================
FILE: dataloader/split/train_modelnet40.txt
================================================
glass_box/train/glass_box_0001.off
glass_box/train/glass_box_0002.off
glass_box/train/glass_box_0003.off
glass_box/train/glass_box_0004.off
glass_box/train/glass_box_0005.off
glass_box/train/glass_box_0006.off
glass_box/train/glass_box_0007.off
glass_box/train/glass_box_0008.off
glass_box/train/glass_box_0009.off
glass_box/train/glass_box_0010.off
glass_box/train/glass_box_0011.off
glass_box/train/glass_box_0012.off
glass_box/train/glass_box_0013.off
glass_box/train/glass_box_0014.off
glass_box/train/glass_box_0015.off
glass_box/train/glass_box_0016.off
glass_box/train/glass_box_0017.off
glass_box/train/glass_box_0018.off
glass_box/train/glass_box_0019.off
glass_box/train/glass_box_0020.off
glass_box/train/glass_box_0021.off
glass_box/train/glass_box_0022.off
glass_box/train/glass_box_0023.off
glass_box/train/glass_box_0024.off
glass_box/train/glass_box_0025.off
glass_box/train/glass_box_0026.off
glass_box/train/glass_box_0027.off
glass_box/train/glass_box_0028.off
glass_box/train/glass_box_0029.off
glass_box/train/glass_box_0030.off
glass_box/train/glass_box_0031.off
glass_box/train/glass_box_0032.off
glass_box/train/glass_box_0033.off
glass_box/train/glass_box_0034.off
glass_box/train/glass_box_0035.off
glass_box/train/glass_box_0036.off
glass_box/train/glass_box_0037.off
glass_box/train/glass_box_0038.off
glass_box/train/glass_box_0039.off
glass_box/train/glass_box_0040.off
glass_box/train/glass_box_0041.off
glass_box/train/glass_box_0042.off
glass_box/train/glass_box_0043.off
glass_box/train/glass_box_0044.off
glass_box/train/glass_box_0045.off
glass_box/train/glass_box_0046.off
glass_box/train/glass_box_0047.off
glass_box/train/glass_box_0048.off
glass_box/train/glass_box_0049.off
glass_box/train/glass_box_0050.off
glass_box/train/glass_box_0051.off
glass_box/train/glass_box_0052.off
glass_box/train/glass_box_0053.off
glass_box/train/glass_box_0054.off
glass_box/train/glass_box_0055.off
glass_box/train/glass_box_0056.off
glass_box/train/glass_box_0057.off
glass_box/train/glass_box_0058.off
glass_box/train/glass_box_0059.off
glass_box/train/glass_box_0060.off
glass_box/train/glass_box_0061.off
glass_box/train/glass_box_0062.off
glass_box/train/glass_box_0063.off
glass_box/train/glass_box_0064.off
glass_box/train/glass_box_0065.off
glass_box/train/glass_box_0066.off
glass_box/train/glass_box_0067.off
glass_box/train/glass_box_0068.off
glass_box/train/glass_box_0069.off
glass_box/train/glass_box_0070.off
glass_box/train/glass_box_0071.off
glass_box/train/glass_box_0072.off
glass_box/train/glass_box_0073.off
glass_box/train/glass_box_0074.off
glass_box/train/glass_box_0075.off
glass_box/train/glass_box_0076.off
glass_box/train/glass_box_0077.off
glass_box/train/glass_box_0078.off
glass_box/train/glass_box_0079.off
glass_box/train/glass_box_0080.off
glass_box/train/glass_box_0081.off
glass_box/train/glass_box_0082.off
glass_box/train/glass_box_0083.off
glass_box/train/glass_box_0084.off
glass_box/train/glass_box_0085.off
glass_box/train/glass_box_0086.off
glass_box/train/glass_box_0087.off
glass_box/train/glass_box_0088.off
glass_box/train/glass_box_0089.off
glass_box/train/glass_box_0090.off
glass_box/train/glass_box_0091.off
glass_box/train/glass_box_0092.off
glass_box/train/glass_box_0093.off
glass_box/train/glass_box_0094.off
glass_box/train/glass_box_0095.off
glass_box/train/glass_box_0096.off
glass_box/train/glass_box_0097.off
glass_box/train/glass_box_0098.off
glass_box/train/glass_box_0099.off
glass_box/train/glass_box_0100.off
glass_box/train/glass_box_0101.off
glass_box/train/glass_box_0102.off
glass_box/train/glass_box_0103.off
glass_box/train/glass_box_0104.off
glass_box/train/glass_box_0105.off
glass_box/train/glass_box_0106.off
glass_box/train/glass_box_0107.off
glass_box/train/glass_box_0108.off
glass_box/train/glass_box_0109.off
glass_box/train/glass_box_0110.off
glass_box/train/glass_box_0111.off
glass_box/train/glass_box_0112.off
glass_box/train/glass_box_0113.off
glass_box/train/glass_box_0114.off
glass_box/train/glass_box_0115.off
glass_box/train/glass_box_0116.off
glass_box/train/glass_box_0117.off
glass_box/train/glass_box_0118.off
glass_box/train/glass_box_0119.off
glass_box/train/glass_box_0120.off
glass_box/train/glass_box_0121.off
glass_box/train/glass_box_0122.off
glass_box/train/glass_box_0123.off
glass_box/train/glass_box_0124.off
glass_box/train/glass_box_0125.off
glass_box/train/glass_box_0126.off
glass_box/train/glass_box_0127.off
glass_box/train/glass_box_0128.off
glass_box/train/glass_box_0129.off
glass_box/train/glass_box_0130.off
glass_box/train/glass_box_0131.off
glass_box/train/glass_box_0132.off
glass_box/train/glass_box_0133.off
glass_box/train/glass_box_0134.off
glass_box/train/glass_box_0135.off
glass_box/train/glass_box_0136.off
glass_box/train/glass_box_0137.off
glass_box/train/glass_box_0138.off
glass_box/train/glass_box_0139.off
glass_box/train/glass_box_0140.off
glass_box/train/glass_box_0141.off
glass_box/train/glass_box_0142.off
glass_box/train/glass_box_0143.off
glass_box/train/glass_box_0144.off
glass_box/train/glass_box_0145.off
glass_box/train/glass_box_0146.off
glass_box/train/glass_box_0147.off
glass_box/train/glass_box_0148.off
glass_box/train/glass_box_0149.off
glass_box/train/glass_box_0150.off
glass_box/train/glass_box_0151.off
glass_box/train/glass_box_0152.off
glass_box/train/glass_box_0153.off
glass_box/train/glass_box_0154.off
laptop/train/laptop_0001.off
laptop/train/laptop_0002.off
laptop/train/laptop_0003.off
laptop/train/laptop_0004.off
laptop/train/laptop_0005.off
laptop/train/laptop_0006.off
laptop/train/laptop_0007.off
laptop/train/laptop_0008.off
laptop/train/laptop_0009.off
laptop/train/laptop_0010.off
laptop/train/laptop_0011.off
laptop/train/laptop_0012.off
laptop/train/laptop_0013.off
laptop/train/laptop_0014.off
laptop/train/laptop_0015.off
laptop/train/laptop_0016.off
laptop/train/laptop_0017.off
laptop/train/laptop_0018.off
laptop/train/laptop_0019.off
laptop/train/laptop_0020.off
laptop/train/laptop_0021.off
laptop/train/laptop_0022.off
laptop/train/laptop_0023.off
laptop/train/laptop_0024.off
laptop/train/laptop_0025.off
laptop/train/laptop_0026.off
laptop/train/laptop_0027.off
laptop/train/laptop_0028.off
laptop/train/laptop_0029.off
laptop/train/laptop_0030.off
laptop/train/laptop_0031.off
laptop/train/laptop_0032.off
laptop/train/laptop_0033.off
laptop/train/laptop_0034.off
laptop/train/laptop_0035.off
laptop/train/laptop_0036.off
laptop/train/laptop_0037.off
laptop/train/laptop_0038.off
laptop/train/laptop_0039.off
laptop/train/laptop_0040.off
laptop/train/laptop_0041.off
laptop/train/laptop_0042.off
laptop/train/laptop_0043.off
laptop/train/laptop_0044.off
laptop/train/laptop_0045.off
laptop/train/laptop_0046.off
laptop/train/laptop_0047.off
laptop/train/laptop_0048.off
laptop/train/laptop_0049.off
laptop/train/laptop_0050.off
laptop/train/laptop_0051.off
laptop/train/laptop_0052.off
laptop/train/laptop_0053.off
laptop/train/laptop_0054.off
laptop/train/laptop_0055.off
laptop/train/laptop_0056.off
laptop/train/laptop_0057.off
laptop/train/laptop_0058.off
laptop/train/laptop_0059.off
laptop/train/laptop_0060.off
laptop/train/laptop_0061.off
laptop/train/laptop_0062.off
laptop/train/laptop_0063.off
laptop/train/laptop_0064.off
laptop/train/laptop_0065.off
laptop/train/laptop_0066.off
laptop/train/laptop_0067.off
laptop/train/laptop_0068.off
laptop/train/laptop_0069.off
laptop/train/laptop_0070.off
laptop/train/laptop_0071.off
laptop/train/laptop_0072.off
laptop/train/laptop_0073.off
laptop/train/laptop_0074.off
laptop/train/laptop_0075.off
laptop/train/laptop_0076.off
laptop/train/laptop_0077.off
laptop/train/laptop_0078.off
laptop/train/laptop_0079.off
laptop/train/laptop_0080.off
laptop/train/laptop_0081.off
laptop/train/laptop_0082.off
laptop/train/laptop_0083.off
laptop/train/laptop_0084.off
laptop/train/laptop_0085.off
laptop/train/laptop_0086.off
laptop/train/laptop_0087.off
laptop/train/laptop_0088.off
laptop/train/laptop_0089.off
laptop/train/laptop_0090.off
laptop/train/laptop_0091.off
laptop/train/laptop_0092.off
laptop/train/laptop_0093.off
laptop/train/laptop_0094.off
laptop/train/laptop_0095.off
laptop/train/laptop_0096.off
laptop/train/laptop_0097.off
laptop/train/laptop_0098.off
laptop/train/laptop_0099.off
laptop/train/laptop_0100.off
laptop/train/laptop_0101.off
laptop/train/laptop_0102.off
laptop/train/laptop_0103.off
laptop/train/laptop_0104.off
laptop/train/laptop_0105.off
laptop/train/laptop_0106.off
laptop/train/laptop_0107.off
laptop/train/laptop_0108.off
laptop/train/laptop_0109.off
laptop/train/laptop_0110.off
laptop/train/laptop_0111.off
laptop/train/laptop_0112.off
laptop/train/laptop_0113.off
laptop/train/laptop_0114.off
laptop/train/laptop_0115.off
laptop/train/laptop_0116.off
laptop/train/laptop_0117.off
laptop/train/laptop_0118.off
laptop/train/laptop_0119.off
laptop/train/laptop_0120.off
laptop/train/laptop_0121.off
laptop/train/laptop_0122.off
laptop/train/laptop_0123.off
laptop/train/laptop_0124.off
laptop/train/laptop_0125.off
laptop/train/laptop_0126.off
laptop/train/laptop_0127.off
laptop/train/laptop_0128.off
laptop/train/laptop_0129.off
laptop/train/laptop_0130.off
laptop/train/laptop_0131.off
laptop/train/laptop_0132.off
laptop/train/laptop_0133.off
laptop/train/laptop_0134.off
laptop/train/laptop_0135.off
sink/train/sink_0001.off
sink/train/sink_0002.off
sink/train/sink_0003.off
sink/train/sink_0004.off
sink/train/sink_0005.off
sink/train/sink_0006.off
sink/train/sink_0007.off
sink/train/sink_0008.off
sink/train/sink_0009.off
sink/train/sink_0010.off
sink/train/sink_0011.off
sink/train/sink_0012.off
sink/train/sink_0013.off
sink/train/sink_0014.off
sink/train/sink_0015.off
sink/train/sink_0016.off
sink/train/sink_0017.off
sink/train/sink_0018.off
sink/train/sink_0019.off
sink/train/sink_0020.off
sink/train/sink_0021.off
sink/train/sink_0022.off
sink/train/sink_0023.off
sink/train/sink_0024.off
sink/train/sink_0025.off
sink/train/sink_0026.off
sink/train/sink_0027.off
sink/train/sink_0028.off
sink/train/sink_0029.off
sink/train/sink_0030.off
sink/train/sink_0031.off
sink/train/sink_0032.off
sink/train/sink_0033.off
sink/train/sink_0034.off
sink/train/sink_0035.off
sink/train/sink_0036.off
sink/train/sink_0037.off
sink/train/sink_0038.off
sink/train/sink_0039.off
sink/train/sink_0040.off
sink/train/sink_0041.off
sink/train/sink_0042.off
sink/train/sink_0043.off
sink/train/sink_0044.off
sink/train/sink_0045.off
sink/train/sink_0046.off
sink/train/sink_0047.off
sink/train/sink_0048.off
sink/train/sink_0049.off
sink/train/sink_0050.off
sink/train/sink_0051.off
sink/train/sink_0052.off
sink/train/sink_0053.off
sink/train/sink_0054.off
sink/train/sink_0055.off
sink/train/sink_0056.off
sink/train/sink_0057.off
sink/train/sink_0058.off
sink/train/sink_0059.off
sink/train/sink_0060.off
sink/train/sink_0061.off
sink/train/sink_0062.off
sink/train/sink_0063.off
sink/train/sink_0064.off
sink/train/sink_0065.off
sink/train/sink_0066.off
sink/train/sink_0067.off
sink/train/sink_0068.off
sink/train/sink_0069.off
sink/train/sink_0070.off
sink/train/sink_0071.off
sink/train/sink_0072.off
sink/train/sink_0073.off
sink/train/sink_0074.off
sink/train/sink_0075.off
sink/train/sink_0076.off
sink/train/sink_0077.off
sink/train/sink_0078.off
sink/train/sink_0079.off
sink/train/sink_0080.off
sink/train/sink_0081.off
sink/train/sink_0082.off
sink/train/sink_0083.off
sink/train/sink_0084.off
sink/train/sink_0085.off
sink/train/sink_0086.off
sink/train/sink_0087.off
sink/train/sink_0088.off
sink/train/sink_0089.off
sink/train/sink_0090.off
sink/train/sink_0091.off
sink/train/sink_0092.off
sink/train/sink_0093.off
sink/train/sink_0094.off
sink/train/sink_0095.off
sink/train/sink_0096.off
sink/train/sink_0097.off
sink/train/sink_0098.off
sink/train/sink_0099.off
sink/train/sink_0100.off
sink/train/sink_0101.off
sink/train/sink_0102.off
sink/train/sink_0103.off
sink/train/sink_0104.off
sink/train/sink_0105.off
sink/train/sink_0106.off
sink/train/sink_0107.off
sink/train/sink_0108.off
sink/train/sink_0109.off
sink/train/sink_0110.off
sink/train/sink_0111.off
sink/train/sink_0112.off
sink/train/sink_0113.off
sink/train/sink_0114.off
sink/train/sink_0115.off
sink/train/sink_0116.off
night_stand/train/night_stand_0001.off
night_stand/train/night_stand_0002.off
night_stand/train/night_stand_0003.off
night_stand/train/night_stand_0004.off
night_stand/train/night_stand_0005.off
night_stand/train/night_stand_0006.off
night_stand/train/night_stand_0007.off
night_stand/train/night_stand_0008.off
night_stand/train/night_stand_0009.off
night_stand/train/night_stand_0010.off
night_stand/train/night_stand_0011.off
night_stand/train/night_stand_0012.off
night_stand/train/night_stand_0013.off
night_stand/train/night_stand_0014.off
night_stand/train/night_stand_0015.off
night_stand/train/night_stand_0016.off
night_stand/train/night_stand_0017.off
night_stand/train/night_stand_0018.off
night_stand/train/night_stand_0019.off
night_stand/train/night_stand_0020.off
night_stand/train/night_stand_0021.off
night_stand/train/night_stand_0022.off
night_stand/train/night_stand_0023.off
night_stand/train/night_stand_0024.off
night_stand/train/night_stand_0025.off
night_stand/train/night_stand_0026.off
night_stand/train/night_stand_0027.off
night_stand/train/night_stand_0028.off
night_stand/train/night_stand_0029.off
night_stand/train/night_stand_0030.off
night_stand/train/night_stand_0031.off
night_stand/train/night_stand_0032.off
night_stand/train/night_stand_0033.off
night_stand/train/night_stand_0034.off
night_stand/train/night_stand_0035.off
night_stand/train/night_stand_0036.off
night_stand/train/night_stand_0037.off
night_stand/train/night_stand_0038.off
night_stand/train/night_stand_0039.off
night_stand/train/night_stand_0040.off
night_stand/train/night_stand_0041.off
night_stand/train/night_stand_0042.off
night_stand/train/night_stand_0043.off
night_stand/train/night_stand_0044.off
night_stand/train/night_stand_0045.off
night_stand/train/night_stand_0046.off
night_stand/train/night_stand_0047.off
night_stand/train/night_stand_0048.off
night_stand/train/night_stand_0049.off
night_stand/train/night_stand_0050.off
night_stand/train/night_stand_0051.off
night_stand/train/night_stand_0052.off
night_stand/train/night_stand_0053.off
night_stand/train/night_stand_0054.off
night_stand/train/night_stand_0055.off
night_stand/train/night_stand_0056.off
night_stand/train/night_stand_0057.off
night_stand/train/night_stand_0058.off
night_stand/train/night_stand_0059.off
night_stand/train/night_stand_0060.off
night_stand/train/night_stand_0061.off
night_stand/train/night_stand_0062.off
night_stand/train/night_stand_0063.off
night_stand/train/night_stand_0064.off
night_stand/train/night_stand_0065.off
night_stand/train/night_stand_0066.off
night_stand/train/night_stand_0067.off
night_stand/train/night_stand_0068.off
night_stand/train/night_stand_0069.off
night_stand/train/night_stand_0070.off
night_stand/train/night_stand_0071.off
night_stand/train/night_stand_0072.off
night_stand/train/night_stand_0073.off
night_stand/train/night_stand_0074.off
night_stand/train/night_stand_0075.off
night_stand/train/night_stand_0076.off
night_stand/train/night_stand_0077.off
night_stand/train/night_stand_0078.off
night_stand/train/night_stand_0079.off
night_stand/train/night_stand_0080.off
night_stand/train/night_stand_0081.off
night_stand/train/night_stand_0082.off
night_stand/train/night_stand_0083.off
night_stand/train/night_stand_0084.off
night_stand/train/night_stand_0085.off
night_stand/train/night_stand_0086.off
night_stand/train/night_stand_0087.off
night_stand/train/night_stand_0088.off
night_stand/train/night_stand_0089.off
night_stand/train/night_stand_0090.off
night_stand/train/night_stand_0091.off
night_stand/train/night_stand_0092.off
night_stand/train/night_stand_0093.off
night_stand/train/night_stand_0094.off
night_stand/train/night_stand_0095.off
night_stand/train/night_stand_0096.off
night_stand/train/night_stand_0097.off
night_stand/train/night_stand_0098.off
night_stand/train/night_stand_0099.off
night_stand/train/night_stand_0100.off
night_stand/train/night_stand_0101.off
night_stand/train/night_stand_0102.off
night_stand/train/night_stand_0103.off
night_stand/train/night_stand_0104.off
night_stand/train/night_stand_0105.off
night_stand/train/night_stand_0106.off
night_stand/train/night_stand_0107.off
night_stand/train/night_stand_0108.off
night_stand/train/night_stand_0109.off
night_stand/train/night_stand_0110.off
night_stand/train/night_stand_0111.off
night_stand/train/night_stand_0112.off
night_stand/train/night_stand_0113.off
night_stand/train/night_stand_0114.off
night_stand/train/night_stand_0115.off
night_stand/train/night_stand_0116.off
night_stand/train/night_stand_0117.off
night_stand/train/night_stand_0118.off
night_stand/train/night_stand_0119.off
night_stand/train/night_stand_0120.off
night_stand/train/night_stand_0121.off
night_stand/train/night_stand_0122.off
night_stand/train/night_stand_0123.off
night_stand/train/night_stand_0124.off
night_stand/train/night_stand_0125.off
night_stand/train/night_stand_0126.off
night_stand/train/night_stand_0127.off
night_stand/train/night_stand_0128.off
night_stand/train/night_stand_0129.off
night_stand/train/night_stand_0130.off
night_stand/train/night_stand_0131.off
night_stand/train/night_stand_0132.off
night_stand/train/night_stand_0133.off
night_stand/train/night_stand_0134.off
night_stand/train/night_stand_0135.off
night_stand/train/night_stand_0136.off
night_stand/train/night_stand_0137.off
night_stand/train/night_stand_0138.off
night_stand/train/night_stand_0139.off
night_stand/train/night_stand_0140.off
night_stand/train/night_stand_0141.off
night_stand/train/night_stand_0142.off
night_stand/train/night_stand_0143.off
night_stand/train/night_stand_0144.off
night_stand/train/night_stand_0145.off
night_stand/train/night_stand_0146.off
night_stand/train/night_stand_0147.off
night_stand/train/night_stand_0148.off
night_stand/train/night_stand_0149.off
night_stand/train/night_stand_0150.off
night_stand/train/night_stand_0151.off
night_stand/train/night_stand_0152.off
night_stand/train/night_stand_0153.off
night_stand/train/night_stand_0154.off
night_stand/train/night_stand_0155.off
night_stand/train/night_stand_0156.off
night_stand/train/night_stand_0157.off
night_stand/train/night_stand_0158.off
night_stand/train/night_stand_0159.off
night_stand/train/night_stand_0160.off
night_stand/train/night_stand_0161.off
night_stand/train/night_stand_0162.off
night_stand/train/night_stand_0163.off
night_stand/train/night_stand_0164.off
night_stand/train/night_stand_0165.off
night_stand/train/night_stand_0166.off
night_stand/train/night_stand_0167.off
night_stand/train/night_stand_0168.off
night_stand/train/night_stand_0169.off
night_stand/train/night_stand_0170.off
night_stand/train/night_stand_0171.off
night_stand/train/night_stand_0172.off
night_stand/train/night_stand_0173.off
night_stand/train/night_stand_0174.off
night_stand/train/night_stand_0175.off
night_stand/train/night_stand_0176.off
night_stand/train/night_stand_0177.off
night_stand/train/night_stand_0178.off
night_stand/train/night_stand_0179.off
night_stand/train/night_stand_0180.off
car/train/car_0001.off
car/train/car_0002.off
car/train/car_0003.off
car/train/car_0004.off
car/train/car_0005.off
car/train/car_0006.off
car/train/car_0007.off
car/train/car_0008.off
car/train/car_0009.off
car/train/car_0010.off
car/train/car_0011.off
car/train/car_0012.off
car/train/car_0013.off
car/train/car_0014.off
car/train/car_0015.off
car/train/car_0016.off
car/train/car_0017.off
car/train/car_0018.off
car/train/car_0019.off
car/train/car_0020.off
car/train/car_0021.off
car/train/car_0022.off
car/train/car_0023.off
car/train/car_0024.off
car/train/car_0025.off
car/train/car_0026.off
car/train/car_0027.off
car/train/car_0028.off
car/train/car_0029.off
car/train/car_0030.off
car/train/car_0031.off
car/train/car_0032.off
car/train/car_0033.off
car/train/car_0034.off
car/train/car_0035.off
car/train/car_0036.off
car/train/car_0037.off
car/train/car_0038.off
car/train/car_0039.off
car/train/car_0040.off
car/train/car_0041.off
car/train/car_0042.off
car/train/car_0043.off
car/train/car_0044.off
car/train/car_0045.off
car/train/car_0046.off
car/train/car_0047.off
car/train/car_0048.off
car/train/car_0049.off
car/train/car_0050.off
car/train/car_0051.off
car/train/car_0052.off
car/train/car_0053.off
car/train/car_0054.off
car/train/car_0055.off
car/train/car_0056.off
car/train/car_0057.off
car/train/car_0058.off
car/train/car_0059.off
car/train/car_0060.off
car/train/car_0061.off
car/train/car_0062.off
car/train/car_0063.off
car/train/car_0064.off
car/train/car_0065.off
car/train/car_0066.off
car/train/car_0067.off
car/train/car_0068.off
car/train/car_0069.off
car/train/car_0070.off
car/train/car_0071.off
car/train/car_0072.off
car/train/car_0073.off
car/train/car_0074.off
car/train/car_0075.off
car/train/car_0076.off
car/train/car_0077.off
car/train/car_0078.off
car/train/car_0079.off
car/train/car_0080.off
car/train/car_0081.off
car/train/car_0082.off
car/train/car_0083.off
car/train/car_0084.off
car/train/car_0085.off
car/train/car_0086.off
car/train/car_0087.off
car/train/car_0088.off
car/train/car_0089.off
car/train/car_0090.off
car/train/car_0091.off
car/train/car_0092.off
car/train/car_0093.off
car/train/car_0094.off
car/train/car_0095.off
car/train/car_0096.off
car/train/car_0097.off
car/train/car_0098.off
car/train/car_0099.off
car/train/car_0100.off
car/train/car_0101.off
car/train/car_0102.off
car/train/car_0103.off
car/train/car_0104.off
car/train/car_0105.off
car/train/car_0106.off
car/train/car_0107.off
car/train/car_0108.off
car/train/car_0109.off
car/train/car_0110.off
car/train/car_0111.off
car/train/car_0112.off
car/train/car_0113.off
car/train/car_0114.off
car/train/car_0115.off
car/train/car_0116.off
car/train/car_0117.off
car/train/car_0118.off
car/train/car_0119.off
car/train/car_0120.off
car/train/car_0121.off
car/train/car_0122.off
car/train/car_0123.off
car/train/car_0124.off
car/train/car_0125.off
car/train/car_0126.off
car/train/car_0127.off
car/train/car_0128.off
car/train/car_0129.off
car/train/car_0130.off
car/train/car_0131.off
car/train/car_0132.off
car/train/car_0133.off
car/train/car_0134.off
car/train/car_0135.off
car/train/car_0136.off
car/train/car_0137.off
car/train/car_0138.off
car/train/car_0139.off
car/train/car_0140.off
car/train/car_0141.off
car/train/car_0142.off
car/train/car_0143.off
car/train/car_0144.off
car/train/car_0145.off
car/train/car_0146.off
car/train/car_0147.off
car/train/car_0148.off
car/train/car_0149.off
car/train/car_0150.off
car/train/car_0151.off
car/train/car_0152.off
car/train/car_0153.off
car/train/car_0154.off
car/train/car_0155.off
car/train/car_0156.off
car/train/car_0157.off
car/train/car_0158.off
car/train/car_0159.off
car/train/car_0160.off
car/train/car_0161.off
car/train/car_0162.off
car/train/car_0163.off
car/train/car_0164.off
car/train/car_0165.off
car/train/car_0166.off
car/train/car_0167.off
car/train/car_0168.off
car/train/car_0169.off
car/train/car_0170.off
car/train/car_0171.off
car/train/car_0172.off
car/train/car_0173.off
car/train/car_0174.off
car/train/car_0175.off
car/train/car_0176.off
car/train/car_0177.off
car/train/car_0178.off
dresser/train/dresser_0001.off
dresser/train/dresser_0002.off
dresser/train/dresser_0003.off
dresser/train/dresser_0004.off
dresser/train/dresser_0005.off
dresser/train/dresser_0006.off
dresser/train/dresser_0007.off
dresser/train/dresser_0008.off
dresser/train/dresser_0009.off
dresser/train/dresser_0010.off
dresser/train/dresser_0011.off
dresser/train/dresser_0012.off
dresser/train/dresser_0013.off
dresser/train/dresser_0014.off
dresser/train/dresser_0015.off
dresser/train/dresser_0016.off
dresser/train/dresser_0017.off
dresser/train/dresser_0018.off
dresser/train/dresser_0019.off
dresser/train/dresser_0020.off
dresser/train/dresser_0021.off
dresser/train/dresser_0022.off
dresser/train/dresser_0023.off
dresser/train/dresser_0024.off
dresser/train/dresser_0025.off
dresser/train/dresser_0026.off
dresser/train/dresser_0027.off
dresser/train/dresser_0028.off
dresser/train/dresser_0029.off
dresser/train/dresser_0030.off
dresser/train/dresser_0031.off
dresser/train/dresser_0032.off
dresser/train/dresser_0033.off
dresser/train/dresser_0034.off
dresser/train/dresser_0035.off
dresser/train/dresser_0036.off
dresser/train/dresser_0037.off
dresser/train/dresser_0038.off
dresser/train/dresser_0039.off
dresser/train/dresser_0040.off
dresser/train/dresser_0041.off
dresser/train/dresser_0042.off
dresser/train/dresser_0043.off
dresser/train/dresser_0044.off
dresser/train/dresser_0045.off
dresser/train/dresser_0046.off
dresser/train/dresser_0047.off
dresser/train/dresser_0048.off
dresser/train/dresser_0049.off
dresser/train/dresser_0050.off
dresser/train/dresser_0051.off
dresser/train/dresser_0052.off
dresser/train/dresser_0053.off
dresser/train/dresser_0054.off
dresser/train/dresser_0055.off
dresser/train/dresser_0056.off
dresser/train/dresser_0057.off
dresser/train/dresser_0058.off
dresser/train/dresser_0059.off
dresser/train/dresser_0060.off
dresser/train/dresser_0061.off
dresser/train/dresser_0062.off
dresser/train/dresser_0063.off
dresser/train/dresser_0064.off
dresser/train/dresser_0065.off
dresser/train/dresser_0066.off
dresser/train/dresser_0067.off
dresser/train/dresser_0068.off
dresser/train/dresser_0069.off
dresser/train/dresser_0070.off
dresser/train/dresser_0071.off
dresser/train/dresser_0072.off
dresser/train/dresser_0073.off
dresser/train/dresser_0074.off
dresser/train/dresser_0075.off
dresser/train/dresser_0076.off
dresser/train/dresser_0077.off
dresser/train/dresser_0078.off
dresser/train/dresser_0079.off
dresser/train/dresser_0080.off
dresser/train/dresser_0081.off
dresser/train/dresser_0082.off
dresser/train/dresser_0083.off
dresser/train/dresser_0084.off
dresser/train/dresser_0085.off
dresser/train/dresser_0086.off
dresser/train/dresser_0087.off
dresser/train/dresser_0088.off
dresser/train/dresser_0089.off
dresser/train/dresser_0090.off
dresser/train/dresser_0091.off
dresser/train/dresser_0092.off
dresser/train/dresser_0093.off
dresser/train/dresser_0094.off
dresser/train/dresser_0095.off
dresser/train/dresser_0096.off
dresser/train/dresser_0097.off
dresser/train/dresser_0098.off
dresser/train/dresser_0099.off
dresser/train/dresser_0100.off
dresser/train/dresser_0101.off
dresser/train/dresser_0102.off
dresser/train/dresser_0103.off
dresser/train/dresser_0104.off
dresser/train/dresser_0105.off
dresser/train/dresser_0106.off
dresser/train/dresser_0107.off
dresser/train/dresser_0108.off
dresser/train/dresser_0109.off
dresser/train/dresser_0110.off
dresser/train/dresser_0111.off
dresser/train/dresser_0112.off
dresser/train/dresser_0113.off
dresser/train/dresser_0114.off
dresser/train/dresser_0115.off
dresser/train/dresser_0116.off
dresser/train/dresser_0117.off
dresser/train/dresser_0118.off
dresser/train/dresser_0119.off
dresser/train/dresser_0120.off
dresser/train/dresser_0121.off
dresser/train/dresser_0122.off
dresser/train/dresser_0123.off
dresser/train/dresser_0124.off
dresser/train/dresser_0125.off
dresser/train/dresser_0126.off
dresser/train/dresser_0127.off
dresser/train/dresser_0128.off
dresser/train/dresser_0129.off
dresser/train/dresser_0130.off
dresser/train/dresser_0131.off
dresser/train/dresser_0132.off
dresser/train/dresser_0133.off
dresser/train/dresser_0134.off
dresser/train/dresser_0135.off
dresser/train/dresser_0136.off
dresser/train/dresser_0137.off
dresser/train/dresser_0138.off
dresser/train/dresser_0139.off
dresser/train/dresser_0140.off
dresser/train/dresser_0141.off
dresser/train/dresser_0142.off
dresser/train/dresser_0143.off
dresser/train/dresser_0144.off
dresser/train/dresser_0145.off
dresser/train/dresser_0146.off
dresser/train/dresser_0147.off
dresser/train/dresser_0148.off
dresser/train/dresser_0149.off
dresser/train/dresser_0150.off
dresser/train/dresser_0151.off
dresser/train/dresser_0152.off
dresser/train/dresser_0153.off
dresser/train/dresser_0154.off
dresser/train/dresser_0155.off
dresser/train/dresser_0156.off
dresser/train/dresser_0157.off
dresser/train/dresser_0158.off
dresser/train/dresser_0159.off
dresser/train/dresser_0160.off
dresser/train/dresser_0161.off
dresser/train/dresser_0162.off
dresser/train/dresser_0163.off
dresser/train/dresser_0164.off
dresser/train/dresser_0165.off
dresser/train/dresser_0166.off
dresser/train/dresser_0167.off
dresser/train/dresser_0168.off
dresser/train/dresser_0169.off
dresser/train/dresser_0170.off
dresser/train/dresser_0171.off
dresser/train/dresser_0172.off
dresser/train/dresser_0173.off
dresser/train/dresser_0174.off
dresser/train/dresser_0175.off
dresser/train/dresser_0176.off
dresser/train/dresser_0177.off
dresser/train/dresser_0178.off
dresser/train/dresser_0179.off
dresser/train/dresser_0180.off
toilet/train/toilet_0001.off
toilet/train/toilet_0002.off
toilet/train/toilet_0003.off
toilet/train/toilet_0004.off
toilet/train/toilet_0005.off
toilet/train/toilet_0006.off
toilet/train/toilet_0007.off
toilet/train/toilet_0008.off
toilet/train/toilet_0009.off
toilet/train/toilet_0010.off
toilet/train/toilet_0011.off
toilet/train/toilet_0012.off
toilet/train/toilet_0013.off
toilet/train/toilet_0014.off
toilet/train/toilet_0015.off
toilet/train/toilet_0016.off
toilet/train/toilet_0017.off
toilet/train/toilet_0018.off
toilet/train/toilet_0019.off
toilet/train/toilet_0020.off
toilet/train/toilet_0021.off
toilet/train/toilet_0022.off
toilet/train/toilet_0023.off
toilet/train/toilet_0024.off
toilet/train/toilet_0025.off
toilet/train/toilet_0026.off
toilet/train/toilet_0027.off
toilet/train/toilet_0028.off
toilet/train/toilet_0029.off
toilet/train/toilet_0030.off
toilet/train/toilet_0031.off
toilet/train/toilet_0032.off
toilet/train/toilet_0033.off
toilet/train/toilet_0034.off
toilet/train/toilet_0035.off
toilet/train/toilet_0036.off
toilet/train/toilet_0037.off
toilet/train/toilet_0038.off
toilet/train/toilet_0039.off
toilet/train/toilet_0040.off
toilet/train/toilet_0041.off
toilet/train/toilet_0042.off
toilet/train/toilet_0043.off
toilet/train/toilet_0044.off
toilet/train/toilet_0045.off
toilet/train/toilet_0046.off
toilet/train/toilet_0047.off
toilet/train/toilet_0048.off
toilet/train/toilet_0049.off
toilet/train/toilet_0050.off
toilet/train/toilet_0051.off
toilet/train/toilet_0052.off
toilet/train/toilet_0053.off
toilet/train/toilet_0054.off
toilet/train/toilet_0055.off
toilet/train/toilet_0056.off
toilet/train/toilet_0057.off
toilet/train/toilet_0058.off
toilet/train/toilet_0059.off
toilet/train/toilet_0060.off
toilet/train/toilet_0061.off
toilet/train/toilet_0062.off
toilet/train/toilet_0063.off
toilet/train/toilet_0064.off
toilet/train/toilet_0065.off
toilet/train/toilet_0066.off
toilet/train/toilet_0067.off
toilet/train/toilet_0068.off
toilet/train/toilet_0069.off
toilet/train/toilet_0070.off
toilet/train/toilet_0071.off
toilet/train/toilet_0072.off
toilet/train/toilet_0073.off
toilet/train/toilet_0074.off
toilet/train/toilet_0075.off
toilet/train/toilet_0076.off
toilet/train/toilet_0077.off
toilet/train/toilet_0078.off
toilet/train/toilet_0079.off
toilet/train/toilet_0080.off
toilet/train/toilet_0081.off
toilet/train/toilet_0082.off
toilet/train/toilet_0083.off
toilet/train/toilet_0084.off
toilet/train/toilet_0085.off
toilet/train/toilet_0086.off
toilet/train/toilet_0087.off
toilet/train/toilet_0088.off
toilet/train/toilet_0089.off
toilet/train/toilet_0090.off
toilet/train/toilet_0091.off
toilet/train/toilet_0092.off
toilet/train/toilet_0093.off
toilet/train/toilet_0094.off
toilet/train/toilet_0095.off
toilet/train/toilet_0096.off
toilet/train/toilet_0097.off
toilet/train/toilet_0098.off
toilet/train/toilet_0099.off
toilet/train/toilet_0100.off
toilet/train/toilet_0101.off
toilet/train/toilet_0102.off
toilet/train/toilet_0103.off
toilet/train/toilet_0104.off
toilet/train/toilet_0105.off
toilet/train/toilet_0106.off
toilet/train/toilet_0107.off
toilet/train/toilet_0108.off
toilet/train/toilet_0109.off
toilet/train/toilet_0110.off
toilet/train/toilet_0111.off
toilet/train/toilet_0112.off
toilet/train/toilet_0113.off
toilet/train/toilet_0114.off
toilet/train/toilet_0115.off
toilet/train/toilet_0116.off
toilet/train/toilet_0117.off
toilet/train/toilet_0118.off
toilet/train/toilet_0119.off
toilet/train/toilet_0120.off
toilet/train/toilet_0121.off
toilet/train/toilet_0122.off
toilet/train/toilet_0123.off
toilet/train/toilet_0124.off
toilet/train/toilet_0125.off
toilet/train/toilet_0126.off
toilet/train/toilet_0127.off
toilet/train/toilet_0128.off
toilet/train/toilet_0129.off
toilet/train/toilet_0130.off
toilet/train/toilet_0131.off
toilet/train/toilet_0132.off
toilet/train/toilet_0133.off
toilet/train/toilet_0134.off
toilet/train/toilet_0135.off
toilet/train/toilet_0136.off
toilet/train/toilet_0137.off
toilet/train/toilet_0138.off
toilet/train/toilet_0139.off
toilet/train/toilet_0140.off
toilet/train/toilet_0141.off
toilet/train/toilet_0142.off
toilet/train/toilet_0143.off
toilet/train/toilet_0144.off
toilet/train/toilet_0145.off
toilet/train/toilet_0146.off
toilet/train/toilet_0147.off
toilet/train/toilet_0148.off
toilet/train/toilet_0149.off
toilet/train/toilet_0150.off
toilet/train/toilet_0151.off
toilet/train/toilet_0152.off
toilet/train/toilet_0153.off
toilet/train/toilet_0154.off
toilet/train/toilet_0155.off
toilet/train/toilet_0156.off
toilet/train/toilet_0157.off
toilet/train/toilet_0158.off
toilet/train/toilet_0159.off
toilet/train/toilet_0160.off
toilet/train/toilet_0161.off
toilet/train/toilet_0162.off
toilet/train/toilet_0163.off
toilet/train/toilet_0164.off
toilet/train/toilet_0165.off
toilet/train/toilet_0166.off
toilet/train/toilet_0167.off
toilet/train/toilet_0168.off
toilet/train/toilet_0169.off
toilet/train/toilet_0170.off
toilet/train/toilet_0171.off
toilet/train/toilet_0172.off
toilet/train/toilet_0173.off
toilet/train/toilet_0174.off
toilet/train/toilet_0175.off
toilet/train/toilet_0176.off
toilet/train/toilet_0177.off
toilet/train/toilet_0178.off
toilet/train/toilet_0179.off
toilet/train/toilet_0180.off
toilet/train/toilet_0181.off
toilet/train/toilet_0182.off
toilet/train/toilet_0183.off
toilet/train/toilet_0184.off
toilet/train/toilet_0185.off
toilet/train/toilet_0186.off
toilet/train/toilet_0187.off
toilet/train/toilet_0188.off
toilet/train/toilet_0189.off
toilet/train/toilet_0190.off
toilet/train/toilet_0191.off
toilet/train/toilet_0192.off
toilet/train/toilet_0193.off
toilet/train/toilet_0194.off
toilet/train/toilet_0195.off
toilet/train/toilet_0196.off
toilet/train/toilet_0197.off
toilet/train/toilet_0198.off
toilet/train/toilet_0199.off
toilet/train/toilet_0200.off
toilet/train/toilet_0201.off
toilet/train/toilet_0202.off
toilet/train/toilet_0203.off
toilet/train/toilet_0204.off
toilet/train/toilet_0205.off
toilet/train/toilet_0206.off
toilet/train/toilet_0207.off
toilet/train/toilet_0208.off
toilet/train/toilet_0209.off
toilet/train/toilet_0210.off
toilet/train/toilet_0211.off
toilet/train/toilet_0212.off
toilet/train/toilet_0213.off
toilet/train/toilet_0214.off
toilet/tra
gitextract_yw16jmpj/
├── .gitignore
├── LICENSE
├── README.md
├── assets/
│ └── results.npz
├── config.py
├── core/
│ ├── __init__.py
│ ├── correspondence.py
│ ├── deep_global_registration.py
│ ├── knn.py
│ ├── loss.py
│ ├── metrics.py
│ ├── registration.py
│ └── trainer.py
├── dataloader/
│ ├── base_loader.py
│ ├── data_loaders.py
│ ├── inf_sampler.py
│ ├── kitti_loader.py
│ ├── split/
│ │ ├── test_3dmatch.txt
│ │ ├── test_kitti.txt
│ │ ├── test_modelnet40.txt
│ │ ├── test_scan2cad.txt
│ │ ├── train_3dmatch.txt
│ │ ├── train_kitti.txt
│ │ ├── train_modelnet40.txt
│ │ ├── train_scan2cad.txt
│ │ ├── val_3dmatch.txt
│ │ ├── val_kitti.txt
│ │ ├── val_modelnet40.txt
│ │ └── val_scan2cad.txt
│ ├── threedmatch_loader.py
│ └── transforms.py
├── demo.py
├── model/
│ ├── __init__.py
│ ├── common.py
│ ├── pyramidnet.py
│ ├── residual_block.py
│ ├── resunet.py
│ └── simpleunet.py
├── requirements.txt
├── scripts/
│ ├── analyze_stats.py
│ ├── download_3dmatch.sh
│ ├── test_3dmatch.py
│ ├── test_kitti.py
│ ├── train_3dmatch.sh
│ └── train_kitti.sh
├── train.py
└── util/
├── __init__.py
├── file.py
├── integration.py
├── pointcloud.py
└── timer.py
SYMBOL INDEX (249 symbols across 28 files)
FILE: config.py
function add_argument_group (line 13) | def add_argument_group(name):
function str2bool (line 19) | def str2bool(v):
function get_config (line 139) | def get_config():
FILE: core/correspondence.py
function _hash (line 14) | def _hash(arr, M=None):
function find_correct_correspondence (line 29) | def find_correct_correspondence(pos_pairs, pred_pairs, hash_seed=None, l...
FILE: core/deep_global_registration.py
function registration_ransac_based_on_feature_matching (line 29) | def registration_ransac_based_on_feature_matching(pcd0, pcd1, feats0, fe...
function registration_ransac_based_on_correspondence (line 50) | def registration_ransac_based_on_correspondence(pcd0, pcd1, idx0, idx1,
class DeepGlobalRegistration (line 67) | class DeepGlobalRegistration:
method __init__ (line 68) | def __init__(self, config, device=torch.device('cuda')):
method preprocess (line 134) | def preprocess(self, pcd):
method fcgf_feature_extraction (line 163) | def fcgf_feature_extraction(self, feats, coords):
method fcgf_feature_matching (line 171) | def fcgf_feature_matching(self, feats0, feats1):
method inlier_feature_generation (line 185) | def inlier_feature_generation(self, xyz0, xyz1, coords0, coords1, fcgf...
method inlier_prediction (line 210) | def inlier_prediction(self, inlier_feats, coords):
method safeguard_registration (line 219) | def safeguard_registration(self, pcd0, pcd1, idx0, idx1, feats0, feats1,
method register (line 238) | def register(self, xyz0, xyz1, inlier_thr=0.00):
FILE: core/knn.py
function find_knn_cpu (line 14) | def find_knn_cpu(feat0, feat1, knn=1, return_distance=False):
function find_knn_gpu (line 23) | def find_knn_gpu(F0, F1, nn_max_n=-1, knn=1, return_distance=False):
function find_knn_batch (line 77) | def find_knn_batch(F0,
function find_knn_gpu_batch (line 106) | def find_knn_gpu_batch(F0,
function find_knn_cpu_batch (line 143) | def find_knn_cpu_batch(F0,
FILE: core/loss.py
class UnbalancedLoss (line 13) | class UnbalancedLoss(nn.Module):
method __init__ (line 16) | def __init__(self):
method forward (line 20) | def forward(self, logits, label):
class BalancedLoss (line 24) | class BalancedLoss(nn.Module):
method __init__ (line 27) | def __init__(self):
method forward (line 31) | def forward(self, logits, label):
class HighDimSmoothL1Loss (line 42) | class HighDimSmoothL1Loss:
method __init__ (line 44) | def __init__(self, weights, quantization_size=1, eps=np.finfo(np.float...
method __call__ (line 51) | def __call__(self, X, Y):
FILE: core/metrics.py
function rotation_mat2angle (line 11) | def rotation_mat2angle(R):
function rotation_error (line 15) | def rotation_error(R1, R2):
function translation_error (line 20) | def translation_error(t1, t2):
function batch_rotation_error (line 25) | def batch_rotation_error(rots1, rots2):
function batch_translation_error (line 37) | def batch_translation_error(trans1, trans2):
function eval_metrics (line 47) | def eval_metrics(output, target):
function corr_dist (line 53) | def corr_dist(est, gth, xyz0, xyz1, weight=None, max_dist=1):
function pdist (line 62) | def pdist(A, B, dist_type='L2'):
function get_loss_fn (line 72) | def get_loss_fn(loss):
FILE: core/registration.py
function ortho2rotation (line 16) | def ortho2rotation(poses):
function argmin_se3_squared_dist (line 67) | def argmin_se3_squared_dist(X, Y):
function weighted_procrustes (line 91) | def weighted_procrustes(X, Y, w, eps):
class Transformation (line 116) | class Transformation(torch.nn.Module):
method __init__ (line 117) | def __init__(self, R_init=None, t_init=None):
method forward (line 130) | def forward(self, points):
function GlobalRegistration (line 135) | def GlobalRegistration(points,
FILE: core/trainer.py
class WeightedProcrustesTrainer (line 38) | class WeightedProcrustesTrainer:
method __init__ (line 39) | def __init__(self, config, data_loader, val_data_loader=None):
method train (line 120) | def train(self):
method _train_epoch (line 157) | def _train_epoch(self, epoch):
method _valid_epoch (line 353) | def _valid_epoch(self):
method _load_weights (line 491) | def _load_weights(self, config):
method _save_checkpoint (line 527) | def _save_checkpoint(self, epoch, filename='checkpoint'):
method get_data (line 551) | def get_data(self, iterator):
method decompose_by_length (line 561) | def decompose_by_length(self, tensor, reference_tensors):
method decompose_rotation_translation (line 570) | def decompose_rotation_translation(self, Ts):
method weighted_procrustes (line 580) | def weighted_procrustes(self, xyz0s, xyz1s, pred_pairs, weights):
method generate_inlier_features (line 602) | def generate_inlier_features(self, xyz0, xyz1, C0, C1, F0, F1, pair_in...
method generate_inlier_input (line 630) | def generate_inlier_input(self, xyz0, xyz1, iC0, iC1, iF0, iF1, len_ba...
method find_pairs (line 660) | def find_pairs(self, F0, F1, len_batch):
FILE: dataloader/base_loader.py
class CollationFunctionFactory (line 24) | class CollationFunctionFactory:
method __init__ (line 25) | def __init__(self, concat_correspondences=True, collation_type='defaul...
method __call__ (line 34) | def __call__(self, list_data):
method collate_default (line 37) | def collate_default(self, list_data):
method collate_pair_fn (line 40) | def collate_pair_fn(self, list_data):
class PairDataset (line 101) | class PairDataset(torch.utils.data.Dataset):
method __init__ (line 104) | def __init__(self,
method reset_seed (line 128) | def reset_seed(self, seed=0):
method apply_transform (line 132) | def apply_transform(self, pts, trans):
method __len__ (line 138) | def __len__(self):
FILE: dataloader/data_loaders.py
function make_data_loader (line 17) | def make_data_loader(config, phase, batch_size, num_workers=0, shuffle=N...
FILE: dataloader/inf_sampler.py
class InfSampler (line 11) | class InfSampler(Sampler):
method __init__ (line 18) | def __init__(self, data_source, shuffle=False):
method reset_permutation (line 23) | def reset_permutation(self):
method __iter__ (line 29) | def __iter__(self):
method __next__ (line 32) | def __next__(self):
method __len__ (line 37) | def __len__(self):
FILE: dataloader/kitti_loader.py
class KITTIPairDataset (line 17) | class KITTIPairDataset(PairDataset):
method __init__ (line 27) | def __init__(self,
method get_all_scan_ids (line 59) | def get_all_scan_ids(self, drive_id):
method velo2cam (line 67) | def velo2cam(self):
method get_video_odometry (line 80) | def get_video_odometry(self, drive, indices=None, ext='.txt', return_a...
method odometry_to_positions (line 89) | def odometry_to_positions(self, odometry):
method rot3d (line 94) | def rot3d(self, axis, angle):
method pos_transform (line 106) | def pos_transform(self, pos):
method get_position_transform (line 113) | def get_position_transform(self, pos0, pos1, invert=False):
method _get_velodyne_fn (line 119) | def _get_velodyne_fn(self, drive, t):
method __getitem__ (line 123) | def __getitem__(self, idx):
class KITTINMPairDataset (line 229) | class KITTINMPairDataset(KITTIPairDataset):
method __init__ (line 235) | def __init__(self,
FILE: dataloader/threedmatch_loader.py
class IndoorPairDataset (line 16) | class IndoorPairDataset(PairDataset):
method __init__ (line 23) | def __init__(self,
method __getitem__ (line 48) | def __getitem__(self, idx):
class ThreeDMatchPairDataset03 (line 127) | class ThreeDMatchPairDataset03(IndoorPairDataset):
class ThreeDMatchPairDataset05 (line 136) | class ThreeDMatchPairDataset05(ThreeDMatchPairDataset03):
class ThreeDMatchPairDataset07 (line 140) | class ThreeDMatchPairDataset07(ThreeDMatchPairDataset03):
class ThreeDMatchTrajectoryDataset (line 144) | class ThreeDMatchTrajectoryDataset(PairDataset):
method __init__ (line 154) | def __init__(self,
method __getitem__ (line 184) | def __getitem__(self, pair_index):
FILE: dataloader/transforms.py
function M (line 14) | def M(axis, theta):
function sample_random_trans (line 18) | def sample_random_trans(pcd, randg, rotation_range=360):
class Compose (line 26) | class Compose:
method __init__ (line 27) | def __init__(self, transforms):
method __call__ (line 30) | def __call__(self, coords, feats):
class Jitter (line 36) | class Jitter:
method __init__ (line 37) | def __init__(self, mu=0, sigma=0.01):
method __call__ (line 41) | def __call__(self, coords, feats):
class ChromaticShift (line 49) | class ChromaticShift:
method __init__ (line 50) | def __init__(self, mu=0, sigma=0.1):
method __call__ (line 54) | def __call__(self, coords, feats):
FILE: model/__init__.py
function add_models (line 15) | def add_models(module):
function load_model (line 24) | def load_model(name):
FILE: model/common.py
function get_norm (line 11) | def get_norm(norm_type, num_feats, bn_momentum=0.05, dimension=-1):
function get_nonlinearity (line 24) | def get_nonlinearity(non_type):
FILE: model/pyramidnet.py
class PyramidModule (line 15) | class PyramidModule(ME.MinkowskiNetwork):
method __init__ (line 20) | def __init__(self,
method forward (line 74) | def forward(self, x):
class PyramidModuleINBN (line 83) | class PyramidModuleINBN(PyramidModule):
class PyramidNet (line 87) | class PyramidNet(ME.MinkowskiNetwork):
method __init__ (line 100) | def __init__(self,
method initialize_network (line 113) | def initialize_network(self, in_channels, out_channels, bn_momentum, d...
method forward (line 152) | def forward(self, x):
class PyramidNet6 (line 166) | class PyramidNet6(PyramidNet):
class PyramidNet6NoBlock (line 172) | class PyramidNet6NoBlock(PyramidNet6):
class PyramidNet6INBN (line 176) | class PyramidNet6INBN(PyramidNet6):
class PyramidNet6INBNNoBlock (line 181) | class PyramidNet6INBNNoBlock(PyramidNet6INBN):
class PyramidNet8 (line 185) | class PyramidNet8(PyramidNet):
class PyramidNet8INBN (line 191) | class PyramidNet8INBN(PyramidNet8):
FILE: model/residual_block.py
function conv (line 15) | def conv(in_channels,
function conv_tr (line 47) | def conv_tr(in_channels,
class BasicBlockBase (line 83) | class BasicBlockBase(nn.Module):
method __init__ (line 87) | def __init__(self,
method forward (line 118) | def forward(self, x):
class BasicBlockBN (line 137) | class BasicBlockBN(BasicBlockBase):
class BasicBlockIN (line 141) | class BasicBlockIN(BasicBlockBase):
class BasicBlockINBN (line 145) | class BasicBlockINBN(BasicBlockBase):
function get_block (line 149) | def get_block(norm_type,
function conv_norm_non (line 171) | def conv_norm_non(inc,
FILE: model/resunet.py
class ResUNet (line 16) | class ResUNet(ME.MinkowskiNetwork):
method __init__ (line 25) | def __init__(self,
method forward (line 152) | def forward(self, x):
class ResUNetBN (line 194) | class ResUNetBN(ResUNet):
class ResUNetBNF (line 198) | class ResUNetBNF(ResUNet):
class ResUNetBNFX (line 204) | class ResUNetBNFX(ResUNetBNF):
class ResUNetSP (line 208) | class ResUNetSP(ME.MinkowskiNetwork):
method __init__ (line 220) | def __init__(self,
method forward (line 364) | def forward(self, x):
class ResUNetBNSPC (line 411) | class ResUNetBNSPC(ResUNetSP):
class ResUNetINBNSPC (line 415) | class ResUNetINBNSPC(ResUNetBNSPC):
class ResUNet2 (line 419) | class ResUNet2(ME.MinkowskiNetwork):
method __init__ (line 428) | def __init__(self,
method forward (line 598) | def forward(self, x):
class ResUNetBN2 (line 652) | class ResUNetBN2(ResUNet2):
class ResUNetBN2B (line 656) | class ResUNetBN2B(ResUNet2):
class ResUNetBN2C (line 662) | class ResUNetBN2C(ResUNet2):
class ResUNetBN2CX (line 668) | class ResUNetBN2CX(ResUNetBN2C):
class ResUNetBN2D (line 672) | class ResUNetBN2D(ResUNet2):
class ResUNetBN2E (line 678) | class ResUNetBN2E(ResUNet2):
class ResUNetBN2F (line 684) | class ResUNetBN2F(ResUNet2):
class ResUNetBN2FX (line 690) | class ResUNetBN2FX(ResUNetBN2F):
class ResUNet2v2 (line 694) | class ResUNet2v2(ME.MinkowskiNetwork):
method __init__ (line 706) | def __init__(self,
method weight_initialization (line 878) | def weight_initialization(self):
method forward (line 887) | def forward(self, x): # Receptive field size
class ResUNetBN2v2 (line 941) | class ResUNetBN2v2(ResUNet2v2):
class ResUNetBN2Bv2 (line 945) | class ResUNetBN2Bv2(ResUNet2v2):
class ResUNetBN2Cv2 (line 951) | class ResUNetBN2Cv2(ResUNet2v2):
class ResUNetBN2Dv2 (line 957) | class ResUNetBN2Dv2(ResUNet2v2):
class ResUNetBN2Ev2 (line 963) | class ResUNetBN2Ev2(ResUNet2v2):
class ResUNetBN2Fv2 (line 969) | class ResUNetBN2Fv2(ResUNet2v2):
class ResUNet2SP (line 975) | class ResUNet2SP(ME.MinkowskiNetwork):
method __init__ (line 984) | def __init__(self,
method forward (line 1157) | def forward(self, x):
class ResUNetBN2SPC (line 1214) | class ResUNetBN2SPC(ResUNet2SP):
class ResUNetBN2SPCX (line 1220) | class ResUNetBN2SPCX(ResUNetBN2SPC):
FILE: model/simpleunet.py
class SimpleNet (line 13) | class SimpleNet(ME.MinkowskiNetwork):
method __init__ (line 20) | def __init__(self,
method forward (line 101) | def forward(self, x):
class SimpleNetIN (line 140) | class SimpleNetIN(SimpleNet):
class SimpleNetBN (line 144) | class SimpleNetBN(SimpleNet):
class SimpleNetBNE (line 148) | class SimpleNetBNE(SimpleNetBN):
class SimpleNetINE (line 153) | class SimpleNetINE(SimpleNetBNE):
class SimpleNet2 (line 157) | class SimpleNet2(ME.MinkowskiNetwork):
method __init__ (line 164) | def __init__(self,
method forward (line 269) | def forward(self, x):
class SimpleNetIN2 (line 318) | class SimpleNetIN2(SimpleNet2):
class SimpleNetBN2 (line 322) | class SimpleNetBN2(SimpleNet2):
class SimpleNetBN2B (line 326) | class SimpleNetBN2B(SimpleNet2):
class SimpleNetBN2C (line 332) | class SimpleNetBN2C(SimpleNet2):
class SimpleNetBN2D (line 338) | class SimpleNetBN2D(SimpleNet2):
class SimpleNetBN2E (line 344) | class SimpleNetBN2E(SimpleNet2):
class SimpleNetIN2E (line 350) | class SimpleNetIN2E(SimpleNetBN2E):
class SimpleNet3 (line 354) | class SimpleNet3(ME.MinkowskiNetwork):
method __init__ (line 361) | def __init__(self,
method forward (line 476) | def forward(self, x):
class SimpleNetIN3 (line 531) | class SimpleNetIN3(SimpleNet3):
class SimpleNetBN3 (line 535) | class SimpleNetBN3(SimpleNet3):
class SimpleNetBN3B (line 539) | class SimpleNetBN3B(SimpleNet3):
class SimpleNetBN3C (line 545) | class SimpleNetBN3C(SimpleNet3):
class SimpleNetBN3D (line 551) | class SimpleNetBN3D(SimpleNet3):
class SimpleNetBN3E (line 557) | class SimpleNetBN3E(SimpleNet3):
class SimpleNetIN3E (line 563) | class SimpleNetIN3E(SimpleNetBN3E):
FILE: scripts/analyze_stats.py
function analyze_by_pair (line 21) | def analyze_by_pair(stats, rte_thresh, rre_thresh):
function analyze_by_scene (line 45) | def analyze_by_scene(stats, scene_id_list, rte_thresh=0.3, rre_thresh=15):
function plot_precision_recall_curves (line 78) | def plot_precision_recall_curves(stats, method_names, rte_precisions, rr...
function plot_scene_wise_stats (line 122) | def plot_scene_wise_stats(scene_wise_stats, method_names, scene_names, p...
function plot_pareto_frontier (line 163) | def plot_pareto_frontier(pairwise_stats, method_names, cmap):
FILE: scripts/test_3dmatch.py
function rte_rre (line 38) | def rte_rre(T_pred, T_gt, rte_thresh, rre_thresh, eps=1e-16):
function analyze_stats (line 49) | def analyze_stats(stats, mask, method_names):
function create_pcd (line 66) | def create_pcd(xyz, color):
function draw_geometries_flip (line 77) | def draw_geometries_flip(pcds):
function evaluate (line 87) | def evaluate(methods, method_names, data_loader, config, debug=False):
FILE: scripts/test_kitti.py
function visualize_pair (line 38) | def visualize_pair(xyz0, xyz1, T, voxel_size):
function analyze_stats (line 51) | def analyze_stats(stats):
function evaluate (line 59) | def evaluate(config, data_loader, method):
FILE: train.py
function main (line 33) | def main(config, resume=False):
FILE: util/file.py
function read_txt (line 15) | def read_txt(path):
function ensure_dir (line 24) | def ensure_dir(path):
function sorted_alphanum (line 29) | def sorted_alphanum(file_list_ordered):
function get_file_list (line 39) | def get_file_list(path, extension=None):
function get_file_list_specific (line 51) | def get_file_list_specific(path, color_depth, extension=None):
function get_folder_list (line 63) | def get_folder_list(path):
function read_trajectory (line 69) | def read_trajectory(filename, dim=4):
FILE: util/integration.py
function read_rgbd_image (line 13) | def read_rgbd_image(color_file, depth_file, max_depth=4.5):
function read_pose (line 26) | def read_pose(pose_file):
function read_intrinsics (line 35) | def read_intrinsics(intrinsic_file):
function integrate_rgb_frames_for_fragment (line 44) | def integrate_rgb_frames_for_fragment(color_files,
function process_seq (line 74) | def process_seq(seq_path, output_path, n_frames_per_fragment, display=Fa...
FILE: util/pointcloud.py
function make_open3d_point_cloud (line 15) | def make_open3d_point_cloud(xyz, color=None):
function make_open3d_feature (line 25) | def make_open3d_feature(data, dim, npts):
function make_open3d_feature_from_numpy (line 32) | def make_open3d_feature_from_numpy(data):
function pointcloud_to_spheres (line 42) | def pointcloud_to_spheres(pcd, voxel_size, color, sphere_size=0.6):
function prepare_single_pointcloud (line 59) | def prepare_single_pointcloud(pcd, voxel_size):
function prepare_pointcloud (line 64) | def prepare_pointcloud(filename, voxel_size):
function compute_overlap_ratio (line 72) | def compute_overlap_ratio(pcd0, pcd1, trans, voxel_size):
function get_matching_indices (line 83) | def get_matching_indices(source, target, trans, search_voxel_size, K=None):
function evaluate_feature (line 99) | def evaluate_feature(pcd0, pcd1, feat0, feat1, trans_gth, search_voxel_s...
function valid_feat_ratio (line 112) | def valid_feat_ratio(pcd0, pcd1, feat0, feat1, trans_gth, thresh=0.1):
function evaluate_feature_3dmatch (line 120) | def evaluate_feature_3dmatch(pcd0, pcd1, feat0, feat1, trans_gth, inlier...
function get_matching_matrix (line 133) | def get_matching_matrix(source, target, trans, voxel_size, debug_mode):
function get_random_transformation (line 148) | def get_random_transformation(pcd_input):
function draw_registration_result (line 193) | def draw_registration_result(source, target, transformation):
FILE: util/timer.py
class AverageMeter (line 12) | class AverageMeter(object):
method __init__ (line 15) | def __init__(self):
method reset (line 18) | def reset(self):
method update (line 25) | def update(self, val, n=1):
class Timer (line 40) | class Timer(AverageMeter):
method tic (line 43) | def tic(self):
method toc (line 48) | def toc(self, average=True):
Condensed preview — 51 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (585K chars).
[
{
"path": ".gitignore",
"chars": 163,
"preview": "# Temp files\n.DS_Store\n__pycache__\n*.swp\n*.swo\n*.orig\n.idea\noutputs/\n*.pyc\n*.npy\n*.pdf\nutil/*.sh\ncheckpoints\n# *.npz\n3dm"
},
{
"path": "LICENSE",
"chars": 1933,
"preview": "MIT License\n\nCopyright (c) 2020 Chris Choy (chrischoy@ai.stanford.edu), Wei Dong (weidong@andrew.cmu.edu)\n\nPermission is"
},
{
"path": "README.md",
"chars": 8193,
"preview": "# Deep Global Registration\n\n## Introduction\nThis repository contains python scripts for training and testing [Deep Globa"
},
{
"path": "config.py",
"chars": 7018,
"preview": "# Copyright (c) Chris Choy (chrischoy@ai.stanford.edu) and Wei Dong (weidong@andrew.cmu.edu)\n#\n# Please cite the followi"
},
{
"path": "core/__init__.py",
"chars": 482,
"preview": "# Copyright (c) Chris Choy (chrischoy@ai.stanford.edu) and Wei Dong (weidong@andrew.cmu.edu)\n#\n# Please cite the followi"
},
{
"path": "core/correspondence.py",
"chars": 1651,
"preview": "# Copyright (c) Chris Choy (chrischoy@ai.stanford.edu) and Wei Dong (weidong@andrew.cmu.edu)\n#\n# Please cite the followi"
},
{
"path": "core/deep_global_registration.py",
"chars": 12837,
"preview": "# Copyright (c) Chris Choy (chrischoy@ai.stanford.edu) and Wei Dong (weidong@andrew.cmu.edu)\n#\n# Please cite the followi"
},
{
"path": "core/knn.py",
"chars": 4835,
"preview": "# Copyright (c) Chris Choy (chrischoy@ai.stanford.edu) and Wei Dong (weidong@andrew.cmu.edu)\n#\n# Please cite the followi"
},
{
"path": "core/loss.py",
"chars": 1933,
"preview": "# Copyright (c) Chris Choy (chrischoy@ai.stanford.edu) and Wei Dong (weidong@andrew.cmu.edu)\n#\n# Please cite the followi"
},
{
"path": "core/metrics.py",
"chars": 2317,
"preview": "# Copyright (c) Chris Choy (chrischoy@ai.stanford.edu) and Wei Dong (weidong@andrew.cmu.edu)\n#\n# Please cite the followi"
},
{
"path": "core/registration.py",
"chars": 5283,
"preview": "# Copyright (c) Chris Choy (chrischoy@ai.stanford.edu) and Wei Dong (weidong@andrew.cmu.edu)\n#\n# Please cite the followi"
},
{
"path": "core/trainer.py",
"chars": 25594,
"preview": "# Copyright (c) Chris Choy (chrischoy@ai.stanford.edu) and Wei Dong (weidong@andrew.cmu.edu)\n#\n# Please cite the followi"
},
{
"path": "dataloader/base_loader.py",
"chars": 4610,
"preview": "# Copyright (c) Chris Choy (chrischoy@ai.stanford.edu) and Wei Dong (weidong@andrew.cmu.edu)\n#\n# Please cite the followi"
},
{
"path": "dataloader/data_loaders.py",
"chars": 2227,
"preview": "# Copyright (c) Chris Choy (chrischoy@ai.stanford.edu) and Wei Dong (weidong@andrew.cmu.edu)\n#\n# Please cite the followi"
},
{
"path": "dataloader/inf_sampler.py",
"chars": 1198,
"preview": "# Copyright (c) Chris Choy (chrischoy@ai.stanford.edu) and Wei Dong (weidong@andrew.cmu.edu)\n#\n# Please cite the followi"
},
{
"path": "dataloader/kitti_loader.py",
"chars": 10385,
"preview": "# Copyright (c) Chris Choy (chrischoy@ai.stanford.edu) and Wei Dong (weidong@andrew.cmu.edu)\n#\n# Please cite the followi"
},
{
"path": "dataloader/split/test_3dmatch.txt",
"chars": 272,
"preview": "7-scenes-redkitchen\nsun3d-home_at-home_at_scan1_2013_jan_1\nsun3d-home_md-home_md_scan9_2012_sep_30\nsun3d-hotel_uc-scan3\n"
},
{
"path": "dataloader/split/test_kitti.txt",
"chars": 7,
"preview": "8\n9\n10\n"
},
{
"path": "dataloader/split/test_modelnet40.txt",
"chars": 69651,
"preview": "glass_box/test/glass_box_0172.off\nglass_box/test/glass_box_0173.off\nglass_box/test/glass_box_0174.off\nglass_box/test/gla"
},
{
"path": "dataloader/split/test_scan2cad.txt",
"chars": 33,
"preview": "full_annotations_clean_test.json\n"
},
{
"path": "dataloader/split/train_3dmatch.txt",
"chars": 1275,
"preview": "sun3d-brown_bm_1-brown_bm_1\nsun3d-brown_cogsci_1-brown_cogsci_1\nsun3d-brown_cs_2-brown_cs2\nsun3d-brown_cs_3-brown_cs3\nsu"
},
{
"path": "dataloader/split/train_kitti.txt",
"chars": 12,
"preview": "0\n1\n2\n3\n4\n5\n"
},
{
"path": "dataloader/split/train_modelnet40.txt",
"chars": 254772,
"preview": "glass_box/train/glass_box_0001.off\nglass_box/train/glass_box_0002.off\nglass_box/train/glass_box_0003.off\nglass_box/train"
},
{
"path": "dataloader/split/train_scan2cad.txt",
"chars": 34,
"preview": "full_annotations_clean_train.json\n"
},
{
"path": "dataloader/split/val_3dmatch.txt",
"chars": 150,
"preview": "sun3d-brown_bm_4-brown_bm_4\nsun3d-harvard_c11-hv_c11_2\n7-scenes-heads\nrgbd-scenes-v2-scene_10\nbundlefusion-office0\nanaly"
},
{
"path": "dataloader/split/val_kitti.txt",
"chars": 4,
"preview": "6\n7\n"
},
{
"path": "dataloader/split/val_modelnet40.txt",
"chars": 27725,
"preview": "glass_box/train/glass_box_0155.off\nglass_box/train/glass_box_0156.off\nglass_box/train/glass_box_0157.off\nglass_box/train"
},
{
"path": "dataloader/split/val_scan2cad.txt",
"chars": 32,
"preview": "full_annotations_clean_val.json\n"
},
{
"path": "dataloader/threedmatch_loader.py",
"chars": 6614,
"preview": "# Copyright (c) Chris Choy (chrischoy@ai.stanford.edu) and Wei Dong (weidong@andrew.cmu.edu)\n#\n# Please cite the followi"
},
{
"path": "dataloader/transforms.py",
"chars": 1725,
"preview": "# Copyright (c) Chris Choy (chrischoy@ai.stanford.edu) and Wei Dong (weidong@andrew.cmu.edu)\n#\n# Please cite the followi"
},
{
"path": "demo.py",
"chars": 1676,
"preview": "# Copyright (c) Chris Choy (chrischoy@ai.stanford.edu) and Wei Dong (weidong@andrew.cmu.edu)\n#\n# Please cite the followi"
},
{
"path": "model/__init__.py",
"chars": 1298,
"preview": "# Copyright (c) Chris Choy (chrischoy@ai.stanford.edu) and Wei Dong (weidong@andrew.cmu.edu)\n#\n# Please cite the followi"
},
{
"path": "model/common.py",
"chars": 1268,
"preview": "# Copyright (c) Chris Choy (chrischoy@ai.stanford.edu) and Wei Dong (weidong@andrew.cmu.edu)\n#\n# Please cite the followi"
},
{
"path": "model/pyramidnet.py",
"chars": 5648,
"preview": "# Copyright (c) Chris Choy (chrischoy@ai.stanford.edu) and Wei Dong (weidong@andrew.cmu.edu)\n#\n# Please cite the followi"
},
{
"path": "model/residual_block.py",
"chars": 5016,
"preview": "# Copyright (c) Chris Choy (chrischoy@ai.stanford.edu) and Wei Dong (weidong@andrew.cmu.edu)\n#\n# Please cite the followi"
},
{
"path": "model/resunet.py",
"chars": 34234,
"preview": "# Copyright (c) Chris Choy (chrischoy@ai.stanford.edu) and Wei Dong (weidong@andrew.cmu.edu)\n#\n# Please cite the followi"
},
{
"path": "model/simpleunet.py",
"chars": 15663,
"preview": "# Copyright (c) Chris Choy (chrischoy@ai.stanford.edu) and Wei Dong (weidong@andrew.cmu.edu)\n#\n# Please cite the followi"
},
{
"path": "requirements.txt",
"chars": 1336,
"preview": "ansi2html==1.8.0\nattrs==23.1.0\ncertifi==2023.7.22\ncharset-normalizer==3.1.0\nclick==8.1.3\ncmake==3.26.4\nConfigArgParse==1"
},
{
"path": "scripts/analyze_stats.py",
"chars": 9627,
"preview": "# Copyright (c) Chris Choy (chrischoy@ai.stanford.edu) and Wei Dong (weidong@andrew.cmu.edu)\n#\n# Please cite the followi"
},
{
"path": "scripts/download_3dmatch.sh",
"chars": 1058,
"preview": "#!/usr/bin/env bash\n\nDATA_DIR=$1\n\nfunction download() {\n TMP_PATH=\"$DATA_DIR/tmp\"\n echo \"#########################"
},
{
"path": "scripts/test_3dmatch.py",
"chars": 5987,
"preview": "# Copyright (c) Chris Choy (chrischoy@ai.stanford.edu) and Wei Dong (weidong@andrew.cmu.edu)\n#\n# Please cite the followi"
},
{
"path": "scripts/test_kitti.py",
"chars": 4875,
"preview": "# Copyright (c) Chris Choy (chrischoy@ai.stanford.edu) and Wei Dong (weidong@andrew.cmu.edu)\n#\n# Please cite the followi"
},
{
"path": "scripts/train_3dmatch.sh",
"chars": 2234,
"preview": "#! /bin/bash\nexport PATH_POSTFIX=$1\nexport MISC_ARGS=$2\n\nexport DATA_ROOT=\"./outputs/Experiment2\"\nexport DATASET=${DATAS"
},
{
"path": "scripts/train_kitti.sh",
"chars": 2186,
"preview": "#! /bin/bash\nexport PATH_POSTFIX=$1\nexport MISC_ARGS=$2\n\nexport DATA_ROOT=\"./outputs/Experiment3\"\nexport DATASET=${DATAS"
},
{
"path": "train.py",
"chars": 2422,
"preview": "# Copyright (c) Chris Choy (chrischoy@ai.stanford.edu) and Wei Dong (weidong@andrew.cmu.edu)\n#\n# Please cite the followi"
},
{
"path": "util/__init__.py",
"chars": 482,
"preview": "# Copyright (c) Chris Choy (chrischoy@ai.stanford.edu) and Wei Dong (weidong@andrew.cmu.edu)\n#\n# Please cite the followi"
},
{
"path": "util/file.py",
"chars": 2699,
"preview": "# Copyright (c) Chris Choy (chrischoy@ai.stanford.edu) and Wei Dong (weidong@andrew.cmu.edu)\n#\n# Please cite the followi"
},
{
"path": "util/integration.py",
"chars": 5119,
"preview": "# Copyright (c) Chris Choy (chrischoy@ai.stanford.edu) and Wei Dong (weidong@andrew.cmu.edu)\n#\n# Please cite the followi"
},
{
"path": "util/pointcloud.py",
"chars": 6327,
"preview": "# Copyright (c) Chris Choy (chrischoy@ai.stanford.edu) and Wei Dong (weidong@andrew.cmu.edu)\n#\n# Please cite the followi"
},
{
"path": "util/timer.py",
"chars": 1551,
"preview": "# Copyright (c) Chris Choy (chrischoy@ai.stanford.edu) and Wei Dong (weidong@andrew.cmu.edu)\n#\n# Please cite the followi"
}
]
// ... and 1 more files (download for full content)
About this extraction
This page contains the full source code of the chrischoy/DeepGlobalRegistration GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 51 files (550.5 KB), approximately 182.0k tokens, and a symbol index with 249 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.