compphoto/Intrinsic: Ordinal Shading and Colorful Diffuse Decomposition for In-the-Wild Photos
Repo for the papers "Intrinsic Image Decomposition via Ordinal Shading" (TOG 2023) and "Colorful Diffuse Intrinsic Image Decomposition in the Wild" (TOG 2024)
At a glance
- What is it?
- The reference implementation of two ACM Transactions on Graphics papers on intrinsic image decomposition, packaged as a Python library with pretrained weights. It is research code aimed at graphics and vision researchers, and its academic-only licence is the first thing to check.
- Who is it for?
- Adopt compphoto/Intrinsic if you are doing graphics or vision research that needs albedo, diffuse shading and a residual from ordinary photographs, and you can live with the academic-only licence and the two pinned GitHub dependencies. Do not adopt it if you need a permissively licensed component, a supported API surface, or a single-image relighting service.
- 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?
- Activity is slowing. The repository last received commits 6 months ago.
- What is it written in?
- Mainly Python, 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 intrinsic decomposition is for, and who this repository is aimed at
An intrinsic image is a decomposition of a photograph into the properties of the surfaces in the scene rather than the pixels the camera recorded. The repository's README describes the goal as generating high-resolution intrinsic image decompositions for in-the-wild images, and the two papers behind it are Intrinsic Image Decomposition via Ordinal Shading (TOG 2023) and Colorful Diffuse Intrinsic Image Decomposition in the Wild (TOG 2024). The outputs are albedo, shading and a residual that holds specularities and light sources.
The intended audience is narrow. This is the code that accompanies two papers, and the README says the implementation is provided for academic use only. The practical uses it advertises are illumination-aware editing operations such as per-pixel white balancing and specularity removal, which is a research and post-production framing, not a product framing. If you are building a photo editor and want a drop-in relighting module, you are looking at the wrong artifact until you have talked to the licensing office named in the README.
The staged pipeline: ordinal shading, low-resolution chroma, sparse albedo
The README describes a multi-stage method rather than one network. First a grayscale shading layer is estimated with an ordinal shading pipeline. Then low-resolution chromaticity is estimated to account for colorful illumination while keeping global consistency. From that initial colorful decomposition the method estimates a high-resolution, sparse albedo layer. A separate diffuse shading network is trained using only a single rendered indoor dataset, which the README presents as a consequence of the decomposition rather than a separate contribution.
You do not see the stages as separate calls. The inference example calls load_models('v2') and then run_pipeline(models, image), and the returned dictionary exposes the intermediates. The README's own table lists keys including ord_full for full-resolution ordinal shading, gry_shd for grayscale shading, lr_clr for low-resolution shading chromaticity, hr_alb for the final albedo, hr_shd for the implied shading of that albedo, dif_shd for diffuse shading, and residual. Two rows of that table share the key name ord_full, one described as full-resolution and one as base-resolution, which looks like a documentation slip rather than a real duplicate key; treat the table as a guide and inspect the dictionary you actually get.
One design detail worth noting: the pipeline works on linear values. The README says the result is linear intrinsic components, and the table includes lin_img, described as the input image after undoing gamma correction. If you feed in an sRGB array without accounting for that, your albedo and shading will not mean what the papers mean by them.
Installing compphoto/Intrinsic and running a first decomposition
The README gives two setup paths. Both start with a fresh virtual environment. The first installs the repository as a package after cloning.
python3 -m venv intrinsic_env
source intrinsic_env/bin/activate
git clone https://github.com/compphoto/Intrinsic
cd Intrinsic
pip install .If you plan to edit the code, the README says to use pip install --editable instead so your changes take effect on import. There is also a path that skips cloning entirely.
pip install https://github.com/compphoto/Intrinsic/archive/main.zipBe aware of what setup.py pulls in. The install_requires list contains two dependencies pinned to specific GitHub commits: altered_midas from the CCareaga/MiDaS fork and chrislib from CCareaga/chrislib. Neither is on PyPI under those names, so installation reaches out to GitHub and will fail in an offline or network-restricted environment. The package declares python_requires as >3.6, and the version is 0.0.1.
Once installed, the README's inference example is the shortest real use. It loads the v2 models, loads an image as a NumPy float array in [0, 1], and runs the pipeline.
from chrislib.data_util import load_image
from intrinsic.pipeline import load_models, run_pipeline
models = load_models('v2')
image = load_image('/path/to/input/image')
results = run_pipeline(models, image)
albedo = results['hr_alb']
diffuse_shading = results['dif_shd']
residual = results['residual']The README notes this runs the pipeline using R_0 resizing and returns linear components. What you should see is a dictionary with the keys from the table above, not a file on disk; saving images is left to you. The repository also ships intrinsic_inference.ipynb and recoloring.ipynb at the top level, plus an examples directory containing brown_chairs, spain_museum and yellow_chair, which is the fastest way to see expected output without preparing your own image. If you would rather not install anything, the README links a Colab notebook and a Hugging Face Space.
Where the pipeline breaks down
The residual is the honest part of the output. The README splits it into neg_res, described as the negative part of the residual due to saturated input pixels, and pos_res, described as specularities and light sources. Saturated pixels are therefore not modeled; they are dumped into a residual channel and left there. If your input is a clipped JPEG of a bright window, the decomposition around that region is not something the method claims to recover.
The diffuse shading network is another boundary. The README states it was trained using only a single rendered indoor dataset. The papers target in-the-wild images, so the claim is that the decomposition generalizes well enough to train the network that way, not that the network has seen outdoor or studio lighting distributions. Expect the diffuse shading estimate to be the weakest link on images far from that training distribution.
The physical setup is the third limit. The repository is about single-image decomposition. The topics list mentions multi-illumination, and the companion dataset is linked as compphoto/MIDIntrinsics, but the README's inference path takes one image and returns one decomposition. If your problem is genuinely multi-illumination capture, this repository is the wrong entry point.
Finally, there is no documented CLI. The README shows a Python API and notebooks. There is no command-line entry point, no documented environment variables, and no documented output format on disk. Everything is a Python dictionary in memory.
How this differs from pretrained depth and segmentation models
The closest thing in most engineers' toolkits is a pretrained monocular depth or segmentation model. The difference is in what the output means. A depth model returns a single scalar field; a segmentation model returns labels. Intrinsic decomposition returns multiplicative physical quantities whose product should reconstruct the input, which is why the README can define hr_shd as the implied shading of the final albedo and wb_img as hr_alb multiplied by the luminance of hr_shd. That constraint is what makes per-pixel white balancing and specularity removal meaningful downstream operations rather than aesthetic filters.
There is a second difference in the dependency graph. A depth model usually installs from a package index. This one installs from two pinned GitHub forks, which means your build depends on those repositories continuing to exist at those commits. That is a real supply-chain consideration for anything beyond a research prototype, and it is not something the README addresses.
A third difference is the release cadence. The releases listed are v1.0 in November 2023, v2.0 in September 2024 described as the follow-up paper release, and v2.1 in April 2025 described as updated weights. The last push to the repository was on 2026-04-03. That is a research release rhythm, not a library maintenance rhythm.
Licence, patent status and what that means for adoption
The README states plainly that the implementation is provided for academic use only, and asks that the papers be cited if you use the code or the models. The repository's licence metadata is reported as NOASSERTION, and setup.py sets the license field to an empty string, so there is no standard licence identifier to check against an allowlist. If your organisation runs automated licence scanning, this package will land in the manual review bucket.
The README goes further: the methodology is described as safeguarded under intellectual property protection, with the note Patent pending near the top of the file. It directs licensing inquiries to the SFU Technology Licensing Office and to Dr. Yağız Aksoy, with contact addresses obfuscated in the README against scraping. This is not a legal opinion and none should be inferred from it, but the practical reading is that commercial use requires a conversation, not a code review.
Upgrade cost is low in the normal case and awkward in the unusual one. The package version in setup.py is 0.0.1 and has not tracked the v1.0, v2.0, v2.1 releases, so pip will not tell you which weights generation you are on. The model generation is chosen at runtime by the string passed to load_models, which the README shows as 'v2'. If you move to a newer weight set, expect to re-check the output dictionary rather than the package version.
Editorial conclusion
Adopt compphoto/Intrinsic if you are doing graphics or vision research that needs albedo, diffuse shading and a residual from ordinary photographs, and you can live with the academic-only licence and the two pinned GitHub dependencies. Do not adopt it if you need a permissively licensed component, a supported API surface, or a single-image relighting service. Before writing code, verify three things: that the v2 weights download correctly on your machine, that the academic-use clause covers your intended use, and what the pipeline returns for your own image, since the README lists seventeen output keys and only three appear in the inference example.
Frequently asked questions
What is compphoto/Intrinsic and what does it decompose an image into?
It is the reference implementation for two ACM Transactions on Graphics papers on intrinsic image decomposition. The pipeline returns albedo, diffuse shading and a residual, along with intermediate components such as grayscale shading and low-resolution shading chromaticity.
How do I install compphoto/Intrinsic?
Create a virtual environment, clone the repository and run pip install . inside it, or install directly from the main branch zip without cloning. Note that setup.py depends on two packages pinned to GitHub commits, altered_midas and chrislib, so installation needs network access to GitHub.
Can I use compphoto/Intrinsic commercially?
The README states the implementation is provided for academic use only, and describes the methodology as safeguarded under intellectual property protection with a patent pending note. It directs licensing inquiries to the SFU Technology Licensing Office and to Dr. Yağız Aksoy.
How do I run the pipeline on my own image?
Load the models with load_models('v2'), load your image as a NumPy float array in [0, 1], then call run_pipeline(models, image). The result is a dictionary of linear intrinsic components, including hr_alb, dif_shd and residual.
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/compphoto-intrinsic)