Monodepth2: the self-supervised depth reference implementation, seven years of dependency drift
[ICCV 2019] Monocular depth estimation from a single image
At a glance
- What is it?
- Niantic's PyTorch implementation of ICCV 2019 monocular depth estimation, still documented against PyTorch 0.4.1 and OpenCV 3.3.1, with 4503 stars and no releases.
- Who is it for?
- Monodepth2 is worth using as a baseline and worth reading as an artifact of its year. As a baseline it is excellent: nine published checkpoints with KITTI numbers attached, a single command for single-image inference, and eval scripts that let you check your own model against the same splits.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 7 days ago.
- What is it written in?
- Mainly Jupyter Notebook, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 12, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What the repository is and is not
This is the reference PyTorch implementation for the method described in Digging into Self-Supervised Monocular Depth Prediction, by Clément Godard, Oisin Mac Aodha, Michael Firman and Gabriel J. Brostow, presented at ICCV 2019 with an arXiv link. The word reference is doing real work in that sentence. It means this is the code the paper's numbers came from, which makes it the thing you compare against when you want to know whether your own depth model is competitive.
The licensing is worth settling before anything else. The README states that the code is for non-commercial use and points at a LICENSE file for the terms. GitHub's own license detection reports NOASSERTION, which is a common outcome for custom or non-commercial terms that do not match a standard licence. So the field a package index would show you and the file you must actually read disagree in usefulness rather than in substance. Read the file.
The repository has 4503 stars, 988 forks and 32 open issues, and it is not archived. The last push was on 2026-10-05, which is worth pairing with what you are about to read about the dependency pins. Something in this tree is still receiving commits, and it is almost certainly not the version numbers in the setup section.
The setup instructions belong to 2019
Assuming a fresh Anaconda distribution, the README's install block is four lines:
conda install pytorch=0.4.1 torchvision=0.2.1 -c pytorch
pip install tensorboardX==1.4
conda install opencv=3.3.1 # just needed for evaluationPyTorch 0.4.1 is from December 2018. torchvision 0.2.1 is from the same era. `tensorboardX==1.4` is pinned to an exact version because that project existed specifically to backport TensorBoard logging to older PyTorch, and `opencv=3.3.1` predates OpenCV 4 by two major versions.
The environment paragraph that follows is where the documentation contradicts itself. The README reports that its experiments used PyTorch 0.4.1, CUDA 9.1, Python 3.6.6 and Ubuntu 18.04, then states that the code is also compatible with Python 2.7. A codebase whose reference environment is Python 3.6.6 does not normally run unchanged on 2.7, and for this project the claim is hard to believe: type hints or f-strings anywhere in the training code would break it, and the options and trainer modules in this tree are the kind of files that carry them. Treat Python 2.7 as a stale claim rather than a supported configuration.
The README does concede the practical difficulty and recommends isolating Python 3.6.6 in its own environment, with the conda create command written out. That is the correct advice for anyone chasing an exact reproduction. For anyone who just wants to run inference, the sensible move is a modern PyTorch in a current environment and accepting that the numbers will not match the table below to three decimal places.
One command to a depth map
Single-image inference is the part of this repository that still works as written, which is why it remains the most-used path. Predicting scaled disparity for one image:
python test_simple.py --image_path assets/test_image.jpg --model_name mono+stereo_640x192and estimating metric depth instead, if you picked a stereo-trained checkpoint:
python test_simple.py --image_path assets/test_image.jpg --model_name mono+stereo_640x192 --pred_metric_depthOn its first run either command downloads the pretrained model, 99MB, into a `models/` folder. The distinction the second flag draws is the important one in the whole system. A monocular model trained with monocular supervision only has an unknown scale, so it can give you relative depth and relative disparity but nothing in metres. Adding stereo supervision, where the model sees a paired image and can triangulate, is what makes metric depth possible. That is why the flag only makes sense with a stereo-trained model name, and it is the single most common source of confusion for newcomers.
The repository also publishes ResNet-50 depth models with ImageNet pretrained weights and trained from scratch, and the README is explicit that you must set `--num_layers 50` when using them. That flag is a good example of this codebase's style: the option parsing lives in `options.py`, and the pretrained-model shortcut you would expect does not exist, because ResNet-50 is not the architecture the loader knows about by default.
Nine checkpoints and what their numbers actually rank
The model table is the most valuable thing in the README, because it lets you pick a checkpoint instead of guessing. Nine models are listed, each with its training modality, whether it started from ImageNet pretrained weights, its resolution, an absolute relative error and a delta under 1.25 score.
Reading the table as a ranking rather than a list produces a result worth pausing on. On absolute relative error, the best number in the table is 0.106, achieved twice, by `mono+stereo_640x192` and by `mono+stereo_1024x320`. The resolution buys nothing on that metric. On delta under 1.25, the ordering changes: `mono_1024x320` scores 0.879, which beats the 0.874 of `mono+stereo_640x192`, and beats the 0.876 of the 1024-wide combined model. In other words, on the threshold accuracy metric, spending the budget on resolution rather than on adding stereo supervision pays off more.
The ImageNet pretrained rows tell the same story more starkly. Every model without pretraining sits between 0.127 and 0.132 on absolute relative error, and between 0.831 and 0.845 on delta, while every pretrained model lands between 0.106 and 0.115 and between 0.864 and 0.879. That is a larger gap than any modality or resolution choice produces on this benchmark, and it is the single most transferable fact in the table for anyone training their own depth model.
Two further sets of weights exist but sit outside the table: models trained on the odometry split, available in monocular and mono plus stereo modalities, and the pair of ResNet-50 models. All weights are hosted on Google Cloud Storage rather than in the repository or on a package index, which means there is no way to verify a checksum against a manifest, and no release history to correlate them with.
Preparing KITTI, where the reproduction details hide
Training requires the raw KITTI dataset, fetched by pointing wget at a file listing in the splits directory:
wget -i splits/kitti_archives_to_download.txt -P kitti_data/followed by unzipping each archive in place. The README warns that the result weighs about 175GB and that you need room to unpack it as well. Those archives come from the KITTI raw data page, which is a separate registration step, so this is the step where a first run usually stalls.
The interesting part comes next. By default the training code expects KITTI PNG images to have been converted to JPEG, and the README gives the exact command:
find kitti_data/ -name '*.png' | parallel 'convert -quality 92 -sampling-factor 2x2,1x1,1x1 {.}.png {.}.jpg && rm {}'Read what that command does: it converts each PNG, then removes the original with `rm {}`. It is not a dry run and it is not reversible except by re-downloading 175GB. That is a genuinely risky default to leave in a quick start, and the alternative the README offers is adding `--png` when training, which trains from raw files at the cost of slower loading.
The reason for the conversion is the part that matters for anyone comparing numbers. The README explains that the authors converted PNG to JPG on Ubuntu 16.04, where ImageMagick's default chroma subsampling is 2x2,1x1,1x1, and that Ubuntu 18.04 defaults to 2x2,2x2,2x2, which gives different results. Hence the explicit subsampling parameter in the command. In other words, reproducing the published numbers depends on the ImageMagick version and the distro default that was in force in 2018, not just on the model code. If your conversion runs on a current system, check your ImageMagick default before assuming any mismatch is a bug.
The dataset can live anywhere, pointed at with `--data_path`. Train, validation and test splits are defined in the `splits/` folder, and the default train split uses what the README refers to as Zhou's subset rather than the full 652 training frames.
Why GitHub thinks this is a notebook repository
GitHub classifies the primary language as Jupyter Notebook, which is wrong in a way that is worth understanding rather than correcting. The training code in this tree is Python: `train.py`, `trainer.py`, `test_simple.py`, `evaluate_depth.py`, `evaluate_pose.py`, `export_gt_depth.py`, `options.py`, `layers.py`, `utils.py`, plus `networks/` and `datasets/` directories. It is a PyTorch codebase.
The misclassification comes from file volume rather than substance. This is a research repository that carries many example notebooks demonstrating how to load weights and run inference, and notebooks store their code as JSON with embedded source, so byte-count heuristics weigh them heavily. The verdict is a measurement artefact.
It is still a small navigational trap. Someone filtering GitHub by language will find this repository under notebooks, miss it under Python, and possibly conclude it is a tutorial collection rather than a training codebase. If you are searching for self-supervised depth implementations, search by the paper instead.
There are no releases, no tags, and no versioned artefacts. The tree itself carries the code, the evaluation scripts, the KITTI utility module inherited from the SfMLearner lineage, and the split definitions, and everything downloadable lives on a Google Cloud Storage bucket. The absence of releases is consistent with the rest of the project's posture: this is code released alongside a paper, pinned to the environment that produced the paper, and left in place.
Editorial conclusion
Monodepth2 is worth using as a baseline and worth reading as an artifact of its year. As a baseline it is excellent: nine published checkpoints with KITTI numbers attached, a single command for single-image inference, and eval scripts that let you check your own model against the same splits. What the README will not do for you is reproduce the authors' numbers, because the setup instructions pin PyTorch 0.4.1, torchvision 0.2.1, OpenCV 3.3.1 and Python 3.6.6, none of which install cleanly on a current machine. The conversion step that makes your KITTI images match theirs is sensitive to an ImageMagick default that changed between Ubuntu 16.04 and 18.04, and it deletes your raw PNG files as it goes. Budget for a day of environment work before you can trust a number, and read the LICENSE file rather than the licence field, because the terms are non-commercial.
Frequently asked questions
Can Monodepth2 predict metric depth from a single image?
Only with a stereo-trained checkpoint. Monocular training alone leaves the scale unknown, so a mono model gives you scaled disparity and relative depth only. Passing `--pred_metric_depth` to `test_simple.py` with a stereo-trained model name such as `mono+stereo_640x192` is what enables depth in metres.
Which pretrained Monodepth2 model should I use?
The combined `mono+stereo_640x192` is the usual choice, with an absolute relative error of 0.106 and a delta under 1.25 score of 0.874. If delta accuracy matters more, `mono_1024x320` scores 0.879 on that metric despite being monocular only. For the ResNet-50 weights you must add `--num_layers 50`. All models download from Google Cloud Storage on first use.
Is Monodepth2 usable on a recent PyTorch install?
Inference generally works, since `test_simple.py` is a small script, but the README's documented environment is PyTorch 0.4.1, torchvision 0.2.1, OpenCV 3.3.1 and Python 3.6.6. Training and evaluation are where the version drift bites, and the evaluation scripts need OpenCV. Expect to port the code to a modern PyTorch if you want to reproduce the published numbers.
Can I use Monodepth2 commercially?
Probably not without permission. The README states the code is for non-commercial use and refers you to the LICENSE file for terms, while GitHub's licence field reads NOASSERTION because the custom terms match no standard licence. Read the LICENSE file directly, since the metadata field will not tell you what you need to know.
Why does the KITTI preparation step convert PNGs to JPEG and delete the originals?
Because the authors' published results were obtained on JPEG-converted images, so matching their setup means converting too. The README pins the chroma subsampling explicitly, because Ubuntu 16.04 defaulted to 2x2,1x1,1x1 and Ubuntu 18.04 to 2x2,2x2,2x2, which changes the images and the results. The conversion command ends in `rm {}`, so the raw PNGs are destroyed; train with `--png` to skip it at the cost of slower data loading.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/nianticlabs-monodepth2)