Experiments with a scene-referred local contrast module - proof of concept

Hello all!

I am currently playing around with some ways to achieve fast and controllable local contrast / clarity enhancement within the scene-referred workflow.
Within the process, I’ve experimented with a new module that leverages the luminance masking logic of the tone equalizer module to extract the local features to emphasize.
It aims to provide direct artistic control and is relatively consistent when zooming the viewport except for very small feature scale settings.

It’s really just an experiment out of interest and most boilerplate-code is just vibe-coded around the core-logic with AI. But maybe it’s interesting for some to play around with it :wink:

You can try it out from my branch:

and here is an Appimage:

(For some reason, the import dialog is blank in the AppImage. Any help using the appimage build script properly on arch linux is wamly appreciated)

Let’s start with some visuals (with A Winter Scene to Play With - #14 by Zbyma72age)
Basic development:


With local contrast RGB:

Motivation
I tend to struggle with the existing tools for local contrast alteration in the scene-referred workflow:

  • With Contrast Equalizer, it is often hard to achieve results that do not look overprocessed. Although the edge preservation control exists, edge artifacts are common and it is hard to target the desired detail levels exactly.
  • Local contrast is designed for the display-referred workflow and hence not really usable before the tone mapper. It also breaks colors and global contrast easily.
  • Diffuse and sharpen is a very versatile tool, but due to it’s design as an all-purpose-precision-tool, it is inconvenient for focusing on the task of controlling local contrast. The settings are complex and do not directly correspond to the controls over the local contrast you want to achieve. Also, it is relatively slow. What’s most problematic for me is the scale variance. With most local contrast presets, you really need to have high quality preset mode on all the time when editing your image once D&S is enabled to get an accurate preview. This renders the whole editing process quite cumbersome.

In sum, I’d like to have a simple module for local contrast that allows me to control which details to enhance while not producing strong halos or other artifacts.

Principle
The module applies scene-referred unsharp masking.
First, it generates a smoothed and edge-aware luminance mask like the tone equalizer.
Then, the luminance is also calculated for each pixel locally (without any smoothing).
The exposure difference (in EV) between the smoothed and the local and smoothed luminance is then calculated for each pixel and used as a detail mask.
To enhance / reduce those local details, we simply increase the exposure difference by some factor (the “detail boost” parameter).

For example, given a pixel is 1 EV darker than the smooth luminance mask at this location and the detail boost parameter is set to 2.
We hence want to double the exposure difference, so that the pixel will be 2 EV darker than the smooth luminance mask value.
So the pixel’s exposure is reduced by 1 EV.

As the alteration of the image data is simply a per-pixel exposure shift realized by multiplication in scene-linear space, the channel ratios and corresponding image properties for the downstream processing are preserved.

Usage

detail boost: The strength of the effect. values > 1 will enhance features and < 1 will mute features

The other settings control how the features are extracted (most important first):

  • feature scale: Remapped version of the “Smoothing diameter” from tone eq. It controls which scale of features to enhance
  • edges refinement / feathering: like from tone eq. Larger values control edge halos and reduce the effect on already pronounced features so that only the more subtle features get enhanced.
  • display detail mask: Show the extracted details. It helps to understand which details the current settings extract that will be modified.
  • luminance estimator: Exactly the luminance estimator of tone eq
  • feature extractor: the preserve details setting of tone eq. Renamed to make it more clear that it now acts for feature extraction
  • filter diffusion: Like in tone eq

A good workflow is to sweep through feature scale to find the scale you are interested in and then adjust the other parameters.

Examples
Crops from the images above - notice that the snow texture is enhanced without halos on the branches :


Some portrait stuff - toying around with the skin structure. Also showing the detail masks:

Without local contrast:


Larger Details - enhance the rough patches of makeup

Finer Details - pronounce the small skin features and make edges look sharper:

40 Likes

Uhh exciting! Looking forward to trying this :-)! I’ve been longing for a scene referred local contrast module for a quite some time.

1 Like

Thanks for doing this! I share your frustration with existing tools for local contrast.

The logic of your design seems very intuitive, people who have invested in understanding how the tone equalizer works can use that knowledge to in your module too, and the approach should lend itself very well to presets and multiple instances.

5 Likes

Hello,

I tried to test it, but I’m having a problem with the appimage,

cc@Laptop-CB:~/.local/Programmes/Darktable_Test$ ./DT.sh/tmp/.mount_DarktaiKNNHn/usr/bin/darktable: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.42’ not found (required by /tmp/.mount_DarktaiKNNHn/usr/bin/…/lib/libssh.so.4)

