GHS - more intuitive and simpler for the user

GHS (Generalized Hyperbolic Stretch) is an image processing algorithm, especially for difficult images that require a “tone mapper”.

It has the particularity of going off the beaten track by not using the usual concepts (and therefore vocabulary) - introduced by Adobe - ACES - Agx, etc. This complicates its understanding and use.

To make it more intuitive and easier to use, I added (easily) 2 features

  1. Automatically calculate black points and white points (not in Inverse GHS mode). This allows to compensate for example (as poor Dehaze does) the black point in foggy images and take into account the reconstruction of highlights
    As a reminder, unlike other Tone-mappers, these 2 points are in linear mode. The aim of the operation is to bring the data back into the interval [0 1]. Of course it is possible to retouch in manual mode, for example negative values ​​(depending on the images) to open up overly pronounced shadows and help GHS

  2. Provide an evaluation, estimation…, of the Symmetry Point (SP). This value, which has nothing to do with “middle gray,” is essential to understanding GHS and the results. By default, I chose 0.015. The evaluation seems good to me in RGB Luminance mode, acceptable in RGB mode and it is not provided for the other modes, because it has no value. It doesn’t make much sense to try to automate this, as it’s just an evaluation of the symmetry point from the data in linear mode. This point corresponds to the maximum of the histogram in linear mode and with the working profile. It is up to the user to choose and adapt this value by adjusting the slider (SP)

I open a pull request
Pull request 7442

Executables (Appimage, Windows)
ghsauto

I attach the link to Rawpedia which I cannot update
Rawpedia - GHS

Jacques

7 Likes

You can update the page in the git repo for rawpedia now.

This certainly makes it easier to get a good result. There is a small issue with the Auto checkbox on Ubuntu 24.04. When you click on the box to enable Auto mode, it sets the parameters OK but the check mark doesn’t appear in the box. If you click on the box a second time, the check mark appears.

1 Like

@Wayne_Sutton

I have just pushed a change (executables in progress, good I think in 30 minutes) which should overcome this failure

jacques

ghsauto

1 Like

This seems to work properly now. I also have a question regarding the position of the black and white point adjustments in the UI. The RawPedia description recommends carrying out these adjustments before invoking the GHS algorithm to avoid clipping data. Would it not be preferable in this case to put them at the top of the module to avoid having to scroll down and then back up again?

@Wayne_Sutton

Indeed, this seems preferable and more consistent with the other places where the WP and BP are set.
I just moved the White and Black Point settings, as well as the inverse GHS settings, because in this case (rare use), the BP and WP settings are completely different.

Running executables

Jacques

1 Like

I’ve just merged the Pull Request that automatically adjusts (if you want them) the essential white point and black point settings, and provides (I didn’t want to make it automatic) an indication of the symmetry point value.
GHS Auto

Currently, there’s a lot of discussion on the forums about everything related to the concept of “tone mapping”, which is a bit of a catch-all. I’m aiming to write a text on this, but the complexity lies as much in making it understood by different audiences as in the technical descriptions.

I say this because who hasn’t heard of (you’d have to be blind and deaf…) Filmic, Sigmoid, Agx… ‘toe points’ and ‘shoulder points’? This isn’t a criticism, but an observation. These are very good tools, well documented.

Who has heard of GHS or Abstract Profile?

Who knows that RT has a significant number of ‘tone mappers’ (with all the vagueness that lies behind this notion). I’ll list them in no particular order of quality?

  • Dynamic range compression – based on the Fattal algorithm.
  • Tone mapping – based on the Cholesky algorithm.
  • Tone Curves… yes, it’s simple but effective.
  • Abstract profile – my own design based on a virtual ICC profile and the implementation of TRC (Tone Response Curve).
  • Retinex (complex)
  • Log encoding (similar to Filmic)
  • Freeman tone mapper – which I called: gamma based, slope based, RGB channel slope
  • Sigmoid – derived from Darktable’s
  • etc.
  • etc.

