proper scaling of the Jinc filter for EWA use

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: proper scaling of the Jinc filter for EWA use

Post by NicolasRobidoux » 2012-07-19T05:56:03-07:00

imaggie wrote:Just thinking on the hoof here, how does adding a small slice of a lobe compare to removing a similar amount?

Does adding a small slice soften , as I suspect, or increase the ringing due having fractionally more lobes ?
Just making sure that you understand what -define filter:blur=.75 does (say): It keeps the same shape, lobes and all (so, Jinc still has exactly three lobes, and the kernel is zero at the limit of the extent of the filter). All it does, is rescale the support (without chopping anything). The "natural" support of the Jinc function is a disk of radius about 3.238. blur=.75 shrinks the disk, "pulling in" the shape, down to a disk of radius about 2.429.

"Chopping off" or "adding bits" of lobes is not an option when enlarging more than a little, because it introduces "jump" artifacts.

NicolasRobidoux
Posts: 1944
Joined: 2010-08-28T11:16:00-07:00
Authentication code: 8675308
Location: Montreal, Canada

Re: proper scaling of the Jinc filter for EWA use

Post by NicolasRobidoux » 2012-08-18T11:47:29-07:00

I do not recommend the schemes I've called LanczosSharpest, at least with 3-lobes (the most interesting case). (De)blurs below .91 or so with EWA Jinc-windowed Jinc 3-lobe lead to subtle artifacts I really dislike. This is despite that the LanczosSharpest schemes rank very high in the re-enlargement tests of my student Adam Turcotte when the input natural image is fairly smooth and denoised.
Last edited by NicolasRobidoux on 2012-08-19T10:23:59-07:00, edited 1 time in total.

NicolasRobidoux
Posts: 1944
Joined: 2010-08-28T11:16:00-07:00
Authentication code: 8675308
Location: Montreal, Canada

Re: proper scaling of the Jinc filter for EWA use

Post by NicolasRobidoux » 2012-08-18T12:22:03-07:00

Another thing: For quite a while I've been advocating a different LanczosSharp blur value (for 3-lobe Jinc-windowed Jinc EWA) than the one currently used by ImageMagick, namely .9891028367558475 (advocated for a few months) instead of .9812505644269356 (implemented in IM for more than a year now?).

Now that I am looking at things very very carefully, I am reasonably certain that the (de)blur currently implemented in IM is actually preferable (!). I'll document what motivates this when I have a minute. It has to do with aligning the zero crossings of what's obtained when interpolating delta function data which is constant on pixel columns (or rows). That is, enlarging "infinitely" an image which has one white column on a black background. The currently implemented value gets the first two crossings on each side almost perfectly aligned with grid lines. Not the more recent value.

When I have some time, I'll compute the (de)blur that aligns the first crossing exactly with a grid line. It's going to be a nudge smaller than the one currently implemented. And there are other good reasons why a nudge smaller is good.
Last edited by NicolasRobidoux on 2012-08-19T10:24:59-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: proper scaling of the Jinc filter for EWA use

Post by NicolasRobidoux » 2012-08-18T12:29:31-07:00

Now I'm really happy that I told Anthony to hold off implementing the new values or adding LanczosSharpest. (LanczosRadiusN, however, seems pretty good.)
Last edited by NicolasRobidoux on 2012-08-18T13:09:02-07:00, edited 1 time in total.

imaggie
Posts: 88
Joined: 2011-12-19T04:15:36-07:00
Authentication code: 8675308

Re: proper scaling of the Jinc filter for EWA use

Post by imaggie » 2012-08-18T12:57:51-07:00

NicolasRobidoux wrote:I do not recommend the schemes I've called LanczosSharpest, at least with 3-lobes (the most interesting case). (De)blurs below .91 or so with EWA Jinc-windowed Jinc 3-lobe lead to subtle artifacts I really dislike. This is despite that the LanczosSharpest schemes rank very high in the re-enlargement tests of my student Adam Turcotte when the input natural image is quite smooth and denoised.
There is a degree of "horses for courses" in all this but I think that smoothe and denoised images are likely to minimse ringing defects that may manifest as defects on sharper source images. As you know, it's sharp egdes that trigger ringing so using a soft image as a test sample is probably not such a good choice unless you are looking for the best filter for soft images.

Maybe it's unrealistic to seek one solution for all types of image.

NicolasRobidoux
Posts: 1944
Joined: 2010-08-28T11:16:00-07:00
Authentication code: 8675308
Location: Montreal, Canada

Re: proper scaling of the Jinc filter for EWA use

Post by NicolasRobidoux » 2012-08-18T15:51:27-07:00

