"Sigmoidal" minimization of resampling filter haloing & blur

Discuss digital image processing techniques and algorithms. We encourage its application to ImageMagick but you can discuss any software solutions here.
NicolasRobidoux
Posts: 1944
Joined: 2010-08-28T11:16:00-07:00
Authentication code: 8675308
Location: Montreal, Canada

Re: "Sigmoidal" minimization of resampling filter haloing

Post by NicolasRobidoux »

fmw42 wrote:...
Are you suggesting there is a bug in -sigmoidal-contrast in either IM 6 or 7?
A bug, or a feature I don't like. (I checked the formulas---not the code---at http://osdir.com/ml/video.image-magick. ... 00006.html, and they seem correct.)
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: "Sigmoidal" minimization of resampling filter haloing

Post by fmw42 »

NicolasRobidoux wrote:
fmw42 wrote:...
Are you suggesting there is a bug in -sigmoidal-contrast in either IM 6 or 7?
A bug, or a feature I don't like. (I checked the formulas---not the code---at http://osdir.com/ml/video.image-magick. ... 00006.html, and they seem correct.)

What version did you go back to for it to work the way you liked?
NicolasRobidoux
Posts: 1944
Joined: 2010-08-28T11:16:00-07:00
Authentication code: 8675308
Location: Montreal, Canada

Re: "Sigmoidal" minimization of resampling filter haloing

Post by NicolasRobidoux »

Fred: I did not revert version. The enhance.c source code contains alternate versions of the sigmoidal-contrast formulas which can be turned on by modifying precompiler conditionals. So, I changed two "#if 1"s to "#if 0"s and recompiled.
Find "#define sigmoidal(a,b,x)" in the source code. The first "#if 1" is right after, and the second is the following one.
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: "Sigmoidal" minimization of resampling filter haloing

Post by magick »

We'll restore the expanded sigmoidal contrast definition assuming Anthony does not object.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: "Sigmoidal" minimization of resampling filter haloing

Post by fmw42 »

magick wrote:We'll restore the expanded sigmoidal contrast definition assuming Anthony does not object.

What is the functional difference? When was it changed?

If a significant functional difference, then how about a -define to switch between them?
NicolasRobidoux
Posts: 1944
Joined: 2010-08-28T11:16:00-07:00
Authentication code: 8675308
Location: Montreal, Canada

Re: "Sigmoidal" minimization of resampling filter haloing

Post by NicolasRobidoux »

fmw42 wrote:...What is the functional difference?...

Code: Select all

#define sigmoidal(a,b,x)  (1/(1+exp((a)*((b)-(x)))))
#if 0
        /* Simpilified function scaling,
         * with better 'contrast=0' or 'flatline' handling (greyscale)
         */
        double
          u0 = sigmoidal(contrast,QuantumScale*midpoint,0.0),
          u1 = sigmoidal(contrast,QuantumScale*midpoint,1.0);
        sigmoidal_map[i]=(MagickRealType) ScaleMapToQuantum(
           (MagickRealType)(MaxMap*(
               (sigmoidal(contrast,QuantumScale*midpoint,(double)i/MaxMap)
                  -(u0+u1)/2.0)/(u1-u0+MagickEpsilon)+0.5)   ));
#else
        /* Scaled sigmoidal formula...
             (1/(1+exp(a*(b-u))) - 1/(1+exp(a))) /
                     (1/(1+exp(a*(b-1)))/(1+exp(a)))) */
        sigmoidal_map[i]=(MagickRealType) ScaleMapToQuantum((MagickRealType)
          (MaxMap*((1.0/(1.0+exp(contrast*(midpoint/(double) QuantumRange-
          (double) i/MaxMap))))-(1.0/(1.0+exp(contrast*(midpoint/
          (double) QuantumRange)))))/((1.0/(1.0+exp(contrast*(midpoint/
          (double) QuantumRange-1.0))))-(1.0/(1.0+exp(contrast*(midpoint/
          (double) QuantumRange)))))+0.5));
#endif
        continue;
      }
