|
| 1 | +# NinjaDesc: Content-Concealing Visual Descriptors via Adversarial Learning |
| 2 | + |
| 3 | +Reference implementation for the CVPR 2022 paper *"NinjaDesc: Content-Concealing Visual Descriptors via Adversarial Learning"* by Tony Ng, Hyo Jin Kim, Vincent T. Lee, Daniel DeTone, Tsun-Yi Yang, Tianwei Shen, Eddy Ilg, Vassileios Balntas, Krystian Mikolajczyk, and Chris Sweeney (Reality Labs, Meta and Imperial College London). |
| 4 | + |
| 5 | +[Paper (arXiv 2112.12785)](https://arxiv.org/abs/2112.12785) |
| 6 | + |
| 7 | +## Abstract |
| 8 | + |
| 9 | +In the light of recent analyses on privacy-concerning scene revelation from visual descriptors, we develop descriptors that conceal the input image content. We propose an adversarial learning framework for training visual descriptors that prevent image reconstruction, while maintaining the matching accuracy. We let a feature encoding network (**NinjaNet**) and an image reconstruction network compete with each other, such that the encoder tries to impede the image reconstruction with its generated descriptors (**NinjaDesc**), while the reconstructor tries to recover the input image from the descriptors. The experimental results demonstrate that the resulting visual descriptors significantly deteriorate the image reconstruction quality with minimal impact on correspondence matching and camera localization performance. |
| 10 | + |
| 11 | +## Citation |
| 12 | + |
| 13 | +```bibtex |
| 14 | +@inproceedings{ng2022ninjadesc, |
| 15 | + title = {NinjaDesc: Content-Concealing Visual Descriptors via Adversarial Learning}, |
| 16 | + author = {Ng, Tony and Kim, Hyo Jin and Lee, Vincent T. and DeTone, Daniel |
| 17 | + and Yang, Tsun-Yi and Shen, Tianwei and Ilg, Eddy |
| 18 | + and Balntas, Vassileios and Mikolajczyk, Krystian and Sweeney, Chris}, |
| 19 | + booktitle = {Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition (CVPR)}, |
| 20 | + year = {2022} |
| 21 | +} |
| 22 | +``` |
| 23 | + |
| 24 | +## Installation |
| 25 | + |
| 26 | +Tested with Python 3.8+ and PyTorch >= 1.10. |
| 27 | + |
| 28 | +```bash |
| 29 | +git clone https://github.com/facebookresearch/ninjadesc.git |
| 30 | +cd ninjadesc |
| 31 | +pip install -r requirements.txt |
| 32 | +pip install -e . |
| 33 | +``` |
| 34 | + |
| 35 | +Set the data and output roots that the configs read from: |
| 36 | + |
| 37 | +```bash |
| 38 | +export NINJADESC_DATA_ROOT=/path/to/data # raw + prepared datasets |
| 39 | +export NINJADESC_OUTPUT_ROOT=/path/to/outputs # checkpoints, tensorboard logs |
| 40 | +``` |
| 41 | + |
| 42 | +## Pretrained models |
| 43 | + |
| 44 | +Weights are released as GitHub Release assets. They are downloaded automatically into `~/.cache/ninjadesc/` the first time a model is requested via `ninjadesc._compat.weights.download_weights(name)`. |
| 45 | + |
| 46 | +| Logical name | File | |
| 47 | +| -------------------------------------------------- | ---------------------------------------------------------- | |
| 48 | +| `pa_desc_sosnet_init` | `pa_desc_sos_init_torchscript.pt` | |
| 49 | +| `pa_desc_sift_init` | `pa_desc_sift_init_torchscript.pt` | |
| 50 | +| `pa_desc_hardnet_init` | `pa_desc_hardnet_init_torchscript.pt` | |
| 51 | +| `pa_desc_hardnet_init_normalize` | `pa_desc_hardnet_init_normalize_torchscript.pt` | |
| 52 | +| `lemuria_unet_padesc_sos_init` | `LemuriaNet_Unet_PADesc_INIT.pth` | |
| 53 | +| `lemuria_unet_padesc_sift_init` | `LemuriaNet_UNet_PADesc_SIFT_INIT.pth` | |
| 54 | +| `lemuria_unet_padesc_hardnet_init` | `LemuriaNet_UNet_PADesc_HARDNET_INIT.pth` | |
| 55 | +| `lemuria_unet_padesc_hardnet_nontorchscript_init` | `LemuriaNet_UNet_PADesc_HARDNET_NONTORCHSCRIPT_INIT.pth` | |
| 56 | +| `lemuria_unet_sos` | `LemuriaNet_UNet_SOS.pth` | |
| 57 | +| `lemuria_unet_hard` | `LemuriaNet_UNet_HARD.pth` | |
| 58 | +| `lemuria_unet_sift` | `LemuriaNet_UNet_SIFT.pth` | |
| 59 | +| `lemuria_sos_mpa_3303` | `SOS_MPA_3303_epoch_249.ckpt` | |
| 60 | +| `lemuria_sift_mpa_1302` | `SIFT_MPA_1302_epoch_248.ckpt` | |
| 61 | +| `sosnet_hpatches` | `sosnet-32x32-hpatches_a.pth` | |
| 62 | +| `sosnet_liberty` | `sosnet-32x32-liberty.pth` | |
| 63 | +| `sosnet_scape_pipeline` | `sosnet_scape.pt` | |
| 64 | +| `sosnet_padesc_liberty` | `padesc_liberty.pt` | |
| 65 | +| `hardnet_lib` | `hardnet_lib.pt` | |
| 66 | +| `hardnet_liberty_aug` | `checkpoint_liberty_with_aug.pth` | |
| 67 | + |
| 68 | +## Dataset preparation |
| 69 | + |
| 70 | +The image-based reconstruction trainer/tester uses MegaDepth features pre-extracted into `.h5` files. Generate them with: |
| 71 | + |
| 72 | +```bash |
| 73 | +python -m ninjadesc.pa_desc.megadepth_prep.prep \ |
| 74 | + --data_root /path/to/MegaDepth_v1 \ |
| 75 | + --kpt SOS \ |
| 76 | + --worker_id 0 |
| 77 | +``` |
| 78 | + |
| 79 | +This writes `${NINJADESC_DATA_ROOT}/megadepth_h5s_<kpt>_hpatches-a_original/*.hdf5`. Repeat with `--kpt sift` and `--kpt hardnet` for the other base descriptors. The patch-based descriptor trainer additionally uses the UBC PhotoTour dataset (Liberty / Notredame / Yosemite); torchvision downloads it automatically into `${NINJADESC_DATA_ROOT}/PhotoTour/`. |
| 80 | + |
| 81 | +## Usage |
| 82 | + |
| 83 | +All trainers/testers are Hydra entry points; CLI overrides take the form `key=value`. |
| 84 | + |
| 85 | +**Inference** — extract a NinjaDesc from base SOSNet descriptors: |
| 86 | + |
| 87 | +```python |
| 88 | +import torch |
| 89 | +from ninjadesc.pa_desc.models.privacy import PrivacyEncoder |
| 90 | + |
| 91 | +encoder = PrivacyEncoder().eval() |
| 92 | +ninja = encoder(torch.randn(N, 128)) # NinjaDesc, shape (N, 128) |
| 93 | +``` |
| 94 | + |
| 95 | +**Step 1 — utility initialization of NinjaNet** (UBC PhotoTour): |
| 96 | + |
| 97 | +```bash |
| 98 | +python -m ninjadesc.pa_desc.tools.desc_trainer \ |
| 99 | + profiler=simple datasets@data.train.ds=liberty \ |
| 100 | + trainer.max_epochs=300 trainer.gpus=4 |
| 101 | +``` |
| 102 | + |
| 103 | +**Step 2 — initialize the reconstruction adversary** (MegaDepth): |
| 104 | + |
| 105 | +```bash |
| 106 | +python -m ninjadesc.pa_desc.tools.recon_trainer \ |
| 107 | + profiler=simple trainer.max_epochs=300 trainer.gpus=4 |
| 108 | +``` |
| 109 | + |
| 110 | +**Step 3 — joint adversarial training**: |
| 111 | + |
| 112 | +```bash |
| 113 | +python -m ninjadesc.pa_desc.tools.trainer \ |
| 114 | + profiler=simple trainer.max_epochs=300 trainer.gpus=4 loss._lambda=1.5 |
| 115 | +``` |
| 116 | + |
| 117 | +`loss._lambda` is the privacy parameter that trades off matching utility against image-reconstruction concealment. |
| 118 | + |
| 119 | +**Evaluation** on MegaDepth: |
| 120 | + |
| 121 | +```bash |
| 122 | +python -m ninjadesc.pa_desc.tools.tester \ |
| 123 | + base_desc=sosnet \ |
| 124 | + padesc_checkpoint.base_dir=${NINJADESC_OUTPUT_ROOT}/pa_desc_joint/<run> \ |
| 125 | + padesc_checkpoint.epoch=21 padesc_checkpoint.step=13749 |
| 126 | +``` |
| 127 | + |
| 128 | +## Repository layout |
| 129 | + |
| 130 | +``` |
| 131 | +ninjadesc/ |
| 132 | +├── _compat/ # thin shims (Hydra/PL helpers, weight download, IO) |
| 133 | +├── lemuria/recon/ # image reconstruction networks (UNet, UResNet, VGG, Discriminator) |
| 134 | +└── pa_desc/ |
| 135 | + ├── core/ # losses (perceptual loss) |
| 136 | + ├── data/ # MegaDepth, PhotoTour, HPatches dataset adapters |
| 137 | + ├── engine/ # PyTorch Lightning modules (PADesc, joint, lemurianet) |
| 138 | + ├── megadepth_prep/ # h5 feature extraction script |
| 139 | + ├── models/ # SOSNet, HardNet, NinjaNet (PrivacyEncoder), reconstructor |
| 140 | + ├── tools/ # desc_trainer, recon_trainer, trainer (joint), tester |
| 141 | + └── config/ # Hydra configs (yaml) |
| 142 | +``` |
| 143 | + |
| 144 | +## Acknowledgements |
| 145 | + |
| 146 | +This codebase builds on a number of open-source projects: |
| 147 | +- **SOSNet** ([Tian et al., 2019](https://github.com/scape-research/SOSNet)) — base descriptor. |
| 148 | +- **HardNet** ([Mishchuk et al., 2017](https://github.com/DagnyT/hardnet)) — base descriptor. |
| 149 | +- **InvSfM / `dangwal21`** — descriptor inversion baseline. |
| 150 | +- **MegaDepth** ([Li & Snavely, 2018](https://www.cs.cornell.edu/projects/megadepth/)) — adversarial training data. |
| 151 | +- **HPatches** ([Balntas et al., 2017](https://hpatches.github.io/)) — matching benchmark. |
| 152 | +- **PyTorch Lightning**, **Hydra**, **kornia**, **torchvision** — frameworks. |
| 153 | + |
| 154 | +## Known limitations |
| 155 | + |
| 156 | +- The `HPatches` dataset adapter (`ninjadesc/pa_desc/data/hpatches.py`) is a stub; populate it with a loader for the official HPatches release before evaluating on it. |
| 157 | +- The `MegaDepthDataset` requires h5 features pre-extracted via the dataset preparation step above. |
| 158 | +- No unit tests are included. |
| 159 | + |
| 160 | +## License |
| 161 | + |
| 162 | +This project is released under CC-BY-NC 4.0. See `LICENSE`. |
0 commit comments