Here is the value of the deblur that ensures that a single column of white does not affect at all the nearest neighbouring two (one on each side) columns:
-define filter:blur=.9812505644269356
It is exactly the built-in value currently used for LanczosSharp. I had forgotten the details of how it was computed!
The short description is that under no-op a single vertical line of constant data does not affect the nearest two columns.
Here is the Axiom code that computes it:

Code: Select all

)cl a

digits 100

R1 := 3.831705970207512315614435886308160766564545274287801928762298989918839309519011470214112874757423127

r1 := R1 / %pi

R3 := 10.17346813506272207718571177677584406981951250019168555611465006811578704378288387382891893264510929

r3 := R3 / %pi

jinc x == besselJ(1,%pi*x)/x

wind x == besselJ(1,x*(R1/r3))/x

l x == if (x<r3) then ( wind(x) * jinc(x) ) else 0.

f r == [ r, sqrt(1.+1)*r, 2*r, sqrt(1.+4)*r, sqrt(4.+4)*r, 3*r, sqrt(9.+1.)*r, sqrt(9.+4)*r, 4*r, sqrt(16.+1)*r, sqrt(9.+9)*r, sqrt(16.+4)*r, 5*r ]

z := l 1.e-128

rite r == _
( _
  l((f(r)).1) _
+ 2 * _
  ( _
    l((f(r)).2) _
  + l((f(r)).4) _
  + l((f(r)).7) _
  ) ) / ( z + _
4 * _
( l((f(r)).1) _
+ l((f(r)).2) _
+ l((f(r)).3) _
+ l((f(r)).5) _
+ l((f(r)).6) _
+ l((f(r)).9) _
+ l((f(r)).11) _
+ l((f(r)).13) _
+ 2 * _
( l((f(r)).4) _
+ l((f(r)).7) _
+ l((f(r)).8) _
+ l((f(r)).10) _
+ l((f(r)).12) ) ) )

-- To find the one with sum closest to 0 (this is a fully converged result):

[ rite(1.0191076940516353587568741952667+.00000000000000000000000000000001*i) for i in 0..10 ]

1/1.0191076940516353587568741952667
P.S. This is why I need to write articles once in a while: To remember how I put things together!

NicolasRobidoux
Posts: 1944
Joined: 2010-08-28T11:16:00-07:00
Authentication code: 8675308
Location: Montreal, Canada

Re: proper scaling of the Jinc filter for EWA use

Post by NicolasRobidoux » 2012-08-19T06:58:28-07:00

Applying the same criterion to 4-lobe Jinc-windowed Jinc gives (de)blur=.9885973386557245. Here is the Axiom code:

Code: Select all

)cl a

digits 200

R1 := 3.831705970207512315614435886308160766564545274287801928762298989918839309519011470214112874757423127

r1 := R1 / %pi

R4 := 13.323691936314223032393684126947876751216644731357865785477571526496567063347304782547119017948839951109445358057000268451481978642541401546368509755789722112502852743021277168603949713032474504688907

r4 := R4 / %pi

jinc x == besselJ(1,%pi*x)/x

wind x == besselJ(1,x*(R1/r4))/x

l x == if (x<r4) then ( wind(x) * jinc(x) ) else 0.

f r == _
[ r, 2*r, 3*r, 4*r, 5*r, _
sqrt(1.+1^2)*r, sqrt(1.+2^2)*r, sqrt(1.+3^2)*r, sqrt(1.+4^2)*r, sqrt(1.+5^2)*r, _
sqrt(4.+1^2)*r, sqrt(4.+2^2)*r, sqrt(4.+3^2)*r, sqrt(4.+4^2)*r, sqrt(4.+5^2)*r, _
sqrt(9.+1^2)*r, sqrt(9.+2^2)*r, sqrt(9.+3^2)*r, sqrt(9.+4^2)*r, sqrt(9.+5^2)*r, _
sqrt(25.+1^2)*r, sqrt(25.+2^2)*r, sqrt(25.+3^2)*r, sqrt(25.+4^2)*r, sqrt(25.+5^2)*r ]

z := l 1.e-128