Coming back to GHS, it’s seen from afar as being ‘close’ to Agx… The differences:

  • we work entirely in linear mode instead of Ev (log) scales
  • the White points and Black points (linear) as well as the use of ‘Highlight Reconstruction’, especially ‘Color Propagation’, are more than desirable.
  • the reference value is not a Middle Gray, but the peak of the histogram - Symmetry point.
  • GHS stands for ‘Generalized Hyperbolic Stretch’, meaning that depending on the position of the ‘Local Intensity’ slider, the laws and formulas applied are all hyperbolic (Sigmoid is a hyperbolic function) and therefore variable and adapted to the context.
  • the equivalent (if we can use this term by analogy) of ‘toe point’ and ‘shoulder point’ is ‘Protect shadows’ and ‘Protect highlights’.

I’ll stop my comparison there.

Try GHS.

Jacques

1 Like

Hello.
I create a Pull Request for GHS improvement’s
GHS improvments

This PR has two objectives:

  1. To better adapt the maximum possible white-point setting in difficult situations (artificial lighting, LEDs, shows, etc.)

The maximum is currently set to 5 (linear scale where the theoretical maximum is 1) and in the original PixInsight software (astro photo) it is set to 2.
On difficult images and with ‘Color propagation’ as the Highlight Reconstruction method, I get 10.6…By comparison, the same image gives 2.8 with ‘Inpaint opposed’. This does not mean that Color Propagation is ‘perfect’, but it must at least be possible to make the adjustment possible.
So I raised the maximum to 50 and added a logarithmic scale for the slider.

  1. Set the Symmetry point (SP) to the calculated value of the histogram peak by default (as recommended by the algorithm author).

I’ve tried this on many images and this recommended setting works well, although it can still be adjusted manually.
This is only functional in RGB mode (if possible RGB luminance). The system is inactive in other modes (HSL, etc.). Similarly, the display of the recommended value which remains displayed when switching to ‘manual’ is only activated in RGB mode
So I added a checkbox integrated into the “Symmetry point” slider…

Executables running (always with windows problem)
Text ghsimprov

Jacques

2 Likes

Hello all.

A few additional details on the implementation of GHS in RT and its implications.

GHS was developed by two researchers in 2021/2022 and ported to PixInsight and Siril, but limited to Astrophoto. After examining the GHS code (complex and partial - Siril’s is incomplete), I found that it should allow for elegant and seamless resolution of problems known as tone mapping, or more simply adjusting image contrast. Mathematically, it is - by far, if we exclude solutions based on Laplacian transformations and Fourier transform - the most complex processing method compared to TRC, Sigmoid, Filmic, etc. (as the title says, it’s all about using multiple hyperbolic functions and not just one).

But, there are several buts:

  • The system was designed for astrophotography, generally low-exposure images – where highlights are rare. The exposed areas of ‘stars and nebulae’ are fairly easily identifiable. This has two consequences: the Symmetry Point (SP) setting is done fairly intuitively by pointing at the brightest nebula. Adjusting the WP and BP is desirable but not critical; BP is often close to 0, and HP is rarely above 1. Note that GHS works entirely in linear mode (Ev is not used), and all data must be between 0 and 1. If they fall outside these values, the values ​​are ‘clipped’ and lose much of their relevance. If they fall within these values, the images will be underutilized and low in contrast.
  • Daytime images used in ‘normal’ photography - those that we are trying to process with a ‘Tone mapper’ - have strong dynamics, BPs that can be very different from 0 (from 0 to 0.2) and WPs (e.g. sunset, LED, etc.) that can have very high values, for example 10.5. On the other hand, I challenge anyone on a ‘normal’ image to find where the Symmetry point (SP) is. This Symmetry point has very little to do with the Midgrey used in almost all tone mappers.

