├── .gitignore ├── LICENSE ├── README.md ├── active_selection ├── __init__.py ├── ceal.py ├── core_set.py ├── max_repr.py ├── random_selection.py ├── regional_view_entropy_kl.py ├── regional_vote_entropy.py ├── softmax_confidence.py ├── softmax_entropy.py ├── softmax_margin.py ├── view_entropy.py └── vote_entropy.py ├── argument_parser.py ├── constants.py ├── dataloader ├── custom_transforms.py ├── dataset_base.py ├── indoor_scenes.py └── paths.py ├── dataset ├── matterport3d │ └── selections │ │ ├── seedset_0_frames.txt │ │ ├── test_frames.txt │ │ ├── train_frames.txt │ │ └── val_frames.txt ├── preprocessing-scripts │ ├── selections.py │ └── to_lmdb.py ├── scannet-sample │ ├── dataset.lmdb │ ├── raw │ │ └── selections │ │ │ ├── color │ │ │ ├── scene0007_00_000000.jpg │ │ │ ├── scene0007_00_000035.jpg │ │ │ ├── scene0007_00_000070.jpg │ │ │ ├── scene0007_00_000105.jpg │ │ │ ├── scene0007_00_000140.jpg │ │ │ ├── scene0007_00_000455.jpg │ │ │ ├── scene0007_00_000560.jpg │ │ │ ├── scene0007_00_000595.jpg │ │ │ ├── scene0007_00_000735.jpg │ │ │ ├── scene0007_00_000840.jpg │ │ │ ├── scene0014_00_000000.jpg │ │ │ ├── scene0014_00_000070.jpg │ │ │ ├── scene0014_00_000105.jpg │ │ │ ├── scene0014_00_000175.jpg │ │ │ ├── scene0014_00_000210.jpg │ │ │ ├── scene0014_00_000245.jpg │ │ │ ├── scene0014_00_000280.jpg │ │ │ ├── scene0014_00_000350.jpg │ │ │ ├── scene0014_00_000490.jpg │ │ │ ├── scene0014_00_000595.jpg │ │ │ ├── scene0014_00_000840.jpg │ │ │ ├── scene0014_00_000980.jpg │ │ │ ├── scene0014_00_001015.jpg │ │ │ ├── scene0014_00_001120.jpg │ │ │ ├── scene0014_00_001225.jpg │ │ │ ├── scene0014_00_001330.jpg │ │ │ ├── scene0014_00_001365.jpg │ │ │ ├── scene0014_00_001435.jpg │ │ │ ├── scene0014_00_001470.jpg │ │ │ ├── scene0014_00_001505.jpg │ │ │ ├── scene0014_00_001540.jpg │ │ │ ├── scene0014_00_001680.jpg │ │ │ ├── scene0014_00_001715.jpg │ │ │ ├── scene0014_00_001855.jpg │ │ │ ├── scene0014_00_001890.jpg │ │ │ ├── scene0014_00_001925.jpg │ │ │ └── scene0014_00_002065.jpg │ │ │ ├── coverage_superpixel │ │ │ ├── scene0007_00.npy │ │ │ └── scene0014_00.npy │ │ │ ├── depth │ │ │ ├── scene0007_00_000000.pgm │ │ │ ├── scene0007_00_000035.pgm │ │ │ ├── scene0007_00_000070.pgm │ │ │ ├── scene0007_00_000105.pgm │ │ │ ├── scene0007_00_000140.pgm │ │ │ ├── scene0007_00_000455.pgm │ │ │ ├── scene0007_00_000560.pgm │ │ │ ├── scene0007_00_000595.pgm │ │ │ ├── scene0007_00_000735.pgm │ │ │ ├── scene0007_00_000840.pgm │ │ │ ├── scene0014_00_000000.pgm │ │ │ ├── scene0014_00_000070.pgm │ │ │ ├── scene0014_00_000105.pgm │ │ │ ├── scene0014_00_000175.pgm │ │ │ ├── scene0014_00_000210.pgm │ │ │ ├── scene0014_00_000245.pgm │ │ │ ├── scene0014_00_000280.pgm │ │ │ ├── scene0014_00_000350.pgm │ │ │ ├── scene0014_00_000490.pgm │ │ │ ├── scene0014_00_000595.pgm │ │ │ ├── scene0014_00_000840.pgm │ │ │ ├── scene0014_00_000980.pgm │ │ │ ├── scene0014_00_001015.pgm │ │ │ ├── scene0014_00_001120.pgm │ │ │ ├── scene0014_00_001225.pgm │ │ │ ├── scene0014_00_001330.pgm │ │ │ ├── scene0014_00_001365.pgm │ │ │ ├── scene0014_00_001435.pgm │ │ │ ├── scene0014_00_001470.pgm │ │ │ ├── scene0014_00_001505.pgm │ │ │ ├── scene0014_00_001540.pgm │ │ │ ├── scene0014_00_001680.pgm │ │ │ ├── scene0014_00_001715.pgm │ │ │ ├── scene0014_00_001855.pgm │ │ │ ├── scene0014_00_001890.pgm │ │ │ ├── scene0014_00_001925.pgm │ │ │ └── scene0014_00_002065.pgm │ │ │ ├── info │ │ │ ├── scene0007_00.txt │ │ │ └── scene0014_00.txt │ │ │ ├── label │ │ │ ├── scene0007_00_000000.png │ │ │ ├── scene0007_00_000035.png │ │ │ ├── scene0007_00_000070.png │ │ │ ├── scene0007_00_000105.png │ │ │ ├── scene0007_00_000140.png │ │ │ ├── scene0007_00_000455.png │ │ │ ├── scene0007_00_000560.png │ │ │ ├── scene0007_00_000595.png │ │ │ ├── scene0007_00_000735.png │ │ │ ├── scene0007_00_000840.png │ │ │ ├── scene0014_00_000000.png │ │ │ ├── scene0014_00_000070.png │ │ │ ├── scene0014_00_000105.png │ │ │ ├── scene0014_00_000175.png │ │ │ ├── scene0014_00_000210.png │ │ │ ├── scene0014_00_000245.png │ │ │ ├── scene0014_00_000280.png │ │ │ ├── scene0014_00_000350.png │ │ │ ├── scene0014_00_000490.png │ │ │ ├── scene0014_00_000595.png │ │ │ ├── scene0014_00_000840.png │ │ │ ├── scene0014_00_000980.png │ │ │ ├── scene0014_00_001015.png │ │ │ ├── scene0014_00_001120.png │ │ │ ├── scene0014_00_001225.png │ │ │ ├── scene0014_00_001330.png │ │ │ ├── scene0014_00_001365.png │ │ │ ├── scene0014_00_001435.png │ │ │ ├── scene0014_00_001470.png │ │ │ ├── scene0014_00_001505.png │ │ │ ├── scene0014_00_001540.png │ │ │ ├── scene0014_00_001680.png │ │ │ ├── scene0014_00_001715.png │ │ │ ├── scene0014_00_001855.png │ │ │ ├── scene0014_00_001890.png │ │ │ ├── scene0014_00_001925.png │ │ │ └── scene0014_00_002065.png │ │ │ ├── pose │ │ │ ├── scene0007_00_000000.txt │ │ │ ├── scene0007_00_000035.txt │ │ │ ├── scene0007_00_000070.txt │ │ │ ├── scene0007_00_000105.txt │ │ │ ├── scene0007_00_000140.txt │ │ │ ├── scene0007_00_000455.txt │ │ │ ├── scene0007_00_000560.txt │ │ │ ├── scene0007_00_000595.txt │ │ │ ├── scene0007_00_000735.txt │ │ │ ├── scene0007_00_000840.txt │ │ │ ├── scene0014_00_000000.txt │ │ │ ├── scene0014_00_000070.txt │ │ │ ├── scene0014_00_000105.txt │ │ │ ├── scene0014_00_000175.txt │ │ │ ├── scene0014_00_000210.txt │ │ │ ├── scene0014_00_000245.txt │ │ │ ├── scene0014_00_000280.txt │ │ │ ├── scene0014_00_000350.txt │ │ │ ├── scene0014_00_000490.txt │ │ │ ├── scene0014_00_000595.txt │ │ │ ├── scene0014_00_000840.txt │ │ │ ├── scene0014_00_000980.txt │ │ │ ├── scene0014_00_001015.txt │ │ │ ├── scene0014_00_001120.txt │ │ │ ├── scene0014_00_001225.txt │ │ │ ├── scene0014_00_001330.txt │ │ │ ├── scene0014_00_001365.txt │ │ │ ├── scene0014_00_001435.txt │ │ │ ├── scene0014_00_001470.txt │ │ │ ├── scene0014_00_001505.txt │ │ │ ├── scene0014_00_001540.txt │ │ │ ├── scene0014_00_001680.txt │ │ │ ├── scene0014_00_001715.txt │ │ │ ├── scene0014_00_001855.txt │ │ │ ├── scene0014_00_001890.txt │ │ │ ├── scene0014_00_001925.txt │ │ │ └── scene0014_00_002065.txt │ │ │ └── superpixel │ │ │ ├── scene0007_00_000000.png │ │ │ ├── scene0007_00_000035.png │ │ │ ├── scene0007_00_000070.png │ │ │ ├── scene0007_00_000105.png │ │ │ ├── scene0007_00_000140.png │ │ │ ├── scene0007_00_000455.png │ │ │ ├── scene0007_00_000560.png │ │ │ ├── scene0007_00_000595.png │ │ │ ├── scene0007_00_000735.png │ │ │ ├── scene0007_00_000840.png │ │ │ ├── scene0014_00_000000.png │ │ │ ├── scene0014_00_000070.png │ │ │ ├── scene0014_00_000105.png │ │ │ ├── scene0014_00_000175.png │ │ │ ├── scene0014_00_000210.png │ │ │ ├── scene0014_00_000245.png │ │ │ ├── scene0014_00_000280.png │ │ │ ├── scene0014_00_000350.png │ │ │ ├── scene0014_00_000490.png │ │ │ ├── scene0014_00_000595.png │ │ │ ├── scene0014_00_000840.png │ │ │ ├── scene0014_00_000980.png │ │ │ ├── scene0014_00_001015.png │ │ │ ├── scene0014_00_001120.png │ │ │ ├── scene0014_00_001225.png │ │ │ ├── scene0014_00_001330.png │ │ │ ├── scene0014_00_001365.png │ │ │ ├── scene0014_00_001435.png │ │ │ ├── scene0014_00_001470.png │ │ │ ├── scene0014_00_001505.png │ │ │ ├── scene0014_00_001540.png │ │ │ ├── scene0014_00_001680.png │ │ │ ├── scene0014_00_001715.png │ │ │ ├── scene0014_00_001855.png │ │ │ ├── scene0014_00_001890.png │ │ │ ├── scene0014_00_001925.png │ │ │ └── scene0014_00_002065.png │ └── selections │ │ ├── seedset_0_frames.txt │ │ ├── test_frames.txt │ │ ├── train_frames.txt │ │ └── val_frames.txt ├── scannet │ └── selections │ │ ├── seedset_0_frames.txt │ │ ├── test_frames.txt │ │ ├── train_frames.txt │ │ └── val_frames.txt └── scenenet-rgbd │ └── selections │ ├── seedset_0_frames.txt │ ├── test_frames.txt │ ├── train_frames.txt │ └── val_frames.txt ├── model ├── __init__.py ├── aspp.py ├── backbone │ ├── __init__.py │ ├── drn.py │ ├── mobilenet.py │ ├── resnet.py │ └── xception.py ├── decoder.py ├── deeplab.py └── sync_batchnorm │ ├── __init__.py │ ├── batchnorm.py │ ├── comm.py │ ├── replicate.py │ └── unittest.py ├── requirements.txt ├── train.py ├── train_active.py └── utils ├── calculate_weights.py ├── colormaps.py ├── loss.py ├── metrics.py ├── misc.py ├── saver.py ├── summary.py ├── superpixel_projections.py └── trainer.py /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__ 2 | dataset/scannet/raw 3 | dataset/scannet/dataset.lmdb 4 | dataset/matterport3d/raw 5 | dataset/matterport3d/dataset.lmdb 6 | dataset/scenenet-rgbd/raw 7 | dataset/scenenet-rgbd/dataset.lmdb 8 | runs/ 9 | .vscode/ 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2019 Yawar Siddiqui 2 | 3 | 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: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | 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. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ViewAL: Active Learning with Viewpoint Entropy for Semantic Segmentation 2 | 3 | This repository contains the implementation for the paper: 4 | 5 | Yawar Siddiqui, Julien Valentin and Matthias Niessner, ["ViewAL: Active Learning with Viewpoint Entropy for Semantic Segmentation"](https://arxiv.org/abs/1911.11789) ([video](https://youtu.be/tAGdx2j-X_g)) 6 | 7 | ![VisualizationGIF](https://user-images.githubusercontent.com/932110/69557468-f190ae00-0fa6-11ea-9321-309ba55da63d.gif) 8 | 9 | ## Running 10 | 11 | #### Arguments 12 | 13 | ``` 14 | train_active.py [-h] [--backbone {resnet,xception,drn,mobilenet}] 15 | [--out-stride OUT_STRIDE] 16 | [--dataset {scannet,scenenet-rgbd,matterport3d,scannet-sample}] 17 | [--workers N] [--base-size BASE_SIZE] 18 | [--sync-bn SYNC_BN] [--loss-type {ce,focal}] 19 | [--epochs N] [--batch-size N] [--use-balanced-weights] 20 | [--lr LR] [--lr-scheduler {step}] 21 | [--optimizer {SGD,Adam}] [--step-size STEP_SIZE] 22 | [--use-lr-scheduler] [--momentum M] [--weight-decay M] 23 | [--nesterov] [--gpu-ids GPU_IDS] [--seed S] 24 | [--checkname CHECKNAME] [--eval-interval EVAL_INTERVAL] 25 | [--memory-hog] 26 | [--max-iterations MAX_ITERATIONS] 27 | [--active-selection-size ACTIVE_SELECTION_SIZE] 28 | [--region-size REGION_SIZE] 29 | [--region-selection-mode REGION_SELECTION_MODE] 30 | [--view-entropy-mode {soft,vote,mc_dropout}] 31 | [--active-selection-mode {random,viewentropy_region,voteentropy_soft,voteentropy_region,softmax_entropy,softmax_confidence,softmax_margin,coreset,voteentropy_max_repr,viewmc_kldiv_region,ceal}] 32 | [--superpixel-dir SUPERPIXEL_DIR] 33 | [--superpixel-coverage-dir SUPERPIXEL_COVERAGE_DIR] 34 | [--superpixel-overlap SUPERPIXEL_OVERLAP] 35 | [--start-entropy-threshold START_ENTROPY_THRESHOLD] 36 | [--entropy-change-per-selection ENTROPY_CHANGE_PER_SELECTION] 37 | ``` 38 | 39 | Run `--help` for more details. 40 | 41 | #### Active Selection Modes 42 | 43 | Apart from implementation of our method, we provide implementation of other popular active selection methods adapted for semantic segmentation. 44 | 45 | | Option | Method | 46 | | --------------- | ------------ | 47 | |random| RAND selection | 48 | |voteentropy_max_repr| MAXRPR selection| 49 | |voteentropy_soft| MCDR selection| 50 | |voteentropy_region| RMCDR selection| 51 | |softmax_entropy| ENT selection| 52 | |softmax_confidence| CONF selection | 53 | |softmax_margin| MAR selection | 54 | |coreset| CSET selection | 55 | |ceal| CEAL selection | 56 | |viewmc_kldiv_region| ViewAL selection| 57 | 58 | For a description of the methods, check out appendix section of the paper. 59 | 60 | #### Example commands 61 | 62 | 63 | ##### View AL 64 | ```sh 65 | # sample dataset 66 | python train_active.py --dataset scenenet-rgbd --workers 2 --epochs 50 --eval-interval 5 --batch-size=6 --lr 0.0004 --use-lr-scheduler --lr-scheduler step --step-size 35 --checkname regional_viewmckldiv_spx_1_7x2_lr-0.0004_bs-6_ep-60_wb-0_lrs-1_240x320 --base-size 240,320 --max-iterations 7 --active-selection-size 2 --active-selection-mode viewmc_kldiv_region --region-selection-mode superpixel 67 | 68 | # scenenet-rgbd 69 | python train_active.py --dataset scenenet-rgbd --workers 2 --epochs 50 --eval-interval 5 --batch-size=6 --lr 0.0004 --use-lr-scheduler --lr-scheduler step --step-size 35 --checkname regional_viewmckldiv_spx_1_7x1500_lr-0.0004_bs-6_ep-60_wb-0_lrs-1_240x320 --base-size 240,320 --max-iterations 7 --active-selection-size 1500 --active-selection-mode viewmc_kldiv_region --region-selection-mode superpixel 70 | ``` 71 | 72 | ##### Random 73 | ```sh 74 | python train_active.py --dataset scenenet-rgbd --workers 2 --epochs 50 --eval-interval 5 --batch-size=6 --lr 0.0004 --use-lr-scheduler --lr-scheduler step --step-size 35 --checkname random_0_7x1500_lr-0.0004_bs-6_ep-60_wb-0_lrs-0_240x320 --base-size 240,320 --max-iterations 7 --active-selection-size 1500 --active-selection-mode random 75 | ``` 76 | 77 | ##### Softmax Entropy 78 | ```sh 79 | python train_active.py --dataset scenenet-rgbd --workers 2 --epochs 50 --eval-interval 5 --batch-size=6 --lr 0.0004 --use-lr-scheduler --lr-scheduler step --step-size 35 --checkname softmax_entropy_0_7x1500_lr-0.0004_bs-6_ep-50_wb-0_lrs-1_240x320 --base-size 240,320 --max-iterations 7 --active-selection-size 1500 --active-selection-mode softmax_entropy 80 | ``` 81 | 82 | ##### Regional MCDR 83 | ```sh 84 | python train_active.py --dataset scenenet-rgbd --workers 2 --epochs 50 --eval-interval 5 --batch-size=6 --lr 0.0004 --use-lr-scheduler --lr-scheduler step --step-size 35 --checkname regional_voteentropy_window_0_7x1500_lr-0.0004_bs-6_ep-60_wb-0_lrs-1_240x320 --base-size 240,320 --max-iterations 7 --active-selection-size 1500 --active-selection-mode voteentropy_region --region-selection-mode window 85 | ``` 86 | 87 | ##### CEAL 88 | ```sh 89 | python train_active.py --dataset scenenet-rgbd --workers 2 --epochs 50 --eval-interval 5 --batch-size=6 --lr 0.0004 --use-lr-scheduler --lr-scheduler step --step-size 35 --checkname ceal-0.00275_7x1500_lr-0.0005_bs-6_ep-50_wb-0_lrs-1_240x320 --max-iterations 7 --active-selection-size 1500 --base-size 240,320 --active-selection-mode ceal --start-entropy-threshold 0.0275 --entropy-change-per-selection 0.001815 90 | ``` 91 | 92 | ##### MCDR 93 | ```sh 94 | python train_active.py --dataset scenenet-rgbd --workers 2 --epochs 50 --eval-interval 5 --batch-size=6 --lr 0.0004 --use-lr-scheduler --lr-scheduler step --step-size 35 --checkname mcdropoutentropy_0_7x1500_lr-0.0004_bs-6_ep-50_wb-0_lrs-1_240x320 --base-size 240,320 --max-iterations 7 --active-selection-size 1500 --active-selection-mode voteentropy_soft 95 | ``` 96 | 97 | ##### Full training 98 | ```sh 99 | python train.py --dataset scenenet-rgbd --workers 2 --epochs 70 --eval-interval 5 --batch-size=6 --lr 0.0004 --use-lr-scheduler --lr-scheduler step --step-size 40 --checkname full-run_0_lr-0.0004_bs-6_ep-60_wb-0_lrs-0_240x320 --base-size 240,320 100 | ``` 101 | 102 | ## Files 103 | 104 | Overall code structure is as follows: 105 | 106 | | File / Folder | Description | 107 | | ------------- |-------------| 108 | | train_active.py | Training script for active learning methods | 109 | | train.py | Training script for full dataset training | 110 | | constants.py | Constants used across the code | 111 | | argument_parser.py | Arguments parsing code | 112 | | active_selection | Implementation of our method and other active learning methods for semantic segmentation | 113 | | dataloader | Dataset classes | 114 | | dataset | Train/test splits and raw files of datasets | 115 | | model | DeeplabV3+ implementation (inspired from [here](https://github.com/jfzhang95/pytorch-deeplab-xception))| 116 | | utils| Misc utils | 117 | 118 | The datasets must follow the following structure 119 | 120 | ``` 121 | dataset # root dataset directory 122 | ├── dataset-name 123 | ├── raw 124 | ├── selections 125 | ├── color # rgb frames 126 | ├── label # ground truth maps 127 | ├── depth # depth maps 128 | ├── pose # camera extrinsics for each frame 129 | ├── info # camera intrinsics 130 | ├── superpixel # superpixel maps 131 | ├── coverage_superpixel # coverage maps 132 | ├── selections 133 | ├── seedset_0_frames.txt # seed set 134 | ├── train_frames.txt 135 | ├── val_frames.txt 136 | ├── test_frames.txt 137 | ├── dataset.lmdb # rgb frames + labels in lmdb format 138 | ``` 139 | 140 | A small example dataset is provided with this repository in [`dataset/scannet-sample`](https://github.com/nihalsid/ViewAL/tree/master/dataset/scannet-sample). 141 | 142 | ## Data Generation 143 | 144 | To use this repository datasets must be in the structure described in last section. For creating the lmdb database, seed set, train / test splits and superpixel maps check helper scripts in [`dataset/preprocessing-scripts`](https://github.com/nihalsid/ViewAL/tree/master/dataset/preprocessing-scripts). We use [this SEEDS implementation](https://github.com/davidstutz/seeds-revised) for generating superpixels (check [this](https://github.com/nihalsid/ViewAL/issues/4) issue for troubleshooting). Further, to generate superpixel coverage maps (`coverage_superpixel`) check [`utils/superpixel_projections.py`](https://github.com/nihalsid/ViewAL/blob/master/utils/superpixel_projections.py). 145 | 146 | ## Citation 147 | 148 | If you use this code, please cite the paper: 149 | 150 | ``` 151 | @misc{siddiqui2019viewal, 152 | title={ViewAL: Active Learning with Viewpoint Entropy for Semantic Segmentation}, 153 | author={Yawar Siddiqui and Julien Valentin and Matthias Nießner}, 154 | year={2019}, 155 | eprint={1911.11789}, 156 | archivePrefix={arXiv}, 157 | primaryClass={cs.CV} 158 | } 159 | ``` 160 | -------------------------------------------------------------------------------- /active_selection/__init__.py: -------------------------------------------------------------------------------- 1 | from active_selection import random_selection, view_entropy, vote_entropy, softmax_entropy, regional_vote_entropy, softmax_confidence, softmax_margin, core_set, max_repr, regional_view_entropy_kl, ceal 2 | from dataloader.dataset_base import OverlapHandler 3 | import constants 4 | import os 5 | 6 | def get_active_selector(args, lmdb_handle, train_set): 7 | if args.active_selection_mode == 'random': 8 | return random_selection.RandomSelector() 9 | elif args.active_selection_mode == 'ceal': 10 | return ceal.CEALSelector(args.dataset, lmdb_handle, args.base_size, args.batch_size, train_set.num_classes, args.start_entropy_threshold, args.entropy_change_per_selection) 11 | elif args.active_selection_mode == 'voteentropy_soft': 12 | return vote_entropy.VoteEntropySelector(args.dataset, lmdb_handle, args.base_size, args.batch_size, train_set.num_classes, True) 13 | elif args.active_selection_mode == 'softmax_entropy': 14 | return softmax_entropy.SoftmaxEntropySelector(args.dataset, lmdb_handle, args.base_size, args.batch_size, train_set.num_classes) 15 | elif args.active_selection_mode == 'softmax_margin': 16 | return softmax_margin.SoftmaxMarginSelector(args.dataset, lmdb_handle, args.base_size, args.batch_size) 17 | elif args.active_selection_mode == 'softmax_confidence': 18 | return softmax_confidence.SoftmaxConfidenceSelector(args.dataset, lmdb_handle, args.base_size, args.batch_size) 19 | elif args.active_selection_mode == 'voteentropy_region': 20 | overlap_handler = None 21 | if not args.no_overlap: 22 | overlap_handler = OverlapHandler(os.path.join(constants.SSD_DATASET_ROOT, args.dataset, "raw", "selections", args.superpixel_coverage_dir), args.superpixel_overlap, memory_hog_mode=True) 23 | return regional_vote_entropy.RegionalVoteEntropySelector(args.dataset, lmdb_handle, args.superpixel_dir, args.base_size, args.batch_size, train_set.num_classes, args.region_size, overlap_handler, mode=args.region_selection_mode) 24 | elif args.active_selection_mode == 'coreset': 25 | return core_set.CoreSetSelector(args.dataset, lmdb_handle, args.base_size, args.batch_size) 26 | elif args.active_selection_mode == 'voteentropy_max_repr': 27 | return max_repr.MaxRepresentativeSelector(args.dataset, lmdb_handle, args.base_size, args.batch_size, train_set.num_classes) 28 | elif args.active_selection_mode == 'viewmc_kldiv_region': 29 | overlap_handler = None 30 | if not args.no_overlap: 31 | overlap_handler = OverlapHandler(os.path.join(constants.SSD_DATASET_ROOT, args.dataset, "raw", "selections", args.superpixel_coverage_dir), args.superpixel_overlap, memory_hog_mode=True) 32 | return regional_view_entropy_kl.RegionalViewEntropyWithKldivSelector(args.dataset, lmdb_handle, args.superpixel_dir, args.base_size, train_set.num_classes, args.region_size, overlap_handler, mode=args.region_selection_mode) 33 | raise NotImplementedError 34 | -------------------------------------------------------------------------------- /active_selection/ceal.py: -------------------------------------------------------------------------------- 1 | from dataloader.paths import PathsDataset 2 | from dataloader.indoor_scenes import IndoorScenesWithAllInfo 3 | from utils.misc import visualize_entropy, visualize_spx_dataset 4 | from dataloader import indoor_scenes, dataset_base 5 | import constants 6 | import torch 7 | from torch.utils.data import DataLoader 8 | from tqdm import tqdm 9 | import numpy as np 10 | 11 | 12 | class CEALSelector: 13 | 14 | def __init__(self, dataset, lmdb_handle, base_size, batch_size, num_classes, start_entropy_threshold, entropy_change_per_selection): 15 | self.lmdb_handle = lmdb_handle 16 | self.num_classes = num_classes 17 | self.base_size = base_size 18 | self.batch_size = batch_size 19 | self.dataset = dataset 20 | self.current_entropy_threshold = start_entropy_threshold 21 | self.entropy_change_per_selection = entropy_change_per_selection 22 | 23 | def calculate_scores(self, model, paths): 24 | model.eval() 25 | scores = [] 26 | 27 | loader = DataLoader(PathsDataset(self.lmdb_handle, self.base_size, paths), batch_size=self.batch_size, shuffle=False, num_workers=0) 28 | path_ctr = 0 29 | entropy_maps = {} 30 | with torch.no_grad(): 31 | for sample in tqdm(loader): 32 | image_batch = sample['image'].cuda() 33 | label_batch = sample['label'].cuda() 34 | 35 | softmax = torch.nn.Softmax2d() 36 | output = softmax(model(image_batch)) 37 | num_classes = output.shape[1] 38 | for batch_idx in range(output.shape[0]): 39 | entropy_map = torch.cuda.FloatTensor(output.shape[2], output.shape[3]).fill_(0) 40 | for c in range(self.num_classes): 41 | entropy_map = entropy_map - (output[batch_idx, c, :, :] * torch.log2(output[batch_idx, c, :, :] + 1e-12)) 42 | entropy_map[label_batch[batch_idx, :, :] == 255] = 0 43 | scores.append(entropy_map.mean().cpu().item()) 44 | entropy_maps[paths[path_ctr]] = entropy_map.cpu().numpy() 45 | path_ctr += 1 46 | torch.cuda.empty_cache() 47 | return scores, entropy_maps 48 | 49 | 50 | def select_next_batch(self, model, training_set, selection_count): 51 | scores, entropy_maps = self.calculate_scores(model, training_set.remaining_image_paths) 52 | selected_samples = list(zip(*sorted(zip(scores, training_set.remaining_image_paths), key=lambda x: x[0], reverse=True)))[1][:selection_count] 53 | print(f'Selected Samples: {len(selected_samples)}/{len(training_set.remaining_image_paths)}') 54 | unselected_samples = [x for x in entropy_maps if x not in selected_samples] 55 | 56 | loader = DataLoader(PathsDataset(self.lmdb_handle, self.base_size, unselected_samples), batch_size=self.batch_size, shuffle=False, num_workers=0) 57 | pseudolabels = {} 58 | path_ctr = 0 59 | pseudo_images_selected = 0 60 | with torch.no_grad(): 61 | for sample in tqdm(loader): 62 | image_batch = sample['image'].cuda() 63 | label_batch = sample['label'].numpy() 64 | output = model(image_batch) 65 | for batch_idx in range(output.shape[0]): 66 | prediction = np.argmax(output[batch_idx, :, :, :].cpu().numpy().squeeze(), axis=0).astype(np.uint8) 67 | prediction[label_batch[batch_idx, :, :] == 255] = 255 68 | qualified_area = entropy_maps[unselected_samples[path_ctr]] <= self.current_entropy_threshold 69 | qualified_area[label_batch[batch_idx, :, :] == 255] = False 70 | if np.any(qualified_area): 71 | prediction[qualified_area == False] = 255 72 | pseudolabels[unselected_samples[path_ctr]] = prediction 73 | pseudo_images_selected += qualified_area.sum() / (self.base_size[0]*self.base_size[1]) 74 | path_ctr += 1 75 | model.eval() 76 | print(f'Pseudo Samples: {pseudo_images_selected}/{len(unselected_samples)}') 77 | training_set.expand_training_set(selected_samples, pseudolabels) 78 | self.current_entropy_threshold -= self.entropy_change_per_selection 79 | 80 | -------------------------------------------------------------------------------- /active_selection/core_set.py: -------------------------------------------------------------------------------- 1 | from dataloader.paths import PathsDataset 2 | from torch.utils.data import DataLoader 3 | import torch.nn.functional as F 4 | import torch 5 | import numpy as np 6 | from sklearn.metrics import pairwise_distances 7 | from tqdm import tqdm 8 | 9 | 10 | class CoreSetSelector: 11 | 12 | def __init__(self, dataset, lmdb_handle, base_size, batch_size): 13 | self.lmdb_handle = lmdb_handle 14 | self.base_size = base_size 15 | self.batch_size = batch_size 16 | self.dataset = dataset 17 | 18 | def _updated_distances(self, cluster_centers, features, min_distances): 19 | x = features[cluster_centers, :] 20 | dist = pairwise_distances(features, x, metric='euclidean') 21 | if min_distances is None: 22 | return np.min(dist, axis=1).reshape(-1, 1) 23 | else: 24 | return np.minimum(min_distances, dist) 25 | 26 | def _select_batch(self, features, selected_indices, N): 27 | new_batch = [] 28 | min_distances = self._updated_distances(selected_indices, features, None) 29 | for _ in range(N): 30 | ind = np.argmax(min_distances) 31 | # New examples should not be in already selected since those points 32 | # should have min_distance of zero to a cluster center. 33 | assert ind not in selected_indices 34 | min_distances = self._updated_distances([ind], features, min_distances) 35 | new_batch.append(ind) 36 | 37 | print('Maximum distance from cluster centers is %0.5f' % max(min_distances)) 38 | return new_batch 39 | 40 | def select_next_batch(self, model, training_set, selection_count): 41 | combined_paths = training_set.image_path_subset + training_set.remaining_image_paths 42 | loader = DataLoader(PathsDataset(self.lmdb_handle, self.base_size, combined_paths), batch_size=self.batch_size, shuffle=False, num_workers=0) 43 | FEATURE_DIM = 2432 44 | average_pool_kernel_size = (32, 32) 45 | 46 | features = np.zeros((len(combined_paths), FEATURE_DIM)) 47 | model.eval() 48 | model.set_return_features(True) 49 | 50 | average_pool_stride = average_pool_kernel_size[0] // 2 51 | with torch.no_grad(): 52 | for batch_idx, sample in enumerate(tqdm(loader)): 53 | _, features_batch = model(sample['image'].cuda()) 54 | features_batch = F.avg_pool2d(features_batch, average_pool_kernel_size, average_pool_stride) 55 | for feature_idx in range(features_batch.shape[0]): 56 | features[batch_idx * self.batch_size + feature_idx, :] = features_batch[feature_idx, :, :, :].cpu().numpy().flatten() 57 | 58 | 59 | model.set_return_features(False) 60 | selected_indices = self._select_batch(features, list(range(len(training_set.image_path_subset))), selection_count) 61 | training_set.expand_training_set([combined_paths[i] for i in selected_indices]) 62 | -------------------------------------------------------------------------------- /active_selection/max_repr.py: -------------------------------------------------------------------------------- 1 | from active_selection import vote_entropy 2 | from dataloader.paths import PathsDataset 3 | from torch.utils.data import DataLoader 4 | import torch.nn.functional as F 5 | import torch 6 | import numpy as np 7 | from sklearn.metrics import pairwise_distances 8 | import math 9 | from tqdm import tqdm 10 | 11 | 12 | class MaxRepresentativeSelector: 13 | 14 | def __init__(self, dataset, lmdb_handle, base_size, batch_size, num_classes): 15 | self.lmdb_handle = lmdb_handle 16 | self.base_size = base_size 17 | self.batch_size = batch_size 18 | self.dataset = dataset 19 | self.vote_entropy_selector = vote_entropy.VoteEntropySelector(dataset, lmdb_handle, base_size, batch_size, num_classes, True) 20 | 21 | 22 | def _get_features_for_images(self, model, images): 23 | features = [] 24 | loader = DataLoader(PathsDataset(self.lmdb_handle, self.base_size, images), batch_size=self.batch_size, shuffle=False, num_workers=0) 25 | model.eval() 26 | model.set_return_features(True) 27 | average_pool_kernel_size = (32, 32) 28 | average_pool_stride = average_pool_kernel_size[0] // 2 29 | with torch.no_grad(): 30 | for batch_idx, sample in enumerate(tqdm(loader)): 31 | image_batch = sample['image'].cuda() 32 | _, features_batch = model(image_batch) 33 | for feature_idx in range(features_batch.shape[0]): 34 | features.append(F.avg_pool2d(features_batch[feature_idx, :, :, :], average_pool_kernel_size, 35 | average_pool_stride).squeeze().cpu().numpy().flatten()) 36 | model.set_return_features(False) 37 | return features 38 | 39 | def _max_representative_samples(self, image_features, candidate_image_features, selection_count): 40 | all_distances = pairwise_distances(image_features, candidate_image_features, metric='euclidean') 41 | selected_sample_indices = [] 42 | print('Finding max representative candidates..') 43 | minimum_distances = np.ones((len(image_features))) * float('inf') 44 | for _ in tqdm(range(selection_count)): 45 | current_best_score = float("-inf") 46 | current_best_idx = None 47 | current_minimum_distances = None 48 | for i in range(len(candidate_image_features)): 49 | if i not in selected_sample_indices: 50 | selected_sample_indices.append(i) 51 | tmp_distances = np.minimum(minimum_distances, all_distances[:, i]) 52 | tmp_score = np.sum(tmp_distances) * -1 53 | if tmp_score > current_best_score: 54 | current_best_score = tmp_score 55 | current_minimum_distances = tmp_distances 56 | current_best_idx = i 57 | selected_sample_indices.pop() 58 | selected_sample_indices.append(current_best_idx) 59 | minimum_distances = current_minimum_distances 60 | return selected_sample_indices 61 | 62 | def select_next_batch(self, model, training_set, selection_count): 63 | candidate_images = self.vote_entropy_selector.select_next_batch_paths(model, training_set, selection_count * 2) 64 | all_image_features = self._get_features_for_images(model, training_set.image_path_subset + training_set.remaining_image_paths) 65 | candidate_features = self._get_features_for_images(model, candidate_images) 66 | selected_candidate_indices = self._max_representative_samples(all_image_features, candidate_features, selection_count) 67 | training_set.expand_training_set([candidate_images[i] for i in selected_candidate_indices]) 68 | -------------------------------------------------------------------------------- /active_selection/random_selection.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | 4 | class RandomSelector: 5 | 6 | def select_next_batch(self, model, training_set, selection_count): 7 | scores = [] 8 | for i in range(len(training_set.remaining_image_paths)): 9 | scores.append(random.random()) 10 | selected_samples = list(zip(*sorted(zip(scores, training_set.remaining_image_paths), key=lambda x: x[0], reverse=True)))[1][:selection_count] 11 | training_set.expand_training_set(selected_samples) 12 | -------------------------------------------------------------------------------- /active_selection/regional_vote_entropy.py: -------------------------------------------------------------------------------- 1 | from dataloader.paths import PathsDataset 2 | from dataloader import indoor_scenes 3 | from active_selection.vote_entropy import VoteEntropySelector 4 | from utils.misc import turn_on_dropout, visualize_entropy, visualize_spx_dataset 5 | import constants 6 | import torch 7 | from torch.utils.data import DataLoader 8 | from tqdm import tqdm 9 | import numpy as np 10 | from collections import OrderedDict, defaultdict 11 | 12 | class RegionalVoteEntropySelector: 13 | 14 | def __init__(self, dataset, lmdb_handle, superpixel_dir, base_size, batch_size, num_classes, region_size, overlap_handler, mode): 15 | self.lmdb_handle = lmdb_handle 16 | self.base_size = base_size 17 | self.batch_size = batch_size 18 | self.dataset = dataset 19 | self.superpixel_dir = superpixel_dir 20 | self.overlap_handler = overlap_handler 21 | self.vote_entropy_selector = VoteEntropySelector(dataset, lmdb_handle, base_size, batch_size, num_classes) 22 | self.region_size = region_size 23 | if mode == 'window': 24 | self.select_next_batch = self.select_next_batch_with_windows 25 | elif mode == 'superpixel': 26 | self.select_next_batch = self.select_next_batch_with_superpixels 27 | else: 28 | raise NotImplementedError 29 | 30 | # superpixel based selection methods 31 | 32 | def select_next_batch_with_superpixels(self, model, training_set, selection_count): 33 | 34 | model.eval() 35 | model.apply(turn_on_dropout) 36 | 37 | loader = DataLoader(indoor_scenes.IndoorScenesWithAllInfo(self.dataset, self.lmdb_handle, self.superpixel_dir, self.base_size, training_set.all_train_paths), batch_size=self.batch_size, shuffle=False, num_workers=0) 38 | scores = [] 39 | superpixel_masks = [] 40 | 41 | #visualize_entropy.max_weight = 96*96 42 | for sample in tqdm(loader, desc='Entropy'): 43 | image_batch = sample['image'].cuda() 44 | label_batch = sample['label'].cuda() 45 | superpixel_batch = sample['superpixel'] 46 | superpixel_masks.extend([superpixel_batch[i, :, :] for i in range(superpixel_batch.shape[0])]) 47 | scores.extend(self.vote_entropy_selector.batch_entropy_func(model, image_batch, label_batch, superpixel_batch.numpy())) 48 | 49 | all_train_scenes = sorted(list(set([indoor_scenes.IndoorScenesWithAllInfo.get_scene_id_from_image_path(self.dataset, x) for x in training_set.all_train_paths]))) 50 | scene_indices = [all_train_scenes.index(indoor_scenes.IndoorScenesWithAllInfo.get_scene_id_from_image_path(self.dataset, im_path)) for im_path in training_set.all_train_paths] 51 | 52 | superpixel_ids = [] 53 | superpixel_scores_expanded = [] 54 | 55 | for image_score_idx, superpixel_scores in enumerate(scores): 56 | for superpixel_idx in superpixel_scores.keys(): 57 | superpixel_ids.append((scene_indices[image_score_idx], image_score_idx, superpixel_idx)) 58 | superpixel_scores_expanded.append(superpixel_scores[superpixel_idx]) 59 | 60 | _sorted_scores = np.array(list(list(zip(*sorted(zip(superpixel_ids, superpixel_scores_expanded), key=lambda x: x[1], reverse=True)))[0])) 61 | sorted_scores = np.zeros((_sorted_scores.shape[0], _sorted_scores.shape[1] + 1), dtype=np.int32) 62 | sorted_scores[:, 0:_sorted_scores.shape[1]] = _sorted_scores 63 | 64 | total_pixels_selected = 0 65 | selected_regions = OrderedDict() 66 | image_superpixels = defaultdict(list) 67 | ctr = 0 68 | 69 | print('Selecting superpixels...') 70 | pbar = tqdm(total=selection_count) 71 | 72 | while total_pixels_selected < selection_count * self.base_size[0] * self.base_size[1] and ctr < sorted_scores.shape[0]: 73 | if sorted_scores[ctr, 2] not in training_set.image_superpixels[training_set.all_train_paths[sorted_scores[ctr, 1]]] and not (sorted_scores[ctr, 3] == 1): 74 | mask = (superpixel_masks[sorted_scores[ctr, 1]] == sorted_scores[ctr, 2]).numpy().astype(np.uint8) 75 | if training_set.all_train_paths[sorted_scores[ctr, 1]] in selected_regions: 76 | selected_regions[training_set.all_train_paths[sorted_scores[ctr, 1]]] = selected_regions[training_set.all_train_paths[sorted_scores[ctr, 1]]] | mask 77 | else: 78 | selected_regions[training_set.all_train_paths[sorted_scores[ctr, 1]]] = mask 79 | image_superpixels[training_set.all_train_paths[sorted_scores[ctr, 1]]].append(sorted_scores[ctr, 2]) 80 | valid_pixels = mask.sum() 81 | total_pixels_selected += valid_pixels 82 | pbar.update(valid_pixels / (self.base_size[0] * self.base_size[1])) 83 | if not self.overlap_handler is None: 84 | overlapping_indices = [] 85 | tgt_scene_id = indoor_scenes.IndoorScenesWithAllInfo.get_scene_id_from_image_path(self.dataset, training_set.all_train_paths[sorted_scores[ctr, 1]]) 86 | overlap_dict = self.overlap_handler.get_overlap_dict_for_scene(tgt_scene_id) 87 | tgt_scene_list_index = all_train_scenes.index(tgt_scene_id) 88 | sorted_scores_view_mask = sorted_scores[:, 0] == tgt_scene_list_index 89 | sorted_scores_view = sorted_scores[sorted_scores_view_mask] 90 | 91 | for sc_idx in range(sorted_scores_view.shape[0]): 92 | src_scene_id = indoor_scenes.IndoorScenesWithAllInfo.get_scene_id_from_image_path(self.dataset, training_set.all_train_paths[sorted_scores_view[sc_idx, 1]]) 93 | if sorted_scores[ctr, 1] in overlap_dict and (sorted_scores[ctr, 2], sorted_scores_view[sc_idx, 1], sorted_scores_view[sc_idx, 2]) in overlap_dict[sorted_scores[ctr, 1]]: 94 | if overlap_dict[sorted_scores[ctr, 1]][(sorted_scores[ctr, 2], sorted_scores_view[sc_idx, 1], sorted_scores_view[sc_idx, 2])] > self.overlap_handler.superpixel_overlap: 95 | sorted_scores_view[sc_idx, 3] = 1 96 | sorted_scores[sorted_scores_view_mask] = sorted_scores_view 97 | 98 | ctr += 1 99 | 100 | pbar.close() 101 | print('Selected ', total_pixels_selected / (self.base_size[0] * self.base_size[1]), 'images') 102 | model.eval() 103 | training_set.expand_training_set(selected_regions, image_superpixels) 104 | 105 | # window based selection methods 106 | 107 | def nms(self, img_idx, score_map): 108 | selected_score_map_pts = [] 109 | for i in range((score_map.shape[0]*score_map.shape[1])//(self.region_size*self.region_size)): 110 | argmax = score_map.view(-1).argmax() 111 | r, c = argmax // score_map.shape[1], argmax % score_map.shape[1] 112 | selected_score_map_pts.append((img_idx, r.cpu().item(), c.cpu().item(), score_map[r, c].cpu().item())) 113 | score_map[max(0, r - self.region_size): min(score_map.shape[0], r + self.region_size), max(0, c - self.region_size): min(score_map.shape[1], c + self.region_size)] = 0 114 | 115 | return selected_score_map_pts 116 | 117 | 118 | 119 | def select_next_batch_with_windows(self, model, training_set, selection_count): 120 | model.eval() 121 | model.apply(turn_on_dropout) 122 | 123 | weights = torch.cuda.FloatTensor(self.region_size, self.region_size).fill_(1.) 124 | loader = DataLoader(PathsDataset(self.lmdb_handle, self.base_size, training_set.all_train_paths), batch_size=self.batch_size, shuffle=False, num_workers=0) 125 | map_ctr = 0 126 | scores = [] 127 | 128 | for sample in tqdm(loader, desc='Entropy'): 129 | image_batch = sample['image'].cuda() 130 | label_batch = sample['label'].cuda() 131 | for batch_idx, entropy_map in enumerate(self.vote_entropy_selector.batch_entropy_func(model, image_batch, label_batch)): 132 | if training_set.all_train_paths[map_ctr] in training_set.get_selections(): 133 | entropy_map[training_set.get_selections()[training_set.all_train_paths[map_ctr]] == 1] = 0 134 | convolution_output = torch.nn.functional.conv2d(torch.cuda.FloatTensor(entropy_map).unsqueeze(0).unsqueeze(0), weights.unsqueeze(0).unsqueeze(0)).squeeze().squeeze() 135 | scores.extend(self.nms(map_ctr, convolution_output)) 136 | map_ctr += 1 137 | 138 | selected_samples = sorted(scores, key=lambda x: x[3], reverse=True)[:int(0.5 + selection_count * self.base_size[0] * self.base_size[1] / (self.region_size * self.region_size))] 139 | print('Last selected sample: ', selected_samples[-1]) 140 | selected_regions = OrderedDict() 141 | 142 | total_pixels_selected = 0 143 | for ss in selected_samples: 144 | mask = np.zeros(self.base_size, dtype=np.int) == 1 145 | mask[ss[1] : ss[1] + self.region_size, ss[2] : ss[2] + self.region_size] = True 146 | valid_pixels = mask.sum() 147 | total_pixels_selected += valid_pixels 148 | if training_set.all_train_paths[ss[0]] in selected_regions: 149 | selected_regions[training_set.all_train_paths[ss[0]]] = selected_regions[training_set.all_train_paths[ss[0]]] | mask 150 | else: 151 | selected_regions[training_set.all_train_paths[ss[0]]] = mask 152 | 153 | 154 | model.eval() 155 | print('Selected ', total_pixels_selected / (self.base_size[0] * self.base_size[1]), 'images') 156 | training_set.expand_training_set(selected_regions, []) 157 | 158 | -------------------------------------------------------------------------------- /active_selection/softmax_confidence.py: -------------------------------------------------------------------------------- 1 | from dataloader.paths import PathsDataset 2 | from utils.misc import turn_on_dropout, visualize_entropy 3 | import constants 4 | import torch 5 | from torch.utils.data import DataLoader 6 | from tqdm import tqdm 7 | 8 | 9 | class SoftmaxConfidenceSelector: 10 | 11 | def __init__(self, dataset, lmdb_handle, base_size, batch_size): 12 | self.lmdb_handle = lmdb_handle 13 | self.base_size = base_size 14 | self.batch_size = batch_size 15 | self.dataset = dataset 16 | 17 | def calculate_scores(self, model, paths): 18 | model.eval() 19 | scores = [] 20 | 21 | loader = DataLoader(PathsDataset(self.lmdb_handle, self.base_size, paths), batch_size=self.batch_size, shuffle=False, num_workers=0) 22 | 23 | with torch.no_grad(): 24 | for sample in tqdm(loader): 25 | image_batch = sample['image'].cuda() 26 | label_batch = sample['label'].cuda() 27 | softmax = torch.nn.Softmax2d() 28 | max_conf_batch = torch.max(softmax(model(image_batch)), dim=1)[0] 29 | 30 | for batch_idx in range(max_conf_batch.shape[0]): 31 | max_conf_batch[batch_idx, (label_batch[batch_idx, :, :] == 255)] = 1 32 | scores.append(torch.mean(max_conf_batch[batch_idx, :, :]).cpu().item()) 33 | del max_conf_batch 34 | torch.cuda.empty_cache() 35 | return scores 36 | 37 | 38 | def select_next_batch(self, model, training_set, selection_count): 39 | 40 | scores = self.calculate_scores(model, training_set.remaining_image_paths) 41 | selected_samples = list(zip(*sorted(zip(scores, training_set.remaining_image_paths), key=lambda x: x[0], reverse=False)))[1][:selection_count] 42 | 43 | model.eval() 44 | training_set.expand_training_set(selected_samples) 45 | -------------------------------------------------------------------------------- /active_selection/softmax_entropy.py: -------------------------------------------------------------------------------- 1 | from dataloader.paths import PathsDataset 2 | from utils.misc import turn_on_dropout, visualize_entropy 3 | import constants 4 | import torch 5 | from torch.utils.data import DataLoader 6 | from tqdm import tqdm 7 | 8 | 9 | class SoftmaxEntropySelector: 10 | 11 | def __init__(self, dataset, lmdb_handle, base_size, batch_size, num_classes): 12 | self.lmdb_handle = lmdb_handle 13 | self.num_classes = num_classes 14 | self.base_size = base_size 15 | self.batch_size = batch_size 16 | self.dataset = dataset 17 | 18 | def calculate_scores(self, model, paths): 19 | model.eval() 20 | scores = [] 21 | 22 | loader = DataLoader(PathsDataset(self.lmdb_handle, self.base_size, paths), batch_size=self.batch_size, shuffle=False, num_workers=0) 23 | 24 | with torch.no_grad(): 25 | for sample in tqdm(loader): 26 | image_batch = sample['image'].cuda() 27 | label_batch = sample['label'].cuda() 28 | softmax = torch.nn.Softmax2d() 29 | output = softmax(model(image_batch)) 30 | num_classes = output.shape[1] 31 | for batch_idx in range(output.shape[0]): 32 | entropy_map = torch.cuda.FloatTensor(output.shape[2], output.shape[3]).fill_(0) 33 | for c in range(self.num_classes): 34 | entropy_map = entropy_map - (output[batch_idx, c, :, :] * torch.log2(output[batch_idx, c, :, :] + 1e-12)) 35 | entropy_map[label_batch[batch_idx, :, :] == 255] = 0 36 | scores.append(entropy_map.mean().cpu().item()) 37 | del entropy_map 38 | torch.cuda.empty_cache() 39 | return scores 40 | 41 | 42 | def select_next_batch(self, model, training_set, selection_count): 43 | 44 | scores = self.calculate_scores(model, training_set.remaining_image_paths) 45 | selected_samples = list(zip(*sorted(zip(scores, training_set.remaining_image_paths), key=lambda x: x[0], reverse=True)))[1][:selection_count] 46 | model.eval() 47 | training_set.expand_training_set(selected_samples) 48 | -------------------------------------------------------------------------------- /active_selection/softmax_margin.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from dataloader.paths import PathsDataset 3 | from utils.misc import turn_on_dropout, visualize_entropy 4 | import constants 5 | import torch 6 | from torch.utils.data import DataLoader 7 | from tqdm import tqdm 8 | 9 | 10 | class SoftmaxMarginSelector: 11 | 12 | def __init__(self, dataset, lmdb_handle, base_size, batch_size): 13 | self.lmdb_handle = lmdb_handle 14 | self.base_size = base_size 15 | self.batch_size = batch_size 16 | self.dataset = dataset 17 | 18 | def calculate_scores(self, model, paths): 19 | model.eval() 20 | scores = [] 21 | 22 | loader = DataLoader(PathsDataset(self.lmdb_handle, self.base_size, paths), batch_size=self.batch_size, shuffle=False, num_workers=0) 23 | 24 | with torch.no_grad(): 25 | for sample in tqdm(loader): 26 | image_batch = sample['image'].cuda() 27 | label_batch = sample['label'].cuda() 28 | softmax = torch.nn.Softmax2d() 29 | output = softmax(model(image_batch)) 30 | for batch_idx in range(output.shape[0]): 31 | most_confident_scores = torch.max(output[batch_idx, :, :].squeeze(), dim=0)[0].cpu().numpy() 32 | output_numpy = output[batch_idx, :, :, :].cpu().numpy() 33 | ndx = np.indices(output_numpy.shape) 34 | second_most_confident_scores = output_numpy[output_numpy.argsort(0), ndx[1], ndx[2]][-2] 35 | margin = most_confident_scores - second_most_confident_scores 36 | margin[(label_batch[batch_idx, :, :] == 255).cpu().numpy()] = 1 37 | scores.append(np.mean(margin)) 38 | del output, margin 39 | torch.cuda.empty_cache() 40 | return scores 41 | 42 | 43 | def select_next_batch(self, model, training_set, selection_count): 44 | 45 | scores = self.calculate_scores(model, training_set.remaining_image_paths) 46 | selected_samples = list(zip(*sorted(zip(scores, training_set.remaining_image_paths), key=lambda x: x[0], reverse=False)))[1][:selection_count] 47 | 48 | model.eval() 49 | training_set.expand_training_set(selected_samples) 50 | -------------------------------------------------------------------------------- /active_selection/vote_entropy.py: -------------------------------------------------------------------------------- 1 | from dataloader.paths import PathsDataset 2 | from utils.misc import turn_on_dropout, visualize_entropy 3 | import constants 4 | import torch 5 | from torch.utils.data import DataLoader 6 | from tqdm import tqdm 7 | import numpy as np 8 | from collections import OrderedDict, defaultdict 9 | 10 | 11 | class VoteEntropySelector: 12 | 13 | def __init__(self, dataset, lmdb_handle, base_size, batch_size, num_classes, soft_mode=False): 14 | self.lmdb_handle = lmdb_handle 15 | self.num_classes = num_classes 16 | self.base_size = base_size 17 | self.batch_size = batch_size 18 | self.dataset = dataset 19 | if soft_mode: 20 | self.batch_entropy_func = self._get_soft_vote_entropy_for_batch 21 | else: 22 | self.batch_entropy_func = self._get_vote_entropy_for_batch 23 | 24 | def _get_vote_entropy_for_batch(self, model, image_batch, label_batch, superpixels=None): 25 | 26 | outputs = torch.cuda.FloatTensor(image_batch.shape[0], constants.MC_STEPS, image_batch.shape[2], image_batch.shape[3]) 27 | 28 | with torch.no_grad(): 29 | for step in range(constants.MC_STEPS): 30 | outputs[:, step, :, :] = torch.argmax(model(image_batch), dim=1) 31 | 32 | scores = [] 33 | for i in range(image_batch.shape[0]): 34 | entropy_map = torch.cuda.FloatTensor(image_batch.shape[2], image_batch.shape[3]).fill_(0) 35 | for c in range(self.num_classes): 36 | p = torch.sum(outputs[i, :, :, :] == c, dim=0, dtype=torch.float32) / constants.MC_STEPS 37 | entropy_map = entropy_map - (p * torch.log2(p + 1e-12)) 38 | entropy_map[label_batch[i, :, :] == 255] = 0 39 | 40 | if not superpixels is None: 41 | score = entropy_map.cpu().numpy() 42 | unique_superpixels_as_list = np.unique(superpixels[i, :, :]).tolist() 43 | score_per_superpixel = defaultdict(int) 44 | for spx_id in unique_superpixels_as_list: 45 | spx_mean = score[superpixels[i, :, :] == spx_id].mean() 46 | 47 | score_per_superpixel[spx_id] = spx_mean 48 | score[superpixels[i, :, :] == spx_id] = spx_mean 49 | scores.append(score_per_superpixel) 50 | else: 51 | scores.append(entropy_map.cpu().numpy()) 52 | 53 | del outputs 54 | torch.cuda.empty_cache() 55 | 56 | return scores 57 | 58 | def _get_soft_vote_entropy_for_batch(self, model, image_batch, label_batch, superpixels=None): 59 | 60 | outputs = torch.cuda.FloatTensor(image_batch.shape[0], self.num_classes, image_batch.shape[2], image_batch.shape[3]).fill_(0) 61 | softmax = torch.nn.Softmax2d() 62 | with torch.no_grad(): 63 | for step in range(constants.MC_STEPS): 64 | outputs[:, :, :, :] += softmax(model(image_batch)) 65 | 66 | outputs /= constants.MC_STEPS 67 | scores = [] 68 | for i in range(image_batch.shape[0]): 69 | entropy_map = torch.cuda.FloatTensor(image_batch.shape[2], image_batch.shape[3]).fill_(0) 70 | for c in range(self.num_classes): 71 | entropy_map = entropy_map - (outputs[i, c, :, :] * torch.log2(outputs[i, c, :, :] + 1e-12)) 72 | entropy_map[label_batch[i, :, :] == 255] = 0 73 | 74 | if not superpixels is None: 75 | score = entropy_map.cpu().numpy() 76 | unique_superpixels_as_list = np.unique(superpixels[i, :, :]).tolist() 77 | score_per_superpixel = defaultdict(int) 78 | for spx_id in unique_superpixels_as_list: 79 | spx_mean = score[superpixels[i, :, :] == spx_id].mean() 80 | score_per_superpixel[spx_id] = spx_mean 81 | score[superpixels[i, :, :] == spx_id] = spx_mean 82 | scores.append(score_per_superpixel) 83 | else: 84 | scores.append(entropy_map.cpu().numpy()) 85 | 86 | del outputs 87 | torch.cuda.empty_cache() 88 | 89 | return scores 90 | 91 | def calculate_scores(self, model, paths, return_score_maps=False): 92 | model.eval() 93 | model.apply(turn_on_dropout) 94 | scores = [] 95 | 96 | loader = DataLoader(PathsDataset(self.lmdb_handle, self.base_size, paths), batch_size=self.batch_size, shuffle=False, num_workers=0) 97 | 98 | for sample in tqdm(loader, desc='Entropy'): 99 | image_batch = sample['image'].cuda() 100 | label_batch = sample['label'].cuda() 101 | if return_score_maps: 102 | scores.extend(self.batch_entropy_func(model, image_batch, label_batch)) 103 | else: 104 | scores.extend([x.sum() for x in self.batch_entropy_func(model, image_batch, label_batch)]) 105 | 106 | model.eval() 107 | return scores 108 | 109 | 110 | def select_next_batch_paths(self, model, training_set, selection_count): 111 | 112 | scores = self.calculate_scores(model, training_set.remaining_image_paths) 113 | selected_samples = list(zip(*sorted(zip(scores, training_set.remaining_image_paths), key=lambda x: x[0], reverse=True)))[1][:selection_count] 114 | model.eval() 115 | return selected_samples 116 | 117 | def select_next_batch(self, model, training_set, selection_count): 118 | training_set.expand_training_set(self.select_next_batch_paths(model, training_set, selection_count)) 119 | -------------------------------------------------------------------------------- /argument_parser.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import torch 3 | import random 4 | 5 | 6 | def parse_args(): 7 | parser = argparse.ArgumentParser(description="ViewAL") 8 | parser.add_argument('--backbone', type=str, default='mobilenet', 9 | choices=['resnet', 'xception', 'drn', 'mobilenet'], 10 | help='backbone name (default: mobilenet)') 11 | parser.add_argument('--out-stride', type=int, default=16, 12 | help='network output stride (default: 16)') 13 | parser.add_argument('--dataset', type=str, default='scannet-sample', 14 | choices=['scannet', 'scenenet-rgbd', 'matterport3d','scannet-sample'], 15 | help='dataset name (default: scannet-sample)') 16 | parser.add_argument('--workers', type=int, default=4, 17 | metavar='N', help='dataloader threads') 18 | parser.add_argument('--base-size', type=str, default="384,512", 19 | help='base image size') 20 | parser.add_argument('--sync-bn', type=bool, default=False, 21 | help='whether to use sync bn (default: False)') 22 | parser.add_argument('--loss-type', type=str, default='ce', 23 | choices=['ce', 'focal'], 24 | help='loss func type (default: ce)') 25 | 26 | # training hyper params 27 | parser.add_argument('--epochs', type=int, default=None, metavar='N', 28 | help='number of epochs to train (default: auto)') 29 | parser.add_argument('--batch-size', type=int, default=None, 30 | metavar='N', help='input batch size for \ 31 | training (default: auto)') 32 | parser.add_argument('--use-balanced-weights', action='store_true', default=False, 33 | help='whether to use balanced weights (default: True)') 34 | # optimizer params 35 | parser.add_argument('--lr', type=float, default=0.001, metavar='LR', 36 | help='learning rate (default: auto)') 37 | parser.add_argument('--lr-scheduler', type=str, default='step', 38 | choices=['step'], 39 | help='lr scheduler mode: (default: step)') 40 | parser.add_argument('--optimizer', type=str, default='SGD', choices=['SGD', 'Adam']) 41 | parser.add_argument('--step-size', type=str, default='35', help='step size for lr-step-scheduler') 42 | parser.add_argument('--use-lr-scheduler', default=False, help='use learning rate scheduler', action='store_true') 43 | parser.add_argument('--momentum', type=float, default=0.9, 44 | metavar='M', help='momentum (default: 0.9)') 45 | parser.add_argument('--weight-decay', type=float, default=5e-4, 46 | metavar='M', help='w-decay (default: 5e-4)') 47 | parser.add_argument('--nesterov', action='store_true', default=False, 48 | help='whether use nesterov (default: False)') 49 | # cuda, seed and logging 50 | parser.add_argument('--no-cuda', action='store_true', default=False, help='disables CUDA training') 51 | parser.add_argument('--gpu-ids', type=str, default='0', 52 | help='use which gpu to train, must be a \ 53 | comma-separated list of integers only (default=0)') 54 | parser.add_argument('--seed', type=int, default=-1, metavar='S', 55 | help='random seed (default: -1)') 56 | # checking point 57 | parser.add_argument('--checkname', type=str, default=None, 58 | help='set the checkpoint name') 59 | 60 | # evaluation option 61 | parser.add_argument('--eval-interval', type=int, default=5, 62 | help='evaluation interval (default: 5) - record metrics every Nth iteration') 63 | parser.add_argument('--memory-hog', action='store_true', default=False, help='load the whole dataset in RAM if true') 64 | parser.add_argument('--no-overlap', action='store_true', default=False, help='No overlap check - should be False') 65 | parser.add_argument('--max-iterations', type=int, default=8, help='max active iterations') 66 | parser.add_argument('--active-selection-size', type=int, default=1750, help='active selection size') 67 | parser.add_argument('--region-size', type=int, default=65, help='window size for window region methods') 68 | parser.add_argument('--region-selection-mode', type=str, default='superpixel', help='use superpixels or windows as region selection mode') 69 | parser.add_argument('--view-entropy-mode', type=str, default='mc_dropout', choices=['soft', 'vote', 'mc_dropout'], help='probability estimate = softmax or vote or mcdropout') 70 | parser.add_argument('--active-selection-mode', type=str, default='random', 71 | choices=['random', 'viewentropy_region', 'voteentropy_soft', 'voteentropy_region', 'softmax_entropy', 'softmax_confidence', 'softmax_margin', 'coreset', 'voteentropy_max_repr', 'viewmc_kldiv_region', 'ceal']) 72 | parser.add_argument('--view-prob-aggr', type=str, default='entropy') 73 | parser.add_argument('--superpixel-dir', type=str, default='superpixel', help='directory for supepixel maps inside the dataset raw root') 74 | parser.add_argument('--superpixel-coverage-dir', type=str, default='coverage_superpixel', help='directory for coverage maps inside the dataset raw root') 75 | parser.add_argument('--superpixel-overlap', type=float, default=0.25, help='superpixel overlap threshold') 76 | parser.add_argument('--start-entropy-threshold', type=float, default=0.005, help='ceal hyperparameter') 77 | parser.add_argument('--entropy-change-per-selection', type=float, default=0.00033, help='ceal hyperparameter') 78 | args = parser.parse_args() 79 | args.cuda = not args.no_cuda and torch.cuda.is_available() 80 | args.base_size = [int(s) for s in args.base_size.split(',')] 81 | # manual seeding 82 | if args.seed == -1: 83 | args.seed = int(random.random() * 2000) 84 | print('Using random seed = ', args.seed) 85 | print('ActiveSelector: ', args.active_selection_mode) 86 | return args 87 | -------------------------------------------------------------------------------- /constants.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | HDD_DATASET_ROOT = "./dataset" 4 | SSD_DATASET_ROOT = "./dataset" 5 | RUNS = "./runs" 6 | DEPTH_WIDTH = 320 7 | DEPTH_HEIGHT = 240 8 | MC_STEPS = 20 9 | MC_DROPOUT_RATE = 0.25 10 | WORLD_DISTANCE_THRESHOLD = 1.0 11 | COVERAGE_IGNORE_THRESHOLD = 0.35 12 | VISUALIZATION = False 13 | -------------------------------------------------------------------------------- /dataloader/custom_transforms.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import torch 3 | import random 4 | from torchvision import transforms 5 | from scipy.ndimage import gaussian_filter 6 | 7 | 8 | class Normalize(object): 9 | """Normalize a tensor image with mean and standard deviation. 10 | Args: 11 | mean (tuple): means for each channel. 12 | std (tuple): standard deviations for each channel. 13 | """ 14 | 15 | def __init__(self, mean=(0., 0., 0.), std=(1., 1., 1.)): 16 | self.mean = mean 17 | self.std = std 18 | 19 | def __call__(self, sample): 20 | img = sample['image'] 21 | mask = sample['label'] 22 | img = img.astype(np.float32) 23 | mask = mask.astype(np.float32) 24 | img /= 255.0 25 | img -= self.mean 26 | img /= self.std 27 | 28 | return {'image': img, 29 | 'label': mask} 30 | 31 | 32 | class ToTensor(object): 33 | """Convert ndarrays in sample to Tensors.""" 34 | 35 | def __call__(self, sample): 36 | # swap color axis because 37 | # numpy image: H x W x C 38 | # torch image: C X H X W 39 | img = sample['image'] 40 | mask = sample['label'] 41 | 42 | img = img.astype(np.float32) 43 | 44 | if len(img.shape) == 3: 45 | img = img.transpose((2, 0, 1)) 46 | 47 | mask = mask.astype(np.float32) 48 | 49 | img = torch.from_numpy(img).float() 50 | mask = torch.from_numpy(mask).float() 51 | 52 | return {'image': img, 53 | 'label': mask} 54 | 55 | 56 | class RandomGaussianBlur(object): 57 | 58 | def __call__(self, sample): 59 | img = sample['image'] 60 | mask = sample['label'] 61 | if random.random() < 0.5: 62 | img = gaussian_filter(img, sigma=random.random()) 63 | 64 | return {'image': img, 65 | 'label': mask} 66 | 67 | 68 | class RandomHorizontalFlip(object): 69 | 70 | def __call__(self, sample): 71 | 72 | img = sample['image'] 73 | mask = sample['label'] 74 | 75 | if random.random() < 0.5: 76 | img = np.fliplr(img) 77 | mask = np.fliplr(mask) 78 | 79 | return {'image': img, 80 | 'label': mask} 81 | 82 | 83 | class FixScaleCrop(object): 84 | 85 | def __init__(self, crop_size): 86 | self.crop_size = crop_size 87 | 88 | def __call__(self, sample): 89 | img = sample['image'] 90 | mask = sample['label'] 91 | w, h = img.shape[1], img.shape[0] 92 | 93 | if w > h: 94 | oh = self.crop_size[0] 95 | ow = int(1.0 * w * oh / h) 96 | else: 97 | ow = self.crop_size[1] 98 | oh = int(1.0 * h * ow / w) 99 | 100 | img = np.array(Image.fromarray(img).resize(ow, oh)) 101 | mask = np.array(Image.fromarray(mask).resize(ow, oh), PIL.Image.NEAREST) 102 | 103 | # center crop 104 | w, h = img.shape[1], img.shape[0] 105 | x1 = int(round((w - self.crop_size[1]) / 2.)) 106 | y1 = int(round((h - self.crop_size[0]) / 2.)) 107 | img = img[y1: y1 + self.crop_size[0], x1: x1 + self.crop_size[1], :] 108 | mask = mask[y1: y1 + self.crop_size[0], x1: x1 + self.crop_size[1]] 109 | 110 | return {'image': img, 111 | 'label': mask} 112 | 113 | 114 | def transform_training_sample(image, target, base_size): 115 | composed_transforms = transforms.Compose([ 116 | RandomHorizontalFlip(), 117 | RandomGaussianBlur(), 118 | Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]), 119 | ToTensor() 120 | ]) 121 | 122 | return composed_transforms({'image': image, 'label': target}) 123 | 124 | 125 | def transform_validation_sample(image, target, base_size=None): 126 | composed_transforms = transforms.Compose([ 127 | Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]), 128 | ToTensor() 129 | ]) 130 | 131 | return composed_transforms({'image': image, 'label': target}) 132 | -------------------------------------------------------------------------------- /dataloader/dataset_base.py: -------------------------------------------------------------------------------- 1 | import lmdb 2 | import os 3 | from torch.utils import data 4 | import PIL 5 | import pickle 6 | import numpy as np 7 | from dataloader import custom_transforms 8 | from tqdm import tqdm 9 | 10 | 11 | class LMDBHandle: 12 | 13 | def __init__(self, lmdb_path, memory_hog_mode=False): 14 | 15 | self.env = lmdb.open(lmdb_path, subdir=False, readonly=True, lock=False, readahead=False, meminit=False) 16 | self.memory_hog_mode = memory_hog_mode 17 | 18 | with self.env.begin(write=False) as txn: 19 | self.image_paths = pickle.loads(txn.get(b'__keys__')) 20 | 21 | if self.memory_hog_mode: 22 | self.path_to_npy = {} 23 | print('Acquiring dataset in memory') 24 | for n in tqdm(self.image_paths): 25 | with self.env.begin(write=False) as txn: 26 | loaded_npy = pickle.loads(txn.get(n)) 27 | self.path_to_npy[n] = loaded_npy 28 | 29 | def get_image_paths(self): 30 | return self.image_paths 31 | 32 | def get_numpy_object(self, image_path): 33 | loaded_npy = None 34 | if self.memory_hog_mode and image_path in self.path_to_npy: 35 | loaded_npy = self.path_to_npy[image_path] 36 | else: 37 | with self.env.begin(write=False) as txn: 38 | loaded_npy = pickle.loads(txn.get(image_path)) 39 | return loaded_npy 40 | 41 | class OverlapHandler: 42 | 43 | def __init__(self, overlap_folder, superpixel_overlap, memory_hog_mode, list_of_scenes=None): 44 | 45 | self.memory_hog_mode = memory_hog_mode 46 | self.scene_overlaps = {} 47 | self.superpixel_overlap = superpixel_overlap 48 | self.overlap_folder = overlap_folder 49 | if memory_hog_mode: 50 | print('Acquiring overlaps..') 51 | for f in tqdm(os.listdir(overlap_folder)): 52 | if f.endswith(".npy"): 53 | if not list_of_scenes: 54 | self.scene_overlaps[f.split(".")[0]] = np.load(os.path.join(overlap_folder, f), allow_pickle=True)[()] 55 | elif f.split(".")[0] in list_of_scenes: 56 | self.scene_overlaps[f.split(".")[0]] = np.load(os.path.join(overlap_folder, f), allow_pickle=True)[()] 57 | 58 | def get_overlap_dict_for_scene(self, scene_id): 59 | loaded_dict = {} 60 | if self.memory_hog_mode and scene_id in self.scene_overlaps: 61 | loaded_dict = self.scene_overlaps[scene_id] 62 | else: 63 | loaded_dict = np.load(os.path.join(self.overlap_folder, scene_id+".npy"))[()] 64 | return loaded_dict 65 | 66 | 67 | class DatasetBase(data.Dataset): 68 | 69 | def __init__(self, lmdb_handle, base_size): 70 | 71 | self.lmdb_handle = lmdb_handle 72 | self.image_paths = lmdb_handle.get_image_paths() 73 | self.base_size = base_size 74 | self.image_path_subset = self.image_paths 75 | self.augmentation_transform = custom_transforms.transform_training_sample 76 | 77 | if len(self.image_path_subset) == 0: 78 | raise Exception("No images found in dataset directory") 79 | 80 | def __len__(self): 81 | return len(self.image_path_subset) 82 | 83 | def __getitem__(self, index): 84 | 85 | image_path = self.image_path_subset[index] 86 | loaded_npy = self.lmdb_handle.get_numpy_object(image_path) 87 | 88 | image = loaded_npy[:, :, 0:3] 89 | target = loaded_npy[:, :, 3] 90 | 91 | return self.augmentation_transform(image, target, self.base_size) 92 | 93 | def _fix_list_multiple_of_batch_size(self, paths, batch_size): 94 | remainder = len(paths) % batch_size 95 | if remainder != 0: 96 | num_new_entries = batch_size - remainder 97 | new_entries = paths[:num_new_entries] 98 | paths.extend(new_entries) 99 | return paths 100 | 101 | def reset_dataset(self): 102 | self.image_path_subset = self.image_path_subset[:self.len_image_path_subset] 103 | 104 | def make_dataset_multiple_of_batchsize(self, batch_size): 105 | self.len_image_path_subset = len(self.image_path_subset) 106 | self.image_path_subset = self._fix_list_multiple_of_batch_size(self.image_path_subset, batch_size) 107 | 108 | -------------------------------------------------------------------------------- /dataloader/paths.py: -------------------------------------------------------------------------------- 1 | from dataloader import dataset_base 2 | from dataloader import custom_transforms 3 | 4 | 5 | class PathsDataset(dataset_base.DatasetBase): 6 | 7 | def __init__(self, lmdb_handle, base_size, paths): 8 | super(PathsDataset, self).__init__(lmdb_handle, base_size) 9 | self.image_path_subset = paths 10 | 11 | def __getitem__(self, index): 12 | 13 | image_path = self.image_path_subset[index] 14 | loaded_npy = self.lmdb_handle.get_numpy_object(image_path) 15 | image = loaded_npy[:, :, 0:3] 16 | target = loaded_npy[:, :, 3] 17 | 18 | ret_dict = custom_transforms.transform_validation_sample(image, target) 19 | return ret_dict 20 | -------------------------------------------------------------------------------- /dataset/preprocessing-scripts/selections.py: -------------------------------------------------------------------------------- 1 | from tqdm import tqdm 2 | import os 3 | from pathlib import Path 4 | import random 5 | from multiprocessing import Pool 6 | from skimage.io import imread 7 | 8 | raw_files_location = "ViewAL/dataset/scannet-sample/raw/selections" 9 | seeds_segmentor_path = "seeds-revised/bin/Release/reseeds_cli.exe" 10 | splits_path = Path('ViewAL/dataset/scannet-sample/selections') 11 | 12 | def read_scene_list(path): 13 | with open(path, "r") as fptr: 14 | return [x.strip() for x in fptr.readlines() if x.strip() != ""] 15 | 16 | def write_frames_list(name, paths): 17 | with open((splits_path / f"{name}_frames.txt"), "w") as fptr: 18 | for x in paths: 19 | fptr.write(f"{x}\n") 20 | 21 | def create_splits(): 22 | 23 | train_scenes = read_scene_list(str(splits_path / "scenes_train.txt")) 24 | val_scenes = read_scene_list(str(splits_path / "scenes_val.txt")) 25 | test_scenes = read_scene_list(str(splits_path / "scenes_test.txt")) 26 | 27 | train_frames = [] 28 | val_frames = [] 29 | test_frames = [] 30 | 31 | for x in (raw_files_location / "color").iterdir(): 32 | # For scannet names - format = {sceneid_rescanid}_frameid 33 | if "_".join(x.name.split("_")[0:2]) in train_scenes: 34 | train_frames.append(x.name.split(".")[0]) 35 | elif "_".join(x.name.split("_")[0:2]) in val_scenes: 36 | val_frames.append(x.name.split(".")[0]) 37 | elif "_".join(x.name.split("_")[0:2]) in test_scenes: 38 | test_frames.append(x.name.split(".")[0]) 39 | 40 | print(len(train_frames), len(val_frames), len(test_frames)) 41 | 42 | write_frames_list("train", train_frames) 43 | write_frames_list("val", val_frames) 44 | write_frames_list("test", test_frames) 45 | 46 | def call(*popenargs, **kwargs): 47 | from subprocess import Popen, PIPE 48 | kwargs['stdout'] = PIPE 49 | kwargs['stderr'] = PIPE 50 | p = Popen(popenargs, **kwargs) 51 | stdout, stderr = p.communicate() 52 | if stdout: 53 | for line in stdout.decode("utf-8").strip().split("\n"): 54 | print(line) 55 | if stderr: 56 | for line in stderr.decode("utf-8").strip().split("\n"): 57 | print(line) 58 | return p.returncode 59 | 60 | def create_superpixel_segmentations(): 61 | all_args = "--spatial-weight 0.2 --superpixels 40 --iterations 10 --confidence 0.001" 62 | colordir_src = os.path.join(raw_files_location, "color") 63 | args = all_args.split(" ") 64 | with Pool(processes=8) as pool: 65 | arg_list = [] 66 | for c in tqdm(os.listdir(colordir_src)): 67 | color_base_name = c.split(".")[0] 68 | spx_target = os.path.join(raw_files_location, "superpixel", f"{color_base_name}.png") 69 | arg_list.append((seeds_segmentor_path, "--input", os.path.join(colordir_src, c), "--output", spx_target, 70 | args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], "--index")) 71 | pool.starmap(call, tqdm(arg_list)) 72 | 73 | 74 | def create_split_mixed(): 75 | list_of_frames = [x.split(".")[0] for x in os.listdir(os.path.join(raw_files_location, "color"))] 76 | train_frames = [list_of_frames[i] for i in random.sample(range(len(list_of_frames)), int(0.60 * len(list_of_frames)))] 77 | remaining_frames = [x for x in list_of_frames if x not in train_frames] 78 | val_frames = [remaining_frames[i] for i in random.sample(range(len(remaining_frames)), int(0.15 * len(list_of_frames)))] 79 | test_frames = [x for x in remaining_frames if x not in val_frames] 80 | print(len(train_frames)/len(list_of_frames), len(val_frames)/len(list_of_frames), len(test_frames)/len(list_of_frames)) 81 | with open(splits_path / "train_frames.txt", "w") as fptr: 82 | for x in train_frames: 83 | fptr.write(x+"\n") 84 | with open(splits_path / "val_frames.txt", "w") as fptr: 85 | for x in val_frames: 86 | fptr.write(x+"\n") 87 | with open(splits_path / "test_frames.txt", "w") as fptr: 88 | for x in test_frames: 89 | fptr.write(x+"\n") 90 | 91 | def create_seed_set(): 92 | train_frames = (splits_path / "train_frames.txt").read_text().split() 93 | seed_frames = [train_frames[i] for i in random.sample(range(len(train_frames)), int(0.05 * len(train_frames)))] 94 | print(len(seed_frames)) 95 | with open(splits_path / "seedset_0_frames.txt", "w") as fptr: 96 | for x in seed_frames: 97 | fptr.write(x.split(".")[0]+"\n") 98 | 99 | if __name__=='__main__': 100 | create_superpixel_segmentations() 101 | create_split_mixed() # or create_split() 102 | create_seed_set() 103 | -------------------------------------------------------------------------------- /dataset/preprocessing-scripts/to_lmdb.py: -------------------------------------------------------------------------------- 1 | import pickle 2 | import lmdb 3 | import os 4 | import glob 5 | from PIL import Image 6 | from pathlib import Path 7 | from tqdm import tqdm 8 | import numpy as np 9 | from scipy import ndimage 10 | 11 | 12 | def to_lmdb(root_path, lmdb_path): 13 | 14 | image_paths = [x.split(".")[0] for x in os.listdir(os.path.join(root_path, "color"))] 15 | print('#images: ', len(image_paths)) 16 | print("Generate LMDB to %s" % lmdb_path) 17 | 18 | image_size = Image.open(os.path.join(root_path, "color", f'{image_paths[0]}.jpg')).size 19 | pixels = image_size[0] * image_size[1] * len(image_paths) 20 | 21 | print("Pixels in split: ", pixels) 22 | 23 | map_size = pixels * 4 + 1500 * 320 * 240 * 4 24 | 25 | print("Estimated Size: ", map_size / (1024 * 1024 * 1024)) 26 | 27 | isdir = os.path.isdir(lmdb_path) 28 | 29 | db = lmdb.open(lmdb_path, subdir=isdir, map_size=map_size, readonly=False, meminit=False, map_async=True, writemap=True) 30 | 31 | txn = db.begin(write=True) 32 | 33 | key_list = [] 34 | 35 | for idx, path in tqdm(enumerate(image_paths)): 36 | jpg_path = os.path.join(root_path, 'color', f'{path}.jpg') 37 | png_path = os.path.join(root_path, 'label', f'{path}.png') 38 | image = np.array(Image.open(jpg_path).convert('RGB'), dtype=np.uint8) 39 | label = np.array(Image.open(png_path), dtype=np.uint8) 40 | label -= 1 41 | label[label == -1] = 255 42 | label[label >= 40] = 255 43 | 44 | txn.put(u'{}'.format(path).encode('ascii'), pickle.dumps(np.dstack((image, label)), protocol=3)) 45 | key_list.append(path) 46 | 47 | print('Committing..') 48 | txn.commit() 49 | 50 | print('Writing keys..') 51 | keys = [u'{}'.format(k).encode('ascii') for k in key_list] 52 | 53 | with db.begin(write=True) as txn: 54 | txn.put(b'__keys__', pickle.dumps(keys, protocol=3)) 55 | txn.put(b'__len__', pickle.dumps(len(keys), protocol=3)) 56 | 57 | print('Syncing..') 58 | db.sync() 59 | db.close() 60 | 61 | 62 | if __name__ == '__main__': 63 | PATH_TO_SELECTIONS = "ViewAL/dataset/scannet-sample/raw/selections" 64 | PATH_TO_LMDB = "ViewAL/dataset/scannet-sample/dataset.lmdb" 65 | to_lmdb(PATH_TO_SELECTIONS, PATH_TO_LMDB) -------------------------------------------------------------------------------- /dataset/scannet-sample/dataset.lmdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/dataset.lmdb -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/color/scene0007_00_000000.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/color/scene0007_00_000000.jpg -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/color/scene0007_00_000035.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/color/scene0007_00_000035.jpg -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/color/scene0007_00_000070.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/color/scene0007_00_000070.jpg -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/color/scene0007_00_000105.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/color/scene0007_00_000105.jpg -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/color/scene0007_00_000140.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/color/scene0007_00_000140.jpg -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/color/scene0007_00_000455.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/color/scene0007_00_000455.jpg -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/color/scene0007_00_000560.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/color/scene0007_00_000560.jpg -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/color/scene0007_00_000595.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/color/scene0007_00_000595.jpg -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/color/scene0007_00_000735.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/color/scene0007_00_000735.jpg -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/color/scene0007_00_000840.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/color/scene0007_00_000840.jpg -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/color/scene0014_00_000000.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/color/scene0014_00_000000.jpg -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/color/scene0014_00_000070.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/color/scene0014_00_000070.jpg -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/color/scene0014_00_000105.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/color/scene0014_00_000105.jpg -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/color/scene0014_00_000175.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/color/scene0014_00_000175.jpg -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/color/scene0014_00_000210.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/color/scene0014_00_000210.jpg -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/color/scene0014_00_000245.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/color/scene0014_00_000245.jpg -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/color/scene0014_00_000280.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/color/scene0014_00_000280.jpg -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/color/scene0014_00_000350.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/color/scene0014_00_000350.jpg -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/color/scene0014_00_000490.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/color/scene0014_00_000490.jpg -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/color/scene0014_00_000595.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/color/scene0014_00_000595.jpg -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/color/scene0014_00_000840.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/color/scene0014_00_000840.jpg -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/color/scene0014_00_000980.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/color/scene0014_00_000980.jpg -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/color/scene0014_00_001015.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/color/scene0014_00_001015.jpg -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/color/scene0014_00_001120.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/color/scene0014_00_001120.jpg -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/color/scene0014_00_001225.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/color/scene0014_00_001225.jpg -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/color/scene0014_00_001330.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/color/scene0014_00_001330.jpg -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/color/scene0014_00_001365.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/color/scene0014_00_001365.jpg -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/color/scene0014_00_001435.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/color/scene0014_00_001435.jpg -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/color/scene0014_00_001470.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/color/scene0014_00_001470.jpg -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/color/scene0014_00_001505.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/color/scene0014_00_001505.jpg -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/color/scene0014_00_001540.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/color/scene0014_00_001540.jpg -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/color/scene0014_00_001680.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/color/scene0014_00_001680.jpg -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/color/scene0014_00_001715.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/color/scene0014_00_001715.jpg -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/color/scene0014_00_001855.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/color/scene0014_00_001855.jpg -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/color/scene0014_00_001890.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/color/scene0014_00_001890.jpg -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/color/scene0014_00_001925.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/color/scene0014_00_001925.jpg -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/color/scene0014_00_002065.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/color/scene0014_00_002065.jpg -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/coverage_superpixel/scene0007_00.npy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/coverage_superpixel/scene0007_00.npy -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/coverage_superpixel/scene0014_00.npy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/coverage_superpixel/scene0014_00.npy -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/depth/scene0007_00_000000.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/depth/scene0007_00_000000.pgm -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/depth/scene0007_00_000035.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/depth/scene0007_00_000035.pgm -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/depth/scene0007_00_000070.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/depth/scene0007_00_000070.pgm -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/depth/scene0007_00_000105.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/depth/scene0007_00_000105.pgm -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/depth/scene0007_00_000140.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/depth/scene0007_00_000140.pgm -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/depth/scene0007_00_000455.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/depth/scene0007_00_000455.pgm -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/depth/scene0007_00_000560.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/depth/scene0007_00_000560.pgm -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/depth/scene0007_00_000595.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/depth/scene0007_00_000595.pgm -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/depth/scene0007_00_000735.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/depth/scene0007_00_000735.pgm -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/depth/scene0007_00_000840.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/depth/scene0007_00_000840.pgm -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/depth/scene0014_00_000000.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/depth/scene0014_00_000000.pgm -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/depth/scene0014_00_000070.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/depth/scene0014_00_000070.pgm -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/depth/scene0014_00_000105.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/depth/scene0014_00_000105.pgm -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/depth/scene0014_00_000175.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/depth/scene0014_00_000175.pgm -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/depth/scene0014_00_000210.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/depth/scene0014_00_000210.pgm -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/depth/scene0014_00_000245.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/depth/scene0014_00_000245.pgm -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/depth/scene0014_00_000280.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/depth/scene0014_00_000280.pgm -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/depth/scene0014_00_000350.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/depth/scene0014_00_000350.pgm -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/depth/scene0014_00_000490.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/depth/scene0014_00_000490.pgm -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/depth/scene0014_00_000595.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/depth/scene0014_00_000595.pgm -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/depth/scene0014_00_000840.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/depth/scene0014_00_000840.pgm -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/depth/scene0014_00_000980.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/depth/scene0014_00_000980.pgm -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/depth/scene0014_00_001015.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/depth/scene0014_00_001015.pgm -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/depth/scene0014_00_001120.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/depth/scene0014_00_001120.pgm -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/depth/scene0014_00_001225.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/depth/scene0014_00_001225.pgm -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/depth/scene0014_00_001330.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/depth/scene0014_00_001330.pgm -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/depth/scene0014_00_001365.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/depth/scene0014_00_001365.pgm -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/depth/scene0014_00_001435.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/depth/scene0014_00_001435.pgm -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/depth/scene0014_00_001470.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/depth/scene0014_00_001470.pgm -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/depth/scene0014_00_001505.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/depth/scene0014_00_001505.pgm -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/depth/scene0014_00_001540.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/depth/scene0014_00_001540.pgm -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/depth/scene0014_00_001680.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/depth/scene0014_00_001680.pgm -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/depth/scene0014_00_001715.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/depth/scene0014_00_001715.pgm -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/depth/scene0014_00_001855.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/depth/scene0014_00_001855.pgm -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/depth/scene0014_00_001890.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/depth/scene0014_00_001890.pgm -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/depth/scene0014_00_001925.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/depth/scene0014_00_001925.pgm -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/depth/scene0014_00_002065.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/depth/scene0014_00_002065.pgm -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/info/scene0007_00.txt: -------------------------------------------------------------------------------- 1 | m_versionNumber = 4 2 | m_sensorName = StructureSensor 3 | m_colorWidth = 1296 4 | m_colorHeight = 968 5 | m_depthWidth = 640 6 | m_depthHeight = 480 7 | m_depthShift = 1000 8 | m_calibrationColorIntrinsic = 1170.19 0 647.75 0 0 1170.19 483.75 0 0 0 1 0 0 0 0 1 9 | m_calibrationColorExtrinsic = 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 10 | m_calibrationDepthIntrinsic = 577.871 0 319.5 0 0 577.871 239.5 0 0 0 1 0 0 0 0 1 11 | m_calibrationDepthExtrinsic = 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 12 | m_frames.size = 1041 13 | -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/info/scene0014_00.txt: -------------------------------------------------------------------------------- 1 | m_versionNumber = 4 2 | m_sensorName = StructureSensor (calibrated) 3 | m_colorWidth = 1296 4 | m_colorHeight = 968 5 | m_depthWidth = 640 6 | m_depthHeight = 480 7 | m_depthShift = 1000 8 | m_calibrationColorIntrinsic = 1161.75 0 658.042 0 0 1159.11 486.467 0 0 0 1 0 0 0 0 1 9 | m_calibrationColorExtrinsic = 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 10 | m_calibrationDepthIntrinsic = 573.702 0 324.702 0 0 574.764 240.97 0 0 0 1 0 0 0 0 1 11 | m_calibrationDepthExtrinsic = 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 12 | m_frames.size = 2396 13 | -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/label/scene0007_00_000000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/label/scene0007_00_000000.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/label/scene0007_00_000035.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/label/scene0007_00_000035.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/label/scene0007_00_000070.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/label/scene0007_00_000070.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/label/scene0007_00_000105.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/label/scene0007_00_000105.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/label/scene0007_00_000140.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/label/scene0007_00_000140.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/label/scene0007_00_000455.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/label/scene0007_00_000455.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/label/scene0007_00_000560.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/label/scene0007_00_000560.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/label/scene0007_00_000595.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/label/scene0007_00_000595.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/label/scene0007_00_000735.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/label/scene0007_00_000735.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/label/scene0007_00_000840.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/label/scene0007_00_000840.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/label/scene0014_00_000000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/label/scene0014_00_000000.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/label/scene0014_00_000070.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/label/scene0014_00_000070.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/label/scene0014_00_000105.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/label/scene0014_00_000105.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/label/scene0014_00_000175.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/label/scene0014_00_000175.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/label/scene0014_00_000210.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/label/scene0014_00_000210.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/label/scene0014_00_000245.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/label/scene0014_00_000245.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/label/scene0014_00_000280.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/label/scene0014_00_000280.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/label/scene0014_00_000350.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/label/scene0014_00_000350.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/label/scene0014_00_000490.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/label/scene0014_00_000490.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/label/scene0014_00_000595.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/label/scene0014_00_000595.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/label/scene0014_00_000840.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/label/scene0014_00_000840.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/label/scene0014_00_000980.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/label/scene0014_00_000980.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/label/scene0014_00_001015.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/label/scene0014_00_001015.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/label/scene0014_00_001120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/label/scene0014_00_001120.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/label/scene0014_00_001225.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/label/scene0014_00_001225.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/label/scene0014_00_001330.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/label/scene0014_00_001330.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/label/scene0014_00_001365.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/label/scene0014_00_001365.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/label/scene0014_00_001435.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/label/scene0014_00_001435.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/label/scene0014_00_001470.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/label/scene0014_00_001470.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/label/scene0014_00_001505.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/label/scene0014_00_001505.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/label/scene0014_00_001540.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/label/scene0014_00_001540.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/label/scene0014_00_001680.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/label/scene0014_00_001680.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/label/scene0014_00_001715.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/label/scene0014_00_001715.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/label/scene0014_00_001855.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/label/scene0014_00_001855.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/label/scene0014_00_001890.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/label/scene0014_00_001890.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/label/scene0014_00_001925.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/label/scene0014_00_001925.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/label/scene0014_00_002065.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/label/scene0014_00_002065.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/pose/scene0007_00_000000.txt: -------------------------------------------------------------------------------- 1 | 0.645842 -0.099101 0.757012 3.72995 2 | -0.761541 -0.0131481 0.647984 1.43245 3 | -0.0542625 -0.994991 -0.083961 1.73354 4 | 0 0 0 1 -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/pose/scene0007_00_000035.txt: -------------------------------------------------------------------------------- 1 | 0.685103 -0.0843731 0.723543 3.72395 2 | -0.725927 0.0034535 0.687763 1.43307 3 | -0.0605274 -0.996428 -0.0588827 1.7467 4 | 0 0 0 1 -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/pose/scene0007_00_000070.txt: -------------------------------------------------------------------------------- 1 | 0.686685 -0.20956 0.696095 3.7556 2 | -0.724893 -0.125319 0.677366 1.47476 3 | -0.054715 -0.969732 -0.237963 1.60214 4 | 0 0 0 1 -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/pose/scene0007_00_000105.txt: -------------------------------------------------------------------------------- 1 | 0.735699 -0.15138 0.660175 3.74024 2 | -0.672472 -0.0469715 0.738631 1.42786 3 | -0.0808047 -0.987359 -0.136356 1.63603 4 | 0 0 0 1 -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/pose/scene0007_00_000140.txt: -------------------------------------------------------------------------------- 1 | 0.783894 -0.0839625 0.615191 3.3213 2 | -0.616015 0.018792 0.78751 1.41774 3 | -0.077682 -0.996292 -0.0369912 1.75668 4 | 0 0 0 1 -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/pose/scene0007_00_000455.txt: -------------------------------------------------------------------------------- 1 | -0.362613 0.386655 -0.847944 4.76974 2 | 0.931937 0.152554 -0.328969 1.89708 3 | 0.00215975 -0.909519 -0.415656 1.38969 4 | 0 0 0 1 -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/pose/scene0007_00_000560.txt: -------------------------------------------------------------------------------- 1 | -0.748894 0.142248 -0.647242 5.07693 2 | 0.662612 0.145833 -0.734627 1.82664 3 | -0.0101097 -0.979029 -0.203469 1.53711 4 | 0 0 0 1 -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/pose/scene0007_00_000595.txt: -------------------------------------------------------------------------------- 1 | -0.821282 0.0731555 -0.565812 5.39427 2 | 0.568897 0.0302148 -0.821853 1.86919 3 | -0.0430272 -0.996863 -0.0664328 1.60727 4 | 0 0 0 1 -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/pose/scene0007_00_000735.txt: -------------------------------------------------------------------------------- 1 | -0.287227 -0.198 0.937175 4.10005 2 | -0.956345 0.114331 -0.268947 1.73269 3 | -0.0538967 -0.973511 -0.222196 1.57776 4 | 0 0 0 1 -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/pose/scene0007_00_000840.txt: -------------------------------------------------------------------------------- 1 | 0.586954 -0.209397 0.782073 3.71003 2 | -0.805134 -0.0494088 0.591032 1.78703 3 | -0.0851191 -0.976581 -0.197594 1.60824 4 | 0 0 0 1 -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/pose/scene0014_00_000000.txt: -------------------------------------------------------------------------------- 1 | -0.566304 -0.590941 0.574533 2.14352 2 | -0.823945 0.423135 -0.376925 1.76012 3 | -0.0203646 -0.686838 -0.726526 1.34319 4 | 0 0 0 1 -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/pose/scene0014_00_000070.txt: -------------------------------------------------------------------------------- 1 | -0.98226 -0.136039 0.129072 2.13822 2 | -0.186735 0.646378 -0.739814 1.61678 3 | 0.0172144 -0.750792 -0.660314 1.37115 4 | 0 0 0 1 -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/pose/scene0014_00_000105.txt: -------------------------------------------------------------------------------- 1 | -0.98241 0.140166 -0.12339 2.31614 2 | 0.1866 0.711381 -0.677582 1.48111 3 | -0.00719646 -0.688687 -0.725023 1.36072 4 | 0 0 0 1 -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/pose/scene0014_00_000175.txt: -------------------------------------------------------------------------------- 1 | -0.966452 0.0337991 -0.254614 2.36903 2 | 0.256401 0.185429 -0.948617 1.25276 3 | 0.0151504 -0.982076 -0.187874 1.56179 4 | 0 0 0 1 -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/pose/scene0014_00_000210.txt: -------------------------------------------------------------------------------- 1 | -0.822955 0.0944601 -0.560199 2.34044 2 | 0.565669 0.227501 -0.79263 1.15754 3 | 0.0525741 -0.969186 -0.240656 1.55516 4 | 0 0 0 1 -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/pose/scene0014_00_000245.txt: -------------------------------------------------------------------------------- 1 | -0.51474 0.1805 -0.838131 2.28622 2 | 0.852394 0.212673 -0.477698 1.07716 3 | 0.0920231 -0.960307 -0.263328 1.53826 4 | 0 0 0 1 -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/pose/scene0014_00_000280.txt: -------------------------------------------------------------------------------- 1 | -0.604804 0.332558 -0.723614 2.23572 2 | 0.795873 0.284643 -0.534383 1.23378 3 | 0.0282581 -0.899102 -0.436827 1.46215 4 | 0 0 0 1 -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/pose/scene0014_00_000350.txt: -------------------------------------------------------------------------------- 1 | -0.989375 -0.0536302 0.135131 1.67979 2 | -0.13883 0.624452 -0.768626 1.08961 3 | -0.0431615 -0.77922 -0.625263 1.35476 4 | 0 0 0 1 -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/pose/scene0014_00_000490.txt: -------------------------------------------------------------------------------- 1 | -0.906788 0.0880617 -0.412287 2.46443 2 | 0.41783 0.317991 -0.851058 1.0543 3 | 0.0561582 -0.943995 -0.325145 1.5343 4 | 0 0 0 1 -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/pose/scene0014_00_000595.txt: -------------------------------------------------------------------------------- 1 | -0.780861 0.137716 -0.609336 2.09569 2 | 0.624521 0.19576 -0.756077 1.14725 3 | 0.0151599 -0.970934 -0.238868 1.55719 4 | 0 0 0 1 -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/pose/scene0014_00_000840.txt: -------------------------------------------------------------------------------- 1 | 0.297787 0.290366 -0.909402 2.10377 2 | 0.953053 -0.0356475 0.300699 0.819892 3 | 0.0548949 -0.956252 -0.287349 1.5641 4 | 0 0 0 1 -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/pose/scene0014_00_000980.txt: -------------------------------------------------------------------------------- 1 | -0.44635 0.462698 -0.765952 2.14704 2 | 0.881556 0.0803226 -0.465196 1.46206 3 | -0.153722 -0.882869 -0.443747 1.51349 4 | 0 0 0 1 -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/pose/scene0014_00_001015.txt: -------------------------------------------------------------------------------- 1 | -0.72462 0.157002 -0.671027 2.09077 2 | 0.68279 0.0315944 -0.729931 1.64755 3 | -0.0933999 -0.987093 -0.130094 1.58791 4 | 0 0 0 1 -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/pose/scene0014_00_001120.txt: -------------------------------------------------------------------------------- 1 | -0.949825 0.261192 -0.17208 1.69295 2 | 0.305519 0.656862 -0.68934 1.87438 3 | -0.0670175 -0.707327 -0.703703 1.5071 4 | 0 0 0 1 -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/pose/scene0014_00_001225.txt: -------------------------------------------------------------------------------- 1 | -0.870375 0.410938 -0.271252 0.990536 2 | 0.491285 0.761651 -0.422525 1.21974 3 | 0.0329675 -0.501017 -0.864809 1.30417 4 | 0 0 0 1 -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/pose/scene0014_00_001330.txt: -------------------------------------------------------------------------------- 1 | -0.966436 -0.229492 0.115478 0.611335 2 | -0.251643 0.75508 -0.605417 1.27807 3 | 0.0517437 -0.614156 -0.787487 1.39548 4 | 0 0 0 1 -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/pose/scene0014_00_001365.txt: -------------------------------------------------------------------------------- 1 | -0.977328 0.177332 -0.115684 0.716752 2 | 0.209582 0.887873 -0.409581 1.16997 3 | 0.0300802 -0.42454 -0.904909 1.25639 4 | 0 0 0 1 -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/pose/scene0014_00_001435.txt: -------------------------------------------------------------------------------- 1 | -0.733505 0.432957 -0.523946 0.899029 2 | 0.678031 0.519845 -0.519649 1.11625 3 | 0.0473851 -0.736417 -0.674867 1.28233 4 | 0 0 0 1 -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/pose/scene0014_00_001470.txt: -------------------------------------------------------------------------------- 1 | -0.324263 0.587679 -0.741274 0.748482 2 | 0.945739 0.218621 -0.240381 1.15482 3 | 0.0207911 -0.778998 -0.626682 1.43867 4 | 0 0 0 1 -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/pose/scene0014_00_001505.txt: -------------------------------------------------------------------------------- 1 | -0.0365244 0.52885 -0.847929 0.97731 2 | 0.998601 0.0517625 -0.0107303 1.28907 3 | 0.0382161 -0.847135 -0.530001 1.46526 4 | 0 0 0 1 -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/pose/scene0014_00_001540.txt: -------------------------------------------------------------------------------- 1 | -0.0532822 0.752995 -0.655866 0.597625 2 | 0.995208 -0.0138812 -0.096787 1.23598 3 | -0.0819844 -0.65788 -0.748647 1.67881 4 | 0 0 0 1 -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/pose/scene0014_00_001680.txt: -------------------------------------------------------------------------------- 1 | -0.994143 0.0370484 -0.101524 0.46908 2 | 0.0725655 0.924977 -0.37303 0.857865 3 | 0.0800873 -0.378212 -0.922248 1.43046 4 | 0 0 0 1 -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/pose/scene0014_00_001715.txt: -------------------------------------------------------------------------------- 1 | -0.995614 0.0550631 -0.0756387 0.532183 2 | 0.0749693 0.953201 -0.292895 0.923963 3 | 0.0559713 -0.297281 -0.953148 1.39829 4 | 0 0 0 1 -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/pose/scene0014_00_001855.txt: -------------------------------------------------------------------------------- 1 | 0.410857 -0.0452574 0.910576 0.660923 2 | -0.91167 -0.0123446 0.410737 1.35522 3 | -0.00734815 -0.998899 -0.0463317 1.56696 4 | 0 0 0 1 -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/pose/scene0014_00_001890.txt: -------------------------------------------------------------------------------- 1 | 0.348337 -0.0228221 0.937092 0.759747 2 | -0.936967 -0.0377507 0.347371 1.42677 3 | 0.0274481 -0.999027 -0.0345335 1.59162 4 | 0 0 0 1 -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/pose/scene0014_00_001925.txt: -------------------------------------------------------------------------------- 1 | 0.493952 -0.0223526 0.869202 1.17499 2 | -0.86872 0.0293573 0.494433 1.52671 3 | -0.0365692 -0.999319 -0.00491704 1.58981 4 | 0 0 0 1 -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/pose/scene0014_00_002065.txt: -------------------------------------------------------------------------------- 1 | -0.18819 -0.63887 0.745942 1.96977 2 | -0.981139 0.156446 -0.113537 1.73325 3 | -0.0441642 -0.75324 -0.656262 1.3604 4 | 0 0 0 1 -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/superpixel/scene0007_00_000000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/superpixel/scene0007_00_000000.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/superpixel/scene0007_00_000035.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/superpixel/scene0007_00_000035.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/superpixel/scene0007_00_000070.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/superpixel/scene0007_00_000070.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/superpixel/scene0007_00_000105.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/superpixel/scene0007_00_000105.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/superpixel/scene0007_00_000140.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/superpixel/scene0007_00_000140.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/superpixel/scene0007_00_000455.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/superpixel/scene0007_00_000455.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/superpixel/scene0007_00_000560.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/superpixel/scene0007_00_000560.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/superpixel/scene0007_00_000595.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/superpixel/scene0007_00_000595.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/superpixel/scene0007_00_000735.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/superpixel/scene0007_00_000735.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/superpixel/scene0007_00_000840.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/superpixel/scene0007_00_000840.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/superpixel/scene0014_00_000000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/superpixel/scene0014_00_000000.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/superpixel/scene0014_00_000070.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/superpixel/scene0014_00_000070.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/superpixel/scene0014_00_000105.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/superpixel/scene0014_00_000105.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/superpixel/scene0014_00_000175.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/superpixel/scene0014_00_000175.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/superpixel/scene0014_00_000210.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/superpixel/scene0014_00_000210.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/superpixel/scene0014_00_000245.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/superpixel/scene0014_00_000245.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/superpixel/scene0014_00_000280.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/superpixel/scene0014_00_000280.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/superpixel/scene0014_00_000350.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/superpixel/scene0014_00_000350.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/superpixel/scene0014_00_000490.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/superpixel/scene0014_00_000490.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/superpixel/scene0014_00_000595.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/superpixel/scene0014_00_000595.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/superpixel/scene0014_00_000840.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/superpixel/scene0014_00_000840.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/superpixel/scene0014_00_000980.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/superpixel/scene0014_00_000980.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/superpixel/scene0014_00_001015.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/superpixel/scene0014_00_001015.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/superpixel/scene0014_00_001120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/superpixel/scene0014_00_001120.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/superpixel/scene0014_00_001225.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/superpixel/scene0014_00_001225.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/superpixel/scene0014_00_001330.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/superpixel/scene0014_00_001330.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/superpixel/scene0014_00_001365.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/superpixel/scene0014_00_001365.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/superpixel/scene0014_00_001435.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/superpixel/scene0014_00_001435.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/superpixel/scene0014_00_001470.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/superpixel/scene0014_00_001470.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/superpixel/scene0014_00_001505.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/superpixel/scene0014_00_001505.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/superpixel/scene0014_00_001540.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/superpixel/scene0014_00_001540.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/superpixel/scene0014_00_001680.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/superpixel/scene0014_00_001680.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/superpixel/scene0014_00_001715.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/superpixel/scene0014_00_001715.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/superpixel/scene0014_00_001855.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/superpixel/scene0014_00_001855.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/superpixel/scene0014_00_001890.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/superpixel/scene0014_00_001890.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/superpixel/scene0014_00_001925.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/superpixel/scene0014_00_001925.png -------------------------------------------------------------------------------- /dataset/scannet-sample/raw/selections/superpixel/scene0014_00_002065.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/dataset/scannet-sample/raw/selections/superpixel/scene0014_00_002065.png -------------------------------------------------------------------------------- /dataset/scannet-sample/selections/seedset_0_frames.txt: -------------------------------------------------------------------------------- 1 | scene0007_00_000000 2 | -------------------------------------------------------------------------------- /dataset/scannet-sample/selections/test_frames.txt: -------------------------------------------------------------------------------- 1 | scene0014_00_001890 2 | scene0014_00_001925 3 | scene0014_00_002065 4 | scene0007_00_000735 5 | scene0007_00_000840 6 | -------------------------------------------------------------------------------- /dataset/scannet-sample/selections/train_frames.txt: -------------------------------------------------------------------------------- 1 | scene0007_00_000000 2 | scene0007_00_000035 3 | scene0007_00_000070 4 | scene0007_00_000105 5 | scene0007_00_000140 6 | scene0007_00_000455 7 | scene0007_00_000560 8 | scene0007_00_000595 9 | scene0014_00_000000 10 | scene0014_00_000070 11 | scene0014_00_000105 12 | scene0014_00_000175 13 | scene0014_00_000210 14 | scene0014_00_000245 15 | scene0014_00_000280 16 | scene0014_00_000350 17 | scene0014_00_000490 18 | scene0014_00_000595 19 | scene0014_00_000840 20 | scene0014_00_000980 21 | scene0014_00_001015 22 | scene0014_00_001120 23 | scene0014_00_001225 24 | scene0014_00_001330 25 | scene0014_00_001365 26 | scene0014_00_001435 27 | scene0014_00_001470 28 | scene0014_00_001505 29 | scene0014_00_001540 30 | scene0014_00_001680 31 | scene0014_00_001715 32 | scene0014_00_001855 33 | -------------------------------------------------------------------------------- /dataset/scannet-sample/selections/val_frames.txt: -------------------------------------------------------------------------------- 1 | scene0014_00_001890 2 | scene0014_00_001925 3 | scene0014_00_002065 4 | scene0007_00_000735 5 | scene0007_00_000840 6 | -------------------------------------------------------------------------------- /dataset/scannet/selections/seedset_0_frames.txt: -------------------------------------------------------------------------------- 1 | scene0010_00_000385 2 | scene0385_01_001295 3 | scene0511_00_000875 4 | scene0646_01_002205 5 | scene0604_01_000420 6 | scene0024_02_000595 7 | scene0313_01_000595 8 | scene0041_00_000385 9 | scene0250_00_000385 10 | scene0362_02_001050 11 | scene0105_01_000525 12 | scene0142_00_000945 13 | scene0089_00_000035 14 | scene0111_00_000280 15 | scene0411_01_000630 16 | scene0688_00_000280 17 | scene0646_01_000875 18 | scene0142_01_000700 19 | scene0602_00_000245 20 | scene0542_00_000315 21 | scene0590_00_002625 22 | scene0395_00_001750 23 | scene0232_01_001330 24 | scene0385_02_003360 25 | scene0604_02_000070 26 | scene0280_01_000140 27 | scene0212_00_001785 28 | scene0448_00_000350 29 | scene0261_02_001260 30 | scene0233_01_006300 31 | scene0385_02_001890 32 | scene0220_02_000840 33 | scene0590_01_000525 34 | scene0006_00_000700 35 | scene0600_00_000140 36 | scene0392_01_000245 37 | scene0079_00_000525 38 | scene0383_02_001470 39 | scene0582_00_000350 40 | scene0161_00_000000 41 | scene0320_00_000490 42 | scene0039_00_000770 43 | scene0129_00_000665 44 | scene0006_02_002625 45 | scene0261_02_000805 46 | scene0275_00_000210 47 | scene0388_00_000455 48 | scene0465_00_000875 49 | scene0195_01_000525 50 | scene0582_02_001610 51 | scene0411_01_001505 52 | scene0503_00_000770 53 | scene0097_00_000315 54 | scene0227_00_000665 55 | scene0517_01_002205 56 | scene0344_00_000455 57 | scene0281_00_000980 58 | scene0572_01_000805 59 | scene0395_00_001995 60 | scene0114_00_000700 61 | scene0332_00_000140 62 | scene0174_00_000910 63 | scene0610_00_002520 64 | scene0376_00_000770 65 | scene0654_01_000875 66 | scene0138_00_000210 67 | scene0564_00_002485 68 | scene0233_01_003220 69 | scene0385_00_000105 70 | scene0040_00_001050 71 | scene0542_00_000070 72 | scene0312_00_001050 73 | scene0177_02_000245 74 | scene0093_01_000070 75 | scene0055_01_000805 76 | scene0477_01_000665 77 | scene0294_01_001050 78 | scene0000_01_004200 79 | scene0418_02_000875 80 | scene0619_00_000735 81 | scene0206_00_000210 82 | scene0417_00_000665 83 | scene0250_00_003290 84 | scene0255_00_001435 85 | scene0262_00_002800 86 | scene0448_00_000385 87 | scene0320_00_002135 88 | scene0152_02_002170 89 | scene0584_00_000350 90 | scene0166_00_002170 91 | scene0274_01_000315 92 | scene0294_02_000070 93 | scene0233_00_001155 94 | scene0116_00_000945 95 | scene0060_00_001015 96 | scene0061_01_000210 97 | scene0628_02_000945 98 | scene0024_01_000000 99 | scene0092_00_000630 100 | scene0517_02_001995 101 | scene0261_01_002240 102 | scene0029_01_001505 103 | scene0092_00_001155 104 | scene0270_00_001505 105 | scene0297_00_000595 106 | scene0012_02_000840 107 | scene0137_01_000805 108 | scene0404_01_002765 109 | scene0533_01_000910 110 | scene0031_00_002450 111 | scene0262_01_001820 112 | scene0623_01_002135 113 | scene0096_02_000210 114 | scene0646_02_002205 115 | scene0270_00_000805 116 | scene0274_02_000385 117 | scene0335_02_001295 118 | scene0209_00_001015 119 | scene0676_01_001015 120 | scene0042_00_000140 121 | scene0557_00_001120 122 | scene0666_00_001995 123 | scene0612_00_000210 124 | scene0404_00_001120 125 | scene0286_00_003290 126 | scene0661_00_001610 127 | scene0163_01_000630 128 | scene0656_00_001435 129 | scene0209_01_001505 130 | scene0012_01_001015 131 | scene0006_00_001330 132 | scene0006_02_000595 133 | scene0452_00_002520 134 | scene0392_01_000700 135 | scene0297_01_000385 136 | scene0274_00_000350 137 | scene0396_01_000070 138 | scene0297_00_001015 139 | scene0252_00_000070 140 | scene0404_01_001435 141 | scene0206_02_001435 142 | scene0468_00_001575 143 | scene0250_01_000665 144 | scene0440_02_000735 145 | scene0541_02_001295 146 | scene0155_01_000735 147 | scene0399_01_001050 148 | scene0477_01_002275 149 | scene0028_00_000595 150 | scene0394_00_002450 151 | scene0265_01_000070 152 | scene0634_00_000245 153 | scene0613_01_002485 154 | scene0523_00_000245 155 | scene0530_00_000700 156 | scene0223_02_000490 157 | scene0210_01_000805 158 | scene0384_00_000980 159 | scene0589_02_001470 160 | scene0041_00_000525 161 | scene0116_01_001925 162 | scene0220_00_000910 163 | scene0163_00_000595 164 | scene0029_02_001120 165 | scene0509_02_000910 166 | scene0661_00_000630 167 | scene0174_00_002415 168 | scene0422_00_000070 169 | scene0126_02_001750 170 | scene0186_01_000035 171 | scene0223_01_000665 172 | scene0448_00_001085 173 | scene0674_00_000560 174 | scene0600_02_001120 175 | scene0385_02_002415 176 | scene0265_02_000630 177 | scene0121_01_000035 178 | scene0173_00_000070 179 | scene0261_01_003430 180 | scene0116_01_000945 181 | scene0294_00_001540 182 | scene0501_02_001540 183 | scene0294_02_001015 184 | scene0151_00_000630 185 | scene0457_01_000315 186 | scene0640_02_000420 187 | scene0219_00_000980 188 | scene0372_00_000840 189 | scene0327_00_000700 190 | scene0270_02_001400 191 | scene0622_01_000280 192 | scene0066_00_000490 193 | scene0105_02_000560 194 | scene0012_00_002240 195 | scene0415_02_000000 196 | scene0623_01_001750 197 | scene0199_00_000280 198 | scene0000_01_005390 199 | scene0029_01_000210 200 | scene0006_01_001365 201 | scene0152_01_001890 202 | scene0570_00_000210 203 | scene0085_00_000105 204 | scene0336_01_000105 205 | scene0656_01_001050 206 | scene0611_01_001260 207 | scene0465_01_004060 208 | scene0226_00_000455 209 | scene0276_01_001085 210 | scene0418_00_003325 211 | scene0190_00_000385 212 | scene0282_00_000350 213 | scene0166_02_000840 214 | scene0031_02_001330 215 | scene0166_02_000525 216 | scene0335_00_000245 217 | scene0348_01_000140 218 | scene0600_00_001225 219 | scene0452_00_001750 220 | scene0239_01_000350 221 | scene0061_01_001225 222 | scene0465_00_005530 223 | scene0282_01_001505 224 | scene0589_01_001155 225 | scene0661_00_000525 226 | scene0446_00_001330 227 | scene0122_00_000665 228 | scene0087_02_000945 229 | scene0212_01_000805 230 | scene0031_00_000175 231 | scene0465_01_001540 232 | scene0404_00_000420 233 | scene0477_01_003045 234 | scene0672_00_001190 235 | scene0261_02_001715 236 | scene0452_01_002205 237 | scene0212_01_000770 238 | scene0155_00_001470 239 | scene0449_02_000105 240 | scene0228_00_001365 241 | scene0582_01_000910 242 | scene0181_02_001400 243 | scene0447_01_000315 244 | scene0166_00_003220 245 | scene0523_00_000455 246 | scene0111_01_001785 247 | scene0206_02_001225 248 | scene0640_02_001505 249 | scene0335_02_000105 250 | scene0255_02_001015 251 | scene0136_02_001260 252 | scene0600_01_000455 253 | scene0141_00_000770 254 | scene0211_00_000630 255 | scene0404_02_001260 256 | scene0459_01_000210 257 | scene0509_02_000315 258 | scene0358_00_002100 259 | scene0101_01_000665 260 | scene0679_00_002170 261 | scene0124_01_001190 262 | scene0012_01_001435 263 | scene0554_00_001715 264 | scene0541_01_000175 265 | scene0447_00_000490 266 | scene0404_00_001435 267 | scene0012_00_003325 268 | scene0233_00_001785 269 | scene0181_01_000245 270 | scene0078_02_000420 271 | scene0677_02_000070 272 | scene0413_00_001785 273 | scene0087_02_000280 274 | scene0523_01_001645 275 | scene0525_01_000035 276 | scene0335_00_002345 277 | scene0252_00_000175 278 | scene0151_01_002695 279 | scene0209_00_001855 280 | scene0024_01_001295 281 | scene0029_00_001260 282 | scene0197_01_000980 283 | scene0667_00_001435 284 | scene0489_01_000490 285 | scene0006_02_002485 286 | scene0062_01_000000 287 | scene0035_01_000105 288 | scene0000_01_000455 289 | scene0114_01_000840 290 | scene0457_00_001400 291 | scene0294_00_002800 292 | scene0421_01_000210 293 | scene0631_01_000175 294 | scene0282_00_000735 295 | scene0000_00_002240 296 | scene0024_01_001470 297 | scene0000_01_002520 298 | scene0096_02_000875 299 | scene0698_01_000595 300 | scene0667_02_002485 301 | scene0589_02_001680 302 | scene0572_01_000770 303 | scene0492_01_000490 304 | scene0590_01_001085 305 | scene0233_00_005845 306 | scene0523_02_000140 307 | scene0009_02_000490 308 | scene0233_01_007945 309 | scene0572_01_000735 310 | scene0261_00_004340 311 | scene0401_00_000280 312 | scene0654_01_001505 313 | scene0317_01_000595 314 | scene0022_00_001050 315 | scene0457_01_002065 316 | scene0662_01_000735 317 | scene0408_00_001995 318 | scene0667_02_001120 319 | scene0280_02_001435 320 | scene0486_00_000420 321 | scene0158_01_000875 322 | scene0679_01_000630 323 | scene0451_02_001540 324 | scene0667_00_002870 325 | scene0434_01_000490 326 | scene0421_02_001820 327 | scene0472_02_000105 328 | scene0294_01_001260 329 | scene0013_00_000385 330 | scene0274_00_000385 331 | scene0024_00_002065 332 | scene0002_00_001085 333 | scene0613_00_002660 334 | scene0396_01_001155 335 | scene0477_00_004340 336 | scene0404_01_003220 337 | scene0195_00_000210 338 | scene0418_01_001085 339 | scene0452_01_001575 340 | scene0174_01_000000 341 | scene0420_02_001120 342 | scene0005_00_000245 343 | scene0667_00_003815 344 | scene0421_02_001015 345 | scene0448_01_002170 346 | scene0211_02_001575 347 | scene0223_02_001050 348 | scene0610_00_001120 349 | scene0192_00_000805 350 | scene0320_01_002100 351 | scene0233_00_004095 352 | scene0523_00_000105 353 | scene0320_00_003850 354 | scene0087_02_000630 355 | scene0276_01_000805 356 | scene0667_02_001645 357 | -------------------------------------------------------------------------------- /model/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nihalsid/ViewAL/7969d9c32fc7d0ff43dbb3021fd6645e67725257/model/__init__.py -------------------------------------------------------------------------------- /model/aspp.py: -------------------------------------------------------------------------------- 1 | import math 2 | import torch 3 | import torch.nn as nn 4 | import torch.nn.functional as F 5 | from model.sync_batchnorm.batchnorm import SynchronizedBatchNorm2d 6 | 7 | 8 | class _ASPPModule(nn.Module): 9 | 10 | def __init__(self, inplanes, planes, kernel_size, padding, dilation, BatchNorm): 11 | super(_ASPPModule, self).__init__() 12 | self.atrous_conv = nn.Conv2d(inplanes, planes, kernel_size=kernel_size, 13 | stride=1, padding=padding, dilation=dilation, bias=False) 14 | self.bn = BatchNorm(planes) 15 | self.relu = nn.ReLU() 16 | 17 | self._init_weight() 18 | 19 | def forward(self, x): 20 | x = self.atrous_conv(x) 21 | x = self.bn(x) 22 | 23 | return self.relu(x) 24 | 25 | def _init_weight(self): 26 | for m in self.modules(): 27 | if isinstance(m, nn.Conv2d): 28 | torch.nn.init.kaiming_normal_(m.weight) 29 | elif isinstance(m, SynchronizedBatchNorm2d): 30 | m.weight.data.fill_(1) 31 | m.bias.data.zero_() 32 | elif isinstance(m, nn.BatchNorm2d): 33 | m.weight.data.fill_(1) 34 | m.bias.data.zero_() 35 | 36 | 37 | class ASPP(nn.Module): 38 | 39 | def __init__(self, backbone, output_stride, BatchNorm): 40 | super(ASPP, self).__init__() 41 | if backbone == 'drn': 42 | inplanes = 512 43 | elif backbone == 'mobilenet': 44 | inplanes = 320 45 | else: 46 | inplanes = 2048 47 | if output_stride == 16: 48 | dilations = [1, 6, 12, 18] 49 | elif output_stride == 8: 50 | dilations = [1, 12, 24, 36] 51 | else: 52 | raise NotImplementedError 53 | 54 | self.aspp1 = _ASPPModule(inplanes, 256, 1, padding=0, dilation=dilations[0], BatchNorm=BatchNorm) 55 | self.aspp2 = _ASPPModule(inplanes, 256, 3, padding=dilations[1], dilation=dilations[1], BatchNorm=BatchNorm) 56 | self.aspp3 = _ASPPModule(inplanes, 256, 3, padding=dilations[2], dilation=dilations[2], BatchNorm=BatchNorm) 57 | self.aspp4 = _ASPPModule(inplanes, 256, 3, padding=dilations[3], dilation=dilations[3], BatchNorm=BatchNorm) 58 | 59 | self.global_avg_pool = nn.Sequential(nn.AdaptiveAvgPool2d((1, 1)), 60 | nn.Conv2d(inplanes, 256, 1, stride=1, bias=False), 61 | BatchNorm(256), 62 | nn.ReLU()) 63 | self.conv1 = nn.Conv2d(1280, 256, 1, bias=False) 64 | self.bn1 = BatchNorm(256) 65 | self.relu = nn.ReLU() 66 | self.dropout = nn.Dropout(0.5) 67 | self._init_weight() 68 | 69 | def forward(self, x): 70 | x1 = self.aspp1(x) 71 | x2 = self.aspp2(x) 72 | x3 = self.aspp3(x) 73 | x4 = self.aspp4(x) 74 | x5 = self.global_avg_pool(x) 75 | x5 = F.interpolate(x5, size=x4.size()[2:], mode='bilinear', align_corners=True) 76 | x = torch.cat((x1, x2, x3, x4, x5), dim=1) 77 | 78 | x = self.conv1(x) 79 | x = self.bn1(x) 80 | x = self.relu(x) 81 | 82 | return self.dropout(x) 83 | 84 | def _init_weight(self): 85 | for m in self.modules(): 86 | if isinstance(m, nn.Conv2d): 87 | torch.nn.init.kaiming_normal_(m.weight) 88 | elif isinstance(m, SynchronizedBatchNorm2d): 89 | m.weight.data.fill_(1) 90 | m.bias.data.zero_() 91 | elif isinstance(m, nn.BatchNorm2d): 92 | m.weight.data.fill_(1) 93 | m.bias.data.zero_() 94 | 95 | 96 | def build_aspp(backbone, output_stride, BatchNorm): 97 | return ASPP(backbone, output_stride, BatchNorm) 98 | -------------------------------------------------------------------------------- /model/backbone/__init__.py: -------------------------------------------------------------------------------- 1 | from model.backbone import resnet, xception, drn, mobilenet 2 | 3 | 4 | def build_backbone(backbone, output_stride, BatchNorm, mc_dropout): 5 | if backbone == 'resnet': 6 | return resnet.ResNet101(output_stride, BatchNorm) 7 | elif backbone == 'xception': 8 | return xception.AlignedXception(output_stride, BatchNorm) 9 | elif backbone == 'drn': 10 | return drn.drn_d_54(BatchNorm) 11 | elif backbone == 'mobilenet': 12 | return mobilenet.MobileNetV2(output_stride, BatchNorm, mc_dropout=mc_dropout) 13 | else: 14 | raise NotImplementedError 15 | -------------------------------------------------------------------------------- /model/backbone/mobilenet.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn.functional as F 3 | import torch.nn as nn 4 | import math 5 | from model.sync_batchnorm.batchnorm import SynchronizedBatchNorm2d 6 | import torch.utils.model_zoo as model_zoo 7 | import constants 8 | 9 | 10 | def conv_bn(inp, oup, stride, BatchNorm): 11 | return nn.Sequential( 12 | nn.Conv2d(inp, oup, 3, stride, 1, bias=False), 13 | BatchNorm(oup), 14 | nn.ReLU6(inplace=True) 15 | ) 16 | 17 | 18 | def fixed_padding(inputs, kernel_size, dilation): 19 | kernel_size_effective = kernel_size + (kernel_size - 1) * (dilation - 1) 20 | pad_total = kernel_size_effective - 1 21 | pad_beg = pad_total // 2 22 | pad_end = pad_total - pad_beg 23 | padded_inputs = F.pad(inputs, (pad_beg, pad_end, pad_beg, pad_end)) 24 | return padded_inputs 25 | 26 | 27 | class InvertedResidual(nn.Module): 28 | 29 | def __init__(self, inp, oup, stride, dilation, expand_ratio, BatchNorm): 30 | super(InvertedResidual, self).__init__() 31 | self.stride = stride 32 | assert stride in [1, 2] 33 | 34 | hidden_dim = round(inp * expand_ratio) 35 | self.use_res_connect = self.stride == 1 and inp == oup 36 | self.kernel_size = 3 37 | self.dilation = dilation 38 | 39 | if expand_ratio == 1: 40 | self.conv = nn.Sequential( 41 | # dw 42 | nn.Conv2d(hidden_dim, hidden_dim, 3, stride, 0, dilation, groups=hidden_dim, bias=False), 43 | BatchNorm(hidden_dim), 44 | nn.ReLU6(inplace=True), 45 | # pw-linear 46 | nn.Conv2d(hidden_dim, oup, 1, 1, 0, 1, 1, bias=False), 47 | BatchNorm(oup), 48 | ) 49 | else: 50 | self.conv = nn.Sequential( 51 | # pw 52 | nn.Conv2d(inp, hidden_dim, 1, 1, 0, 1, bias=False), 53 | BatchNorm(hidden_dim), 54 | nn.ReLU6(inplace=True), 55 | # dw 56 | nn.Conv2d(hidden_dim, hidden_dim, 3, stride, 0, dilation, groups=hidden_dim, bias=False), 57 | BatchNorm(hidden_dim), 58 | nn.ReLU6(inplace=True), 59 | # pw-linear 60 | nn.Conv2d(hidden_dim, oup, 1, 1, 0, 1, bias=False), 61 | BatchNorm(oup), 62 | ) 63 | 64 | def forward(self, x): 65 | x_pad = fixed_padding(x, self.kernel_size, dilation=self.dilation) 66 | if self.use_res_connect: 67 | x = x + self.conv(x_pad) 68 | else: 69 | x = self.conv(x_pad) 70 | return x 71 | 72 | 73 | class MobileNetV2(nn.Module): 74 | 75 | def __init__(self, output_stride=8, BatchNorm=None, width_mult=1., pretrained=True, mc_dropout=False): 76 | super(MobileNetV2, self).__init__() 77 | block = InvertedResidual 78 | input_channel = 32 79 | current_stride = 1 80 | rate = 1 81 | interverted_residual_setting = [ 82 | # t, c, n, s 83 | [1, 16, 1, 1], 84 | [6, 24, 2, 2], 85 | [6, 32, 3, 2], 86 | [6, 64, 4, 2], 87 | [6, 96, 3, 1], 88 | [6, 160, 3, 2], 89 | [6, 320, 1, 1], 90 | ] 91 | 92 | # building first layer 93 | input_channel = int(input_channel * width_mult) 94 | self.features = [conv_bn(3, input_channel, 2, BatchNorm)] 95 | current_stride *= 2 96 | # building inverted residual blocks 97 | for t, c, n, s in interverted_residual_setting: 98 | if current_stride == output_stride: 99 | stride = 1 100 | dilation = rate 101 | rate *= s 102 | else: 103 | stride = s 104 | dilation = 1 105 | current_stride *= s 106 | output_channel = int(c * width_mult) 107 | for i in range(n): 108 | if i == 0: 109 | self.features.append(block(input_channel, output_channel, stride, dilation, t, BatchNorm)) 110 | else: 111 | self.features.append(block(input_channel, output_channel, 1, dilation, t, BatchNorm)) 112 | input_channel = output_channel 113 | 114 | if mc_dropout: 115 | self.features.append(nn.Dropout2d(p=constants.MC_DROPOUT_RATE)) 116 | 117 | self.features = nn.Sequential(*self.features) 118 | self._initialize_weights() 119 | 120 | if pretrained: 121 | self._load_pretrained_model() 122 | 123 | self.low_level_features = self.features[0:4] 124 | self.high_level_features = self.features[4:] 125 | self.dropout = nn.Dropout2d(p=constants.MC_DROPOUT_RATE) 126 | self.mc_dropout = mc_dropout 127 | 128 | def forward(self, x): 129 | low_level_feat = self.low_level_features(x) 130 | x = self.high_level_features(low_level_feat) 131 | if self.mc_dropout: 132 | low_level_feat = self.dropout(low_level_feat) 133 | return x, low_level_feat 134 | 135 | def _load_pretrained_model(self): 136 | pretrain_dict = model_zoo.load_url('http://jeff95.me/models/mobilenet_v2-6a65762b.pth') 137 | model_dict = {} 138 | state_dict = self.state_dict() 139 | for k, v in pretrain_dict.items(): 140 | if k in state_dict: 141 | model_dict[k] = v 142 | state_dict.update(model_dict) 143 | self.load_state_dict(state_dict) 144 | 145 | def _initialize_weights(self): 146 | for m in self.modules(): 147 | if isinstance(m, nn.Conv2d): 148 | # n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels 149 | # m.weight.data.normal_(0, math.sqrt(2. / n)) 150 | torch.nn.init.kaiming_normal_(m.weight) 151 | elif isinstance(m, SynchronizedBatchNorm2d): 152 | m.weight.data.fill_(1) 153 | m.bias.data.zero_() 154 | elif isinstance(m, nn.BatchNorm2d): 155 | m.weight.data.fill_(1) 156 | m.bias.data.zero_() 157 | 158 | if __name__ == "__main__": 159 | input = torch.rand(1, 3, 512, 512) 160 | model = MobileNetV2(output_stride=16, BatchNorm=nn.BatchNorm2d) 161 | output, low_level_feat = model(input) 162 | print(output.size()) 163 | print(low_level_feat.size()) 164 | -------------------------------------------------------------------------------- /model/backbone/resnet.py: -------------------------------------------------------------------------------- 1 | import math 2 | import torch.nn as nn 3 | import torch.utils.model_zoo as model_zoo 4 | from model.sync_batchnorm.batchnorm import SynchronizedBatchNorm2d 5 | 6 | 7 | class Bottleneck(nn.Module): 8 | expansion = 4 9 | 10 | def __init__(self, inplanes, planes, stride=1, dilation=1, downsample=None, BatchNorm=None): 11 | super(Bottleneck, self).__init__() 12 | self.conv1 = nn.Conv2d(inplanes, planes, kernel_size=1, bias=False) 13 | self.bn1 = BatchNorm(planes) 14 | self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=stride, 15 | dilation=dilation, padding=dilation, bias=False) 16 | self.bn2 = BatchNorm(planes) 17 | self.conv3 = nn.Conv2d(planes, planes * 4, kernel_size=1, bias=False) 18 | self.bn3 = BatchNorm(planes * 4) 19 | self.relu = nn.ReLU(inplace=True) 20 | self.downsample = downsample 21 | self.stride = stride 22 | self.dilation = dilation 23 | 24 | def forward(self, x): 25 | residual = x 26 | 27 | out = self.conv1(x) 28 | out = self.bn1(out) 29 | out = self.relu(out) 30 | 31 | out = self.conv2(out) 32 | out = self.bn2(out) 33 | out = self.relu(out) 34 | 35 | out = self.conv3(out) 36 | out = self.bn3(out) 37 | 38 | if self.downsample is not None: 39 | residual = self.downsample(x) 40 | 41 | out += residual 42 | out = self.relu(out) 43 | 44 | return out 45 | 46 | 47 | class ResNet(nn.Module): 48 | 49 | def __init__(self, block, layers, output_stride, BatchNorm, pretrained=True): 50 | self.inplanes = 64 51 | super(ResNet, self).__init__() 52 | blocks = [1, 2, 4] 53 | if output_stride == 16: 54 | strides = [1, 2, 2, 1] 55 | dilations = [1, 1, 1, 2] 56 | elif output_stride == 8: 57 | strides = [1, 2, 1, 1] 58 | dilations = [1, 1, 2, 4] 59 | else: 60 | raise NotImplementedError 61 | 62 | # Modules 63 | self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3, 64 | bias=False) 65 | self.bn1 = BatchNorm(64) 66 | self.relu = nn.ReLU(inplace=True) 67 | self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1) 68 | 69 | self.layer1 = self._make_layer(block, 64, layers[0], stride=strides[0], dilation=dilations[0], BatchNorm=BatchNorm) 70 | self.layer2 = self._make_layer(block, 128, layers[1], stride=strides[1], dilation=dilations[1], BatchNorm=BatchNorm) 71 | self.layer3 = self._make_layer(block, 256, layers[2], stride=strides[2], dilation=dilations[2], BatchNorm=BatchNorm) 72 | self.layer4 = self._make_MG_unit(block, 512, blocks=blocks, stride=strides[3], dilation=dilations[3], BatchNorm=BatchNorm) 73 | # self.layer4 = self._make_layer(block, 512, layers[3], stride=strides[3], dilation=dilations[3], BatchNorm=BatchNorm) 74 | self._init_weight() 75 | 76 | if pretrained: 77 | self._load_pretrained_model() 78 | 79 | def _make_layer(self, block, planes, blocks, stride=1, dilation=1, BatchNorm=None): 80 | downsample = None 81 | if stride != 1 or self.inplanes != planes * block.expansion: 82 | downsample = nn.Sequential( 83 | nn.Conv2d(self.inplanes, planes * block.expansion, 84 | kernel_size=1, stride=stride, bias=False), 85 | BatchNorm(planes * block.expansion), 86 | ) 87 | 88 | layers = [] 89 | layers.append(block(self.inplanes, planes, stride, dilation, downsample, BatchNorm)) 90 | self.inplanes = planes * block.expansion 91 | for i in range(1, blocks): 92 | layers.append(block(self.inplanes, planes, dilation=dilation, BatchNorm=BatchNorm)) 93 | 94 | return nn.Sequential(*layers) 95 | 96 | def _make_MG_unit(self, block, planes, blocks, stride=1, dilation=1, BatchNorm=None): 97 | downsample = None 98 | if stride != 1 or self.inplanes != planes * block.expansion: 99 | downsample = nn.Sequential( 100 | nn.Conv2d(self.inplanes, planes * block.expansion, 101 | kernel_size=1, stride=stride, bias=False), 102 | BatchNorm(planes * block.expansion), 103 | ) 104 | 105 | layers = [] 106 | layers.append(block(self.inplanes, planes, stride, dilation=blocks[0] * dilation, 107 | downsample=downsample, BatchNorm=BatchNorm)) 108 | self.inplanes = planes * block.expansion 109 | for i in range(1, len(blocks)): 110 | layers.append(block(self.inplanes, planes, stride=1, 111 | dilation=blocks[i] * dilation, BatchNorm=BatchNorm)) 112 | 113 | return nn.Sequential(*layers) 114 | 115 | def forward(self, input): 116 | x = self.conv1(input) 117 | x = self.bn1(x) 118 | x = self.relu(x) 119 | x = self.maxpool(x) 120 | 121 | x = self.layer1(x) 122 | low_level_feat = x 123 | x = self.layer2(x) 124 | x = self.layer3(x) 125 | x = self.layer4(x) 126 | return x, low_level_feat 127 | 128 | def _init_weight(self): 129 | for m in self.modules(): 130 | if isinstance(m, nn.Conv2d): 131 | n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels 132 | m.weight.data.normal_(0, math.sqrt(2. / n)) 133 | elif isinstance(m, SynchronizedBatchNorm2d): 134 | m.weight.data.fill_(1) 135 | m.bias.data.zero_() 136 | elif isinstance(m, nn.BatchNorm2d): 137 | m.weight.data.fill_(1) 138 | m.bias.data.zero_() 139 | 140 | def _load_pretrained_model(self): 141 | pretrain_dict = model_zoo.load_url('https://download.pytorch.org/models/resnet101-5d3b4d8f.pth') 142 | model_dict = {} 143 | state_dict = self.state_dict() 144 | for k, v in pretrain_dict.items(): 145 | if k in state_dict: 146 | model_dict[k] = v 147 | state_dict.update(model_dict) 148 | self.load_state_dict(state_dict) 149 | 150 | 151 | def ResNet101(output_stride, BatchNorm, pretrained=True): 152 | """Constructs a ResNet-101 model. 153 | Args: 154 | pretrained (bool): If True, returns a model pre-trained on ImageNet 155 | """ 156 | model = ResNet(Bottleneck, [3, 4, 23, 3], output_stride, BatchNorm, pretrained=pretrained) 157 | return model 158 | 159 | if __name__ == "__main__": 160 | import torch 161 | model = ResNet101(BatchNorm=nn.BatchNorm2d, pretrained=True, output_stride=8) 162 | input = torch.rand(1, 3, 512, 512) 163 | output, low_level_feat = model(input) 164 | print(output.size()) 165 | print(low_level_feat.size()) 166 | -------------------------------------------------------------------------------- /model/decoder.py: -------------------------------------------------------------------------------- 1 | import math 2 | import torch 3 | import torch.nn as nn 4 | import torch.nn.functional as F 5 | from model.sync_batchnorm.batchnorm import SynchronizedBatchNorm2d 6 | import constants 7 | 8 | 9 | class Decoder(nn.Module): 10 | 11 | def __init__(self, num_classes, backbone, BatchNorm): 12 | super(Decoder, self).__init__() 13 | if backbone == 'resnet' or backbone == 'drn': 14 | low_level_inplanes = 256 15 | elif backbone == 'xception': 16 | low_level_inplanes = 128 17 | elif backbone == 'mobilenet': 18 | low_level_inplanes = 24 19 | else: 20 | raise NotImplementedError 21 | 22 | self.conv1 = nn.Conv2d(low_level_inplanes, 48, 1, bias=False) 23 | self.bn1 = BatchNorm(48) 24 | self.relu = nn.ReLU() 25 | self.last_conv = nn.Sequential(nn.Conv2d(304, 256, kernel_size=3, stride=1, padding=1, bias=False), 26 | BatchNorm(256), 27 | nn.ReLU(), 28 | nn.Dropout(0.5), 29 | nn.Conv2d(256, 256, kernel_size=3, stride=1, padding=1, bias=False), 30 | BatchNorm(256), 31 | nn.ReLU(), 32 | nn.Dropout(constants.MC_DROPOUT_RATE), 33 | nn.Conv2d(256, num_classes, kernel_size=1, stride=1)) 34 | self._init_weight() 35 | 36 | def forward(self, x, low_level_feat): 37 | low_level_feat = self.conv1(low_level_feat) 38 | low_level_feat = self.bn1(low_level_feat) 39 | low_level_feat = self.relu(low_level_feat) 40 | 41 | x = F.interpolate(x, size=low_level_feat.size()[2:], mode='bilinear', align_corners=True) 42 | second_to_last_features = torch.cat((x, low_level_feat), dim=1) 43 | x = self.last_conv(second_to_last_features) 44 | 45 | return x, second_to_last_features 46 | 47 | def _init_weight(self): 48 | for m in self.modules(): 49 | if isinstance(m, nn.Conv2d): 50 | torch.nn.init.kaiming_normal_(m.weight) 51 | elif isinstance(m, SynchronizedBatchNorm2d): 52 | m.weight.data.fill_(1) 53 | m.bias.data.zero_() 54 | elif isinstance(m, nn.BatchNorm2d): 55 | m.weight.data.fill_(1) 56 | m.bias.data.zero_() 57 | 58 | 59 | def build_decoder(num_classes, backbone, BatchNorm): 60 | return Decoder(num_classes, backbone, BatchNorm) 61 | -------------------------------------------------------------------------------- /model/deeplab.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | import torch.nn.functional as F 4 | from model.sync_batchnorm.batchnorm import SynchronizedBatchNorm2d 5 | from model.aspp import build_aspp 6 | from model.decoder import build_decoder 7 | from model.backbone import build_backbone 8 | 9 | 10 | class DeepLab(nn.Module): 11 | 12 | def __init__(self, backbone='resnet', output_stride=16, num_classes=21, 13 | sync_bn=False, freeze_bn=False, mc_dropout=False): 14 | super(DeepLab, self).__init__() 15 | if backbone == 'drn': 16 | output_stride = 8 17 | 18 | if sync_bn == True: 19 | BatchNorm = SynchronizedBatchNorm2d 20 | else: 21 | BatchNorm = nn.BatchNorm2d 22 | 23 | self.backbone = build_backbone(backbone, output_stride, BatchNorm, mc_dropout=mc_dropout) 24 | self.aspp = build_aspp(backbone, output_stride, BatchNorm) 25 | self.decoder = build_decoder(num_classes, backbone, BatchNorm) 26 | self.return_features = False 27 | 28 | if freeze_bn: 29 | self.freeze_bn() 30 | 31 | def set_return_features(self, return_features): 32 | self.return_features = return_features 33 | 34 | def forward(self, input): 35 | x, low_level_feat = self.backbone(input) 36 | x = self.aspp(x) 37 | x, features = self.decoder(x, low_level_feat) 38 | x = F.interpolate(x, size=input.size()[2:], mode='bilinear', align_corners=True) 39 | if self.return_features: 40 | return x, features 41 | return x 42 | 43 | def freeze_bn(self): 44 | for m in self.modules(): 45 | if isinstance(m, SynchronizedBatchNorm2d): 46 | m.eval() 47 | elif isinstance(m, nn.BatchNorm2d): 48 | m.eval() 49 | 50 | def get_1x_lr_params(self): 51 | modules = [self.backbone] 52 | for i in range(len(modules)): 53 | for m in modules[i].named_modules(): 54 | if isinstance(m[1], nn.Conv2d) or isinstance(m[1], SynchronizedBatchNorm2d) \ 55 | or isinstance(m[1], nn.BatchNorm2d): 56 | for p in m[1].parameters(): 57 | if p.requires_grad: 58 | yield p 59 | 60 | def get_10x_lr_params(self): 61 | modules = [self.aspp, self.decoder] 62 | for i in range(len(modules)): 63 | for m in modules[i].named_modules(): 64 | if isinstance(m[1], nn.Conv2d) or isinstance(m[1], SynchronizedBatchNorm2d) \ 65 | or isinstance(m[1], nn.BatchNorm2d): 66 | for p in m[1].parameters(): 67 | if p.requires_grad: 68 | yield p 69 | 70 | 71 | if __name__ == "__main__": 72 | model = DeepLab(backbone='mobilenet', output_stride=16) 73 | model.eval() 74 | input = torch.rand(1, 3, 513, 513) 75 | output = model(input) 76 | print(output.size()) 77 | -------------------------------------------------------------------------------- /model/sync_batchnorm/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # File : __init__.py 3 | # Author : Jiayuan Mao 4 | # Email : maojiayuan@gmail.com 5 | # Date : 27/01/2018 6 | # 7 | # This file is part of Synchronized-BatchNorm-PyTorch. 8 | # https://github.com/vacancy/Synchronized-BatchNorm-PyTorch 9 | # Distributed under MIT License. 10 | 11 | from .batchnorm import SynchronizedBatchNorm1d, SynchronizedBatchNorm2d, SynchronizedBatchNorm3d 12 | from .replicate import DataParallelWithCallback, patch_replication_callback -------------------------------------------------------------------------------- /model/sync_batchnorm/comm.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # File : comm.py 3 | # Author : Jiayuan Mao 4 | # Email : maojiayuan@gmail.com 5 | # Date : 27/01/2018 6 | # 7 | # This file is part of Synchronized-BatchNorm-PyTorch. 8 | # https://github.com/vacancy/Synchronized-BatchNorm-PyTorch 9 | # Distributed under MIT License. 10 | 11 | import queue 12 | import collections 13 | import threading 14 | 15 | __all__ = ['FutureResult', 'SlavePipe', 'SyncMaster'] 16 | 17 | 18 | class FutureResult(object): 19 | """A thread-safe future implementation. Used only as one-to-one pipe.""" 20 | 21 | def __init__(self): 22 | self._result = None 23 | self._lock = threading.Lock() 24 | self._cond = threading.Condition(self._lock) 25 | 26 | def put(self, result): 27 | with self._lock: 28 | assert self._result is None, 'Previous result has\'t been fetched.' 29 | self._result = result 30 | self._cond.notify() 31 | 32 | def get(self): 33 | with self._lock: 34 | if self._result is None: 35 | self._cond.wait() 36 | 37 | res = self._result 38 | self._result = None 39 | return res 40 | 41 | 42 | _MasterRegistry = collections.namedtuple('MasterRegistry', ['result']) 43 | _SlavePipeBase = collections.namedtuple('_SlavePipeBase', ['identifier', 'queue', 'result']) 44 | 45 | 46 | class SlavePipe(_SlavePipeBase): 47 | """Pipe for master-slave communication.""" 48 | 49 | def run_slave(self, msg): 50 | self.queue.put((self.identifier, msg)) 51 | ret = self.result.get() 52 | self.queue.put(True) 53 | return ret 54 | 55 | 56 | class SyncMaster(object): 57 | """An abstract `SyncMaster` object. 58 | - During the replication, as the data parallel will trigger an callback of each module, all slave devices should 59 | call `register(id)` and obtain an `SlavePipe` to communicate with the master. 60 | - During the forward pass, master device invokes `run_master`, all messages from slave devices will be collected, 61 | and passed to a registered callback. 62 | - After receiving the messages, the master device should gather the information and determine to message passed 63 | back to each slave devices. 64 | """ 65 | 66 | def __init__(self, master_callback): 67 | """ 68 | Args: 69 | master_callback: a callback to be invoked after having collected messages from slave devices. 70 | """ 71 | self._master_callback = master_callback 72 | self._queue = queue.Queue() 73 | self._registry = collections.OrderedDict() 74 | self._activated = False 75 | 76 | def __getstate__(self): 77 | return {'master_callback': self._master_callback} 78 | 79 | def __setstate__(self, state): 80 | self.__init__(state['master_callback']) 81 | 82 | def register_slave(self, identifier): 83 | """ 84 | Register an slave device. 85 | Args: 86 | identifier: an identifier, usually is the device id. 87 | Returns: a `SlavePipe` object which can be used to communicate with the master device. 88 | """ 89 | if self._activated: 90 | assert self._queue.empty(), 'Queue is not clean before next initialization.' 91 | self._activated = False 92 | self._registry.clear() 93 | future = FutureResult() 94 | self._registry[identifier] = _MasterRegistry(future) 95 | return SlavePipe(identifier, self._queue, future) 96 | 97 | def run_master(self, master_msg): 98 | """ 99 | Main entry for the master device in each forward pass. 100 | The messages were first collected from each devices (including the master device), and then 101 | an callback will be invoked to compute the message to be sent back to each devices 102 | (including the master device). 103 | Args: 104 | master_msg: the message that the master want to send to itself. This will be placed as the first 105 | message when calling `master_callback`. For detailed usage, see `_SynchronizedBatchNorm` for an example. 106 | Returns: the message to be sent back to the master device. 107 | """ 108 | self._activated = True 109 | 110 | intermediates = [(0, master_msg)] 111 | for i in range(self.nr_slaves): 112 | intermediates.append(self._queue.get()) 113 | 114 | results = self._master_callback(intermediates) 115 | assert results[0][0] == 0, 'The first result should belongs to the master.' 116 | 117 | for i, res in results: 118 | if i == 0: 119 | continue 120 | self._registry[i].result.put(res) 121 | 122 | for i in range(self.nr_slaves): 123 | assert self._queue.get() is True 124 | 125 | return results[0][1] 126 | 127 | @property 128 | def nr_slaves(self): 129 | return len(self._registry) 130 | -------------------------------------------------------------------------------- /model/sync_batchnorm/replicate.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # File : replicate.py 3 | # Author : Jiayuan Mao 4 | # Email : maojiayuan@gmail.com 5 | # Date : 27/01/2018 6 | # 7 | # This file is part of Synchronized-BatchNorm-PyTorch. 8 | # https://github.com/vacancy/Synchronized-BatchNorm-PyTorch 9 | # Distributed under MIT License. 10 | 11 | import functools 12 | 13 | from torch.nn.parallel.data_parallel import DataParallel 14 | 15 | __all__ = [ 16 | 'CallbackContext', 17 | 'execute_replication_callbacks', 18 | 'DataParallelWithCallback', 19 | 'patch_replication_callback' 20 | ] 21 | 22 | 23 | class CallbackContext(object): 24 | pass 25 | 26 | 27 | def execute_replication_callbacks(modules): 28 | """ 29 | Execute an replication callback `__data_parallel_replicate__` on each module created by original replication. 30 | The callback will be invoked with arguments `__data_parallel_replicate__(ctx, copy_id)` 31 | Note that, as all modules are isomorphism, we assign each sub-module with a context 32 | (shared among multiple copies of this module on different devices). 33 | Through this context, different copies can share some information. 34 | We guarantee that the callback on the master copy (the first copy) will be called ahead of calling the callback 35 | of any slave copies. 36 | """ 37 | master_copy = modules[0] 38 | nr_modules = len(list(master_copy.modules())) 39 | ctxs = [CallbackContext() for _ in range(nr_modules)] 40 | 41 | for i, module in enumerate(modules): 42 | for j, m in enumerate(module.modules()): 43 | if hasattr(m, '__data_parallel_replicate__'): 44 | m.__data_parallel_replicate__(ctxs[j], i) 45 | 46 | 47 | class DataParallelWithCallback(DataParallel): 48 | """ 49 | Data Parallel with a replication callback. 50 | An replication callback `__data_parallel_replicate__` of each module will be invoked after being created by 51 | original `replicate` function. 52 | The callback will be invoked with arguments `__data_parallel_replicate__(ctx, copy_id)` 53 | Examples: 54 | > sync_bn = SynchronizedBatchNorm1d(10, eps=1e-5, affine=False) 55 | > sync_bn = DataParallelWithCallback(sync_bn, device_ids=[0, 1]) 56 | # sync_bn.__data_parallel_replicate__ will be invoked. 57 | """ 58 | 59 | def replicate(self, module, device_ids): 60 | modules = super(DataParallelWithCallback, self).replicate(module, device_ids) 61 | execute_replication_callbacks(modules) 62 | return modules 63 | 64 | 65 | def patch_replication_callback(data_parallel): 66 | """ 67 | Monkey-patch an existing `DataParallel` object. Add the replication callback. 68 | Useful when you have customized `DataParallel` implementation. 69 | Examples: 70 | > sync_bn = SynchronizedBatchNorm1d(10, eps=1e-5, affine=False) 71 | > sync_bn = DataParallel(sync_bn, device_ids=[0, 1]) 72 | > patch_replication_callback(sync_bn) 73 | # this is equivalent to 74 | > sync_bn = SynchronizedBatchNorm1d(10, eps=1e-5, affine=False) 75 | > sync_bn = DataParallelWithCallback(sync_bn, device_ids=[0, 1]) 76 | """ 77 | 78 | assert isinstance(data_parallel, DataParallel) 79 | 80 | old_replicate = data_parallel.replicate 81 | 82 | @functools.wraps(old_replicate) 83 | def new_replicate(module, device_ids): 84 | modules = old_replicate(module, device_ids) 85 | execute_replication_callbacks(modules) 86 | return modules 87 | 88 | data_parallel.replicate = new_replicate -------------------------------------------------------------------------------- /model/sync_batchnorm/unittest.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # File : unittest.py 3 | # Author : Jiayuan Mao 4 | # Email : maojiayuan@gmail.com 5 | # Date : 27/01/2018 6 | # 7 | # This file is part of Synchronized-BatchNorm-PyTorch. 8 | # https://github.com/vacancy/Synchronized-BatchNorm-PyTorch 9 | # Distributed under MIT License. 10 | 11 | import unittest 12 | 13 | import numpy as np 14 | from torch.autograd import Variable 15 | 16 | 17 | def as_numpy(v): 18 | if isinstance(v, Variable): 19 | v = v.data 20 | return v.cpu().numpy() 21 | 22 | 23 | class TorchTestCase(unittest.TestCase): 24 | def assertTensorClose(self, a, b, atol=1e-3, rtol=1e-3): 25 | npa, npb = as_numpy(a), as_numpy(b) 26 | self.assertTrue( 27 | np.allclose(npa, npb, atol=atol), 28 | 'Tensor close check failed\n{}\n{}\nadiff={}, rdiff={}'.format(a, b, np.abs(npa - npb).max(), np.abs((npa - npb) / np.fmax(npa, 1e-5)).max()) 29 | ) 30 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | imageio==2.5.0 2 | lmdb==0.97 3 | matplotlib==3.1.1 4 | numpy==1.16.2 5 | opencv-python==4.1.0.25 6 | Pillow==8.1.1 7 | scikit-image==0.15.0 8 | scikit-learn==0.21.3 9 | scipy==1.3.1 10 | seaborn==0.9.0 11 | sklearn==0.0 12 | tensorboard==1.14.0 13 | tensorboardX==1.8 14 | torch==1.2.0 15 | torchvision==0.4.0 16 | tqdm==4.35.0 17 | -------------------------------------------------------------------------------- /train.py: -------------------------------------------------------------------------------- 1 | import os 2 | import torch 3 | import argument_parser 4 | import constants 5 | from utils.saver import Saver 6 | from utils.trainer import Trainer 7 | from dataloader.indoor_scenes import IndoorScenes 8 | from dataloader import dataset_base 9 | from model.deeplab import DeepLab 10 | from utils.summary import TensorboardSummary 11 | from utils.calculate_weights import calculate_weights_labels 12 | 13 | def main(): 14 | 15 | # script for training a model using 100% train set 16 | 17 | args = argument_parser.parse_args() 18 | print(args) 19 | torch.manual_seed(args.seed) 20 | 21 | lmdb_handle = dataset_base.LMDBHandle(os.path.join(constants.HDD_DATASET_ROOT, args.dataset, "dataset.lmdb"), args.memory_hog) 22 | train_set = IndoorScenes(args.dataset, lmdb_handle, args.base_size, 'train') 23 | val_set = IndoorScenes(args.dataset, lmdb_handle, args.base_size, 'val') 24 | test_set = IndoorScenes(args.dataset, lmdb_handle, args.base_size, 'test') 25 | train_set.make_dataset_multiple_of_batchsize(args.batch_size) 26 | 27 | model = DeepLab(num_classes=train_set.num_classes, backbone=args.backbone, output_stride=args.out_stride, sync_bn=args.sync_bn) 28 | model = model.cuda() 29 | 30 | class_weights = None 31 | if args.use_balanced_weights: 32 | class_weights = calculate_weights_labels(train_set) 33 | 34 | saver = Saver(args) 35 | trainer = Trainer(args, model, train_set, val_set, test_set, class_weights, Saver(args)) 36 | summary = TensorboardSummary(saver.experiment_dir) 37 | writer = summary.create_summary() 38 | 39 | start_epoch = 0 40 | if args.resume: 41 | args.resume = os.path.join(constants.RUNS, args.dataset, args.resume, 'checkpoint.pth.tar') 42 | if not os.path.isfile(args.resume): 43 | raise RuntimeError(f"=> no checkpoint found at {args.resume}") 44 | checkpoint = torch.load(args.resume) 45 | start_epoch = checkpoint['epoch'] 46 | trainer.model.load_state_dict(checkpoint['state_dict']) 47 | trainer.optimizer.load_state_dict(checkpoint['optimizer']) 48 | trainer.best_pred = checkpoint['best_pred'] 49 | print(f'=> loaded checkpoint {args.resume} (epoch {checkpoint["epoch"]})') 50 | 51 | lr_scheduler = trainer.lr_scheduler 52 | 53 | for epoch in range(start_epoch, args.epochs): 54 | trainer.training(epoch) 55 | if epoch % args.eval_interval == (args.eval_interval - 1): 56 | trainer.validation(epoch) 57 | if lr_scheduler: 58 | lr_scheduler.step() 59 | 60 | epoch = trainer.load_best_checkpoint() 61 | _, best_mIoU, best_mIoU_20, best_Acc, best_Acc_class, best_FWIoU = trainer.validation(epoch, test=True) 62 | 63 | writer.add_scalar('test/mIoU', best_mIoU, epoch) 64 | writer.add_scalar('test/mIoU_20', best_mIoU_20, epoch) 65 | writer.add_scalar('test/Acc', best_Acc, epoch) 66 | writer.add_scalar('test/Acc_class', best_Acc_class, epoch) 67 | writer.add_scalar('test/fwIoU', best_FWIoU, epoch) 68 | 69 | trainer.train_writer.close() 70 | trainer.val_writer.close() 71 | 72 | 73 | if __name__ == '__main__': 74 | main() 75 | -------------------------------------------------------------------------------- /train_active.py: -------------------------------------------------------------------------------- 1 | import os 2 | import torch 3 | import argument_parser 4 | import constants 5 | from utils.saver import Saver 6 | from utils.trainer import Trainer 7 | from dataloader.indoor_scenes import IndoorScenes 8 | from dataloader.indoor_scenes import get_active_dataset 9 | from dataloader import dataset_base 10 | from active_selection import get_active_selector 11 | from model.deeplab import DeepLab 12 | from utils.summary import TensorboardSummary 13 | from utils.calculate_weights import calculate_weights_labels 14 | 15 | 16 | def main(): 17 | 18 | args = argument_parser.parse_args() 19 | print(args) 20 | torch.manual_seed(args.seed) 21 | torch.backends.cudnn.benchmark = True 22 | # hardcoding scannet 23 | 24 | # get handle to lmdb dataset 25 | lmdb_handle = dataset_base.LMDBHandle(os.path.join(constants.HDD_DATASET_ROOT, args.dataset, "dataset.lmdb"), args.memory_hog) 26 | 27 | # create train val and test sets 28 | train_set = get_active_dataset(args.active_selection_mode)(args.dataset, lmdb_handle, args.superpixel_dir, args.base_size, 'seedset_0') 29 | val_set = IndoorScenes(args.dataset, lmdb_handle, args.base_size, 'val') 30 | test_set = IndoorScenes(args.dataset, lmdb_handle, args.base_size, 'test') 31 | 32 | class_weights = None 33 | if args.use_balanced_weights: 34 | class_weights = calculate_weights_labels(get_active_dataset(args.active_selection_mode)(args.dataset, lmdb_handle, args.superpixel_dir, args.base_size, 'train')) 35 | 36 | saver = Saver(args) 37 | saver.save_experiment_config() 38 | summary = TensorboardSummary(saver.experiment_dir) 39 | writer = summary.create_summary() 40 | 41 | # get active selection method 42 | active_selector = get_active_selector(args, lmdb_handle, train_set) 43 | 44 | 45 | # for each active selection iteration 46 | for selection_iter in range(args.max_iterations): 47 | 48 | fraction_of_data_labeled = int(round(train_set.get_fraction_of_labeled_data() * 100)) 49 | 50 | if os.path.exists(os.path.join(constants.RUNS, args.dataset, args.checkname, f'runs_{fraction_of_data_labeled:03d}', "selections")): 51 | # resume: load selections if this is a rerun, and selections are available from a previous run 52 | train_set.load_selections(os.path.join(constants.RUNS, args.dataset, args.checkname, f'runs_{fraction_of_data_labeled:03d}', "selections")) 53 | elif os.path.exists(os.path.join(constants.RUNS, args.dataset, args.checkname, f'runs_{fraction_of_data_labeled:03d}', "selections.txt")): 54 | # resume: load selections if this is a rerun, and selections are available from a previous run 55 | train_set.load_selections(os.path.join(constants.RUNS, args.dataset, args.checkname, f'runs_{fraction_of_data_labeled:03d}', "selections.txt")) 56 | else: 57 | # active selection iteration 58 | 59 | train_set.make_dataset_multiple_of_batchsize(args.batch_size) 60 | # create model from scratch 61 | model = DeepLab(num_classes=train_set.num_classes, backbone=args.backbone, output_stride=args.out_stride, sync_bn=args.sync_bn, 62 | mc_dropout=((args.active_selection_mode.startswith('viewmc')) or(args.active_selection_mode.startswith('vote')) or args.view_entropy_mode == 'mc_dropout')) 63 | model = model.cuda() 64 | # create trainer 65 | trainer = Trainer(args, model, train_set, val_set, test_set, class_weights, Saver(args, suffix=f'runs_{fraction_of_data_labeled:03d}')) 66 | 67 | # train for args.epochs epochs 68 | lr_scheduler = trainer.lr_scheduler 69 | for epoch in range(args.epochs): 70 | trainer.training(epoch) 71 | if epoch % args.eval_interval == (args.eval_interval - 1): 72 | trainer.validation(epoch) 73 | if lr_scheduler: 74 | lr_scheduler.step() 75 | 76 | train_set.reset_dataset() 77 | epoch = trainer.load_best_checkpoint() 78 | 79 | # get best val miou / metrics 80 | _, best_mIoU, best_mIoU_20, best_Acc, best_Acc_class, best_FWIoU = trainer.validation(epoch, test=True) 81 | 82 | trainer.evaluator.dump_matrix(os.path.join(trainer.saver.experiment_dir, "confusion_matrix.npy")) 83 | 84 | writer.add_scalar('active_loop/mIoU', best_mIoU, train_set.get_fraction_of_labeled_data() * 100) 85 | writer.add_scalar('active_loop/mIoU_20', best_mIoU_20, train_set.get_fraction_of_labeled_data() * 100) 86 | writer.add_scalar('active_loop/Acc', best_Acc, train_set.get_fraction_of_labeled_data() * 100) 87 | writer.add_scalar('active_loop/Acc_class', best_Acc_class, train_set.get_fraction_of_labeled_data() * 100) 88 | writer.add_scalar('active_loop/fwIoU', best_FWIoU, train_set.get_fraction_of_labeled_data() * 100) 89 | 90 | # make active selection 91 | active_selector.select_next_batch(model, train_set, args.active_selection_size) 92 | # save selections 93 | trainer.saver.save_active_selections(train_set.get_selections(), args.active_selection_mode.endswith("_region")) 94 | trainer.train_writer.close() 95 | trainer.val_writer.close() 96 | 97 | print(selection_iter, " / Train-set length: ", len(train_set)) 98 | 99 | writer.close() 100 | 101 | if __name__ == '__main__': 102 | main() 103 | -------------------------------------------------------------------------------- /utils/calculate_weights.py: -------------------------------------------------------------------------------- 1 | import os 2 | from tqdm import tqdm 3 | import numpy as np 4 | from torch.utils.data import DataLoader 5 | 6 | 7 | def calculate_weights_labels(dataset): 8 | 9 | z = np.zeros((dataset.num_classes,)) 10 | dataloader = DataLoader(dataset, batch_size=1, shuffle=False, num_workers=0) 11 | print("Calculating class weights..") 12 | 13 | for sample in tqdm(dataloader): 14 | y = sample['label'] 15 | y = y.detach().cpu().numpy() 16 | mask = np.logical_and((y >= 0), (y < dataset.num_classes)) 17 | labels = y[mask].astype(np.uint8) 18 | count_l = np.bincount(labels, minlength=dataset.num_classes) 19 | z += count_l 20 | 21 | z = np.nan_to_num(np.sqrt(1 + z)) 22 | total_frequency = np.sum(z) 23 | class_weights = [] 24 | 25 | for frequency in z: 26 | class_weight = 1 / frequency 27 | class_weights.append(class_weight) 28 | 29 | ret = np.nan_to_num(np.array(class_weights)) 30 | ret[ret > 2 * np.median(ret)] = 2 * np.median(ret) 31 | ret = ret / ret.sum() 32 | print('Class weights: ') 33 | print(ret) 34 | return ret 35 | -------------------------------------------------------------------------------- /utils/colormaps.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import torch 3 | 4 | 5 | def create_nyu40_label_colormap(): 6 | return { 7 | 255: [0, 0, 0], 8 | 0: [190, 153, 112], 9 | 1: [189, 198, 255], 10 | 2: [213, 255, 0], 11 | 3: [158, 0, 142], 12 | 4: [32, 99, 155],#[152, 255, 82]#[255,192,0] 13 | 5: [119, 77, 0], 14 | 6: [60, 174, 163],#[122, 71, 130]#[32, 99, 155] 15 | 7: [0, 174, 126], 16 | 8: [0, 125, 181], 17 | 9: [0, 143, 156], 18 | 10: [107, 104, 130], 19 | 11: [255,192,0],#[255, 229, 2]#[60, 174, 163] 20 | 12: [117, 68, 177], 21 | 13: [1, 255, 254], 22 | 14: [0, 21, 68], 23 | 15: [255, 166, 254], 24 | 16: [194, 140, 159], 25 | 17: [98, 14, 0], 26 | 18: [0, 71, 84], 27 | 19: [255, 219, 102], 28 | 20: [0, 118, 255], 29 | 21: [67, 0, 44], 30 | 22: [1, 208, 255], 31 | 23: [232, 94, 190], 32 | 24: [145, 208, 203], 33 | 25: [255, 147, 126], 34 | 26: [95, 173, 78], 35 | 27: [0, 100, 1], 36 | 28: [255, 238, 232], 37 | 29: [0, 155, 255], 38 | 30: [255, 0, 86], 39 | 31: [189, 211, 147], 40 | 32: [133, 169, 0], 41 | 33: [149, 0, 58], 42 | 34: [255, 2, 157], 43 | 35: [187, 136, 0], 44 | 36: [0, 185, 23], 45 | 37: [1, 0, 103], 46 | 38: [0, 0, 255], 47 | 39: [255, 0, 246] 48 | } 49 | 50 | 51 | def get_colormap(dataset): 52 | 53 | if dataset.startswith('scannet') or dataset.startswith('suncg') or dataset.startswith('matterport') or dataset.startswith('scenenet'): 54 | return create_nyu40_label_colormap() 55 | raise Exception('No colormap for dataset found') 56 | 57 | 58 | def map_segmentations_to_colors(segmentations, dataset): 59 | rgb_masks = [] 60 | for segmentation in segmentations: 61 | rgb_mask = map_segmentation_to_colors(segmentation, dataset) 62 | rgb_masks.append(rgb_mask) 63 | rgb_masks = torch.from_numpy(np.array(rgb_masks).transpose([0, 3, 1, 2])) 64 | return rgb_masks 65 | 66 | 67 | def map_segmentation_to_colors(segmentation, dataset): 68 | colormap = get_colormap(dataset) 69 | colored_segmentation = np.zeros((segmentation.shape[0], segmentation.shape[1], 3)) 70 | for label in np.unique(segmentation).tolist(): 71 | colored_segmentation[segmentation == label, :] = colormap[label] 72 | 73 | colored_segmentation /= 255.0 74 | return colored_segmentation 75 | -------------------------------------------------------------------------------- /utils/loss.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | 4 | 5 | class SegmentationLosses(object): 6 | 7 | def __init__(self, weight=None, batch_average=True, ignore_index=255, cuda=True): 8 | 9 | self.ignore_index = ignore_index 10 | self.weight = weight 11 | self.batch_average = batch_average 12 | self.cuda = cuda 13 | 14 | def build_loss(self, mode='ce'): 15 | if mode == 'ce': 16 | return self.CrossEntropyLoss 17 | elif mode == 'focal': 18 | return self.FocalLoss 19 | else: 20 | raise NotImplementedError 21 | 22 | def CrossEntropyLoss(self, logit, target): 23 | n, c, h, w = logit.size() 24 | criterion = nn.CrossEntropyLoss(weight=self.weight, ignore_index=self.ignore_index, reduction='mean') 25 | 26 | if self.cuda: 27 | criterion = criterion.cuda() 28 | 29 | loss = criterion(logit, target.long()) 30 | 31 | if self.batch_average: 32 | loss /= n 33 | 34 | return loss 35 | 36 | def FocalLoss(self, logit, target, gamma=2, alpha=0.5): 37 | n, c, h, w = logit.size() 38 | criterion = nn.CrossEntropyLoss(weight=self.weight, ignore_index=self.ignore_index, reduction='mean') 39 | 40 | if self.cuda: 41 | criterion = criterion.cuda() 42 | 43 | logpt = -criterion(logit, target.long()) 44 | pt = torch.exp(logpt) 45 | 46 | if alpha is not None: 47 | logpt *= alpha 48 | loss = -((1 - pt) ** gamma) * logpt 49 | 50 | if self.batch_average: 51 | loss /= n 52 | 53 | return loss 54 | 55 | 56 | if __name__ == "__main__": 57 | 58 | loss = SegmentationLosses(cuda=True) 59 | a = torch.rand(2, 3, 7, 7).cuda() 60 | b = torch.rand(2, 7, 7).cuda() 61 | print(loss.CrossEntropyLoss(a, b).item()) 62 | print(loss.FocalLoss(a, b, gamma=0, alpha=None).item()) 63 | print(loss.FocalLoss(a, b, gamma=2, alpha=0.5).item()) 64 | -------------------------------------------------------------------------------- /utils/metrics.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | # https://stats.stackexchange.com/questions/179835/how-to-build-a-confusion-matrix-for-a-multiclass-classifier 4 | 5 | def calculate_miou(confusion_matrix): 6 | MIoU = np.divide(np.diag(confusion_matrix), ( 7 | np.sum(confusion_matrix, axis=1) + np.sum(confusion_matrix, axis=0) - 8 | np.diag(confusion_matrix))) 9 | MIoU = np.nanmean(MIoU) 10 | return MIoU 11 | 12 | class Evaluator(object): 13 | 14 | def __init__(self, num_class): 15 | np.seterr(divide='ignore', invalid='ignore') 16 | self.num_class = num_class 17 | self.confusion_matrix = np.zeros((self.num_class,) * 2) 18 | 19 | def Pixel_Accuracy(self): 20 | return np.diag(self.confusion_matrix).sum() / self.confusion_matrix.sum() 21 | 22 | def Pixel_Accuracy_Class(self): 23 | Acc = np.divide(np.diag(self.confusion_matrix), self.confusion_matrix.sum(axis=1)) 24 | Acc = np.nanmean(Acc) 25 | return Acc 26 | 27 | def Mean_Intersection_over_Union(self): 28 | MIoU = np.divide(np.diag(self.confusion_matrix), ( 29 | np.sum(self.confusion_matrix, axis=1) + np.sum(self.confusion_matrix, axis=0) - 30 | np.diag(self.confusion_matrix))) 31 | MIoU = np.nanmean(MIoU) 32 | return MIoU 33 | 34 | def Mean_Intersection_over_Union_20(self): 35 | MIoU = 0 36 | if self.num_class > 20: 37 | subset_20 = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 23, 27, 32, 33, 35, 38]) 38 | confusion_matrix = self.confusion_matrix[subset_20[:, None], subset_20] 39 | MIoU = np.divide(np.diag(confusion_matrix), ( 40 | np.sum(confusion_matrix, axis=1) + np.sum(confusion_matrix, axis=0) - 41 | np.diag(confusion_matrix))) 42 | MIoU = np.nanmean(MIoU) 43 | return MIoU 44 | 45 | def Frequency_Weighted_Intersection_over_Union(self): 46 | freq = np.sum(self.confusion_matrix, axis=1) / np.sum(self.confusion_matrix) 47 | iu = np.divide(np.diag(self.confusion_matrix), ( 48 | np.sum(self.confusion_matrix, axis=1) + np.sum(self.confusion_matrix, axis=0) - 49 | np.diag(self.confusion_matrix))) 50 | 51 | FWIoU = (freq[freq > 0] * iu[freq > 0]).sum() 52 | return FWIoU 53 | 54 | def _generate_matrix(self, gt_image, pre_image): 55 | mask = (gt_image >= 0) & (gt_image < self.num_class) 56 | label = self.num_class * gt_image[mask].astype('int') + pre_image[mask] 57 | count = np.bincount(label, minlength=self.num_class**2) 58 | confusion_matrix = count.reshape(self.num_class, self.num_class) 59 | return confusion_matrix 60 | 61 | def add_batch(self, gt_image, pre_image, return_miou=False): 62 | assert gt_image.shape == pre_image.shape 63 | confusion_matrix = self._generate_matrix(gt_image, pre_image) 64 | self.confusion_matrix += confusion_matrix 65 | if return_miou: 66 | return calculate_miou(confusion_matrix) 67 | 68 | def reset(self): 69 | self.confusion_matrix = np.zeros((self.num_class,) * 2) 70 | 71 | def dump_matrix(self, path): 72 | np.save(path, self.confusion_matrix) 73 | -------------------------------------------------------------------------------- /utils/saver.py: -------------------------------------------------------------------------------- 1 | import os 2 | import shutil 3 | import torch 4 | from collections import OrderedDict 5 | import glob 6 | import constants 7 | import json 8 | import imageio 9 | import numpy as np 10 | 11 | class Saver: 12 | 13 | def __init__(self, args, suffix='', experiment_group=None, remove_existing=False): 14 | 15 | self.args = args 16 | 17 | if experiment_group == None: 18 | experiment_group = args.dataset 19 | 20 | self.experiment_dir = os.path.join(constants.RUNS, experiment_group, args.checkname, suffix) 21 | 22 | if remove_existing and os.path.exists(self.experiment_dir): 23 | shutil.rmtree(self.experiment_dir) 24 | 25 | if not os.path.exists(self.experiment_dir): 26 | print(f'Creating dir {self.experiment_dir}') 27 | os.makedirs(self.experiment_dir) 28 | 29 | def save_checkpoint(self, state, filename='checkpoint.pth.tar'): 30 | 31 | filename = os.path.join(self.experiment_dir, filename) 32 | torch.save(state, filename) 33 | 34 | def load_checkpoint(self, filename='checkpoint.pth.tar'): 35 | filename = os.path.join(self.experiment_dir, filename) 36 | return torch.load(filename) 37 | 38 | def save_experiment_config(self): 39 | 40 | logfile = os.path.join(self.experiment_dir, 'parameters.txt') 41 | log_file = open(logfile, 'w') 42 | arg_dictionary = vars(self.args) 43 | log_file.write(json.dumps(arg_dictionary, indent=4, sort_keys=True)) 44 | log_file.close() 45 | 46 | def save_active_selections(self, paths, regional=False): 47 | if regional: 48 | Saver.save_masks(os.path.join(self.experiment_dir, "selections") , paths) 49 | else: 50 | filename = os.path.join(self.experiment_dir, 'selections.txt') 51 | with open(filename, 'w') as fptr: 52 | for p in paths: 53 | fptr.write(p.decode('utf-8') + '\n') 54 | 55 | @staticmethod 56 | def save_masks(directory, paths): 57 | if not os.path.exists(directory): 58 | os.makedirs(directory) 59 | for p in paths: 60 | imageio.imwrite(os.path.join(directory, p.decode('utf-8') +'.png'), (paths[p]*255).astype(np.uint8)) 61 | -------------------------------------------------------------------------------- /utils/summary.py: -------------------------------------------------------------------------------- 1 | import os 2 | import torch 3 | from torchvision.utils import make_grid 4 | from tensorboardX import SummaryWriter 5 | from utils.colormaps import map_segmentations_to_colors, map_segmentation_to_colors 6 | import scipy.misc 7 | import constants 8 | import numpy as np 9 | 10 | 11 | class TensorboardSummary: 12 | 13 | def __init__(self, directory): 14 | self.directory = directory 15 | 16 | def create_summary(self): 17 | writer = SummaryWriter(log_dir=self.directory) 18 | return writer 19 | 20 | def visualize_state(self, writer, dataset, image, target, output, global_step): 21 | cat_tensors = [] 22 | print(dataset) 23 | for k in range(min(5, image.shape[0])): 24 | tensor_image = torch.from_numpy(np.transpose((np.transpose(image[k].clone().cpu().numpy(), axes=[ 25 | 1, 2, 0]) * (0.229, 0.224, 0.225) + (0.485, 0.456, 0.406)), [2, 0, 1])).float().unsqueeze(0) 26 | target_image = map_segmentations_to_colors(torch.squeeze(target[k:k + 1], 1).detach().cpu().numpy(), dataset=dataset).float() 27 | output_image = map_segmentations_to_colors(torch.max(output[k:k + 1], 1)[1].detach().cpu().numpy(), dataset=dataset).float() 28 | cat_tensors.append(torch.cat((tensor_image, target_image, output_image), -1)) 29 | grid_image = make_grid(torch.cat(cat_tensors, -2), 3, normalize=False, range=(0, 255)) 30 | writer.add_image('segmentations', grid_image, global_step) 31 | -------------------------------------------------------------------------------- /utils/superpixel_projections.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import os 3 | import constants 4 | from numpy.linalg import inv 5 | from dataloader import indoor_scenes 6 | import torch 7 | from collections import OrderedDict, Counter 8 | from tqdm import tqdm 9 | 10 | def project_image_to_world(x, y, depth, cam2world, depth_intrinsic): 11 | I = torch.zeros(4, depth.shape[0]).type(torch.cuda.FloatTensor) 12 | I[0, :] = x * depth 13 | I[1, :] = y * depth 14 | I[2, :] = depth 15 | I[3, :] = 1.0 16 | world_coordinates = torch.mm(torch.from_numpy(cam2world).type(torch.cuda.FloatTensor), torch.mm( 17 | torch.from_numpy(inv(depth_intrinsic)).type(torch.cuda.FloatTensor), I)) 18 | 19 | del I, x, y, depth 20 | torch.cuda.empty_cache() 21 | 22 | return world_coordinates 23 | 24 | def project_images_to_world(depths, cam2worlds, depth_intrinsic, superpixels, frames): 25 | x = np.linspace(0, constants.DEPTH_WIDTH - 1, constants.DEPTH_WIDTH) 26 | y = np.linspace(0, constants.DEPTH_HEIGHT - 1, constants.DEPTH_HEIGHT) 27 | x_mesh, y_mesh = np.meshgrid(x, y) 28 | 29 | world_coordinates = torch.zeros(4, len(depths) * constants.DEPTH_WIDTH * constants.DEPTH_HEIGHT).type(torch.cuda.FloatTensor) 30 | frame_origins = torch.zeros(len(depths) * constants.DEPTH_WIDTH * constants.DEPTH_HEIGHT).type(torch.cuda.IntTensor) 31 | superpixel_origins = torch.zeros(len(depths) * constants.DEPTH_WIDTH * constants.DEPTH_HEIGHT).type(torch.cuda.IntTensor) 32 | 33 | for im_idx in range(len(depths)): 34 | world_coordinates[:, im_idx * constants.DEPTH_WIDTH * constants.DEPTH_HEIGHT: (im_idx + 1) * constants.DEPTH_WIDTH * constants.DEPTH_HEIGHT] = project_image_to_world(torch.from_numpy(x_mesh).type(torch.cuda.FloatTensor).flatten(), 35 | torch.from_numpy(y_mesh).type(torch.cuda.FloatTensor).flatten(), torch.from_numpy(depths[im_idx][:]).type(torch.cuda.FloatTensor).flatten(), cam2worlds[im_idx], depth_intrinsic) 36 | frame_origins[im_idx * constants.DEPTH_WIDTH * constants.DEPTH_HEIGHT: (im_idx + 1) * constants.DEPTH_WIDTH * constants.DEPTH_HEIGHT] = torch.ones( 37 | constants.DEPTH_WIDTH * constants.DEPTH_HEIGHT).type(torch.cuda.IntTensor) * frames[im_idx] 38 | 39 | superpixel_origins[im_idx * constants.DEPTH_WIDTH * constants.DEPTH_HEIGHT: (im_idx + 1) * constants.DEPTH_WIDTH * constants.DEPTH_HEIGHT] = torch.from_numpy(superpixels[im_idx].astype(np.int).flatten()).type(torch.cuda.IntTensor) 40 | 41 | # visualize_point_cloud(world_coordinates) 42 | 43 | return world_coordinates, frame_origins, superpixel_origins 44 | 45 | def project_world_to_image(depth, superpixel_map, cam2world, depth_intrinsic, world_coordinates, frame_origins, superpixel_origins): 46 | world_coordinates_copy = world_coordinates.transpose(0, 1)[:, :3] 47 | projected_points = torch.mm(torch.mm(torch.from_numpy(depth_intrinsic).type(torch.cuda.FloatTensor), 48 | torch.from_numpy(inv(cam2world)).type(torch.cuda.FloatTensor)), world_coordinates) 49 | projected_points = projected_points.transpose(0, 1)[:, :3] 50 | projected_points[:, 0] /= projected_points[:, 2] 51 | projected_points[:, 1] /= projected_points[:, 2] 52 | projected_points[:, 2] /= projected_points[:, 2] 53 | selection_mask = ~torch.isnan(projected_points[:, 2]) 54 | 55 | projected_points = torch.round(projected_points[selection_mask]) 56 | frame_origins = frame_origins[selection_mask] 57 | superpixel_origins = superpixel_origins[selection_mask] 58 | world_coordinates_copy = world_coordinates_copy[selection_mask] 59 | 60 | # remove out of frame bounds 61 | selection_mask = (projected_points[:, 0] >= 0) & (projected_points[:, 0] < constants.DEPTH_WIDTH) & ( 62 | projected_points[:, 1] >= 0) & (projected_points[:, 1] < constants.DEPTH_HEIGHT) 63 | 64 | projected_points = projected_points[selection_mask][:, :2] 65 | frame_origins = frame_origins[selection_mask] 66 | superpixel_origins = superpixel_origins[selection_mask] 67 | world_coordinates_copy = world_coordinates_copy[selection_mask] 68 | 69 | depth = torch.from_numpy(depth).type(torch.cuda.FloatTensor) 70 | depth = depth[projected_points[:, 1].type(torch.cuda.LongTensor), projected_points[:, 0].type(torch.cuda.LongTensor)].flatten() 71 | backprojected_points = project_image_to_world(projected_points[:, 0], projected_points[ 72 | :, 1], depth, cam2world, depth_intrinsic).transpose(0, 1)[:, :3] 73 | 74 | selection_mask = (torch.norm(world_coordinates_copy - backprojected_points, dim=1) < constants.WORLD_DISTANCE_THRESHOLD) 75 | 76 | projected_points = projected_points[selection_mask] 77 | 78 | if projected_points.shape[0] == 0: 79 | return None 80 | 81 | frame_origins = frame_origins[selection_mask] 82 | superpixel_origins = superpixel_origins[selection_mask] 83 | superpixel_targets = superpixel_map[projected_points[:, 1].type(torch.cuda.LongTensor).cpu().numpy(), projected_points[:, 0].type(torch.cuda.LongTensor).cpu().numpy()].flatten() 84 | t1, t2 = np.unique(superpixel_map, return_counts=True) 85 | target_superpixel_sizes = dict(zip(t1, t2)) 86 | 87 | frame_spx = torch.zeros((frame_origins.shape[0], 3)).type(torch.cuda.IntTensor) 88 | frame_spx[:, 0] = torch.from_numpy(superpixel_targets.astype(np.int)).type(torch.cuda.IntTensor) 89 | frame_spx[:, 1] = frame_origins 90 | frame_spx[:, 2] = superpixel_origins 91 | 92 | uniques, counts = torch.unique(frame_spx, dim=0, return_counts=True) 93 | frame_spx_counts = {} 94 | for idx, u in enumerate(uniques.tolist()): 95 | frame_spx_counts[tuple(u)] = float(counts[idx].cpu().item()) 96 | 97 | coverage_dict = {} 98 | for i in frame_spx_counts: 99 | coverage = frame_spx_counts[i] / target_superpixel_sizes[i[0]] 100 | coverage_dict[(i[0], i[1], i[2])] = coverage 101 | 102 | return coverage_dict # , projected_points 103 | 104 | 105 | def find_superpixel_coverage(dataset_name, lmdb_handle, superpixel_dir, base_size, images): 106 | dataset = indoor_scenes.IndoorScenesWithAllInfo(dataset_name, lmdb_handle, superpixel_dir, base_size, images) 107 | scene_id_to_index = dataset.scene_id_to_index 108 | 109 | image_paths = [] 110 | 111 | for scene_id in tqdm(scene_id_to_index, desc='Scene[Coverage]'): 112 | all_frame_coverages = OrderedDict() 113 | depths = [] 114 | poses = [] 115 | superpixels = [] 116 | intrinsic = None 117 | 118 | for frame_id in scene_id_to_index[scene_id]: 119 | sample = dataset[frame_id] 120 | depths.append(sample['depth']) 121 | poses.append(sample['pose']) 122 | superpixels.append(sample['superpixel']) 123 | intrinsic = sample['intrinsic'] 124 | 125 | world_coordinates, frame_origins, superpixel_origins = project_images_to_world(depths, poses, intrinsic, superpixels, scene_id_to_index[scene_id]) 126 | 127 | for frame_id in tqdm(scene_id_to_index[scene_id], desc='Scene[Project]'): 128 | sample = dataset[frame_id] 129 | frame_coverages = project_world_to_image(sample['depth'], sample['superpixel'], sample['pose'], sample['intrinsic'], world_coordinates, frame_origins, superpixel_origins) 130 | if not frame_coverages is None: 131 | all_frame_coverages[frame_id] = frame_coverages 132 | image_paths.append(images[frame_id]) 133 | #from pprint import pprint 134 | #pprint(all_frame_coverages) 135 | np.save(os.path.join(constants.SSD_DATASET_ROOT, dataset_name, "raw", "selections", "coverage_"+superpixel_dir, f'{scene_id}.npy'), all_frame_coverages) 136 | 137 | del world_coordinates, frame_origins, superpixel_origins 138 | del depths, poses, superpixels, all_frame_coverages 139 | torch.cuda.empty_cache() 140 | 141 | with open(os.path.join(constants.SSD_DATASET_ROOT, dataset_name, "raw", "selections", "coverage_"+superpixel_dir, "coverage_paths.txt"), "w") as fptr: 142 | for p in image_paths: 143 | fptr.write(p.decode() + "\n") 144 | 145 | 146 | def test_coverage_scannet_sample(): 147 | import constants 148 | import os 149 | from dataloader import dataset_base 150 | from dataloader.indoor_scenes import IndoorScenes 151 | lmdb_handle = dataset_base.LMDBHandle(os.path.join(constants.HDD_DATASET_ROOT, "scannet-sample", "dataset.lmdb"), False) 152 | train_set = IndoorScenes('scannet-sample', lmdb_handle, (240, 320), 'train') 153 | find_superpixel_coverage('scannet-sample', lmdb_handle, (240, 320), train_set.image_path_subset) 154 | 155 | if __name__=='__main__': 156 | test_coverage_scannet_sample() 157 | -------------------------------------------------------------------------------- /utils/trainer.py: -------------------------------------------------------------------------------- 1 | import os 2 | import torch 3 | import constants 4 | from utils.misc import get_learning_rate 5 | from utils.summary import TensorboardSummary 6 | from utils.loss import SegmentationLosses 7 | from utils.calculate_weights import calculate_weights_labels 8 | from torch.utils.data import DataLoader 9 | import numpy as np 10 | from utils.metrics import Evaluator 11 | from tqdm import tqdm 12 | import random 13 | 14 | 15 | class Trainer: 16 | 17 | def __init__(self, args, model, train_set, val_set, test_set, class_weights, saver): 18 | self.args = args 19 | self.saver = saver 20 | self.saver.save_experiment_config() 21 | self.train_dataloader = DataLoader(train_set, batch_size=args.batch_size, shuffle=True, num_workers=args.workers) 22 | self.val_dataloader = DataLoader(val_set, batch_size=args.batch_size, shuffle=False, num_workers=args.workers) 23 | self.test_dataloader = DataLoader(test_set, batch_size=args.batch_size, shuffle=False, num_workers=args.workers) 24 | self.train_summary = TensorboardSummary(os.path.join(self.saver.experiment_dir, "train")) 25 | self.train_writer = self.train_summary.create_summary() 26 | self.val_summary = TensorboardSummary(os.path.join(self.saver.experiment_dir, "validation")) 27 | self.val_writer = self.val_summary.create_summary() 28 | self.model = model 29 | self.dataset_size = {'train': len(train_set), 'val': len(val_set), 'test': len(test_set)} 30 | 31 | train_params = [{'params': model.get_1x_lr_params(), 'lr': args.lr}, 32 | {'params': model.get_10x_lr_params(), 'lr': args.lr * 10}] 33 | 34 | if args.use_balanced_weights: 35 | weight = torch.from_numpy(class_weights.astype(np.float32)) 36 | else: 37 | weight = None 38 | 39 | if args.optimizer == 'SGD': 40 | print('Using SGD') 41 | self.optimizer = torch.optim.SGD(train_params, momentum=args.momentum, weight_decay=args.weight_decay, nesterov=args.nesterov) 42 | elif args.optimizer == 'Adam': 43 | print('Using Adam') 44 | self.optimizer = torch.optim.Adam(train_params, weight_decay=args.weight_decay) 45 | else: 46 | raise NotImplementedError 47 | 48 | self.lr_scheduler = None 49 | if args.use_lr_scheduler: 50 | if args.lr_scheduler == 'step': 51 | print('Using step lr scheduler') 52 | self.lr_scheduler = torch.optim.lr_scheduler.MultiStepLR(self.optimizer, milestones=[int(x) for x in args.step_size.split(",")], gamma=0.1) 53 | 54 | self.criterion = SegmentationLosses(weight=weight, ignore_index=255, cuda=args.cuda).build_loss(mode=args.loss_type) 55 | self.evaluator = Evaluator(train_set.num_classes) 56 | self.best_pred = 0.0 57 | 58 | def training(self, epoch): 59 | 60 | train_loss = 0.0 61 | self.model.train() 62 | num_img_tr = len(self.train_dataloader) 63 | tbar = tqdm(self.train_dataloader, desc='\r') 64 | 65 | visualization_index = int(random.random() * len(self.train_dataloader)) 66 | vis_img, vis_tgt, vis_out = None, None, None 67 | 68 | self.train_writer.add_scalar('learning_rate', get_learning_rate(self.optimizer), epoch) 69 | 70 | for i, sample in enumerate(tbar): 71 | image, target = sample['image'], sample['label'] 72 | image, target = image.cuda(), target.cuda() 73 | self.optimizer.zero_grad() 74 | output = self.model(image) 75 | loss = self.criterion(output, target) 76 | loss.backward() 77 | self.optimizer.step() 78 | train_loss += loss.item() 79 | tbar.set_description('Train loss: %.3f' % (train_loss / (i + 1))) 80 | self.train_writer.add_scalar('total_loss_iter', loss.item(), i + num_img_tr * epoch) 81 | 82 | if i == visualization_index: 83 | vis_img, vis_tgt, vis_out = image, target, output 84 | 85 | self.train_writer.add_scalar('total_loss_epoch', train_loss / self.dataset_size['train'], epoch) 86 | if constants.VISUALIZATION: 87 | self.train_summary.visualize_state(self.train_writer, self.args.dataset, vis_img, vis_tgt, vis_out, epoch) 88 | 89 | print('[Epoch: %d, numImages: %5d]' % (epoch, i * self.args.batch_size + image.data.shape[0])) 90 | print('Loss: %.3f' % train_loss) 91 | print('BestPred: %.3f' % self.best_pred) 92 | 93 | def validation(self, epoch, test=False): 94 | self.model.eval() 95 | self.evaluator.reset() 96 | 97 | ret_list = [] 98 | if test: 99 | tbar = tqdm(self.test_dataloader, desc='\r') 100 | else: 101 | tbar = tqdm(self.val_dataloader, desc='\r') 102 | test_loss = 0.0 103 | 104 | visualization_index = int(random.random() * len(self.val_dataloader)) 105 | vis_img, vis_tgt, vis_out = None, None, None 106 | 107 | for i, sample in enumerate(tbar): 108 | image, target = sample['image'], sample['label'] 109 | image, target = image.cuda(), target.cuda() 110 | 111 | with torch.no_grad(): 112 | output = self.model(image) 113 | 114 | if i == visualization_index: 115 | vis_img, vis_tgt, vis_out = image, target, output 116 | 117 | loss = self.criterion(output, target) 118 | test_loss += loss.item() 119 | tbar.set_description('Test loss: %.3f' % (test_loss / (i + 1))) 120 | pred = torch.argmax(output, dim=1).data.cpu().numpy() 121 | target = target.cpu().numpy() 122 | self.evaluator.add_batch(target, pred) 123 | 124 | Acc = self.evaluator.Pixel_Accuracy() 125 | Acc_class = self.evaluator.Pixel_Accuracy_Class() 126 | mIoU = self.evaluator.Mean_Intersection_over_Union() 127 | mIoU_20 = self.evaluator.Mean_Intersection_over_Union_20() 128 | FWIoU = self.evaluator.Frequency_Weighted_Intersection_over_Union() 129 | 130 | if not test: 131 | self.val_writer.add_scalar('total_loss_epoch', test_loss / self.dataset_size['val'], epoch) 132 | self.val_writer.add_scalar('mIoU', mIoU, epoch) 133 | self.val_writer.add_scalar('mIoU_20', mIoU_20, epoch) 134 | self.val_writer.add_scalar('Acc', Acc, epoch) 135 | self.val_writer.add_scalar('Acc_class', Acc_class, epoch) 136 | self.val_writer.add_scalar('fwIoU', FWIoU, epoch) 137 | if constants.VISUALIZATION: 138 | self.val_summary.visualize_state(self.val_writer, self.args.dataset, vis_img, vis_tgt, vis_out, epoch) 139 | 140 | print("Test: " if test else "Validation:") 141 | print('[Epoch: %d, numImages: %5d]' % (epoch, i * self.args.batch_size + image.data.shape[0])) 142 | print("Acc:{}, Acc_class:{}, mIoU:{}, mIoU_20:{}, fwIoU: {}".format(Acc, Acc_class, mIoU, mIoU_20, FWIoU)) 143 | print('Loss: %.3f' % test_loss) 144 | 145 | if not test: 146 | new_pred = mIoU 147 | if new_pred > self.best_pred: 148 | self.best_pred = new_pred 149 | self.saver.save_checkpoint({ 150 | 'epoch': epoch + 1, 151 | 'state_dict': self.model.state_dict(), 152 | 'optimizer': self.optimizer.state_dict(), 153 | 'best_pred': self.best_pred, 154 | }) 155 | 156 | return test_loss, mIoU, mIoU_20, Acc, Acc_class, FWIoU#, ret_list 157 | 158 | def load_best_checkpoint(self): 159 | checkpoint = self.saver.load_checkpoint() 160 | self.model.load_state_dict(checkpoint['state_dict']) 161 | self.optimizer.load_state_dict(checkpoint['optimizer']) 162 | print(f'=> loaded checkpoint - epoch {checkpoint["epoch"]})') 163 | return checkpoint["epoch"] 164 | --------------------------------------------------------------------------------