Sigmoidized Ginseng (pronounced "Jinc-Sinc") resampling

Questions and postings pertaining to the usage of ImageMagick regardless of the interface. This includes the command-line utilities, as well as the C and C++ APIs. Usage questions are like "How do I use ImageMagick to create drop shadows?".
NicolasRobidoux
Posts: 1944
Joined: 2010-08-28T11:16:00-07:00
Authentication code: 8675308
Location: Montreal, Canada

Re: Sigmoidized Ginseng (pronounced "Jinc-Sinc") resampling

Post by NicolasRobidoux »

Indeed, using the alternate sigmoid type function shown in blue in http://en.wikipedia.org/wiki/File:Gjl-t%28x%29.svg, namely x/sqrt(1+x^2), with inverse x/sqrt(1-x^2) gives very similar results to using the standard sigmoid function 1/(1+exp(-x)). Maybe better. Here is the code that goes into enhance.c in case anybody cares. The "safer" value with this version of sigmoidization when used with Ginseng (Jinc-windowed Sinc 3-lobe) is about 6.51875.

Code: Select all

  /*
    Sigmoidal with inflexion point moved to b and "slope constant" set to a.
  */
#if 0
#define Sigmoidal(a,b,x) ( 1.0/(1.0+exp((a)*((b)-(x)))) )
#else
#define Sigmoidal(a,b,x) ( \
  ((a)*((x)-(b)))/sqrt(1.0+((a)*((x)-(b)))*((a)*((x)-(b)))) )
#endif
  /*
    Scaled sigmoidal formula: (1/(1+exp(a*(b-x))) - 1/(1+exp(a*b)))
                              /
                              (1/(1+exp(a*(b-1))) - 1/(1+exp(a*b))).
    See http://osdir.com/ml/video.image-magick.devel/2005-04/msg00006.html and
    http://www.cs.dartmouth.edu/farid/downloads/tutorials/fip.pdf.
  */
#define ScaledSigmoidal(a,b,x) (                    \
  (Sigmoidal((a),(b),(x))-Sigmoidal((a),(b),0.0)) / \
  (Sigmoidal((a),(b),1.0)-Sigmoidal((a),(b),0.0)) )
#if 0
#define InverseScaledSigmoidal(a,b,x) (                                     \
  (b) - log( -1.0+1.0/((Sigmoidal((a),(b),1.0)-Sigmoidal((a),(b),0.0))*(x)+ \
  Sigmoidal((a),(b),0.0)) ) / (a) )
  /*
    The limit of ScaledSigmoidal as a->0 is the identity, but a=0 gives a
    division by zero. This is fixed below by hardwiring the identity when a is
    small. This would appear to be safe because the series expansion of the
    sigmoidal function around x=b is 1/2-a*(b-x)/4+... so that s(1)-s(0) is
    about a/4.
  */
#else
#define InverseScaling(a,b,x) ( \
  ((Sigmoidal((a),(b),1.0)-Sigmoidal((a),(b),0.0))*(x)+ \
  Sigmoidal((a),(b),0.0)) )
#define InverseScaledSigmoidal(a,b,x) ( \
    (b) + \
    InverseScaling((a),(b),(x)) / \
    ( (a)*sqrt(1.0-InverseScaling((a),(b),(x))*InverseScaling((a),(b),(x))) ) )
#endif
Barring more obvious visual differences (or results from quantitative comparison), I'll conclude that it's not worth changing the sigmoidal function in IM for the purpose of improving sigmoidization, but if I move to a system in which I don't want to use LUTs, using the cheaper sigmoidal-type function is probably good enough.
With an equal amount of "artifacts", it kinda looks like the one that's already in IM (with the standard "exponential" sigmoid function") is better at suppressing halos. So, my dirty back of the envelope was not really off. The new one is generally sharper, though. But sharpness is not the be-all and end-all (in my book, at least).
Last edited by NicolasRobidoux on 2012-09-01T16:08:45-07:00, edited 2 times in total.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Sigmoidized Ginseng (pronounced "Jinc-Sinc") resampling

Post by fmw42 »

Just found this which seems to imply that sigmoidal-like (exponential) function used in IM is related or perhaps the same (after proper normalization) to the hyperbolic tangent. http://de.wikipedia.org/wiki/Sigmoidfunktion