In RT how are the WP, BP and Dynamic Range and Midgrey calculated for ‘Log encoding’, Sigmoid, Color Appearance (CAM16 & JzCzHz)? The choice was made to take this calculation out of the loop that manages ‘Selective Editing’. It is done upstream just after demoisaicing. The advantage is that the calculation is independent of what is done downstream (obvious) and therefore does not influence it… The big disadvantage is that if algorithms (especially those of SE) modify the RGB values, the values ​​used are wrong… (in some cases very wrong). To avoid these problems, other software sets default values, which the user has to adjust manually…this requires a significant mastery of the concepts and their implications.

GHS led me to rack my brains and start again with the definitions of BP, WP, and Symmetry Point (SP) in linear mode.
The calculation of BP and HP is done just before the implementation of GHS, in the ‘engine SE’ loop (with possible multi Spot), which is activated with a very low Stretch Factor value (0.001) to have very little influence, but is nevertheless taken into account. This leads to total dependency on the code and makes it almost impossible to ‘go back’. The values ​​are exact (to the precision of the calculations in ‘float’) and bring all the data, which, for example, were in the interval [0.2, 10.5] before calculating the BP and HP, back to [0, 1].
It was more difficult for me to calculate the Symmetry Point. The choice I made:

  • after calculating the BP and WP;
  • I evaluate the histogram in linear mode (without gamma) and with the Working Profile. I simply calculate the maximum value which will become the SP value used by passing parameters. Here again we see that the calculation is ‘exact’ (with the inaccuracies of the calculations) because the calculation is done just before the GHS sliders are activated and after the calculation of the WP and BP. Here again it is difficult to ‘go back’.

I also had to add two additions that are missing from the initial GHS algorithm (at least the accessible code).

  • I adjust the midtones using an ‘Ev’ function derived from ‘Tone Equalizer’ rather than the function used by PixInsight, which is a transform of ‘Stretch Factor’. The reason is that after GHS on ‘normal’ images, we often fall outside the [0 1] range.
  • I added a ‘Highlight attenuation’ checkbox, in particular to account for the fact that there is a gamma in the display and output profile, and that this profile is smaller than the Working profile (often sRGB).

All these specific features had consequences:

  • on the engine code (obvious) and GUI, in particular to count the number of times parameter passing functions are called between ‘engine SE’ and GUI, and to avoid infinite looping.
  • graying out certain parts of the GUI to allow for proper calculation evaluation.
  • the inability to ‘go back’ makes certain features difficult or even impossible in some cases, such as ‘history’ for BP and WP calculations.

I hope this ‘addition’ will clarify things a little and not complicate them.

Jacques

3 Likes

I think I found a simple solution with ‘set_sensitive’, for access to sliders White point et Black point.

This does not change the results but makes the whole thing more coherent.

executable
Text ghsimprov

I had this Pull Request checked (several times) by Copilot, who didn’t find any critical errors. These are often recommendations (my code is complex and long…). I also cleaned up the code and made small changes.

Text ghsimprov

Hello

I just merge with ‘dev’ the pull request "ghsimprov’

I am currently working on fixing the ‘merge’ issues after this commit, for the other 2 Pull Requests in progress which implement common processes and variables (not easy).

Thank you

Jacques

1 Like

A few technical additions

  • I changed the label and tooltip of the BPlinear and WPlinear frames. When I moved it up in the panel, I forgot to remove the highlight checkbox (which is always at the bottom).
  • I reduced the saturation complement (which is normally linked to any tone mapper) by about 50%. I chose not to add a slider to avoid complicating the interface, but I can add one if you wish. This saturation complement fills the gap created by the Stretch.
  • I also limited the calculated and estimated Symmetry Point (SP) value to about 0.85, because for certain illuminant (LED, etc.) and color combinations, it’s easy to end up with colors that are very (very) out of gamut, which distorts the analysis, resulting in a peak that isn’t representative of the overall histogram (in Working Profile mode and gamma=1).