#if 0
    {
      /* Inverse -- See
         http://osdir.com/ml/video.image-magick.devel/2005-04/msg00006.html
      */
      double
        min = sigmoidal(contrast,1.0,0.0),
        max = sigmoidal(contrast,QuantumScale*midpoint,1.0),
        xi  = min+(double)i/MaxMap*(max-min);
      sigmoidal_map[i]=(MagickRealType) ScaleMapToQuantum(
         (MagickRealType)(MaxMap*(
             QuantumScale*midpoint-log((1-xi)/xi)/contrast) ));
    }
#else
    /* expanded form of the above */
    sigmoidal_map[i]=(MagickRealType) ScaleMapToQuantum((MagickRealType)
      (MaxMap*(QuantumScale*midpoint-log((1.0-(1.0/(1.0+exp(midpoint/
      (double) QuantumRange*contrast))+((double) i/MaxMap)*((1.0/
      (1.0+exp(contrast*(midpoint/(double) QuantumRange-1.0))))-(1.0/
      (1.0+exp(midpoint/(double) QuantumRange*contrast))))))/
      (1.0/(1.0+exp(midpoint/(double) QuantumRange*contrast))+
      ((double) i/MaxMap)*((1.0/(1.0+exp(contrast*(midpoint/
      (double) QuantumRange-1.0))))-(1.0/(1.0+exp(midpoint/
      (double) QuantumRange*contrast))))))/contrast)));
#endif
The "#if 0"s above were "#if 1"s until today, so what you are using right now are actually the first version of each of the two functions, which appear to have been put together so that things don't break down when contrast = 0, in which case u0=u1. The bad news for me is that the sigmoidal map which is supposed to be an inverse is then fairly far from being an inverse even when far from contrast=0.
NicolasRobidoux
Posts: 1944
Joined: 2010-08-28T11:16:00-07:00
Authentication code: 8675308
Location: Montreal, Canada

Re: "Sigmoidal" minimization of resampling filter haloing

Post by NicolasRobidoux »

With the "correct" sigmoidal and IM 7 in HDRI, here are code and results:

Code: Select all

magick rose: +sigmoidal-contrast 4,50% -filter lanczos -resize 800x -sigmoidal-contrast 4,50% -depth 8 lanczosFourFifty.png
Image
It's both less aliased and sharper and "straight" sRGB and linear light lanczos. -sigmoidal-contrast 6,50% also looks good (better, arguably), but 10,50% is definitely too much.
NicolasRobidoux
Posts: 1944
Joined: 2010-08-28T11:16:00-07:00
Authentication code: 8675308
Location: Montreal, Canada

Re: "Sigmoidal" minimization of resampling filter haloing

Post by NicolasRobidoux »

Here is the 6,50% version:
Image
It really does look good. The worst haloing artifacts are gone, there is less staircasing, and the image is sharper overall, all without noticeable colour drift.
NicolasRobidoux
Posts: 1944
Joined: 2010-08-28T11:16:00-07:00
Authentication code: 8675308
Location: Montreal, Canada

Re: "Sigmoidal" minimization of resampling filter haloing

Post by NicolasRobidoux »

The next thing I'll try is converting from sRGB to linear RGB, applying the contrast reducing sigmoidal colour transform, enlarging, and then undoing the conversions.
Although the HVS is more sensitive w.r.t. darks than lights and consequently it is probably not necessary or even desirable that the sigmoidal be "symmetric" w.r.t. linear ("physical") light, I suspect that for each sharpening filter there is a "colourspace" in which it gives best results in general. This is a first step toward figuring out what this colourspace may be for lanczos 3. (The other obvious thing to do besides playing with the contrast variable is playing with the midpoint.)
NicolasRobidoux
Posts: 1944
Joined: 2010-08-28T11:16:00-07:00
Authentication code: 8675308
Location: Montreal, Canada

Re: "Sigmoidal" minimization of resampling filter haloing

Post by NicolasRobidoux »

Here is the result of going through "6,50% sigmoidal colorspace" through linear RGB instead of straight sRGB:
Image
Code:

Code: Select all