We already have three modules that work very well and that I always use.

  1. The local contrast module, which I use to recover detail in highlights and shadows

  2. The contrast equaliser module, for which I have created three presets that launch automatically and that I can use to adjust clarity, texture and local contrast

  3. D&S with the sharpness preset without AA

However, I think there is a place for this type of module. Personally, I can see a module that would be easy to use, i.e. one with several sliders for ‘Detail, Clarity, Texture, etc.’ whose mask, which you have designed very well, would be hard-coded.

I also completely agree with this observation.

This is just an idea without having tested it.
Many thanks for sharing your work.
Greetings from Lubéron,
Christian

4 Likes

Results look promising.
You link with a very new version of glibc library. I think, most of Linux distributions use older version, on my Ubuntu I use 2.39.
I would be glad to test it, if you create an image with older glibc library. Thanks.

1 Like

I tried running it, but got the error

/tmp % ./Darktable-5.5.0+99.g01b28e5273-dirty-x86_64.AppImage                   
/tmp/.mount_DarktaLKkLkL/usr/bin/darktable: symbol lookup error: /tmp/.mount_DarktaLKkLkL/usr/bin/../lib/libpangoft2-1.0.so.0: undefined symbol: FcConfigSetDefaultSubstitute

I thought AppImages are self-contained, so it would have the version it needs?

1 Like

Not completely. I encountered similar issues when I did the first AgX AppImage.

2 Likes

Please check this for further info regarding AppImage: Binaries compiled on old enough base system

2 Likes

Thanks, but is the libpangoft2 error above also coming from this?

Thanks for the hints!
I’ve now simply built the AppImage within a docker container, replicating the github action for nightly builds from the darktable Repo.
I hope this works now!

https://github.com/wilecoyote2015/darktable/releases/download/local_contrast_0.2/Darktable-5.5.0+99.g01b28e5273-dirty-x86_64.AppImage
(The link in the first post should also point there)

4 Likes

great, it’s starting!

1 Like

I must say, excellent work!

I’ve just tried it out on a couple of photos and I have to say that I’m very impressed with the module.

In addition to the examples you’ve already shown above for increasing local contrast, what also appeals to me is the diffusion—in other words, the exact opposite.

Similar to contrast equalizer, you can also smooth out the texture. This is particularly advantageous for landscape shots and all other shots where rough local contrasts make the scene look restless.

Here are a few examples:

Here, in addition to diffusion, I used a second instance to enhance fine local contrast:

Here is an example with guided filter. Notice how the harsh local contrast, especially in shadows, is reduced with diffusion, making the scene look much more natural:

17 Likes

As someone who takes lots of woodland shots where there is a lot of chaotic contrast, this also sounds very appealing to me. I already use Contrast Equalizer for this purpose, but another tool in the toolbox would be very welcome.

3 Likes

Nice POC!

Tried it and found that its possible to quite easily add a global contrast adjustment as part of this module with:

apply_local_contrast()
...
    // Apply correction in linear space
    // global_scale has the same range as detail_scale.
    const float multiplier = exp2f(correction_ev) * powf(lum_smoothed / 0.1845f, global_scale) * 0.1845f / lum_smoothed;

Result is similar to the tone equalizer but with just one slider which is kinda nice.

One image for testing, just white balance, denoised, and sigmoid with contrast=1.8, only changing local contrast rgb.

12 Likes

This is fast, compact and works really well…I just played around with it…

I have made a windows build for people to try it but I can’t find my phone to upload it to dropbox…as soon as I do I will share the link…

Really nice…thanks for sharing this with us…

2 Likes

Sorry, probably you don’t need this any more, but that’s the Dockerfile (rename it) I use to build AppImages. Instructions at the end as comments.

Dockerfile.txt (2.3 KB)

1 Like

After playing around a little I haven’t developed a favourite between this, DoS or the original local contrast, but they certainly all offer something different.

My only input at this stage is to ask whether all the different luminance estimators are necessary? I have noticed very little difference, if any, between them. Perhaps only ‘max rgb’ gave something noticeably different to ‘euclidean norm’, though you might have tested more than me. Fewer options might improve user experience? (Same for the feature extractor.)

1 Like

why limit options? These estimators are available so why not use them.
Most images may not require all of these different estimators, but darktable also focuses on those cases where a ‘one size fits all’ approach is not sufficient.

1 Like

My comment was more practical than theoretical. If they all produce essentially the same result there is no point keeping them, it’s just more clutter. Of course, if there are significant differences they could be worth keeping.

1 Like

Thanks anyway!