P.S. Seems like the better results you are getting from the old exponential formula over the last one may be due to the faster saturating curve (greatest slope at 0), the best of which would be the err function (but not by much over the IM sigmodal or hyperbolic tan). But the cost of computing the erf is probably much greater and the difference from the curves is small.

EDIT (by Anthony); English version of link is: http://en.wikipedia.org/wiki/Sigmoid_function
NicolasRobidoux
Posts: 1944
Joined: 2010-08-28T11:16:00-07:00
Authentication code: 8675308
Location: Montreal, Canada

Re: Sigmoidized Ginseng (pronounced "Jinc-Sinc") resampling

Post by NicolasRobidoux »

@Fred: Good find. This explains why the standard 1/(1+exp(-t)) is omitted from the graph I linked earlier: Once you start normalizing the slope (at the "center" for example) as well as the gamut, the standard logistic sigmoid is exactly the same as tanh.
(Note: I have my own normalization: I always use one of two contrast values ("safe" and "not so safe"), which have to do with bringing down haloing to one of two levels. So, in a sense, I always compare methods at "roughly equivalent halo when dealing with black on white text".)
The normalization within IM is close in spirit to the one used in the plot http://en.wikipedia.org/wiki/File:Gjl-t%28x%29.svg, except that it is used to make things "different" instead of "the same". So, what you've found, is that replacing the current IM sigmoid with tanh would give exactly the same family of contrast functions. (To get the same curve, you'd need to double the contrast value, or something like that, but that's it.)
One less thing to check!
Thank you!
NicolasRobidoux
Posts: 1944
Joined: 2010-08-28T11:16:00-07:00
Authentication code: 8675308
Location: Montreal, Canada

Re: Sigmoidized Ginseng (pronounced "Jinc-Sinc") resampling

Post by NicolasRobidoux »

I had been a bit sloppy normalizing the "cheap sigmoid"'s safe contrast value. I think that the logistic (standard) sigmoid wins by a nose when I compare apples to apples.
Also, it looks like things "jump around" more with small contrast change with this one. I like "stability".
NicolasRobidoux
Posts: 1944
Joined: 2010-08-28T11:16:00-07:00
Authentication code: 8675308
Location: Montreal, Canada

Re: Sigmoidized Ginseng (pronounced "Jinc-Sinc") resampling

Post by NicolasRobidoux »