magick rose: -set colorspace sRGB -colorspace RGB +sigmoidal-contrast 6,50% -filter lanczos -resize 800x -sigmoidal-contrast 6,50% -colorspace sRGB -depth 8 lanczosSixFiftyLinear.png 
Rather unsurprisingly, staircasing near sharp dark features is more subdued when the sigmoidal transform is applied directly to sRGB, but near light features, it is less pronounced going through linear first. When working with linear light, moving the midpoint north (up from 50%) may be a good idea.
Last edited by NicolasRobidoux on 2012-07-14T07:41:28-07:00, edited 7 times in total.
NicolasRobidoux
Posts: 1944
Joined: 2010-08-28T11:16:00-07:00
Authentication code: 8675308
Location: Montreal, Canada

Re: "Sigmoidal" minimization of resampling filter haloing

Post by NicolasRobidoux »

If you want to download these images directly: http://web.cs.laurentian.ca/nrobidoux/misc/sigmoidal.
NicolasRobidoux
Posts: 1944
Joined: 2010-08-28T11:16:00-07:00
Authentication code: 8675308
Location: Montreal, Canada

Re: "Sigmoidal" minimization of resampling filter haloing

Post by NicolasRobidoux »

Now, let's put it all together: Sigmoidal with a raised midpoint through linear RGB with the EWA LanczosSharp filter:

Code: Select all

magick rose: -set colorspace sRGB -colorspace RGB +sigmoidal-contrast 10,80% -filter LanczosSharp -distort resize 800x -sigmoidal-contrast 10,80% -colorspace sRGB -depth 8 lanczosSharpTenEightyLinear.png
I need to experiment some more, but it does look pretty good right out of the box:
Image
It's a bit on the blurry side (typical of EWA LanczosSharp), but it does look good. You'd never know this is a three lobe low-pass filter.

Now: I've still not quite figured what the best "really sharp" EWA Lanczos is. For upsampling, it's definitely not what I've been calling LanczosSharpest (-filter lanczos -define filter:blur=0.88549061701764 -distort resize).

But I'm pretty stoked at this, to the extent of wondering if "going through a sigmoidal colour space" would be worthwhile when downsampling.
NicolasRobidoux
Posts: 1944
Joined: 2010-08-28T11:16:00-07:00
Authentication code: 8675308
Location: Montreal, Canada

Re: "Sigmoidal" minimization of resampling filter haloing

Post by NicolasRobidoux »

I may as well add the same "raised midpoint" sigmoidization through Linear RGB to regular (orthogonal) Lanczos:

Code: Select all

magick rose: -set colorspace sRGB -colorspace RGB +sigmoidal-contrast 10,80% -filter Lanczos -resize 800x -sigmoidal-contrast 10,80% -colorspace sRGB -depth 8 lanczosTenEightyLinear.png
Image
NicolasRobidoux
Posts: 1944
Joined: 2010-08-28T11:16:00-07:00
Authentication code: 8675308
Location: Montreal, Canada

Re: "Sigmoidal" minimization of resampling filter haloing

Post by NicolasRobidoux »

For those of you who don't know what image is being enlarged: It's
Image
which is being enlarged from 70x46 to 800x526, that is, more than 11 times.
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: "Sigmoidal" minimization of resampling filter haloing

Post by anthony »

NicolasRobidoux wrote:Final comment: As has been discussed elsewhere, standard -resize methods with negative lobes have artifacts when using non-HDRI ImageMagick that come from over- and undershoots being clipped between the two orthogonal passes. (This does not affect -distort resize methods.) I would guess that, in 16-bit IM (the default), you could minimize these artifacts using this "sigmoidal" trick: If there are less over and undershoots, there is less to clip, and if there is less to clip, clipping between the two orthogonal passes will hurt less.

Yes distort resize will not have a 'between pass clipping', But BOTH will still get clipping after the resize is complete if the halo effects goes beyond the image color range (burn and clip), unless HDRI is used. That is just the nature of things. Distort just does the vertical and horizontal burn and clip equally, Resize does not.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
Post Reply