rite r == _
( _
  l((f(r)).1) _
+ 2 * _
  ( _
    l((f(r)).6) _
  + l((f(r)).7) _
  + l((f(r)).8) _
  + l((f(r)).9) _
  + l((f(r)).10) _
  ) ) / ( z + _
4 * _
( l((f(r)).1) _
+ l((f(r)).2) _
+ l((f(r)).3) _
+ l((f(r)).4) _
+ l((f(r)).5) _
+ l((f(r)).6) _
+ l((f(r)).7) _
+ l((f(r)).8) _
+ l((f(r)).9) _
+ l((f(r)).10) _
+ l((f(r)).11) _
+ l((f(r)).12) _
+ l((f(r)).13) _
+ l((f(r)).14) _
+ l((f(r)).15) _
+ l((f(r)).16) _
+ l((f(r)).17) _
+ l((f(r)).18) _
+ l((f(r)).19) _
+ l((f(r)).20) _
+ l((f(r)).21) _
+ l((f(r)).22) _
+ l((f(r)).23) _
+ l((f(r)).24) _
+ l((f(r)).25 ) ) )

-- To find the one with sum closest to 0 (this is a fully converged result):

[ rite(1.011534181712223316992842+.0000000000000000000000001*i) for i in 0..10 ]

1/1.011534181712223316992842

As one increases the number of lobes, the (de)blur converges to 1, which should surprise no-one: Jinc-windowed Jinc is a windowed low-pass filter that converges to Jinc as one increases the number of lobes. Jinc has the same spectral characteristics (in 2D) as the 1D Sinc. So, as the window gets larger, the "unscaled" version must be doing "the right thing" without tweaking. It's only when the window is small that one needs to fix things, because the discrete and truncated version deviates significantly from the "ideal".
Last edited by NicolasRobidoux on 2012-08-19T10:19:56-07:00, edited 2 times in total.

henrywho
Posts: 188
Joined: 2011-08-17T06:46:40-07:00
Authentication code: 8675308

Re: proper scaling of the Jinc filter for EWA use

Post by henrywho » 2012-08-19T08:48:22-07:00

NicolasRobidoux wrote:It is exactly the built-in value currently used for LanczosSharp.
Probably the same case for Lanczos2Sharp :lol:

NicolasRobidoux
Posts: 1944
Joined: 2010-08-28T11:16:00-07:00
Authentication code: 8675308
Location: Montreal, Canada

Re: proper scaling of the Jinc filter for EWA use

Post by NicolasRobidoux » 2012-08-19T10:22:14-07:00

I'm actually pretty surprised that I got it right the first time, because I'm getting the same optimization criterion from a much more sophisticated viewpoint than I had then.
A rare case of my "back of the envelope divination" getting it "right" in the first pass ;)
Last edited by NicolasRobidoux on 2012-08-19T10:27:28-07:00, edited 1 time in total.

NicolasRobidoux
Posts: 1944
Joined: 2010-08-28T11:16:00-07:00
Authentication code: 8675308
Location: Montreal, Canada

Re: proper scaling of the Jinc filter for EWA use

Post by NicolasRobidoux » 2012-08-19T10:26:43-07:00