I redid the tests more carefully, and it looks to me like the "algebraic" sigmoid is sharper at equivalent halo suppression, which many people will like more.
(*&^%$#@! I thought I was done. Now I'm going to either have to check a bunch of sigmoids or figure out exactly what's going on.)
I'm going to have to see if it makes a visible difference in the colour bleed.
Last edited by NicolasRobidoux on 2012-09-01T16:29:33-07:00, edited 1 time in total.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Sigmoidized Ginseng (pronounced "Jinc-Sinc") resampling

Post by fmw42 »

The erf may be slightly better, though the curves are so close that it probably won't matter. But I expect the computation cost of the erf would be much higher than the tanh. Probably not worth investigating given that your 1/sqrt(1+x^2) was not that much different.
NicolasRobidoux
Posts: 1944
Joined: 2010-08-28T11:16:00-07:00
Authentication code: 8675308
Location: Montreal, Canada

Re: Sigmoidized Ginseng (pronounced "Jinc-Sinc") resampling

Post by NicolasRobidoux »

I suppose the lesson is this: At a fixed level of halo suppression when dealing with sharp text, use the logistic sigmoid if you want less jaggies/more blur, and the algebraic one if you want vice/versa. I think most people like vice versa more.
What the other sigmoid do? Don't really know. But I agree with Fred that erf VS logistic=tanh is not going to be a big deal.
My hunch is that anything "above" the logistic sigmoid is not going to be worth it. But I'm wrong half the time...
P.S. Looking at more examples, it's a toss. Different but no-one's obviously better. >>I<< like the logistic sigmoidal more, because it gives better "small flat colour areas" and slightly less jaggies and colour bleed (which is almost invisible anyway), but many people find sharpness more important, so I think they'd consider the algebraic sigmoid a "win".
P.S. For some images (cockatiel, for example), the difference is impossible to see. When there is a visible difference, I tend to find the logistic sigmoidal more "natural". Sometimes, it has visibly less jaggies.
P.S. Having checked more examples, it's actually no contest: Jaggy reduction is much better with the logistic sigmoidal. Maybe with contrast values set some other way it would be different? But with my way of setting the values in term of halo reduction, the "algebraic" sigmoidal loses the jaggy contest.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Sigmoidized Ginseng (pronounced "Jinc-Sinc") resampling

Post by fmw42 »

Would you get a faster saturation on the curve if you raised the hyperbolic tan to some power less than one for the normal -sigmoidal type? Or is that the same as using a higher contrast value?
NicolasRobidoux
Posts: 1944
Joined: 2010-08-28T11:16:00-07:00
Authentication code: 8675308
Location: Montreal, Canada

Re: Sigmoidized Ginseng (pronounced "Jinc-Sinc") resampling

Post by NicolasRobidoux »

fmw42 wrote:Would you get a faster saturation on the curve if you raised the hyperbolic tan to some power less than one for the normal -sigmoidal type? Or is that the same as using a higher contrast value?
I don't know.
This being said, because of the sigmoidal always being rescaled, it's not only the slope that matters. The shape matters too.
Evidence: If you rescale the function y=mx+b the way it's done in ImageMagick, you get exactly the same values stored in the LUT not matter what m is, provided it's not zero, and no matter what b is. (Actually, the way I've set things up to handle the removable singularity that the rescaling introduces into the logistic curve, you'd get exactly the same thing even if m=0.) Now, when using sigmoidization, the scaling is irrelevant in exact arithmetic. But the fact that you get the exact same LUTs when scaling says that second derivatives are key.
I personally think that the key thing has to do with how the sigmoidal approaches its horizontal asymptotes. And horizontal asymptotes cannot be approached in a straight line. But I may be wrong.
NicolasRobidoux
Posts: 1944
Joined: 2010-08-28T11:16:00-07:00
Authentication code: 8675308
Location: Montreal, Canada

Re: Sigmoidized Ginseng (pronounced "Jinc-Sinc") resampling

Post by NicolasRobidoux »

Fred: erf is a good suggestion, and should not be too expensive: http://stackoverflow.com/questions/6316 ... and-math-h. But if my hunch that approaching the asymptote exponentially slowly---no faster and no slower---at infinity is right, the logistic sigmoidal should be better. I'm using the inverse of the sigmoidal as well, and logarithmic behavior is what I want.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Sigmoidized Ginseng (pronounced "Jinc-Sinc") resampling

Post by fmw42 »

I personally think that the key thing has to do with how the sigmoidal approaches its horizontal asymptotes.
That is what I had in mind. I wanted to increase more rapidly and the saturate more rapidly so that it approaches the limit more flatly. I just did not know what function would do that. The erf seems to be a tad better than the tanh, but not really that much. I was looking for a way to make it a higher but sharper saturation. However, I am not sure there is too much more to "buy" out of this.

What I was really hoping that there would be some way to get more sharpness without the jaggies and the other artifacts. I was hoping that one could use the same sigmoidal trick but use something further along the B+2C=1 line of cubics in the Mitchell diagram. It seems that the catrom is very sharp but I am sure for you has too much artifacts. But perhaps something past the Robidoux-Sharp would achieve a better compromise.

Have you experimented with pushing sharpness and seeing how far it can go without too much artifacts of the jaggies and over/undershoots?

When I ran the demo at http://www.wisdom.weizmann.ac.il/~visio ... ageSR.html with the Maxim chip, their approach did not do so well. It seems to fail with high contrast transitions or high contrast images.
NicolasRobidoux
Posts: 1944
Joined: 2010-08-28T11:16:00-07:00
Authentication code: 8675308
Location: Montreal, Canada

Re: Sigmoidized Ginseng (pronounced "Jinc-Sinc") resampling

Post by NicolasRobidoux »

@Fred: There are a lot of approaches that work well with specific types of images, and generally it is considered fair game to select test images that highlight the strenghts of your method while hiding their weaknesses.

I try my best to avoid doing that, but this practice is definitely not universal.

-----

I have not tried to use sigmoidization with BC-splines. I won't: I'm mostly interested in 3-lobe (and 4- and 5- lobe) windowed Sinc and Jincs.

Not that it's not worth exploring. Just that the "to do" list is getting uncomfortably long. And everything takes a lot longer than expected.
Last edited by NicolasRobidoux on 2012-09-02T07:57:40-07:00, edited 3 times in total.
NicolasRobidoux
Posts: 1944
Joined: 2010-08-28T11:16:00-07:00
Authentication code: 8675308
Location: Montreal, Canada

Re: Sigmoidized Ginseng (pronounced "Jinc-Sinc") resampling

Post by NicolasRobidoux »

@Fred: My guess is that you could reduce the Catmull-Rom (or other BC-splines, Mitchell e.g.) artifacts with sigmoidization.

In my experience, you can push the contrast really high, and on sub-critical images (those that stay away form the Nyquist limit), there is not really much bad to doing this.

However, esp. on colour images with sharp colour transitions, sigmoidization introduces colour bleed. (It really looks like "cheap colour printing".) I suspect that heavy JPEG compression triggers this artifact of sigmoidization, for example.

So, I now "back off" the sigmoidization to a "safer" value, chosen so that there is almost never any hint of colour bleed.

Without going into the detail of exactly why I do things this way, this "safer" contrast value is obtained like this:

Create a (small: 8x8 or 16x16) 8-bit sRGB image which is black of the left and white on the right, with a perfectly sharp vertical transition.

Enlarge it a lot using your candidate sigmoidized method (in the final stages of hunting for the contrast value, as much as 256x).

Find the threshold value of the contrast which ensures that the dark side has no pixel value above 8.

With Cubic (cubic B-spline smoothing), the threshold is infinite, because Cubic (and Point and Box and bilinear and Quadratic) are monotone: no overshoot.

With Catmull-Rom, I would guess that the threshold should be something like 10.5. But I've not tried anything with BC-splines.

P.S. If I had not told you about colour bleed, you may not have noticed. I just happen to scrutinize things, and know about the shortcomings of the methods I design, so hunt for signs of them.
Last edited by NicolasRobidoux on 2012-09-02T08:01:02-07:00, edited 2 times in total.
NicolasRobidoux
Posts: 1944
Joined: 2010-08-28T11:16:00-07:00
Authentication code: 8675308
Location: Montreal, Canada

Re: Sigmoidized Ginseng (pronounced "Jinc-Sinc") resampling

Post by NicolasRobidoux »

@Fred: As mentioned earlier, if you really really wanted to use sigmoidization to increase sharpness as much as it can, you would need to use a sigmoidal function which is locally defined by the range of pixel values in a neighbourhood. Doing this well, let alone programming it, so that the fix not introduce it's own artifacts, is likely to be a major undertaking, which I'm not sure I'm willing to take on.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Sigmoidized Ginseng (pronounced "Jinc-Sinc") resampling

Post by fmw42 »

NicolasRobidoux wrote:@Fred: As mentioned earlier, if you really really wanted to use sigmoidization to increase sharpness as much as it can, you would need to use a sigmoidal function which is locally defined by the range of pixel values in a neighbourhood. Doing this well, let alone programming it, so that the fix not introduce it's own artifacts, is likely to be a major undertaking, which I'm not sure I'm willing to take on.

One way would be to process the image with some local contrast measure say in a 5x5 or 7x7 region at every pixel, such as max-min. (There may be better local contrast measures. But I have not done any search,yet). Save that image. Then determine some scale factor between the image contrast value and the sigmoidal contrast argument. Then use the slow -fx with two input images to apply say tanh and arctanh functions to process the image pixel-by-pixel, getting the contrast value from the contrast image and applying it with the tanh using -fx. If you are really interested and think this might be worthwhile, I can help you with it.

I had Magick add tanh and arctanh a while back when I was trying to create my sigmoidal brightness/contrast script, until I realized that the tanh /arctanh functions produced the same results as the IM -sigmoidal-contrast exponential function. So I dropped the tanh concept. I was suspicious that they were the same, but could not prove it until yesterday when I found that reference, which was a link at the bottom of your reference to sigmoidal like functions.
Post Reply