Just quickly stepping through the main GHS functions in the cam16slope branch, I noticed the following:

  1. If you change from GHS to either the Shadwos/Highlights or Equalizer options, the GHS menu for Black Point, White Point remains (albeit greyed out) as does Inverse GHS.
  2. Checking Inverse GHS and then unchecking it does not return the image to its initial state

I must say that GHS is an exciting innovation and something of a game changer for processing ETTR images. It is quick and simple and produces excellent results.

@Wayne_Sutton

Thanks for this quick test.

To simplify the adjustments, I’ll make them, as far as the GUI is concerned, in the cam16slope branch, even if it concerns GHS… to avoid tedious updates. I just push a change.

I haven’t been able to reconstruct exactly what you’re describing, but something similar. Part of the GHS menu remained present when switching to the other two methods, especially if the complexity level was changed. The Selective Editing GUI is particularly complex…
If the bad behavior continues after this change, it would be interesting to give me the exact process for triggering the various actions, because I may have forgotten something.

As for “Inverse GHS,” I’ll look into it; I’m not sure there’s always a solution, given the dynamic calculations of WP and BP, which are necessarily different in direct and inverse mode. Same remark as above to reconstruct the bad behavior of inverse_GHS

Executables running
Text cam16slope

Thank you

Jacques

1 Like

The two issues raised seem to have been resolved in this latest version. I’m not sure if the following is an issue or not:

1.Neutral Profile
2. GHS with Global spot
3. Auto WP & BP
4. Adjust Stretch slider
5. Check & uncheck Inverse GHS checkbox ==> the curve (and image) do not return to the settings prior to checking and unchecking the Inverse GHS checkbox.

@Wayne_Sutton

Thank you for testing :slight_smile:

It’s already a good thing if the first problem is solved… it’s GUI. To confirm :grinning:

The second problem with “inverse GHS” is much more complex, and it’s only partially GUI. This is because in the ‘engine’ code, the entire action from the calculation of the BP or WP to the final result is performed without clipping the data above 65535. However, to avoid crashes in “inverse” mode, I had to clip the data. :worried:
So if we enable “inverse GHS,” the data is clipped, and if we return to “normal” the data has been clipped, and therefore different (not in all cases).
The solution isn’t simple; I don’t even know if it’s solvable…

My suggestion, still in this branch:

  1. Remove the checkbox from “basic” mode, because it’s not easy to set the BP and WP and to “understand” what’s being done in “inverse” mode.
  2. Leave the checkbox in “standard” and “advanced” mode.
    This will prevent bad behavior in most cases.

Could you open an issue with the problem posed by “inverse GHS”? And I’ll see what I can do. Thank you.

Jacques

@Wayne_Sutton

After further investigation, it turns out that the problem with “Inverse GHS” is more serious than I thought.
I’ll make a simple change to ‘dev’ to disable this checkbox and open an issue myself.
#7528
Issue 7528

Thank you.

Jacques

@Wayne_Sutton and others

I’ve just created a Pull Request to try to resolve the complex “Inverse GHS” issue.

I’ve named it “GHS - Inverse GHS - Bad Behavior - Magic Keys.”
Pull Request

I’ve attached the link to the original issue, with comments.
Issue 7528

Executables (with always Windows problems)
Text ghsinverse

Thank you

Jacques

1 Like

@jdc I’m traveling all week so I have only been able to have a cursory glance at this. I was bewildered by the Magic Keys label (this is the name of a commercial product btw) and had to read the tooltip several times to understand what it was all about. IMHO it’s not necessary because if I have understood correctly the values 0.001 and 0.002 simply unlock the WP, BP and Inverse GHS functions which are normally greyed out when the Stretch factor slider is moved beyond these values. The tooltip explanation should suffice.
In practice, it doesn’t seem to do quite what it says in the tooltip because the WP & BP adjustments stay greyed out at those values “Even in Auto Black Point & White Point mode”.