When I have more time I'll see if I could use a different windowing function to align the first four (two on each side) crossings "just right".
Also, with the "right" (de)blurs, there is basically no visual difference between 3 lobes and 4 lobes. This is a good sign.
P.S. Checked on the chip image, and with sigmoidization the difference between 3 and 4 lobes is just below 2.3 JND. But I can see a slight difference in sharpness where it matters, and there is a very very faint increase in haloing (you have to look for it to see it, but it's just large enough to be noticeable). However, when I check with the text test image, some of the letters have (hard to see) inner halos that are at almost at double the usual 2.3 JND. There is a good chance that 3 lobes is the right balance.
Last edited by NicolasRobidoux on 2012-08-19T11:53:18-07:00, edited 4 times in total.

NicolasRobidoux
Posts: 1944
Joined: 2010-08-28T11:16:00-07:00
Authentication code: 8675308
Location: Montreal, Canada

Re: proper scaling of the Jinc filter for EWA use

Post by NicolasRobidoux » 2012-08-19T10:35:11-07:00

I'm combining LanczosSharp with sigmoidization, and it looks very good: viewtopic.php?f=1&t=21695.

NicolasRobidoux
Posts: 1944
Joined: 2010-08-28T11:16:00-07:00
Authentication code: 8675308
Location: Montreal, Canada

Re: proper scaling of the Jinc filter for EWA use

Post by NicolasRobidoux » 2012-08-22T12:40:18-07:00

henrywho wrote:
NicolasRobidoux wrote:It is exactly the built-in value currently used for LanczosSharp.
Probably the same case for Lanczos2Sharp :lol:
Indeed. And the criterion used to set the (de)blur for Lanczos2Sharp can be translated so that it is exactly the same criterion used to derive the Robidoux filter: With EWA, put the first crossing, when dealing with data consisting of one nonzero column on a black background, exactly at 1.
P.S. Good things tend to be rediscovered many times. Better things are rediscovered many times ... by the same person!

NicolasRobidoux
Posts: 1944
Joined: 2010-08-28T11:16:00-07:00
Authentication code: 8675308
Location: Montreal, Canada

Re: proper scaling of the Jinc filter for EWA use

Post by NicolasRobidoux » 2012-08-25T06:12:38-07:00

Note: The new=old=currently implemented value of the LanczosSharp (de)blurs are best in my book specifically because of how I know sigmoidization interacts with halos. The ones I advocated for about a year may actually be better if sigmoidization is not used. The two values are not very different anyway.

henrywho
Posts: 188
Joined: 2011-08-17T06:46:40-07:00
Authentication code: 8675308

Re: proper scaling of the Jinc filter for EWA use

Post by henrywho » 2012-08-27T20:15:39-07:00

:shock: Have I missed anything? :shock:

Code: Select all

if /i  "%FILTER%" == "JincJinc2Old"    set RESZFT=-filter Lanczos2Sharp
if /i  "%FILTER%" == "JincJinc3Old"    set RESZFT=-filter LanczosSharp
if /i  "%FILTER%" == "JincJinc4Old"    set RESZFT=-define filter:filter=Jinc -define filter:window=Jinc -define filter:lobes=4 -define filter:blur=0.9885973386557245

if /i  "%FILTER%" == "JincJinc2New"    set RESZFT=-define filter:filter=Jinc -define filter:window=Jinc -define filter:lobes=2 -define filter:blur=0.9580278036312191
if /i  "%FILTER%" == "JincJinc3New"    set RESZFT=-define filter:filter=Jinc -define filter:window=Jinc -define filter:lobes=3 -define filter:blur=0.9891028367558475
if /i  "%FILTER%" == "JincJinc4New"    set RESZFT=-define filter:filter=Jinc -define filter:window=Jinc -define filter:lobes=4 -define filter:blur=0.9870395083298263

if /i  "%FILTER%" == "JincJinc3Rad"    set RESZFT=-define filter:filter=Jinc -define filter:window=Jinc -define filter:lobes=3 -define filter:blur=0.9264075766146068
if /i  "%FILTER%" == "JincJinc5Rad"    set RESZFT=-define filter:filter=Jinc -define filter:window=Jinc -define filter:lobes=5 -define filter:blur=0.9536953485948749
if /i  "%FILTER%" == "JincJinc8Rad"    set RESZFT=-define filter:filter=Jinc -define filter:window=Jinc -define filter:lobes=8 -define filter:blur=0.970238549334149

if /i  "%FILTER%" == "JincJinc2VSharp" set RESZFT=-define filter:filter=Jinc -define filter:window=Jinc -define filter:lobes=2 -define filter:blur=0.88826421508540347
if /i  "%FILTER%" == "JincJinc3VSharp" set RESZFT=-define filter:filter=Jinc -define filter:window=Jinc -define filter:lobes=3 -define filter:blur=0.88549061701764
if /i  "%FILTER%" == "JincJinc4VSharp" set RESZFT=-define filter:filter=Jinc -define filter:window=Jinc -define filter:lobes=4 -define filter:blur=0.88451002338585141

NicolasRobidoux
Posts: 1944
Joined: 2010-08-28T11:16:00-07:00
Authentication code: 8675308
Location: Montreal, Canada

Re: proper scaling of the Jinc filter for EWA use

Post by NicolasRobidoux » 2012-08-28T04:42:59-07:00

henrywho wrote:Have I missed anything?
No: They're all there.
The first ones, the "old" ones, are the ones I now recommend most. They are based on matching the first crossing of the "1D impulse response". (I've not double checked that the 4-lobe (de)blur is correct, but I assume it is. To do list.)
The second group, which I've advocated for a year, minimize the maximum possible deviation from being interpolatory on "1D data". This is a powerful and reasonable criterion, but I think that the first group is generally more desirable. (This being said, it's not as if the blur values are very different from the first ones.)
The radiusN ones that come right after are my best suggestion so far if you want sharpness. It will probably take me some time to do better (ever?). They almost clone the orthogonal Lanczoses (but they have slightly less jaggies on diagonal interfaces and lines).
And the "very sharp" ones should not be used unless you downsample and you value sharpness at the expense of everything else. Even then, I don't recommend them.

Makes sense?

P.S. What the first two approaches point it is something that may be refined by additional analysis, which I have to postpone because it requires a significant amount of computation, and I have other things to do right now. As mentioned elsewhere, minute differences in (de)blur only matter when you are not downsampling. And one may argue that two significant digits is enough :) But I like to check things from different angles.

Post Reply