Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

A "slanted edge" analysis program

464 views
Skip to first unread message

Lorenzo J. Lucchini

unread,
Sep 26, 2005, 4:19:09 PM9/26/05
to
Well, my Imatest trial is up, and I'm not going to buy it (though it is
a very nice program that I'd recommend!), but I'd still like to play
with ESF, PSF, MTF and all that.
Specifically, I'm still very interested in findout out what the "best
sharpening" for my scanner is by analysing the edge spread function.

There is another interesting "slanted edge tester" at
http://www.i3a.org/downloads_iso_tools.html (if I'm not mistaken,
Imatest is actually based on its code), but it doesn't give nearly as
much information as Imatest does... even though perhaps the MTF alone
could be turned into the correct deconvolution for my scanner in the
hands of "some of the people here"! ;-)


But. In the last few days I've been busy writing my own "slanted edge"
program. It now sort of works, meaning that it doesn't (often) crash,
and that it gives results that are similar to what Imatest or SFRWin give.
Similar, not really identical... that's why I would be glad if Bart,
Kennedy, or anybody who's into this kind of things could help me a little.


The program can be found at
http://ljl.150m.com/slantededge-alpha1.tar.gz

and I've created a SourceForge project at
http://sourceforge.net/projects/slantededge/

with sourcecode in the CVS.


I'll explain briefly what the program does and in what order it does it,
as the source is not very well commented, er, at the moment.

1) Read in an RGB image
2) We work with vertical edges, so rotate the image if needed
3) Besides the "red", "blue" and "green" channels, create a "gray"
channel that is the average of the other three
4) Normalize the image, so that 0.5% of the pixels clip down, and 0.5%
clip up
5) For each line in the image, find the point with the max adjacent
pixel difference (should be the edge)
6) By doing a least squares regression on those points, find a straight
line that ought to best represent the edge
7) Associate a distance from that line to each pixel in the image. The
function PixelValue(Distance) approximates the edge spread function.
8) Use "some kind" of local regression to create a uniformly-spaced
version of the ESF, from the data described above.
9) Derive the line spread function from the edge spread function:
LSF(i)=ESF(i+1)-ESF(i)
10) Apply a Hanning window to the LSF
11) Take the discrete Fourier transform or the resulting data


Note that, at the moment, the input image must be an RGB, 8-bit ASCII
("plain") PPM file. These can be created using "*topnm" and
"pnmtoplainpnm" from the NetPBM suite, or by using the GIMP.
Type --help for some uncomprehensive help.


I have a lot of doubts and questions to ask, but first I'd like to get
an overall look at the program by someone competent, to find out what I
have done *badly* wrong (something awful is bound to be there).

Please keep in mind that I knew nothing about regressions, spread
functions or Fourier transforms two weeks ago -- and I suppose I don't
know that much more now.
I just read some Internet source and implemented what I thought they meant.


by LjL
ljl...@tiscali.it

Lorenzo J. Lucchini

unread,
Sep 26, 2005, 5:55:54 PM9/26/05
to
Lorenzo J. Lucchini wrote:
> [snip]

Since http://ljl.150m.com appears to be down, the file can also be found at
http://ljl.741.com/slantededge-alpha1.tar.gz

SourceForge's "web" CVS will also take some hours to update, even though
the files are really there.

by LjL
ljl...@tiscali.it

Bart van der Wolf

unread,
Sep 27, 2005, 8:10:45 AM9/27/05
to

"Lorenzo J. Lucchini" <ljl...@tiscali.it> wrote in message
news:P8_Ze.49524$nT3....@tornado.fastwebnet.it...

> Lorenzo J. Lucchini wrote:
> > [snip]
>
> Since http://ljl.150m.com appears to be down,

I was wondering about that, so it wasn't my setup afterall ;-)

> the file can also be found at
> http://ljl.741.com/slantededge-alpha1.tar.gz

Although the source maybe helpful, I'm running on a Windows XP
platform. I don't mind looking into the project, but I have too little
time to compile it myself (I know compilation itself doesn't take
long, but I'd have to install a compiler first). A pre-compiled Win32
version might help.

> SourceForge's "web" CVS will also take some hours to update, even
> though the files are really there.

Didn't find them yesterday, they are available now.

Bart

Lorenzo J. Lucchini

unread,
Sep 27, 2005, 8:54:18 AM9/27/05
to
Bart van der Wolf wrote:
>
> "Lorenzo J. Lucchini" <ljl...@tiscali.it> wrote in message
> news:P8_Ze.49524$nT3....@tornado.fastwebnet.it...
>
>> Lorenzo J. Lucchini wrote:
>> > [snip]
>>
>> Since http://ljl.150m.com appears to be down,
>
> I was wondering about that, so it wasn't my setup afterall ;-)

You know, it's free hosting... I'm starting to worry, though, it's been
down for quite a while now.

>> the file can also be found at
>> http://ljl.741.com/slantededge-alpha1.tar.gz

Hope this one stays up! Anyway, I guess I'll make a release on
SourceForge after I've fixed the really bad bugs.

> Although the source maybe helpful, I'm running on a Windows XP platform.
> I don't mind looking into the project, but I have too little time to
> compile it myself (I know compilation itself doesn't take long, but I'd
> have to install a compiler first). A pre-compiled Win32 version might help.

I know. The main problem is that I'm using the FFTW library for taking
Fourier transforms, and while there seems to be a Windows version
available (several, actually), well... the site is down. The web doesn't
like me apparently.

I'll see what I can do, perhaps I can just write a slow, simple DFT
myself (I have no idea how difficult it is, I'll have to read a bit) as
a compile alternative to FFTW.


Anyway, do you have a SourceForge account? With one, I can just add you
to the project, and then you'll be able to access SF's shell servers.
This way you could easily run - and even easily compile - the program
remotely, without installing anything special on your computer.


Now some of the most important questions I have:

- What is Imatest's "10%" and "90%"? Initially, I took these as the
minimum and maximum pixel values that can constitute the "edge". But it
appears clear that the showed ESF also contains lower and higher values;
besides, it always seem to go from -6 pixels to +8 pixels from the edge
center. Is there a reason for this?
So, now I suppose "10%" and "90%" are simply used to compute (guess
what) the 10%-90% rise.
Which in turns call for: should I normalize the image before doing
anything else? I currently normalize so that 0.5% of pixels clip to
black and 0.5% clip to white.

- Is it ok to take a (single) Fourier transform of the Hanning-windowed
LSF? Without windowing, I get weird results, but with windowing, I'm
afraid I'm affecting the data. My MTF's always look "smoother" than
Imatest's and SFTWin's ones, and too high in the lower frequencies.

- How many samples should my ESF/LSF have? I understand that it only
depends on how high you want your frequencies to be -- i.e., if I want
to show the MTF up to 4xNyquist, I should have 4x more samples than
there are real pixels. Is this correct?

- How do I reduce frequencies spacing in the DFT? If I just transform
the LSF (or a Hanning'ed LSF), I get ridiculously low frequencies
resolution. What I'm doing now to overcome this is... add a lot of
zeroes at the end of the original LSF. But, somehow, I think this is
kinda stupid.

- The method I'm currently using for getting a smooth,
uniformely-spacing sampled ESF from the point I have is naive and very
slow. The sources I've read suggest using "LOESS curve fitting" for
this. I've had some trouble finding good references about this, and it
seems very complicated anyway. The question is: is something simpler
good enough?


by LjL
ljl...@tiscali.it

Bart van der Wolf

unread,
Sep 27, 2005, 9:30:42 AM9/27/05
to

"Lorenzo J. Lucchini" <ljl...@tiscali.it> wrote in message
news:5KYZe.49331$nT3....@tornado.fastwebnet.it...

> Well, my Imatest trial is up, and I'm not going to buy it (though it
> is a very nice program that I'd recommend!), but I'd still like to
> play with ESF, PSF, MTF and all that.

Yes, once you really grasp what you are actually looking at, it will
help with improving the results. e.g. by allowing to optimize capture
sharpening.

> Specifically, I'm still very interested in findout out what the
> "best sharpening" for my scanner is by analysing the edge spread
> function.

Exactly. There are several possibilities to use the ESF to check for
that (e.g. edge halo), and the PSF can be used as input in several
deconvolution programs. The MTF allows to compare systems in an
unambiguous way (assuming test conditions are under control).

> There is another interesting "slanted edge tester" at
> http://www.i3a.org/downloads_iso_tools.html (if I'm not mistaken,
> Imatest is actually based on its code),

Not really based on it, but it helped as an inspiration and discussion
tool with, amongst others, the programmers of the original ISO demo
sourcecode. Imatest uses the basic idea of the slanted edge target, as
it is described in the relevant ISO standards 16067-1&2 for scanners,
and 12233 for digital still cameras.


> but it doesn't give nearly as much information as Imatest does...
> even though perhaps the MTF alone could be turned into the correct
> deconvolution for my scanner in the hands of "some of the people
> here"! ;-)

The MTF is more suited for judging the effect of such a sharpening on
the various spatial frequencies, and the associated risk of aliasing
artifacts when down-sampling afterwards. The PSF is needed for
deconvolution (or for the creation of a high-pass convolution kernel).

> But. In the last few days I've been busy writing my own "slanted
> edge" program. It now sort of works, meaning that it doesn't (often)
> crash, and that it gives results that are similar to what Imatest or
> SFRWin give.
> Similar, not really identical... that's why I would be glad if Bart,

Reporting for duty ;-)

> Kennedy, or anybody who's into this kind of things could help me a
> little.

I'll add some program related comments in a separate message.

Bart

Lorenzo J. Lucchini

unread,
Sep 27, 2005, 9:48:21 AM9/27/05
to
Lorenzo J. Lucchini wrote:
> Bart van der Wolf wrote:
>
> > [snip]

>
> I know. The main problem is that I'm using the FFTW library for taking
> Fourier transforms, and while there seems to be a Windows version
> available (several, actually), well... the site is down. The web doesn't
> like me apparently.

Fortunately, I see that CygWin comes with FFTW. I guess it will be easy
enough then.

by LjL
ljl...@tiscali.it

Bart van der Wolf

unread,
Sep 27, 2005, 2:12:33 PM9/27/05
to

"Lorenzo J. Lucchini" <ljl...@tiscali.it> wrote in message
news:5KYZe.49331$nT3....@tornado.fastwebnet.it...
SNIP

> and I've created a SourceForge project at
> http://sourceforge.net/projects/slantededge/
>
> with sourcecode in the CVS.
>
>
> I'll explain briefly what the program does and in what order it does
> it, as the source is not very well commented, er, at the moment.


I've added a few comments, hopefully it will help to better understand
the reasons behind the steps.

> 1) Read in an RGB image
> 2) We work with vertical edges, so rotate the image if needed

This is only done to simplify the calculations. All that's required is
to get the image data in a uniform orientation, so all subsequent
subroutines will know what to expect (which avoids rechecking
assumptions).

> 3) Besides the "red", "blue" and "green" channels, create a "gray"
> channel that is the average of the other three

The image code values should be linarized at this stage, so
film/sensor non-linearity and gamma adjustments can't influence the
calculations.

It is customary to use a different weighting than the (R+G+B)/3
average. The ISO suggests the calculation of a luminance channel, so a
ratio of approx. 3R:6G:1B is closer to what we experience as
luminance.

> 4) Normalize the image, so that 0.5% of the pixels clip down, and
> 0.5% clip up

I think that, especially on non-linear image codes, this will
influence the MTF results, because the contrast is expanded. On a
perfectly symmetrical brightness distribution its effect will be
small, but the possibility of clipping in later stages should be
avoided. Also a check for at least 20% edge modulation should be made,
in order to avoid a too low input S/N ratio.

It is however perfectly normal to normalize the ESF output to a range
between 0.0 and 1.0, and later to normalize the SFR/MTF to 1.0 (100%)
at zero spatial frequency.

> 5) For each line in the image, find the point with the max adjacent
> pixel difference (should be the edge)

Not necessarily, that is just the maximum gradient and that need not
be the same as the edge.
The ISO suggests to combine this with with your step 9, and determine
the centroid of the LSF (by calculating the discrete derivative of the
ESF). The centroids can be used for regression.
The derivative suggested by the ISO is:
"for each line of pixels perpendicular to the edge, the edge is
differentiated using the discrete derivative "-0,5 ; +0,5", meaning
that the derivative value for pixel "X" is equal to -1/2 times the
value of the pixel immediately to the left, plus 1/2 times the value
of the pixel to the right".
They then specify something different in their centroid formula, but
perhaps they changed that in the official standard.

There is another calculation method possible. That calculation is done
in the orthogonal direction, so almost along the edge instead of
across the edge.

> 6) By doing a least squares regression on those points, find a
> straight line that ought to best represent the edge
> 7) Associate a distance from that line to each pixel in the image.

The ISO method shifts each row of the ESF by the calculated amount
from the regression, but uses quarter pixel bins. This produces a 4x
oversampling per pixel position.

> The function PixelValue(Distance) approximates the edge spread
> function.
> 8) Use "some kind" of local regression to create a uniformly-spaced
> version of the ESF, from the data described above.
> 9) Derive the line spread function from the edge spread function:
> LSF(i)=ESF(i+1)-ESF(i)

See earlier remark, and provisions need to be made to detect multiple
maxima (caused by noise/graininess).

> 10) Apply a Hanning window to the LSF

That is needed to reduce noise and the discontinuity at the borders of
the LSF.

> 11) Take the discrete Fourier transform or the resulting data

And take the Modulus, and normalize.

> Note that, at the moment, the input image must be an RGB, 8-bit
> ASCII ("plain") PPM file. These can be created using "*topnm" and
> "pnmtoplainpnm" from the NetPBM suite, or by using the GIMP.
> Type --help for some uncomprehensive help.

;-) Room for improvement ...

> I have a lot of doubts and questions to ask, but first I'd like to
> get an overall look at the program by someone competent, to find out
> what I have done *badly* wrong (something awful is bound to be
> there).

I'll have to study the source code before I can comment.

> Please keep in mind that I knew nothing about regressions, spread
> functions or Fourier transforms two weeks ago -- and I suppose I
> don't know that much more now.

Isn't that the fun of programming, it forces you to describe the
principles in detail. Learning new stuff is inevitable.

> I just read some Internet source and implemented what I thought they
> meant.

With the program (to be) available to the public, the chance of
helping hands increases. The source code you have probably read will
give a good start. As always, the devil is in the details, but that
can be overcome.

Bart

Bart van der Wolf

unread,
Sep 27, 2005, 6:55:07 PM9/27/05
to

"Lorenzo J. Lucchini" <ljl...@tiscali.it> wrote in message
news:%ib_e.38$U1...@tornado.fastwebnet.it...
SNIP

> I'll see what I can do, perhaps I can just write a slow, simple DFT
> myself (I have no idea how difficult it is, I'll have to read a bit)
> as a compile alternative to FFTW.

http://astronomy.swin.edu.au/~pbourke/other/dft/ and
http://www.library.cornell.edu/nr/bookcpdf/c12-2.pdf has C code for a
DFT function.
http://www.library.cornell.edu/nr/cbookcpdf.html chapter 12 has more
background on Fourier transforms, and chapter 13.1 has routines and
backgound on Deconvolution (although there are better functions for
image restoration).

> Anyway, do you have a SourceForge account? With one, I can just add
> you to the project, and then you'll be able to access SF's shell
> servers. This way you could easily run - and even easily compile -
> the program remotely, without installing anything special on your
> computer.

No, I don't have an SF account.

> Now some of the most important questions I have:
>
> - What is Imatest's "10%" and "90%"? Initially, I took these as the
> minimum and maximum pixel values that can constitute the "edge".

No, there are several ways to quantify an "infinite" function in a
single number. On an Edge Response Function it is a common procedure
to choose the width between the 10% and 90% response points. On a
Gaussian type of function, a Full Width at Half of Maximum is often
used.

> But it appears clear that the showed ESF also contains lower and
> higher values; besides, it always seem to go from -6 pixels to +8
> pixels from the edge center. Is there a reason for this?

I'm not sure about the exact reason for the choice, but I assume it
has to do with the shape of some ESFs that Norman Koren encountered
when he developed the program. The actual data in Imatest is recorded
from -6 to +10 at 0.25 intervals.

> So, now I suppose "10%" and "90%" are simply used to compute (guess
> what) the 10%-90% rise.

Actually the width in pixels between the two response points.

> Which in turns call for: should I normalize the image before doing
> anything else? I currently normalize so that 0.5% of pixels clip to
> black and 0.5% clip to white.

No, it is better to only normalize the output curves but leave the
original data (which is where the truth is hidden) as it is. By
manipulating the image data itself, you run the risk of changing the
data (in case of non-linear response data), and of introducing
quantization errors (by rounding up/down half a bit).

> - Is it ok to take a (single) Fourier transform of the Hanning-
> windowed LSF?

Yes, it's not that much data, so the DFT is fast.

> Without windowing, I get weird results, but with windowing, I'm
> afraid I'm affecting the data.

You'll have to window because of the abrupt edges. That's reality in
Fourier transforms, we deal with a small subset of the real data which
reaches out to infinity.

> My MTF's always look "smoother" than Imatest's and SFTWin's ones,
> and too high in the lower frequencies.

We'll have to see, but make sure you compute the magnitude of the
transform (take the "Modulus" of the DFT).

> - How many samples should my ESF/LSF have? I understand that it only
> depends on how high you want your frequencies to be -- i.e., if I
> want to show the MTF up to 4xNyquist, I should have 4x more samples
> than there are real pixels. Is this correct?

No. In the ISO method you would calculate an ESF for each line (row)
of pixels that crosses the edge. The average of all those ESFs is
produced after shifting each row in proportion with the centroid
regression. It is at that point, the shifting, that you bin the pixels
in an array that's 4x wider than the edge crop. That allows you to bin
the centroid with a 4x higher (=quarter pixel) resolution. After that
it's just statistics, larger numbers of ESFs make a more likely
approximation of the actual ESF.

The ISO takes one additional precaution, they take an integer number
of phase rotations. That means that if you e.g. calculated a slope of
1 pixel for every ten rows, then they take an integer multiple of ten
rows, starting at the top and trunkating the image data at the bottom.

> - How do I reduce frequencies spacing in the DFT?

I'm not sure what you mean, but it may have to do with the previous
quarter pixel binning.
SNIP

> - The method I'm currently using for getting a smooth,
> uniformely-spacing sampled ESF from the point I have is naive and
> very slow. The sources I've read suggest using "LOESS curve fitting"
> for this. I've had some trouble finding good references about this,
> and it seems very complicated anyway.

It apparently is a kind of locally weighted regression with reduced
sensitivity for outliers.

> The question is: is something simpler good enough?

Part of it may have to do with the quarter pixel sampling/binning.
If you just want to fit a monotone curve through regularly sampled
points, a simple interpolation (Cubic or Hermite) seems good enough to
me:
http://astronomy.swin.edu.au/~pbourke/other/interpolation/

Bart

Lorenzo J. Lucchini

unread,
Sep 27, 2005, 8:00:41 PM9/27/05
to
Bart van der Wolf wrote:
>
> "Lorenzo J. Lucchini" <ljl...@tiscali.it> wrote in message
> news:5KYZe.49331$nT3....@tornado.fastwebnet.it...
> SNIP
>
> [snip]

>
> I've added a few comments, hopefully it will help to better understand
> the reasons behind the steps.
>
>> 1) Read in an RGB image
>> 2) We work with vertical edges, so rotate the image if needed
>
> This is only done to simplify the calculations. All that's required is
> to get the image data in a uniform orientation, so all subsequent
> subroutines will know what to expect (which avoids rechecking assumptions).

Sure. I only specified this because I think I used terms like "lines",
"rows" etc. later on.

>> 3) Besides the "red", "blue" and "green" channels, create a "gray"
>> channel that is the average of the other three
>
> The image code values should be linarized at this stage, so film/sensor
> non-linearity and gamma adjustments can't influence the calculations.

Yes, I am currently ignoring gamma, as my test images are gamma=1.0 anyway.
If I'm not mistaken, though, this all boils down to a
"Pixel=InputPixel^Gamma" instead of just "Pixel=InputPixel", so I'll be
be very easy to add.

> It is customary to use a different weighting than the (R+G+B)/3 average.
> The ISO suggests the calculation of a luminance channel, so a ratio of
> approx. 3R:6G:1B is closer to what we experience as luminance.

I suspected this. This is also easy to do, so I'll fix it right now.

>> 4) Normalize the image, so that 0.5% of the pixels clip down, and 0.5%
>> clip up
>
> I think that, especially on non-linear image codes, this will influence
> the MTF results, because the contrast is expanded. On a perfectly
> symmetrical brightness distribution its effect will be small, but the
> possibility of clipping in later stages should be avoided.

I'm not sure I understand why it can affect the MTF, but I'll take your
word for it.

I've included this normalization step mainly because of the way I decide
how many pixels in each line will be considered part of the "edge", i.e.
contribute to the ESF: what I did is consider every pixel above a
certain threshold and below another (e.g. 10% and 90%, or more recently
5% and 95% since the former didn't work out well) part of the edge.

But (also judging from your other message) it seems I was completely off
track about this. I suppose I can just do like Imatest does, and say
that 10 pixels on the right and 6 on the left of the edge center will be
"part of the edge".

This way, the normalization process becomes unnecessary.

> Also a check
> for at least 20% edge modulation should be made, in order to avoid a too
> low input S/N ratio.

I'm taking note, but I think I'll leave such checks for later when the
program is somewhat stable.

> It is however perfectly normal to normalize the ESF output to a range
> between 0.0 and 1.0, and later to normalize the SFR/MTF to 1.0 (100%) at
> zero spatial frequency.

Currently, I'm normalizing the ESF, the LSF and the MTF to between 0.0
and 1.0.

>> 5) For each line in the image, find the point with the max adjacent
>> pixel difference (should be the edge)
>
> Not necessarily, that is just the maximum gradient and that need not be
> the same as the edge.
> The ISO suggests to combine this with with your step 9, and determine
> the centroid of the LSF (by calculating the discrete derivative of the
> ESF). The centroids can be used for regression.
>
> The derivative suggested by the ISO is:
> "for each line of pixels perpendicular to the edge, the edge is
> differentiated using the discrete derivative "-0,5 ; +0,5", meaning that
> the derivative value for pixel "X" is equal to -1/2 times the value of
> the pixel immediately to the left, plus 1/2 times the value of the pixel
> to the right".

Sorry if I'm thick, but mathematics isn't my best friend...
You're implying that, for each line of pixels, the edge center(oid?)
will be the absolute maximum of the above derivative, aren't you?

But isn't the absolute maximum of the derivative precisely the maximum
gradient?

(Though the formula I use is currently simpler than the one you cite:
simply y'[i]=y[i+1]-y[i])

> [snip]


>
>> 6) By doing a least squares regression on those points, find a
>> straight line that ought to best represent the edge
>> 7) Associate a distance from that line to each pixel in the image.
>
> The ISO method shifts each row of the ESF by the calculated amount from
> the regression, but uses quarter pixel bins. This produces a 4x
> oversampling per pixel position.

This doesn't sound like a bad idea at all. It'd probably simplify things
a lot, expecially with my "local regression" problems...

>> The function PixelValue(Distance) approximates the edge spread function.
>> 8) Use "some kind" of local regression to create a uniformly-spaced
>> version of the ESF, from the data described above.
>> 9) Derive the line spread function from the edge spread function:
>> LSF(i)=ESF(i+1)-ESF(i)
>
> See earlier remark, and provisions need to be made to detect multiple
> maxima (caused by noise/graininess).

What kind of provisions?

> [snip]


>> 11) Take the discrete Fourier transform or the resulting data
>
> And take the Modulus, and normalize.

Yes, I forgot to mention these steps, but they're done by the program.

>> Note that, at the moment, the input image must be an RGB, 8-bit ASCII
>> ("plain") PPM file. These can be created using "*topnm" and
>> "pnmtoplainpnm" from the NetPBM suite, or by using the GIMP.
>> Type --help for some uncomprehensive help.
>
> ;-) Room for improvement ...

I know :-) But I was concentrating more on the mathematical aspects
now... after all, I *am* able to write code that loads an image file --
well, I can take some time, but I can -- while to be sure I can manage
to compute an MTF or things like that, I have to try first...

> [snip]


>
>> Please keep in mind that I knew nothing about regressions, spread
>> functions or Fourier transforms two weeks ago -- and I suppose I don't
>> know that much more now.
>
> Isn't that the fun of programming, it forces you to describe the
> principles in detail. Learning new stuff is inevitable.

Sure, one of the reasons why I didn't just uploads some edges and ask
you to do my homework on them with Imatest! ;-)

Even though the SourceForge description currently says little more than
"calculates the MTF from a slanted edge", ultimately I'd like this
program to do automatic deconvolution (or whatever is best) of images
based on the edge results.

Like, "to sharpen an image, first scan a cutter or razor blade using the
'--edge' option, then run the program on the image with '--sharpen'".
Would be nice.

>> I just read some Internet source and implemented what I thought they
>> meant.
>
> With the program (to be) available to the public, the chance of helping
> hands increases.

Hope so!

> The source code you have probably read will give a good
> start. As always, the devil is in the details, but that can be overcome.

To be honest, I've read very little source, if any (well, except the
FFTW tutorial).

My main resource has been
http://www.isprs.org/istanbul2004/comm1/papers/2.pdf

where I took the evil alternative to the "4x bins" that I'm currently
using, with all the regression nighmares it brings ;-)
But it was an interesting document, anyway.


by LjL
ljl...@tiscali.it

Lorenzo J. Lucchini

unread,
Sep 27, 2005, 9:24:33 PM9/27/05
to

The new archive at
http://ljl.741.com/slantededge-alpha2.tar.gz
or
http://ljl.150m.com/slantededge-alpha2.tar.gz
now includes a Windows executable, as well as a test image.
Also, the program now uses luminance instead of RGB average, can be told
to gamma-correct, and doesn't normalize the image anymore.


At
http://ljl.741.com/comparison.gif
there is a a graph showing the MTF calculated both by my program and
SFRWin, from the test image included in the archive.


by LjL
ljl...@tiscali.it

Don

unread,
Sep 28, 2005, 9:16:35 AM9/28/05
to
On Wed, 28 Sep 2005 02:00:41 +0200, "Lorenzo J. Lucchini"
<ljl...@tiscali.it> wrote:

>> It is customary to use a different weighting than the (R+G+B)/3 average.
>> The ISO suggests the calculation of a luminance channel, so a ratio of
>> approx. 3R:6G:1B is closer to what we experience as luminance.
>
>I suspected this. This is also easy to do, so I'll fix it right now.

I've only been skimming this thread and not paying too much attention
because the MTF of my scanner is what it is and there's nothing I can
do about it... So, with that in mind...

In general, if you're doing measurements it makes much more sense to
use the average. You are *not* measuring your *subjective*
*perception* of the pixels but their *objective values*.

Applying perceptive weighing is counterproductive in this case and
will only skew the results. Or, as I like to say, "corrupt" them! ;o)

Actually, what I would do is measure each channel *separately*! That's
the only measurement that makes sense especially if you have a scanner
with 3 separate light sources. But even if you don't, different
filters can also potentially cause trouble. In either case, even
averaging would skew the results.

Don.

Lorenzo J. Lucchini

unread,
Sep 28, 2005, 9:28:36 AM9/28/05
to
Don wrote:
> On Wed, 28 Sep 2005 02:00:41 +0200, "Lorenzo J. Lucchini"
> <ljl...@tiscali.it> wrote:
>
>
>>>It is customary to use a different weighting than the (R+G+B)/3 average.
>>>The ISO suggests the calculation of a luminance channel, so a ratio of
>>>approx. 3R:6G:1B is closer to what we experience as luminance.
>>
>>I suspected this. This is also easy to do, so I'll fix it right now.
>
> I've only been skimming this thread and not paying too much attention
> because the MTF of my scanner is what it is and there's nothing I can
> do about it... So, with that in mind...

Well, but I don't plan to stop here. What I'd mostly like to obtain from
all this is a way to "sharpen" my scans using a function that is
tailored to my scanner's specifics (rather than just "unsharp mask as I
see fit").

So, you see, there is a practical application of the measurements I can
obtain, it's not just about knowing how poor the scanner's resolution is.

> In general, if you're doing measurements it makes much more sense to
> use the average. You are *not* measuring your *subjective*
> *perception* of the pixels but their *objective values*.
>
> Applying perceptive weighing is counterproductive in this case and
> will only skew the results. Or, as I like to say, "corrupt" them! ;o)

I'm not sure. Besides Bart, I think I've read somewhere else that
luminance should be used in this process. Perhaps it's even in the ISO
recommendations.

And why do you say I'm measuring the "objective values" of the pixels
instead of their "perceptual values"? I'm mostly trying to measure
resolution, in the form of the MTF. People usually cite the MTF50 and
the MTF10, because these are points where it *makes perceptual sense* to
measure: MTF10 is about the point where the human eye cannot discern
contrast anymore, Bart said.

So you see that I'm *already* doing measurements that are inherently
"perceptual". So why not be coherent and keep this in mind throughout
the process?

In any case, it makes sense to conform to what other programs of this
kind do, so that the results can be easily compared.

Perhaps I can put an option to use plain RGB average instead of
luminance. But anyway...

> Actually, what I would do is measure each channel *separately*!

... I'm doing this already.
The "gray" channel is measured *in addition* to the other three
channels, and is merely a convenience.

> [snip]

by LjL
ljl...@tiscali.it

Lorenzo J. Lucchini

unread,
Sep 28, 2005, 10:55:33 AM9/28/05
to
Bart van der Wolf wrote:
>
> "Lorenzo J. Lucchini" <ljl...@tiscali.it> wrote in message
> news:%ib_e.38$U1...@tornado.fastwebnet.it...
> SNIP
>
>> I'll see what I can do, perhaps I can just write a slow, simple DFT
>> myself (I have no idea how difficult it is, I'll have to read a bit)
>> as a compile alternative to FFTW.
>
> http://astronomy.swin.edu.au/~pbourke/other/dft/ and
> http://www.library.cornell.edu/nr/bookcpdf/c12-2.pdf has C code for a
> DFT function.
> http://www.library.cornell.edu/nr/cbookcpdf.html chapter 12 has more
> background on Fourier transforms, and chapter 13.1 has routines and
> backgound on Deconvolution (although there are better functions for
> image restoration).

Thanks, good pointers!
Now I can compile for Windows without using a custom DFT, since there is
FFTW in Cygwin, but I'll probably still include a custom transform
procedure in case someone wants to compile without FFTW installed.

It seems that I can't just copy&paste the code (at least from the first
site), though, as it's not public domain or GPL. I guess I'll have to
change some variable names ;-)

What do you propose for image restoration, instead of deconvolution?
("image restoration" obviously being restricted to the things you can do
when you have an ESF or PSF)

> [snip]


>
>> But it appears clear that the showed ESF also contains lower and
>> higher values; besides, it always seem to go from -6 pixels to +8
>> pixels from the edge center. Is there a reason for this?
>
> I'm not sure about the exact reason for the choice, but I assume it has
> to do with the shape of some ESFs that Norman Koren encountered when he
> developed the program. The actual data in Imatest is recorded from -6 to
> +10 at 0.25 intervals.
>
>> So, now I suppose "10%" and "90%" are simply used to compute (guess
>> what) the 10%-90% rise.
>
> Actually the width in pixels between the two response points.

So in your opinion it's ok if I just consider an arbitrary number of
pixels (like Imatest does) as constituting "the edge", without going to
great length trying to have the program make an educated guess?

>> Which in turns call for: should I normalize the image before doing
>> anything else? I currently normalize so that 0.5% of pixels clip to
>> black and 0.5% clip to white.
>
> No, it is better to only normalize the output curves but leave the
> original data (which is where the truth is hidden) as it is. By
> manipulating the image data itself, you run the risk of changing the
> data (in case of non-linear response data), and of introducing
> quantization errors (by rounding up/down half a bit).

Shouldn't incur in quantization errors, as I'm converting the image to
floating point as soon as it's loaded (*while* loading it, actually).
But anyway, I've removed this step from the current build.

>> - Is it ok to take a (single) Fourier transform of the Hanning-
>> windowed LSF?
>
> Yes, it's not that much data, so the DFT is fast.
>
>> Without windowing, I get weird results, but with windowing, I'm afraid
>> I'm affecting the data.
>
> You'll have to window because of the abrupt edges. That's reality in
> Fourier transforms, we deal with a small subset of the real data which
> reaches out to infinity.

Yes, but there are two other options I've considered:

1) taking *many* DFTs of small (Hanning-windowed) pieces of the LSF, and
then average them together. Wouldn't this avoid the change of LSF shape
that using a single, big window may cause?

2) not using any window, but "cropping" the LSF so that the edges are
(very near) zero. Would this have any chances of working? It would
completely avoid changing the LSF's shape.

>> My MTF's always look "smoother" than Imatest's and SFTWin's ones, and
>> too high in the lower frequencies.
>
> We'll have to see, but make sure you compute the magnitude of the
> transform (take the "Modulus" of the DFT).

Yes, I do this.
MTF[i]=SquareRoot(ImaginaryPart[i]^2+RealPart[i]^2)

>> - How many samples should my ESF/LSF have? I understand that it only
>> depends on how high you want your frequencies to be -- i.e., if I want
>> to show the MTF up to 4xNyquist, I should have 4x more samples than
>> there are real pixels. Is this correct?
>
> No.

Well, but it ends up like this anyway, doesn't it? Anyway, the method
I'm using comes from the document I pointed to in the other article, so
it shouldn't be *too* stupid.

Still, the method you describe sounds much simpler to implement, so I
guess I'll go for it.

> In the ISO method you would calculate an ESF for each line (row) of
> pixels that crosses the edge. The average of all those ESFs is produced
> after shifting each row in proportion with the centroid regression. It
> is at that point, the shifting, that you bin the pixels in an array
> that's 4x wider than the edge crop. That allows you to bin the centroid
> with a 4x higher (=quarter pixel) resolution. After that it's just
> statistics, larger numbers of ESFs make a more likely approximation of
> the actual ESF.

Let us see if I've understood this.

What you mean is, for each line "y", for each pixel "x", do

ESF[ (x*4) + (Distance(Pixel[x][y], Centroid[y]) % 4) ] +=
Pixel[x][y];

and then, at the end, divide ESF[i] = ESF[i]/y, to get the average
(well, or just normalize the ESF I have).

By the way, "%" is "modulo", and "a += b" means "a = a + b".
No offense meant ;-) but I don't know how fluent you are in C (and
others who read might not be, anyway).

> The ISO takes one additional precaution, they take an integer number of
> phase rotations. That means that if you e.g. calculated a slope of 1
> pixel for every ten rows, then they take an integer multiple of ten
> rows, starting at the top and trunkating the image data at the bottom.
>
>> - How do I reduce frequencies spacing in the DFT?
>
> I'm not sure what you mean, but it may have to do with the previous
> quarter pixel binning.

Not sure, no.

What I mean is this: imagine your line spread function contains 128
values. The resulting DFT will contain 64 values, which is very few: the
"frequency resolution", or "frequency spacing" - or whatever it should
be called - of this MTF will be much worse than that provider by Imatest
or SFRWin.

Oversampling the LSF doesn't help: even if it's made of 1024 values, for
example, the DFT will now simply contain higher frequencies, but the
spacing between frequencies will remain the same.
(and in fact, you say that Imatest only oversamples 4x)

Now, I have read that the DFT really already "contains" everything it
can contain.
Still, very little is visible.

For example, look again at
http://ljl.741.com/scans/fig-blade2.gif
The MTF looks very detailed, as there are "jaggies" for example between
x=0..20 and y=0.2..0.6 .

The only viable way I have found to obtain this kind of precision is to
zero-pad the input LSF like crazy. But it doesn't seem a very smart or
elegant solution!

>> [snip LOESS]
>
> [snip]


>
>> The question is: is something simpler good enough?
>
> Part of it may have to do with the quarter pixel sampling/binning.
> If you just want to fit a monotone curve through regularly sampled
> points, a simple interpolation (Cubic or Hermite) seems good enough to me:
> http://astronomy.swin.edu.au/~pbourke/other/interpolation/

I'm afraid interpolation isn't really going to make it. If I
scatter-plot my edge data, I don't see many outliers, but I do see a
very "thick" "nebula" of points -- I'm not sure I'm explaining myself.

But anyway, I better try the "4x bins" method before venturing into
this. It that one just works out of the box, then who cares about local
regressions anymore!


by LjL
ljl...@tiscali.it

Lorenzo J. Lucchini

unread,
Sep 28, 2005, 11:04:16 AM9/28/05
to
Lorenzo J. Lucchini wrote:
> [snip]
>
> Let us see if I've understood this.
>
> What you mean is, for each line "y", for each pixel "x", do
>
> ESF[ (x*4) + (Distance(Pixel[x][y], Centroid[y]) % 4) ] +=
> Pixel[x][y];
>
> and then, at the end, divide ESF[i] = ESF[i]/y, to get the average
> (well, or just normalize the ESF I have).

Sorry, probably I should have specified better what I meant with
Centroid[y]: not the position on line y where the edge "appears to be",
but the edge position on line y taken *from the regression*.

That is, first I do
for(y) {
ApproximatedCentroid[y]=FindCentroid(y);
}

Then,
for(y) {
RealCentroid[y]=PointInRegression(ApproximatedCentroid, y);
}

and then use the ReadCentroid array in the "bins" code. I suppose using
the ApproximatedCentroid array would make no sense.


by LjL
ljl...@tiscali.it

Lorenzo J. Lucchini

unread,
Sep 28, 2005, 11:11:24 AM9/28/05
to
Lorenzo J. Lucchini wrote:
> ESF[ (x*4) + (Distance(Pixel[x][y], Centroid[y]) % 4) ] +=
> Pixel[x][y];

Sorry again... this should be

ESF[ (x*4) + (Distance(Pixel[x][y], Centroid[y]) * 4) % 1) += ...

i.e. I should multiply the distance from the edge center by 4, and then
take only the fractionary part.

This way, if the pixel is an integer number of pixels away from the edge
center, it will end up in the "first bin";
if it's an integer number of pixels away, plus 0.25, it will end up in
the "second bin", and so on.


I hope this time I've got it right :-)

by LjL
ljl...@tiscali.it

Bart van der Wolf

unread,
Sep 28, 2005, 12:15:38 PM9/28/05
to

"Lorenzo J. Lucchini" <ljl...@tiscali.it> wrote in message
news:aVw_e.1452$133...@tornado.fastwebnet.it...
SNIP

> I'm not sure. Besides Bart, I think I've read somewhere else that
> luminance should be used in this process. Perhaps it's even in the
> ISO recommendations.

The ISO allows to test whatever one wants, single channels or weigthed
combinations of more than one, whatever suits the purpose, but a
formal test of a device should include R+G+B measurements. However, to
quote them "If desired, a luminance resolution measurement may be made
on a luminance signal formed from an appropriate combination of the
colour records".
Since the purpose is sharpening (which should be done in the Luminance
channel if you want to avoid colored artifacts), it only makes sense
to use a weighting that simulated the luminance sensitivity of the
human eye.

Imatest also calculates a Y channel for luminance (and that was not an
uninformed choice), as it is the most significant for the sensation we
call 'sharpness'. With human eyes, color resolution is much lower than
Luminance resolution.

> And why do you say I'm measuring the "objective values" of the
> pixels instead of their "perceptual values"? I'm mostly trying to
> measure resolution, in the form of the MTF. People usually cite the
> MTF50 and the MTF10, because these are points where it *makes
> perceptual sense* to measure: MTF10 is about the point where the
> human eye cannot discern contrast anymore, Bart said.

You don't have to take my word, but this is what the ISO says:
"A very good correlation between limiting visual resolution and the
spatial frequency associated with a 0,10 SFR response has been found
experimentally. Should this frequency exceed the half-sampling
frequency, the limiting visual resolution shall be the spatial
frequency associated with the half-sampling frequency".

SNIP


> In any case, it makes sense to conform to what other programs of
> this kind do, so that the results can be easily compared.

There are many different opinions on what the mix should be.
If you want to exactly match Imatest, you could use
Y=0.3*R+0.59*G+0.11*B
(http://www.imatest.com/docs/sfr_instructions2.html almost
halfway down the page under Channel).

Other researchers use L=0.299R+0.587G+0.114B .
And Luminance weighting according to ITU-R BT.709 is:
Y=0.2125*R+0.7154*G+0.0721*B
which comes close(r) to:
<http://hyperphysics.phy-astr.gsu.edu/hbase/vision/efficacy.html#c1>

Whatever the choice (ultimately user selectable would be best for
flexibility, but makes comparisons more hazardous), I think Human
perception should carry some weight when the goal is to optimize
sharpening.

Bart

Lorenzo J. Lucchini

unread,
Sep 28, 2005, 12:29:13 PM9/28/05
to
Bart van der Wolf wrote:
>
> "Lorenzo J. Lucchini" <ljl...@tiscali.it> wrote in message
> news:aVw_e.1452$133...@tornado.fastwebnet.it...
>
> [snip]

>
> There are many different opinions on what the mix should be.
> If you want to exactly match Imatest, you could use
> Y=0.3*R+0.59*G+0.11*B
> (http://www.imatest.com/docs/sfr_instructions2.html almost
> halfway down the page under Channel).
>
> Other researchers use L=0.299R+0.587G+0.114B .
> And Luminance weighting according to ITU-R BT.709 is:
> Y=0.2125*R+0.7154*G+0.0721*B
> which comes close(r) to:
> <http://hyperphysics.phy-astr.gsu.edu/hbase/vision/efficacy.html#c1>
>
> Whatever the choice (ultimately user selectable would be best for
> flexibility, but makes comparisons more hazardous), I think Human
> perception should carry some weight when the goal is to optimize
> sharpening.

I think I'll go for user selectable, with a default that's recommended
for comparing others' results.

But all this made me wonder about something else: would it make any
sense to compare the edge *position* of each (red, green and blue)
channel with the edge position in the luminance channel?

I mean. SFRWin gives "red", "blue" and "green" color offsets (for
measuring "color fringing"), but the "green" offset is always zero, as
the other two channels are compared to green.

Would comparing the three channels to luminance, instead, have any
advantage over SFRWin's approach? I don't remember what Imatest does here.


by LjL
ljl...@tiscali.it

Bart van der Wolf

unread,
Sep 28, 2005, 1:06:50 PM9/28/05
to

"Lorenzo J. Lucchini" <ljl...@tiscali.it> wrote in message
news:L3l_e.674$133...@tornado.fastwebnet.it...

> Bart van der Wolf wrote:
SNIP

>> The image code values should be linarized at this stage,
>> so film/sensor non-linearity and gamma adjustments
>> can't influence the calculations.
>
> Yes, I am currently ignoring gamma, as my test images
> are gamma=1.0 anyway.

For real accurate results, that remains to be verified ...
Testing a (transparent) step wedge may/will reveal 'interesting'
features of hardware *and* of scanner driver software.

> If I'm not mistaken, though, this all boils down to a
> "Pixel=InputPixel^Gamma" instead of just "Pixel=InputPixel",
> so I'll > be be very easy to add.

Yes, for straight Gamma only (sRGB profiled images use a
'slope-limited' Gamma). Also beware that Gamma adjustment
may mean 1/Gamma, depending on what is being adjusted where.
This does assume that Gamma is the only non-linearity.

SNIP


>> I think that, especially on non-linear image codes, this will
>> influence the MTF results, because the contrast is expanded.
>> On a perfectly symmetrical brightness distribution its effect
>> will be small, but the possibility of clipping in later stages
>> should be avoided.
>
> I'm not sure I understand why it can affect the MTF, but I'll take
> your word for it.

Assume all it takes is a lowering of the highlight clipping point,
which essentially is the same as multiplying all luminance levels by a
fixed factor. That would work out differently for shadows/highlights
if the response was non-linear.

SNIP


>> Also a check for at least 20% edge modulation should be made, in
>> order to avoid a too low input S/N ratio.
>
> I'm taking note, but I think I'll leave such checks for later when
> the program is somewhat stable.

Obviously, I know how actual programming works (tackle large issues
first, and get a working alpha version before working on the 'icing of
the cake'), but just don't forget some obvious boundary checks in the
end.

>> It is however perfectly normal to normalize the ESF output to a
>> range between 0.0 and 1.0, and later to normalize the SFR/MTF to
>> 1.0 (100%) at zero spatial frequency.
>
> Currently, I'm normalizing the ESF, the LSF and the MTF to between
> 0.0 and 1.0.

Just note that actual MTFs can exceed 1.0, assuming correct
normalization to 1.0 at zero cycles. Edge sharpening halo can achieve
that easily.

SNIP
>> The ISO suggests to [...] determine the centroid of the LSF (by


>> calculating the discrete derivative of the ESF). The centroids can
>> be used for regression.
> >
>> The derivative suggested by the ISO is:
>> "for each line of pixels perpendicular to the edge, the edge is
>> differentiated using the discrete derivative "-0,5 ; +0,5", meaning
>> that the derivative value for pixel "X" is equal to -1/2 times the
>> value of the pixel immediately to the left, plus 1/2 times the
>> value of the pixel to the right".
>
> Sorry if I'm thick, but mathematics isn't my best friend...

Hey, I also know my limitations in that field ... ;-)

> You're implying that, for each line of pixels, the edge center(oid?)
> will be the absolute maximum of the above derivative, aren't you?

Yep.

> But isn't the absolute maximum of the derivative precisely the
> maximum gradient?

Rereading it, yes, but it actually is where the increasing contrast
turns into decreasing contrast (the first derivative being the slope
of the curve).

> (Though the formula I use is currently simpler than the one you
> cite: simply y'[i]=y[i+1]-y[i])

Yes, and it'll produce a difference, but actual nodes will on average
be displaced by half a pixel. Nevertheless, the sample code from
the ISO seems to do what you did, so I'd suggest leaving it that way.

SNIP


>> See earlier remark, and provisions need to be made to detect
>> multiple maxima (caused by noise/graininess).
>
> What kind of provisions?

With noisy images, there can be multiple LSF maxima from a single ESF.
One should decide which maximum to take. I dug up some old Word
document with C code for the SFR calculation. It takes the average
between the leftmost and rightmost maxima.
If your email address in your signature is valid, I can send you that
document.

SNIP


> Even though the SourceForge description currently says little more
> than "calculates the MTF from a slanted edge", ultimately I'd like
> this program to do automatic deconvolution (or whatever is best) of
> images based on the edge results.

Yes, that's a good goal, although it will take more than a single
slanted edge to get a two-dimensional a-symmetric PSF). What's worse,
the PSF can (and does) change throughout the image, but a symmetrical
PSF will already allow to improve image quality.
Some hurdles will need to be taken, but the goal is exactly what I am
looking for.

SNIP


> My main resource has been
> http://www.isprs.org/istanbul2004/comm1/papers/2.pdf
>
> where I took the evil alternative to the "4x bins" that I'm
> currently using, with all the regression nighmares it brings ;-)
> But it was an interesting document, anyway.

Yes, we're not the only ones still looking for the holy grail, it
seems.

I'm working on a method that will produce a PSF, based on the ESF
derived from a slanted edge. That PSF can be used in various
deconvolution methods, and it can be used to create a High-pass filter
kernel. Could be useful to incorporate in the final program.

Bart

Bart van der Wolf

unread,
Sep 28, 2005, 1:58:47 PM9/28/05
to

"Lorenzo J. Lucchini" <ljl...@tiscali.it> wrote in message
news:nim_e.699$133...@tornado.fastwebnet.it...
SNIP

> The new archive at
> http://ljl.741.com/slantededge-alpha2.tar.gz
> or
> http://ljl.150m.com/slantededge-alpha2.tar.gz
> now includes a Windows executable, as well as a test image.

Thanks. Unfortunately I get an error box with:
"This application has failed to start because cygwin1.dll was not
found".

SNIP


> At
> http://ljl.741.com/comparison.gif
> there is a a graph showing the MTF calculated both by my program and
> SFRWin, from the test image included in the archive.

The test image looks a bit odd. It seems like the edge was resized
vertically with a nearest neighbor interpolation. The edge pixels look
like they are 2 pixels high and 1 pixel wide. The noise in the image
is single pixel noise (and has a bit of hardware calibration
striping).

It looks strange, and thus produces strange sharpening artifacts if
pushed to the limits (deconvolution sharpening with a derived PSF, and
a Richardson-Lucy restoration with the same PSF). Nevertheless, the
Imatest SFR analysis looks identical to the SFRWin result.

Bart

Lorenzo J. Lucchini

unread,
Sep 28, 2005, 2:19:39 PM9/28/05
to
Bart van der Wolf wrote:
>
> "Lorenzo J. Lucchini" <ljl...@tiscali.it> wrote in message
> news:nim_e.699$133...@tornado.fastwebnet.it...
> SNIP
>
>> The new archive at
>> http://ljl.741.com/slantededge-alpha2.tar.gz
>> or
>> http://ljl.150m.com/slantededge-alpha2.tar.gz
>> now includes a Windows executable, as well as a test image.
>
>
> Thanks. Unfortunately I get an error box with:
> "This application has failed to start because cygwin1.dll was not found".

Yeah, it's the Unix emulation layer that Cygwin compiled programs
apparently need.
I've uploaded it at
http://ljl.741.com/cygwin1.dll.gz
http://ljl.150m.com/cygwin1.dll.gz

Putting it in the same directory as the program should work, as should
putting in in \Windows\System32.

> SNIP
>
>> At
>> http://ljl.741.com/comparison.gif
>> there is a a graph showing the MTF calculated both by my program and
>> SFRWin, from the test image included in the archive.
>
>
> The test image looks a bit odd. It seems like the edge was resized
> vertically with a nearest neighbor interpolation. The edge pixels look
> like they are 2 pixels high and 1 pixel wide.

It could be: I've scanned some edges at 2400x4800 and resized them down
to see how this affected the MTF (remember the thread "Multi-sampling
and 2400x4800 scanners").

Obviously, I'm stupid enough to give very meaningful names to my files
such as "edge1.tif", "edge2.tif", "edgehg.tif", so it's entirely
possible that I took the wrong edge =)

I guess the next tarball will contain a freshly scanned edge, to avoid
this confusion.

> The noise in the image is
> single pixel noise (and has a bit of hardware calibration striping).

What is single pixel noise -- or, is it "single pixel" as opposed to what)?

> [snip]

by LjL
ljl...@tiscali.it

Lorenzo J. Lucchini

unread,
Sep 28, 2005, 3:24:01 PM9/28/05
to
Bart van der Wolf wrote:
>
> "Lorenzo J. Lucchini" <ljl...@tiscali.it> wrote in message
> news:L3l_e.674$133...@tornado.fastwebnet.it...
>
>> Bart van der Wolf wrote:
>
> SNIP
>
>>> The image code values should be linarized at this stage,
>>> so film/sensor non-linearity and gamma adjustments
>>> can't influence the calculations.
>>
>> Yes, I am currently ignoring gamma, as my test images
>> are gamma=1.0 anyway.
>
> For real accurate results, that remains to be verified ...
> Testing a (transparent) step wedge may/will reveal 'interesting'
> features of hardware *and* of scanner driver software.

True. But test targets cost money, and I'm allergic to expenses ;-)
Well, sooner or later, perhaps I'll go buy an IT8 test target, so that I
have a gray scale for measuring gamma, as well as everything else for
measuring colors.

But not right now. Actually, one of the reasons why I got very
interested in this slanted edge test was its astonishing inexpensiveness :-)

By the way, can the test somehow also tell something about color
corrections? Intuitively, it seems to me that with the ESF and the MTF
for red, green and blue one should be able to fix at least *some* color
correction parameters.

>> If I'm not mistaken, though, this all boils down to a
>> "Pixel=InputPixel^Gamma" instead of just "Pixel=InputPixel",
>> so I'll > be be very easy to add.
>
> Yes, for straight Gamma only (sRGB profiled images use a
> 'slope-limited' Gamma). Also beware that Gamma adjustment
> may mean 1/Gamma, depending on what is being adjusted where.
> This does assume that Gamma is the only non-linearity.

But if I'm not mistaken, Imatest does the same, so I can be content with
it right now.
SFRWin on the other hand allows one to specify a look-up table.

> [snip]


>
> Just note that actual MTFs can exceed 1.0, assuming correct
> normalization to 1.0 at zero cycles. Edge sharpening halo can achieve
> that easily.

Right. I'll have to fix this, as the program currently doesn't give the
zero-cycles point any special treatment, but just normalizes.

> [snip]


>
>>> See earlier remark, and provisions need to be made to detect
>>> multiple maxima (caused by noise/graininess).
>>
>> What kind of provisions?
>
> With noisy images, there can be multiple LSF maxima from a single ESF.
> One should decide which maximum to take. I dug up some old Word document
> with C code for the SFR calculation. It takes the average between the
> leftmost and rightmost maxima.
> If your email address in your signature is valid, I can send you that
> document.

Yes, it's valid. It's usually full because of spam, but I'm keeping it
clean lately... just don't put "enlargement" in the subject and I should
receive it :-)

Anyway, can noise really cause such problems, besides in "extreme"
situations (i.e. when the measurments would be better thrown away anyway)?

I'm thinking that even a very high spike of noise shouldn't be able to
get higher than the edge constrast, considering that *many* lines are
averaged together to obtain the ESF...

Perhaps *very* bad calibration striping could cause that, but then again
one should probably throw away the scan in such a case.

> SNIP
>
>> Even though the SourceForge description currently says little more
>> than "calculates the MTF from a slanted edge", ultimately I'd like
>> this program to do automatic deconvolution (or whatever is best) of
>> images based on the edge results.
>
> Yes, that's a good goal, although it will take more than a single
> slanted edge to get a two-dimensional a-symmetric PSF).

Well, I assume that a vertical+horizontal edge measurement can be
accurate enough for many purposes.

By the way, I've done (but not published) some tests on horizontal edges
(i.e. stepping motor resolution), and the results are a bit depressing!
About 100-200 dpi lower resolution than on the CCD axis, and a
frightening amount of color fringing.

> What's worse,
> the PSF can (and does) change throughout the image, but a symmetrical
> PSF will already allow to improve image quality.
> Some hurdles will need to be taken, but the goal is exactly what I am
> looking for.

Well, it's a bit soon for this perhaps, but... how do I obtain the PSF
from two (h+v) ESFs?
Perhaps for each point, average the two points on the ESFs that are at
the same distance from the "center" of the function, and weight the
average based on the angle between the points and the two (h+v) axes?

But anyway...

> SNIP
>
>> My main resource has been
>> http://www.isprs.org/istanbul2004/comm1/papers/2.pdf
>>
>> where I took the evil alternative to the "4x bins" that I'm
>> currently using, with all the regression nighmares it brings ;-)
>> But it was an interesting document, anyway.
>
> Yes, we're not the only ones still looking for the holy grail, it seems.
>
> I'm working on a method that will produce a PSF, based on the ESF
> derived from a slanted edge. That PSF can be used in various
> deconvolution methods, and it can be used to create a High-pass filter
> kernel. Could be useful to incorporate in the final program.

... of course it can be useful. No need for me to invent the square
wheel when you've already worked on an octagonal one :-)


by LjL
ljl...@tiscali.it

Bart van der Wolf

unread,
Sep 28, 2005, 7:31:10 PM9/28/05
to

"Lorenzo J. Lucchini" <ljl...@tiscali.it> wrote in message
news:Gay_e.1611$133...@tornado.fastwebnet.it...
SNIP

> What do you propose for image restoration, instead of deconvolution?
> ("image restoration" obviously being restricted to the things you
> can do when you have an ESF or PSF)

Straight deconvolution will 'restore' noise (and graininess) as well
as the signal itself, or the noise is even amplified. There are better
methods like the adaptive (damped) Richardson-Lucy algorithm, but that
is a very processing intensive and thus time consuming operation. The
method used in "Image Analyzer", using the "CGLS" algorithm, is much
faster but slightly noisier than RL.
<http://www.mathcs.emory.edu/~nagy/RestoreTools/index.html>

SNIP


> So in your opinion it's ok if I just consider an arbitrary number of
> pixels (like Imatest does) as constituting "the edge", without going
> to great length trying to have the program make an educated guess?

Yes, although flatbed scanners exhibit a significantly wider ESF with
long tails. Don't be too conservative. The range used by Imatest is
from -6 to +10 in quarter pixel increments, and thus allows to handle
at least a symmetrical PSF with a support of 13 pixels, which would be
for a *very* blurry image.

SNIP


>> You'll have to window because of the abrupt edges. That's reality
>> in Fourier transforms, we deal with a small subset of the real data
>> which reaches out to infinity.
>
> Yes, but there are two other options I've considered:
>
> 1) taking *many* DFTs of small (Hanning-windowed) pieces of the LSF,
> and then average them together. Wouldn't this avoid the change of
> LSF shape that using a single, big window may cause?

Although possible, it's probably more efficient to code the
binning/averaging many single row LSFs, thus approaching the real LSF.
It's the real LSF that needs to be 'DFT'ed. IMO it's not so useful to
perform many DFTs on such a small (e.g. 64 quarter pixels if ranging
from ) array, it becomes less efficient and I think complex. Some
calculations are easier/faster in the frequency domain (e.g.
deconvolution) and others in the spatial domain (averaging and small
kernel convolution). The windowing has only to be done once on the
multiple LSF average (which already has lower noise than single
samples).

> 2) not using any window, but "cropping" the LSF so that the edges
> are (very near) zero. Would this have any chances of working? It
> would completely avoid changing the LSF's shape.

Truncation loses information, I don't think that's helpful. Windowing
will further reduce the already low response and it suppresses noise
at the boundaries. That's helpful.

SNIP


> Yes, I do this.
> MTF[i]=SquareRoot(ImaginaryPart[i]^2+RealPart[i]^2)

Depending on the library implementation, for complex numbers , Abs[z]
gives the modulus |z| .
Also note http://www.library.cornell.edu/nr/bookcpdf/c5-4.pdf (5.4.3)
which is a more robust way of doing it in extreme cases (which may
never occur, but it's still more robust).

>>> - How many samples should my ESF/LSF have? I understand that it
>>> only depends on how high you want your frequencies to be -- i.e.,
>>> if I want to show the MTF up to 4xNyquist, I should have 4x more
>>> samples than there are real pixels. Is this correct?
>>
>> No.
>

> Anyway, the method I'm using comes from the document I pointed to in
> the other article, so it shouldn't be *too* stupid.
>
> Still, the method you describe sounds much simpler to implement, so
> I guess I'll go for it.

In the Netherlands we have a saying, "there are several roads, all
leading to Rome" ;-)
All I did is describe how the ISO suggests to do it, and it seems
relatively simple to code it. Simple code reduces the chance on bugs
and unforeseen 'features'.


>
>> In the ISO method you would calculate an ESF for each line (row) of
>> pixels that crosses the edge. The average of all those ESFs is
>> produced after shifting each row in proportion with the centroid
>> regression. It is at that point, the shifting, that you bin the
>> pixels in an array that's 4x wider than the edge crop. That allows
>> you to bin the centroid with a 4x higher (=quarter pixel)
>> resolution. After that it's just statistics, larger numbers of ESFs
>> make a more likely approximation of the actual ESF.
>
> Let us see if I've understood this.

[...]

I think I have an even better suggestion. I have some C code examples
from the ISO that shows how it could be implemented. If I can email
the 48KB Word document (is your ljl...@tiscali.it in the signature
valid?), it'll become quite clear, I'm sure. I also have a 130KB PDF
file you'll love to read because it describes the various steps and
considerations in more detail.

One more remark. I've been having some discussions with Fernando
Carello (also from Italy) about PSFs and types of restoration. He was
willing (if time permits) to attempt to tackle that side of the
challenge. Although I understand that it's always a bit difficult to
fathom a mix of programming styles, it could potentially help (again,
if his time allows).

Bart

Bart van der Wolf

unread,
Sep 28, 2005, 7:55:22 PM9/28/05
to

"Lorenzo J. Lucchini" <ljl...@tiscali.it> wrote in message
news:vyz_e.1841$133....@tornado.fastwebnet.it...
SNIP

> I think I'll go for user selectable, with a default that's
> recommended for comparing others' results.

Yep, seems like the pragmatic approach wins.

> But all this made me wonder about something else: would it make any
> sense to compare the edge *position* of each (red, green and blue)
> channel with the edge position in the luminance channel?

Depends on what one wants to investigate, but I see no direct use for
comparison of a color channel with Luminance. Besides Luminance for
sharpness, one could compare R, G, and B for Chromatic aberrations. In
digicams with a Bayer CFA it can be quite revealing what a difference
Raw converters can make. For scanners that seems less of an issue.

> I mean. SFRWin gives "red", "blue" and "green" color offsets (for
> measuring "color fringing"), but the "green" offset is always zero,
> as the other two channels are compared to green.
>
> Would comparing the three channels to luminance, instead, have any
> advantage over SFRWin's approach? I don't remember what Imatest does
> here.

No advantage for me. Imatest produces a figure for Chromatic
Aberration (http://www.imatest.com/docs/tour_sfr.html#ca).

Bart

Lorenzo J. Lucchini

unread,
Sep 28, 2005, 8:04:22 PM9/28/05
to
Bart van der Wolf wrote:
>
> "Lorenzo J. Lucchini" <ljl...@tiscali.it> wrote in message
> news:Gay_e.1611$133...@tornado.fastwebnet.it...
> SNIP
>
> [snip]

>
>> So in your opinion it's ok if I just consider an arbitrary number of
>> pixels (like Imatest does) as constituting "the edge", without going
>> to great length trying to have the program make an educated guess?
>
> Yes, although flatbed scanners exhibit a significantly wider ESF with
> long tails. Don't be too conservative. The range used by Imatest is from
> -6 to +10 in quarter pixel increments, and thus allows to handle at
> least a symmetrical PSF with a support of 13 pixels, which would be for
> a *very* blurry image.

Well, I will use -10 .. +10 for now, if it doesn't get too slow (but
using the "4x bins" thing it should all go much faster, I think).
That should allow plenty of room.

> SNIP
>
>>> You'll have to window because of the abrupt edges. That's reality in
>>> Fourier transforms, we deal with a small subset of the real data
>>> which reaches out to infinity.
>>
>>
>> Yes, but there are two other options I've considered:
>>
>> 1) taking *many* DFTs of small (Hanning-windowed) pieces of the LSF,
>> and then average them together. Wouldn't this avoid the change of LSF
>> shape that using a single, big window may cause?
>
>
> Although possible, it's probably more efficient to code the
> binning/averaging many single row LSFs, thus approaching the real LSF.
> It's the real LSF that needs to be 'DFT'ed. IMO it's not so useful to
> perform many DFTs on such a small (e.g. 64 quarter pixels if ranging
> from ) array, it becomes less efficient and I think complex. Some
> calculations are easier/faster in the frequency domain (e.g.
> deconvolution) and others in the spatial domain (averaging and small
> kernel convolution). The windowing has only to be done once on the
> multiple LSF average (which already has lower noise than single samples).

No, sorry, I didn't mean to take the DFTs of all single-row LSFs.

What I meant is:
- assume you have a (final) LSF that is 128 values long
- you take the windowed DFT of the first 16 values
- then you take the DFT of values from 8 to 24
- then from 16 to 32
- etc
- then you average all these together

I've not just invented this strange thing, I've read it somewhere,
though not in a graphics context, and I might have misinterpreted it.

>> 2) not using any window, but "cropping" the LSF so that the edges are
>> (very near) zero. Would this have any chances of working? It would
>> completely avoid changing the LSF's shape.
>
> Truncation loses information, I don't think that's helpful. Windowing
> will further reduce the already low response and it suppresses noise at
> the boundaries. That's helpful.

I see. Well, at least I guess that taking a "longer" LSF (i.e.
considering more pixels "part of the edge") could help reduce any
artifacts caused by the windowing, since most of the "important" data is
in a small part of the whole LSF.

Also, do you think a Hanning window is a reasonable choice for my
purposes, or should I choose a different window type?

> SNIP
>
>> Yes, I do this.
>> MTF[i]=SquareRoot(ImaginaryPart[i]^2+RealPart[i]^2)
>
> Depending on the library implementation, for complex numbers , Abs[z]
> gives the modulus |z| .

No, there isn't such a function in FFTW. However, there are functions to
directly obtain a real-to-real FFT; I probably should look at them,
although I'm not sure if the real data they output are the moduli or
simply the real parts of the transform's output.

> Also note http://www.library.cornell.edu/nr/bookcpdf/c5-4.pdf (5.4.3)
> which is a more robust way of doing it in extreme cases (which may never
> occur, but it's still more robust).

Site down at the moment :-) I'm starting to worry that it may somehow be
me...

> [snip]


>
> In the Netherlands we have a saying, "there are several roads, all
> leading to Rome" ;-)

Tutte le strade portano a Roma (all roads bring to Rome), clearly we
have that too, and in our case, it's actually true ;-) at least for
those roads that were originally built in ancient Roman times.

> [snip]


>
>> Let us see if I've understood this.
>
> [...]
>
> I think I have an even better suggestion. I have some C code examples
> from the ISO that shows how it could be implemented. If I can email the
> 48KB Word document (is your ljl...@tiscali.it in the signature valid?),
> it'll become quite clear, I'm sure.

It's valid, yes.
Only, how copyrighted is that stuff, and what's the legal state of those
documents? ISO might get upset with both of us, if somehow I wasn't
supposed to read or use their papers (ok, ok, in the real world they
won't even notice we exist I suppose).

> I also have a 130KB PDF file you'll
> love to read because it describes the various steps and considerations
> in more detail.

Sure, if the main concepts can be understood without going too deeply
technical, it'll be most welcome.

> One more remark. I've been having some discussions with Fernando Carello
> (also from Italy) about PSFs and types of restoration. He was willing
> (if time permits) to attempt to tackle that side of the challenge.

I've read through some of the threads you've had with him.

> Although I understand that it's always a bit difficult to fathom a mix
> of programming styles, it could potentially help (again, if his time
> allows).

Sure! And if we work on separate aspects of the issue, the problem of
mixed programming styles is easily solved by having separate
sources/libraries communicate through an interface, you know, like I've
heard real programmers (rarely) do ;-)

Hm, I see a problem though... these PSF MTF ESF DFT regression curve
fitting etc thingies, I don't know how to call most of them in Italian :-D


by LjL
ljl...@tiscali.it

Bart van der Wolf

unread,
Sep 28, 2005, 8:14:07 PM9/28/05
to

"Lorenzo J. Lucchini" <ljl...@tiscali.it> wrote in message
news:1aB_e.2000$133....@tornado.fastwebnet.it...
SNIP

> Yeah, it's the Unix emulation layer that Cygwin compiled programs
> apparently need.
> I've uploaded it at
> http://ljl.741.com/cygwin1.dll.gz
> http://ljl.150m.com/cygwin1.dll.gz

Getting closer, although now it complains about not being to locate
cygfftw3-3.dll (presumably the FFT routine library).

SNIP


>> The test image looks a bit odd. It seems like the edge was resized
>> vertically with a nearest neighbor interpolation. The edge pixels
>> look like they are 2 pixels high and 1 pixel wide.
>
> It could be: I've scanned some edges at 2400x4800 and resized them
> down to see how this affected the MTF (remember the thread
> "Multi-sampling and 2400x4800 scanners").

Yes, that's what I was thinking of, interpolation in one direction to
compensate for the aspect ratio.

SNIP


>> The noise in the image is single pixel noise (and has a bit of
>> hardware calibration striping).
>
> What is single pixel noise -- or, is it "single pixel" as opposed to
> what)?

No, the edge seems to be NN interpolated, but the noise is not (there
are single (as opposed to 1x2 pixel) variations).

I'll wait for the next tarball, before making further benchmark tests.

Bart

Lorenzo J. Lucchini

unread,
Sep 28, 2005, 8:44:29 PM9/28/05
to
Bart van der Wolf wrote:
>
> "Lorenzo J. Lucchini" <ljl...@tiscali.it> wrote in message
> news:1aB_e.2000$133....@tornado.fastwebnet.it...
> SNIP
>
>> Yeah, it's the Unix emulation layer that Cygwin compiled programs
>> apparently need.
>> I've uploaded it at
>> http://ljl.741.com/cygwin1.dll.gz
>> http://ljl.150m.com/cygwin1.dll.gz
>
>
> Getting closer, although now it complains about not being to locate
> cygfftw3-3.dll (presumably the FFT routine library).

Argh! I hoped that at least FFTW was linked statically.

Well,
http://ljl.741.com/cygfftw3-3.dll.gz

as well as, just in case
http://ljl.741.com/cygfftw3_threads-3.dll.gz

>> [snip]


>
> Yes, that's what I was thinking of, interpolation in one direction to
> compensate for the aspect ratio.
>
> SNIP
>
>>> The noise in the image is single pixel noise (and has a bit of
>>> hardware calibration striping).
>>
>> What is single pixel noise -- or, is it "single pixel" as opposed to
>> what)?
>
> No, the edge seems to be NN interpolated, but the noise is not (there
> are single (as opposed to 1x2 pixel) variations).

Oh, but I hadn't interpolated *up*, but resized *down*! I've resized the
4800dpi direction to 2400dpi. Anyway, this doesn't matter.

> I'll wait for the next tarball, before making further benchmark tests.

It's there. As you might suspect, at
http://ljl.741.com/slantededge-alpha3.tar.gz

I haven't included the libraries, as they're a bit big and my server
doesn't let me upload more than 1 meg or so.

This time I'm positive there is no gamma and no color correction. I've
also used a brand new edge, which if I'm not mistaken is really a razor
blade this time! (No, I don't really know what a razor blade looks like.
So sue me :-)
Anyway, it seems quite sharp, probably sharper than the cutter I was
using before.

There is still something I don't quite understand: the program now
reports that the 10%-90% rise is about 6 pixels, while it was about 4-5
before (and Imatest agreed).
I don't think this is because of the edge, but rather because of the
fact I'm not normalizing the image anymore -- so 10% and 90% "take
longer" to be reached.
Should these 10% and 90% positions fixed as if the image were normalized?


by LjL
ljl...@tiscali.it

ste...@alum.mit.edu

unread,
Sep 28, 2005, 11:42:35 PM9/28/05
to
Lorenzo J. Lucchini wrote:
> > Depending on the library implementation, for complex numbers , Abs[z]
> > gives the modulus |z| .
>
> No, there isn't such a function in FFTW.

FFTW is not a complex-number library. You can easily take the absolute
value of its complex number yourself by sqrt(re*re + im*im), or you can
use the standard C complex math library (or the C++ library via a
typecast).

> However, there are functions to
> directly obtain a real-to-real FFT; I probably should look at them,
> although I'm not sure if the real data they output are the moduli or
> simply the real parts of the transform's output.

Neither. The real-to-real interface is primarily for transforms of
real-even or real-odd data (i.e. DCTs and DSTs), which can be expressed
via purely real outputs. They are also for transforms of real data
where the outputs are packed into a real array of the same length, but
the outputs in this case are still complex numbers (just stored in a
different format).

Cordially,
Steven G. Johnson

Ole-Hjalmar Kristensen

unread,
Sep 29, 2005, 4:47:07 AM9/29/05
to

Here is an implementation of Glassman's method of FFT, which wil work
for any N, not just powers of two. If N is not a power of two, it
degenerates to a DFT. The code is lifted from PAL (Public Ada
Library), if I remember correctly, and I do not think there is any
restrictions on it. You will have to convert it to C of course, but
the code is pretty obvious even if yo don't know Ada. Just beware that
unlike C, Ada allows nested subroutines, and that arrays do not
necessarily start with index 0.....

with Ada.Numerics.Short_Complex_Types;
use Ada.Numerics.Short_Complex_Types;

package FFT_Pack is

type Complex_Vector is array(Integer range <>) of Complex;

procedure Debug(X : Complex_Vector);

procedure FFT (FFT_Data : in out Complex_Vector ;
Inverse_Transform : in boolean );

end FFT_Pack;

with Ada.Numerics.Short_Elementary_Functions;
use Ada.Numerics.Short_Elementary_Functions;
with Ada.Text_Io; use Ada.Text_Io;

package body FFT_Pack is

procedure Debug(X : Complex_Vector) is
begin
for I in x'Range loop
Put_Line(Integer'Image(I) & " : "
& Short_Float'Image(X(I).Re) & " "
& Short_Float'Image(X(I).Im));
end loop;
end Debug;

procedure Glassman (A, B, C : in integer;
Data_Vector : in out Complex_Vector ;
Inverse_Transform : in boolean ) is

Temp : Complex_Vector(1..Data_Vector'length);
Counter : integer := Data_Vector'first;
JC : integer := 0;
Two_Pi : constant short_float := 6.28318530717958;
Del, Omega, Sum : Complex;
Angle : short_float;
C_Plus_1 : integer := C + 1;
begin
Temp(Temp'Range) := Data_Vector;
Angle := Two_Pi / (short_float(A * C));
Del := (Cos(Angle), (-(Sin(Angle))));
if (Inverse_Transform) then
Del := Conjugate(Del);
end if;
Omega := (1.0,0.0);

for IC in 1..C loop
for IA in 1..A loop
for IB in 1..B loop
Sum := Temp((((IA - 1)*C + (C-1))*B) + IB);
for JCR in 2..C loop
JC := C_Plus_1 - JCR; -- No need to add C + 1 each
-- time through loop
Sum := Temp((((IA - 1) * C + (JC - 1)) * B)
+ IB) + (Omega * Sum);
end loop; -- JCR
Data_Vector(Counter) := Sum;
Counter := Counter + 1;
end loop; -- IB
Omega := Del * Omega;
end loop; -- IA
end loop; -- IC
end Glassman;

procedure FFT ( FFT_Data : in out Complex_Vector;
Inverse_Transform : in boolean ) is

A : integer := 1;
B : integer := FFT_Data'length;
C : integer := 1;

begin -- FFT

while (B > 1) loop -- define the integers A, B, and C
A := C * A; -- such that A * B * C = FFT_Data'length
C := 2;
while (B mod C) /= 0 loop
C := C + 1;
end loop;
B := B/C; -- B = 1 causes exit from while loop
Glassman (A,B,C, FFT_Data, Inverse_Transform);
end loop;

if Inverse_Transform then -- optional 1/N scaling for inverse
-- transform only
for i in FFT_Data'range loop
FFT_Data(i) := FFT_Data(i) /
short_float(FFT_Data'length);
end loop;
end if;
end FFT;
end FFT_Pack;


--
C++: The power, elegance and simplicity of a hand grenade.

Don

unread,
Sep 29, 2005, 11:53:07 AM9/29/05
to
On Wed, 28 Sep 2005 18:29:13 +0200, "Lorenzo J. Lucchini"
<ljl...@tiscali.it> wrote:

>But all this made me wonder about something else: would it make any
>sense to compare the edge *position* of each (red, green and blue)
>channel with the edge position in the luminance channel?

That would be a good test.

My point is that there's misalignment between individual channels, so
to combine them (using *any* method) reduces accuracy because the
result is a (fuzzy) mix of all of them. By doing channels individually
you should get more accurate measurements.

In other words (and all other things being equal) I would expect that
individual channels would differ much less in relation to each other,
then any one of them will differ in relation to the combined luminance
or average values.

>I mean. SFRWin gives "red", "blue" and "green" color offsets (for
>measuring "color fringing"), but the "green" offset is always zero, as
>the other two channels are compared to green.

I would do a full permutation and compare all to each other.

Anyway, have fun! :o) And let us know how it turns out!

Don.

Don

unread,
Sep 29, 2005, 11:53:10 AM9/29/05
to
On Wed, 28 Sep 2005 15:28:36 +0200, "Lorenzo J. Lucchini"
<ljl...@tiscali.it> wrote:

>> I've only been skimming this thread and not paying too much attention
>> because the MTF of my scanner is what it is and there's nothing I can
>> do about it... So, with that in mind...
>
>Well, but I don't plan to stop here. What I'd mostly like to obtain from
>all this is a way to "sharpen" my scans using a function that is
>tailored to my scanner's specifics (rather than just "unsharp mask as I
>see fit").
>
>So, you see, there is a practical application of the measurements I can
>obtain, it's not just about knowing how poor the scanner's resolution is.

I agree with that in principle. However, in practical terms I think
that starting with an 8-bit image there's only so much accuracy you
can achieve.

I strongly suspect (but don't know for a fact) that you will not be
able to show a demonstrable difference between any custom sharpening
and just applying unsharp mask at 8-bit depth.

I think you can improve the sharpness considerably more (even at 8-bit
depth) by simply aligning individual channels to each other.

>And why do you say I'm measuring the "objective values" of the pixels
>instead of their "perceptual values"? I'm mostly trying to measure
>resolution, in the form of the MTF.

Because it's all based on those gray pixels which are created because
the scanner can't resolve that border area. So it's much better to
read the actual values of those gray pixels rather than take either an
average or luminance value.

If the three RGB channels are not perfectly aligned (and they never
are!) then combining them in any way will introduce a level of
inaccuracy (fuzziness). In case of luminance that inaccuracy will also
have a green bias, while the average will be more even - which is why
I said that your original idea to use average seems like the "lesser
evil" when compared to the skewed and green-biased luminance values.

>So you see that I'm *already* doing measurements that are inherently
>"perceptual". So why not be coherent and keep this in mind throughout
>the process?

Because perception is subjective. When there is no other way, then
yes, use perception. But since you already have the values of those
gray pixels it just seem much more accurate to use those values.

>> Actually, what I would do is measure each channel *separately*!
>
>... I'm doing this already.
>The "gray" channel is measured *in addition* to the other three
>channels, and is merely a convenience.

That's good. So displaying individual results should be easy.

Don.

Lorenzo J. Lucchini

unread,
Sep 29, 2005, 12:16:04 PM9/29/05
to
Don wrote:
> On Wed, 28 Sep 2005 15:28:36 +0200, "Lorenzo J. Lucchini"
> <ljl...@tiscali.it> wrote:
>
>
>>>I've only been skimming this thread and not paying too much attention
>>>because the MTF of my scanner is what it is and there's nothing I can
>>>do about it... So, with that in mind...
>>
>>Well, but I don't plan to stop here. What I'd mostly like to obtain from
>>all this is a way to "sharpen" my scans using a function that is
>>tailored to my scanner's specifics (rather than just "unsharp mask as I
>>see fit").
>>
>>So, you see, there is a practical application of the measurements I can
>>obtain, it's not just about knowing how poor the scanner's resolution is.
>
> I agree with that in principle. However, in practical terms I think
> that starting with an 8-bit image there's only so much accuracy you
> can achieve.

Don't be so fixated with my 8 bits. I'll start working with 16 bits,
possibly after buying a USB 2 card, if that needs be.

> I strongly suspect (but don't know for a fact) that you will not be
> able to show a demonstrable difference between any custom sharpening
> and just applying unsharp mask at 8-bit depth.

Well, wait a minute: at any rate, I'll be able to use a *measured* --
instead of just *guessed* -- amount (and kind) of sharpening.

Then I guess you'll be able to obtain the same results by using a "right
amount" of unsharp masking... but that's precisely what I want to avoid,
guessing values!
I'm not an experienced photographer, quite the contrary, and I can't
really tell how much unsharp masking "looks right".

> I think you can improve the sharpness considerably more (even at 8-bit
> depth) by simply aligning individual channels to each other.

That's another possibility to explore, sure. Imatest, SFRWin and my
program all give some measurement of color aberrations -- channel
misalignment, chiefly.

Certainly, those values could find some use; however, I don't have much
hope: in fact, unsurprisignly, my scanner seems to have very little
color misalignment in the CCD direction, but it does show quite a bit of
misalignment in the motor direction!
But, I thought, that must be because the motor's steps are not very
regular and precise. If that's the cause, then it'll be impossible to
try and re-align the colors, as misalignment will change at every scan line.

Sort of like what you've found out with multi-pass scans alignment..

>>And why do you say I'm measuring the "objective values" of the pixels
>>instead of their "perceptual values"? I'm mostly trying to measure
>>resolution, in the form of the MTF.
>
> Because it's all based on those gray pixels which are created because
> the scanner can't resolve that border area. So it's much better to
> read the actual values of those gray pixels rather than take either an
> average or luminance value.
>
> If the three RGB channels are not perfectly aligned (and they never
> are!) then combining them in any way will introduce a level of
> inaccuracy (fuzziness). In case of luminance that inaccuracy will also
> have a green bias, while the average will be more even - which is why
> I said that your original idea to use average seems like the "lesser
> evil" when compared to the skewed and green-biased luminance values.

At this point, I think I have a better idea: let's *first* measure the
amount of misalignment, and then average the channels to luminance
*after* re-aligning them.

Of course, I must first be sure the way I currently measure misalignment
is correct, as SFRWin gives different results.
But that's (by far) not the only thing that's currently wrong in my
program...

>>So you see that I'm *already* doing measurements that are inherently
>>"perceptual". So why not be coherent and keep this in mind throughout
>>the process?
>
> Because perception is subjective. When there is no other way, then
> yes, use perception. But since you already have the values of those
> gray pixels it just seem much more accurate to use those values.

I'm not sure. Yes, I have the real values, but... my program tries to
answer the question "how much resolution can my scanner get from the
original?". The answer itself depends on the observer's eye, as a person
might be able to see constrasts less than 10%, and another might only
see up to 15%, say.

So, since an average observer *must* be "invented" anyway for the
results to have any practical meaning, then it makes sense to also
adjust them so that the colors the average eye sees best count more, as
they *will* affect perceived resolution.

And "perceived resolution" is the only viable metric: in fact, if I
wanted to measure "real" resolution, I would have to say that my scanner
really does resolve 2400 dpi (which it doesn't), as just before Nyquist,
there is (for example) a 0.00001 response.
Hey, that's still resolution, isn't it! But it's resolution that counts
nothing, as no observer will be able to see it, and sharpening won't
help because noise will overwhelm everything else.

>>>Actually, what I would do is measure each channel *separately*!
>>
>>... I'm doing this already.
>>The "gray" channel is measured *in addition* to the other three
>>channels, and is merely a convenience.
>
> That's good. So displaying individual results should be easy.

Not should, is. The table I output has the fields "Frequency", "Red
response", "Green response", "Blue response", "Luminance response".

If the users wants to take advantage of the luminance results, they can,
but they also can ignore them just as well.


by LjL
ljl...@tiscali.it

Lorenzo J. Lucchini

unread,
Sep 29, 2005, 6:20:31 PM9/29/05
to
ste...@alum.mit.edu wrote:
> Lorenzo J. Lucchini wrote:
>
>>>Depending on the library implementation, for complex numbers , Abs[z]
>>>gives the modulus |z| .
>>
>>No, there isn't such a function in FFTW.
>
> FFTW is not a complex-number library. You can easily take the absolute
> value of its complex number yourself by sqrt(re*re + im*im), or you can
> use the standard C complex math library (or the C++ library via a
> typecast).

I'd like to remain within plain C; and the complex math library is,
AFAIK, part of C99, so it might not be available on all compilers yet.
(Yeah, I know, I'm using // comments, but *those* are in every stupid
compiler ;-)

Currently I'm precisely doing the computation you say (well, I'm using
pow() actually), it's just that Bart says this is not a robust method
with "extreme" values. But it should be ok for now, in any case.

>>However, there are functions to
>>directly obtain a real-to-real FFT; I probably should look at them,
>>although I'm not sure if the real data they output are the moduli or
>>simply the real parts of the transform's output.
>
> Neither. The real-to-real interface is primarily for transforms of
> real-even or real-odd data (i.e. DCTs and DSTs), which can be expressed
> via purely real outputs. They are also for transforms of real data
> where the outputs are packed into a real array of the same length, but
> the outputs in this case are still complex numbers (just stored in a
> different format).

I see, thanks. It wasn't very clear reading the FFTW manual, for someone
who's meeting Fourier transforms for the first time in his life.


by LjL
ljl...@tiscali.it

Bart van der Wolf

unread,
Sep 29, 2005, 9:02:27 PM9/29/05
to

"Lorenzo J. Lucchini" <ljl...@tiscali.it> wrote in message
news:POG_e.2576$133...@tornado.fastwebnet.it...
SNIP
These two, cygwin1.dll and cygfftw3-3.dll, are sufficient.

SNIP


> It's there. As you might suspect, at
> http://ljl.741.com/slantededge-alpha3.tar.gz

I'll give the "slantededge.exe" a try. I'm just trying to get it to
recognize my options, but no results are saved (only some statistics
are reported on screen). For example "--csv-esf testedge.ppm" is an
"unrecognized" option.

SNIP


> Should these 10% and 90% positions fixed as if the image were
> normalized?

Yes, between the 10% and 90% response of the normalized ESF data
(assuming linearized image gamma 1.0, I would assume since all data
should be linearized).

Bart

Lorenzo J. Lucchini

unread,
Sep 29, 2005, 9:16:11 PM9/29/05
to
Bart van der Wolf wrote:
>
> "Lorenzo J. Lucchini" <ljl...@tiscali.it> wrote in message
> news:POG_e.2576$133...@tornado.fastwebnet.it...
> SNIP
> These two, cygwin1.dll and cygfftw3-3.dll, are sufficient.
>
> SNIP
>
>> It's there. As you might suspect, at
>> http://ljl.741.com/slantededge-alpha3.tar.gz
>
>
> I'll give the "slantededge.exe" a try. I'm just trying to get it to
> recognize my options, but no results are saved (only some statistics are
> reported on screen). For example "--csv-esf testedge.ppm" is an
> "unrecognized" option.

Wait a moment, but you must specify a filename to save the ESF to.

Try with this command line:

slantededge.exe --verbose --csv-esf esf.txt --csv-lsf lsf.txt --csv-mtf
mtf.txt testedge.ppm

It works for me.

> SNIP
>
>> Should these 10% and 90% positions fixed as if the image were normalized?
>
> Yes, between the 10% and 90% response of the normalized ESF data
> (assuming linearized image gamma 1.0, I would assume since all data
> should be linearized).

Fine, thanks. 'll fix.

by LjL
ljl...@tiscali.it

Don

unread,
Sep 30, 2005, 11:23:00 AM9/30/05
to
On Thu, 29 Sep 2005 18:16:04 +0200, "Lorenzo J. Lucchini"
<ljl...@tiscali.it> wrote:

>>>Well, but I don't plan to stop here. What I'd mostly like to obtain from
>>>all this is a way to "sharpen" my scans using a function that is
>>>tailored to my scanner's specifics (rather than just "unsharp mask as I
>>>see fit").

...


>>
>> I agree with that in principle. However, in practical terms I think
>> that starting with an 8-bit image there's only so much accuracy you
>> can achieve.
>
>Don't be so fixated with my 8 bits.

I'm not. It's simply a very important factor when considering the
context because it directly affects the result. So to ignore it would
lead to wrong conclusions.

>> I strongly suspect (but don't know for a fact) that you will not be
>> able to show a demonstrable difference between any custom sharpening
>> and just applying unsharp mask at 8-bit depth.
>
>Well, wait a minute: at any rate, I'll be able to use a *measured* --
>instead of just *guessed* -- amount (and kind) of sharpening.

But that measurement will be so inaccurate as to be virtually
meaningless i.e. the margin of error will be so high that it will not
improve on the guessed amount. Indeed it's quite conceivable that in
significant number of cases it may actually produce worse results than
guessing.

>Then I guess you'll be able to obtain the same results by using a "right
>amount" of unsharp masking... but that's precisely what I want to avoid,
>guessing values!

Please don't get me wrong. I hate guessing. But if the metrics are
inadequate then you may end up making matters worse. I mean you, can't
measure millimeters with a ruler that only has marks for centimeters.

>I'm not an experienced photographer, quite the contrary, and I can't
>really tell how much unsharp masking "looks right".

On a tangent, I personally don't use any sharpening at all. I compared
sharpened images to the originals (at large magnification) and didn't
really like what unsharp mask did. But, that's a matter of personal
taste...

>> I think you can improve the sharpness considerably more (even at 8-bit
>> depth) by simply aligning individual channels to each other.
>
>That's another possibility to explore, sure. Imatest, SFRWin and my
>program all give some measurement of color aberrations -- channel
>misalignment, chiefly.

I was shocked when I discovered this on my film scanner. I expected
that the channel alignment would be much more accurate.

>Certainly, those values could find some use; however, I don't have much
>hope: in fact, unsurprisignly, my scanner seems to have very little
>color misalignment in the CCD direction, but it does show quite a bit of
>misalignment in the motor direction!

Yes, that's a very big problem with all flatbeds! The stepper motor is
also very irregular as the belts slip, etc.

>But, I thought, that must be because the motor's steps are not very
>regular and precise. If that's the cause, then it'll be impossible to
>try and re-align the colors, as misalignment will change at every scan line.
>
>Sort of like what you've found out with multi-pass scans alignment..

Here's a little test to try: Take a ruler and scan it twice at optical
resolution of your scanner: once horizontally, and once vertically.
Rotate one of them and compare! It makes a grown man cry! ;o)

Now, if that weren't bad enough, do several vertical scans (along the
stepper motor axis) and compare! And then really start to cry! ;o)

It sure made me pull my hair! I noticed this when I was scanning some
square images and was surprised that their vertical vs. horizontal
dimensions in Photoshop were not the same. I then rotated the photo,
scanned again, and now it was stretched in the other direction!
Aaaaarrrrggghhh!

That's when I invented "the ruler test". My scans on stepper motor
axis are about 1mm shorter than scans on CCD axis using a 10cm strip.

>> If the three RGB channels are not perfectly aligned (and they never
>> are!) then combining them in any way will introduce a level of
>> inaccuracy (fuzziness). In case of luminance that inaccuracy will also
>> have a green bias, while the average will be more even - which is why
>> I said that your original idea to use average seems like the "lesser
>> evil" when compared to the skewed and green-biased luminance values.
>
>At this point, I think I have a better idea: let's *first* measure the
>amount of misalignment, and then average the channels to luminance
>*after* re-aligning them.

That's what I'm saying (individual channel measurements) only use a
straight average when you combine the results. Luminance will simply
introduce a large green bias at the expense of red, for the most part.

Luminance really has no part in this context because it only skews the
results by favoring the green channel results and neglecting the red.

>Of course, I must first be sure the way I currently measure misalignment
>is correct, as SFRWin gives different results.
>But that's (by far) not the only thing that's currently wrong in my
>program...

That's why we like programming! ;o) It's solving those problems!

>>>So you see that I'm *already* doing measurements that are inherently
>>>"perceptual". So why not be coherent and keep this in mind throughout
>>>the process?
>>
>> Because perception is subjective. When there is no other way, then
>> yes, use perception. But since you already have the values of those
>> gray pixels it just seem much more accurate to use those values.
>
>I'm not sure. Yes, I have the real values, but... my program tries to
>answer the question "how much resolution can my scanner get from the
>original?". The answer itself depends on the observer's eye, as a person
>might be able to see constrasts less than 10%, and another might only
>see up to 15%, say.

No, the answer is not based on any one individual person. The answer
is quite clear if you read out the gray values. Whether one person can
see those grays and the other can't doesn't really matter in the
context of objective measurements.

>So, since an average observer *must* be "invented" anyway for the
>results to have any practical meaning, then it makes sense to also
>adjust them so that the colors the average eye sees best count more, as
>they *will* affect perceived resolution.

If you want to test human perception that's a completely different
test. However, that doesn't change the *objective* resolution of the
scanner.

I mean take number of colors on a monitor. You can objectively
determine how many colors your monitor can display. And then you can
also determine how many of those colors an average person can
distinguish. Those are two totally different test, using different
metrics.

>And "perceived resolution" is the only viable metric: in fact, if I
>wanted to measure "real" resolution, I would have to say that my scanner
>really does resolve 2400 dpi (which it doesn't), as just before Nyquist,
>there is (for example) a 0.00001 response.
>Hey, that's still resolution, isn't it! But it's resolution that counts
>nothing, as no observer will be able to see it, and sharpening won't
>help because noise will overwhelm everything else.

In that case, it appears you're not really interested in your
scanner's actual resolution but your perception of that resolution.
And that's a different test.

>>>>Actually, what I would do is measure each channel *separately*!
>>>
>>>... I'm doing this already.
>>>The "gray" channel is measured *in addition* to the other three
>>>channels, and is merely a convenience.
>>
>> That's good. So displaying individual results should be easy.
>
>Not should, is.

It's a figure of speech.

Don.

Lorenzo J. Lucchini

unread,
Sep 30, 2005, 12:36:39 PM9/30/05
to
Don wrote:
> On Thu, 29 Sep 2005 18:16:04 +0200, "Lorenzo J. Lucchini"
> <ljl...@tiscali.it> wrote:
>
> [snip]

>
>>Don't be so fixated with my 8 bits.
>
> I'm not. It's simply a very important factor when considering the
> context because it directly affects the result. So to ignore it would
> lead to wrong conclusions.

But I'm not even ignoring it, since at the moment I haven't yet reached
the point of trying to apply my "slanted edge" measurements to a *real*
image.

What's the point of arguing that the "real" image should be 16-bit
instad of 8-bit, when I currently have no way to test a "real" image?
When my program will be able to do that, then we'll see if a 16-bit
image is needed.

Unless you mean...

>>>I strongly suspect (but don't know for a fact) that you will not be
>>>able to show a demonstrable difference between any custom sharpening
>>>and just applying unsharp mask at 8-bit depth.
>>
>>Well, wait a minute: at any rate, I'll be able to use a *measured* --
>>instead of just *guessed* -- amount (and kind) of sharpening.
>
> But that measurement will be so inaccurate as to be virtually
> meaningless i.e. the margin of error will be so high that it will not
> improve on the guessed amount. Indeed it's quite conceivable that in
> significant number of cases it may actually produce worse results than
> guessing.

... that I should *scan the slanted edge* at 16 bit -- as you say that
it's the *measurement* that's inaccurate.

But, you see, Imatest's manual doesn't particularly insist on scanning
the edge at 16-bit, and I think I can see the reason: the oversampling
that the slant allows compensates very well for the low bit-depth.

You see, even if I scan the edge at 8-bit, the final edge spread
function I obtain will have a *much higher* bit depth than 8-bit --
that's because I'm scanning the edge transition multiple times (200
times, if the scan is 200 pixels tall).

Wouldn't you think an image would get to have a much higher bit depth
than 8 bit if you multi-scan it 200 times, even if each of the scans is
made at 8-bit? :-)

>>Then I guess you'll be able to obtain the same results by using a "right
>>amount" of unsharp masking... but that's precisely what I want to avoid,
>>guessing values!
>
> Please don't get me wrong. I hate guessing. But if the metrics are
> inadequate then you may end up making matters worse. I mean you, can't
> measure millimeters with a ruler that only has marks for centimeters.

But, you see, the *metrics* are not inadequate (or at least, wouldn't be
if my program wasn't full of bugs).
At worst, it's the (8-bit) scanned *picture* that's inadequate, but in
that case, it can only be as inadequate for "guessing" as it is for
using measured values!

That is, at most you should be able to obtain, by guessing, the *same*
result I obtain with measurement, but no better.
Then, sure, using a 16-bit scan of the picture may well improve the
results of *both* guessing and using measurements.

>>I'm not an experienced photographer, quite the contrary, and I can't
>>really tell how much unsharp masking "looks right".
>
> On a tangent, I personally don't use any sharpening at all. I compared
> sharpened images to the originals (at large magnification) and didn't
> really like what unsharp mask did. But, that's a matter of personal
> taste...

Isn't that because of the haloes perhaps?
Halos are precisely one of the things I wish to avoid with the PSF
method, which should be able to compute optimal sharpening that
*doesn't* cause haloes.

I think the main problem will (still) be noise, as it will be amplified
by the sharpening, and computing the PSF doesn't help much with that.

I think it's going to be a matter of compromise here: how much noise am
I prepared to accept versus how much (or, up to what frequency) do I
want to improve the MTF.

>>>I think you can improve the sharpness considerably more (even at 8-bit
>>>depth) by simply aligning individual channels to each other.
>>
>>That's another possibility to explore, sure. Imatest, SFRWin and my
>>program all give some measurement of color aberrations -- channel
>>misalignment, chiefly.
>
> I was shocked when I discovered this on my film scanner. I expected
> that the channel alignment would be much more accurate.

Well, looking at the MTF graphs, I see that while my scanner does about
1500dpi on the CCD axis, it does something like 1300dpi on the motor axis.

Now, this is the resolution, not the color aberration, but I'm afraid it
gives a measure of color aberration, too. Actually, I think color
aberrations increase *more* than resolution decreases.

> [snip: the ruler test]

I'll try, just for laughs (or cries).
But even after measuring what's going on with a ruler, I'm still afraid
there is very little that can be done.

Possibly, one could scan a ruler next to the film, and use some program
to "reshape" every color channel based on the positions of the ruler
ticks... but, I dunno, I have a feeling this is only going to work in
theory.

>>>If the three RGB channels are not perfectly aligned (and they never
>>>are!) then combining them in any way will introduce a level of
>>>inaccuracy (fuzziness). In case of luminance that inaccuracy will also
>>>have a green bias, while the average will be more even - which is why
>>>I said that your original idea to use average seems like the "lesser
>>>evil" when compared to the skewed and green-biased luminance values.
>>
>>At this point, I think I have a better idea: let's *first* measure the
>>amount of misalignment, and then average the channels to luminance
>>*after* re-aligning them.
>
> That's what I'm saying (individual channel measurements) only use a
> straight average when you combine the results. Luminance will simply
> introduce a large green bias at the expense of red, for the most part.

More at the expense of blue, I think.
But, besides this, what you said before was that either average or
luminance will not be right when the channels are misaligned.

What I'm saying is, well, this will be no issue, as the channels will be
re-aligned *before* taking either average or luminance.
"Will", because this is not currently done in my program -- don't know
about Imatest.

> [snip]


>
>>>>So you see that I'm *already* doing measurements that are inherently
>>>>"perceptual". So why not be coherent and keep this in mind throughout
>>>>the process?
>>>
>>>Because perception is subjective. When there is no other way, then
>>>yes, use perception. But since you already have the values of those
>>>gray pixels it just seem much more accurate to use those values.
>>
>>I'm not sure. Yes, I have the real values, but... my program tries to
>>answer the question "how much resolution can my scanner get from the
>>original?". The answer itself depends on the observer's eye, as a person
>>might be able to see constrasts less than 10%, and another might only
>>see up to 15%, say.
>
> No, the answer is not based on any one individual person. The answer
> is quite clear if you read out the gray values. Whether one person can
> see those grays and the other can't doesn't really matter in the
> context of objective measurements.

But then why were 50% and (expecially) 10% chosen as standard?
Because of some physical reason? No, because they make perceptual sense:
10% is the boundary where the average human eye stops seeing contrast.

Sure, if you read the *whole* MTF instead of just MTF50 and MTF10, you
don't have to chose an observer-dependent frequency; but, like it or
not, MTF50 and MTF10 are standards. Sometimes it makes sense to follow
standards.

>>So, since an average observer *must* be "invented" anyway for the
>>results to have any practical meaning, then it makes sense to also
>>adjust them so that the colors the average eye sees best count more, as
>>they *will* affect perceived resolution.
>
> If you want to test human perception that's a completely different
> test. However, that doesn't change the *objective* resolution of the
> scanner.
>
> I mean take number of colors on a monitor. You can objectively
> determine how many colors your monitor can display. And then you can
> also determine how many of those colors an average person can
> distinguish. Those are two totally different test, using different
> metrics.

But you can express the number of colors a monitor can display with
*one* number.

You can't express a scanner's "objective resolution" with one number;
you must print an MTF grpah.
But what if you want a measure in ppi (which many people want)? Then you
have to *choose a point* on the MTF, and the choice will be based on
human perception: "you scanner can do 1500ppi [at 10% contrast, because
that's what you will see at best]".
It follows that such a figure should be a *perceptually weighted*
average of the three channels' values.

On the other hand, I can see some merit with using a simple average when
presenting someone with the *whole* MTF graph.

But still, for the purpose of sharpening, Bart says color aberrations
will occur if average is used instead of sharpening. We'll see how that
works out (hopefully, if I can complete the program).

>>And "perceived resolution" is the only viable metric: in fact, if I
>>wanted to measure "real" resolution, I would have to say that my scanner
>>really does resolve 2400 dpi (which it doesn't), as just before Nyquist,
>>there is (for example) a 0.00001 response.
>>Hey, that's still resolution, isn't it! But it's resolution that counts
>>nothing, as no observer will be able to see it, and sharpening won't
>>help because noise will overwhelm everything else.
>
> In that case, it appears you're not really interested in your
> scanner's actual resolution but your perception of that resolution.
> And that's a different test.

Maybe, but it seems that Imatest is interested in the same, and Imatest
doesn't look like it was written by idiots who didn't know what they
were testing.

Anyway, let's end it here: my program will default to luminance, but
will offer an option of using average, and it will always also show the
three channels separately anyway.

The beauty of choice!


by LjL
ljl...@tiscali.it

Don

unread,
Oct 1, 2005, 3:32:03 PM10/1/05
to
On Fri, 30 Sep 2005 18:36:39 +0200, "Lorenzo J. Lucchini"
<ljl...@tiscali.it> wrote:

>Unless you mean...

Yes, that's what I mean! ;o)

>... that I should *scan the slanted edge* at 16 bit -- as you say that
>it's the *measurement* that's inaccurate.

Bingo!

>But, you see, Imatest's manual doesn't particularly insist on scanning
>the edge at 16-bit, and I think I can see the reason: the oversampling
>that the slant allows compensates very well for the low bit-depth.

I don't know what Imatest manual says, but I suspect being a generic
type of test they compensate in advance just in case people do use
less that optimal bit depths.

But that doesn't mean one should use lower bit depths if one has more.

>Wouldn't you think an image would get to have a much higher bit depth
>than 8 bit if you multi-scan it 200 times, even if each of the scans is
>made at 8-bit? :-)

Not really, especially not for flatbeds because of the stepper motor
inaccuracies. You will just blur the image more. Not to mention it
will take "forever" to acquire all those 100s of samples. And all
along you have a ready and (compared to 200 * 8-bit scans) a quick
solution i.e. 16-bit!

The point I'm making is why try to "fix" 8-bit when there is 16-bit
readily available? Now, if your scanner did *not* have 16-bit then,
yes, trying to get 8-bit as accurate as possible makes sense.

But having said that, in my life I've done even sillier things (much,
*much*, sillier things!) simply because they were fun. And if that's
the goal, than just ignore everything I say and have fun! :o)

>But, you see, the *metrics* are not inadequate (or at least, wouldn't be
>if my program wasn't full of bugs).
>At worst, it's the (8-bit) scanned *picture* that's inadequate, but in
>that case, it can only be as inadequate for "guessing" as it is for
>using measured values!

Yes, 8-bit image is inadequate which results in inadequate metrics.

>That is, at most you should be able to obtain, by guessing, the *same*
>result I obtain with measurement, but no better.
>Then, sure, using a 16-bit scan of the picture may well improve the
>results of *both* guessing and using measurements.

It will not improve guessing because we only have 8-bit eyes (some say
even only 6-bit) so you will not even be able to perceive or see the
extra color gradation available in 16-bit. But *mathematics* will!

>> On a tangent, I personally don't use any sharpening at all. I compared
>> sharpened images to the originals (at large magnification) and didn't
>> really like what unsharp mask did. But, that's a matter of personal
>> taste...
>
>Isn't that because of the haloes perhaps?

Halos is just one thing, but I don't like the concept behind it, that
edges are changed in such a drastic way.

The problem is the image is *not* made sharper but the contrast of
transition between dark and light is simply increased because humans
perceive high contrast as sharpness. It's an optical illusion, really.

That's what bothered me, conceptually. The image was degraded in order
to generate an optical illusion and that just doesn't make sense to
me. It's like anti-aliasing (which I *HATE*!) and which *pretends* to
"remove" jaggies by blurring everything!!! To me, that's madness! But
that's just me... ;o)

>Halos are precisely one of the things I wish to avoid with the PSF
>method, which should be able to compute optimal sharpening that
>*doesn't* cause haloes.

By definition (because of increased contrast) it will cause haloes.
Whether you see them or not is another matter. If you zoom in and
compare to the original you will see them.

>I think the main problem will (still) be noise, as it will be amplified
>by the sharpening, and computing the PSF doesn't help much with that.
>
>I think it's going to be a matter of compromise here: how much noise am
>I prepared to accept versus how much (or, up to what frequency) do I
>want to improve the MTF.

Yes, that's exactly what it boils down to! You have to balance one
against the other. Which means, back to "guessing" what looks better.

>> [snip: the ruler test]
>
>I'll try, just for laughs (or cries).
>But even after measuring what's going on with a ruler, I'm still afraid
>there is very little that can be done.
>
>Possibly, one could scan a ruler next to the film, and use some program
>to "reshape" every color channel based on the positions of the ruler
>ticks... but, I dunno, I have a feeling this is only going to work in
>theory.

It will work in practice too if you have guides along both axis. The
trouble is that's very clumsy and time consuming.

If you do decided to do that I would create a movable frame so you
have guides on all 4 sides. That's because the whole assembly wiggles
as it travels so the distortion may not be the same at opposite edges.

Also, the misalignment is not uniform but changes because the stepper
motor sometimes goes faster and sometimes slower! So you will not be
able to just change the height/width of the image and have perfect
reproduction. You'll actually have to transform the image. Which means
superimposing a grid... Which means figuring out the size of that grid
i.e. determine the variance of stepper motor speed change... Argh!!

Of course, the key question is, is it worth it? In my case, in the
end, I decided it wasn't. But it still bugs me! ;o)

>> That's what I'm saying (individual channel measurements) only use a
>> straight average when you combine the results. Luminance will simply
>> introduce a large green bias at the expense of red, for the most part.
>
>More at the expense of blue, I think.
>But, besides this, what you said before was that either average or
>luminance will not be right when the channels are misaligned.
>
>What I'm saying is, well, this will be no issue, as the channels will be
>re-aligned *before* taking either average or luminance.

I would *not* align them because that would change the values!!! And
those changes are bound to be much more than what you're measuring!

In principle, you should never do anything to the data coming from the
scanner if the goal is to perform measurements. That's why even gamma
is not applied but only linear data is used for calculations.

I really think the best way is to simply do each channel separately
and then see what the results are. In theory, they should be pretty
equal. If you want a single number I would then just average those
three results.

> > [snip]


> >
>> No, the answer is not based on any one individual person. The answer
>> is quite clear if you read out the gray values. Whether one person can
>> see those grays and the other can't doesn't really matter in the
>> context of objective measurements.
>
>But then why were 50% and (expecially) 10% chosen as standard?
>Because of some physical reason? No, because they make perceptual sense:
>10% is the boundary where the average human eye stops seeing contrast.

No, there is physical reason why those luminance percentages were
chosen. It's to do with how our eyes are built and the sensors for
individual colors.

I mean, if you're measuring how fast a car is going, are you going to
change the scale because of how you perceive speed or are you going to
ignore your subjective perception and just measure the speed?

This is the same thing. You measure the amounts of gray the scanner
can't resolve. How you perceive this gray is, is totally irrelevant to
the measurement.

Now, if you want to measure *your perception*, that's a different
thing altogether. But before you measure something as subjective as
individual perception, you still need objective measurements as a
starting point and a baseline.

>But still, for the purpose of sharpening, Bart says color aberrations
>will occur if average is used instead of sharpening. We'll see how that
>works out (hopefully, if I can complete the program).

Bart has a tendency to be literal and just repeats what he reads
elsewhere without paying enough attention to context. Mind you, it's
good information with good links and I often save his messages because
of that, but it's really just repeating stuff seen somewhere else.

I mean, in this case Bart may very well be right, but I'd ask Kennedy
because Kennedy thinks laterally and actually analyzes what the
implications are in the full context.

>Maybe, but it seems that Imatest is interested in the same, and Imatest
>doesn't look like it was written by idiots who didn't know what they
>were testing.

They may be testing a different thing, though. BTW, why don't you just
use Imatest?

Anyway, as I said on the outset. I'm just kibitzing here and threw in
that luminance note because it seemed contradictory to the task.

But instead of wasting time on replying carry on with programming! :o)

Don.

Lorenzo J. Lucchini

unread,
Oct 1, 2005, 9:23:42 PM10/1/05
to
Don wrote:
> On Fri, 30 Sep 2005 18:36:39 +0200, "Lorenzo J. Lucchini"
> <ljl...@tiscali.it> wrote:
>
> [snip]

>
>>Wouldn't you think an image would get to have a much higher bit depth
>>than 8 bit if you multi-scan it 200 times, even if each of the scans is
>>made at 8-bit? :-)
>
> Not really, especially not for flatbeds because of the stepper motor
> inaccuracies. You will just blur the image more. Not to mention it
> will take "forever" to acquire all those 100s of samples. And all
> along you have a ready and (compared to 200 * 8-bit scans) a quick
> solution i.e. 16-bit!

Ok, you're probably right here for "real" images.
But this doesn't apply to the slanted edge: you aren't *really* taking
200 scans, it's just that every scan line "counts as a sampling pass" in
reconstructing the ESF.

The "16-bit quick solution" don't change much for scanning a slanted
edge, as you have to do the oversampling anyway.

It might be that scanning the edge at 16 bit still gives better results
than scanning it at 8 bit. Let's find out...

No, let's not find out: SFRWin doesn't accept 16 bit edges.
(Which might be a clue that they're not necessary, anyway)

Don't know about Imatest.

By the way, I see that the levels (or perhaps the gamma) are different
if I scan at 16-bit and if I scan at 8-bit, with otherwise the same
settings. Actually, the 16-bit scan clips. Wonderful, another bug in my
fine scanner driver!

> The point I'm making is why try to "fix" 8-bit when there is 16-bit
> readily available? Now, if your scanner did *not* have 16-bit then,
> yes, trying to get 8-bit as accurate as possible makes sense.
>
> But having said that, in my life I've done even sillier things (much,
> *much*, sillier things!) simply because they were fun. And if that's
> the goal, than just ignore everything I say and have fun! :o)

But, no, one goal is to make a program alternative to Imatest (its SFR
function, at least) and SFRWin, and the other goal is to reconstruct a
PSF to sharpen images.

The goal is not to get 16-bit from 8-bit... aren't you just getting
confused with other threads or parts of this thread?

Yes, currently I'm scanning things at 8-bit. Yes, I'm scanning my
slanted edges at 8-bit, too.
But my program works in floating point, it can load both 8-bit or 16-bit
edge images (though the code for loading 16-bit PPM isn't tested right
now); it's just that I'm using it with 8-bit images right now.

It's not functional enough to make a difference at the moment, in any case!

>>But, you see, the *metrics* are not inadequate (or at least, wouldn't be
>>if my program wasn't full of bugs).
>>At worst, it's the (8-bit) scanned *picture* that's inadequate, but in
>>that case, it can only be as inadequate for "guessing" as it is for
>>using measured values!
>
> Yes, 8-bit image is inadequate which results in inadequate metrics.

Let's agree on terms. I took the "metrics" as meaning the slanted edge
test results, and the "image" is just the image, that is the picture to
be sharpened (or whatever).

>>That is, at most you should be able to obtain, by guessing, the *same*
>>result I obtain with measurement, but no better.
>>Then, sure, using a 16-bit scan of the picture may well improve the
>>results of *both* guessing and using measurements.
>
> It will not improve guessing because we only have 8-bit eyes (some say
> even only 6-bit) so you will not even be able to perceive or see the
> extra color gradation available in 16-bit. But *mathematics* will!

No, I was saying that *with an 8-bit image* your "guess" couldn't be
better than my measurements -- the best you can achieve is to make it
*as good as* the measurements. Visibile or not to the eye, there are
only 8 bpc in the image.

And then, if our eyes really have the equivalent of 6 bits, you wouldn't
be able to guess as well as you measure even with a poor 8-bit image!

> [snip]


>
>>Halos are precisely one of the things I wish to avoid with the PSF
>>method, which should be able to compute optimal sharpening that
>>*doesn't* cause haloes.
>
> By definition (because of increased contrast) it will cause haloes.
> Whether you see them or not is another matter. If you zoom in and
> compare to the original you will see them.

No wait -- my understanding is that, by definition, "optimal sharpening"
is the highest amount you can apply *without* causing haloes.
Perhaps unsharp mask in particular always causes them, I don't know, but
there isn't only unsharp mask around.

Haloes show quite clearly on the ESF graph, and I assure you that I
*can* apply some amount of sharpening that doesn't cause "hills" in the
ESF graph.

>>I think the main problem will (still) be noise, as it will be amplified
>>by the sharpening, and computing the PSF doesn't help much with that.
>>
>>I think it's going to be a matter of compromise here: how much noise am
>>I prepared to accept versus how much (or, up to what frequency) do I
>>want to improve the MTF.
>
> Yes, that's exactly what it boils down to! You have to balance one
> against the other. Which means, back to "guessing" what looks better.

As far as noise is concerned, yes, this is mostly true.
But noise and haloes are two separate issues!

Anyway, what would seem a reasonable "balance" to me is this: apply the
best sharpening you can that does not cause noise to go higher than the
noise a non-staggered-CCD-array would have.

This is what I'd call the "right" sharpening for Epson scanners: make it
as sharp as the linear CCD scanners, making noise go no higher than a
linear CCD scanner's (since you know a linear CCD of the same size as my
staggered CCD has more noise in general, as the sensors are smaller).

>>>[snip: the ruler test]
>>
>>I'll try, just for laughs (or cries).
>>But even after measuring what's going on with a ruler, I'm still afraid
>>there is very little that can be done.
>>
>>Possibly, one could scan a ruler next to the film, and use some program
>>to "reshape" every color channel based on the positions of the ruler
>>ticks... but, I dunno, I have a feeling this is only going to work in
>>theory.
>
> It will work in practice too if you have guides along both axis. The
> trouble is that's very clumsy and time consuming.
>
> If you do decided to do that I would create a movable frame so you
> have guides on all 4 sides. That's because the whole assembly wiggles
> as it travels so the distortion may not be the same at opposite edges.
>
> Also, the misalignment is not uniform but changes because the stepper
> motor sometimes goes faster and sometimes slower! So you will not be
> able to just change the height/width of the image and have perfect
> reproduction. You'll actually have to transform the image. Which means
> superimposing a grid... Which means figuring out the size of that grid
> i.e. determine the variance of stepper motor speed change... Argh!!

Yes, this is precisely what I meant with "is only going to work in
theory". Remember also that I was talking in the context of color
aberrations, which means the process would have to be repeated *three
times* separately for each channel!

It'd take ages of processing times... and, also, what kind of
super-ruler should we get? Any common ruler just isn't going to be good
enough: the ticks will be to thick, non-uniformely spaced and unsharp;
and the transparent plastic the ruler is made of will, itself, cause
color aberrations.

> Of course, the key question is, is it worth it? In my case, in the
> end, I decided it wasn't. But it still bugs me! ;o)

I know. By the way, changing slightly the topic, what about two-pass
scanning and rotating the slide/film 90 degrees between the two passes?
I mean, we know the stepper motor axis has worse resolution than the CCD
axis. So, perhaps multi-pass scanning would work best if we let the CCD
axis get a horizontal *and* a vertical view of the image.

Of course, you'd still need to sub-pixel align and all that hassle, but
perhaps the results could be better than the "usual" multi-pass scanning.
Clearly, there is a disadvantage in that you'd have to physically rotate
your slides or film between passes...

>>>That's what I'm saying (individual channel measurements) only use a
>>>straight average when you combine the results. Luminance will simply
>>>introduce a large green bias at the expense of red, for the most part.
>>
>>More at the expense of blue, I think.
>>But, besides this, what you said before was that either average or
>>luminance will not be right when the channels are misaligned.
>>
>>What I'm saying is, well, this will be no issue, as the channels will be
>>re-aligned *before* taking either average or luminance.
>
> I would *not* align them because that would change the values!!! And
> those changes are bound to be much more than what you're measuring!

Hm? I don't follow you. When you have got the ESF, you just *have* your
values. You can then move them around at your heart's will, and you
won't lose anything. Which implies that you can easily move the three
ESFs so that they're all aligned (i.e. the "edge center" is found in the
same place), before taking any kind of average.

> In principle, you should never do anything to the data coming from the
> scanner if the goal is to perform measurements. That's why even gamma
> is not applied but only linear data is used for calculations.

Yes, and I'm not doing anything to the data *coming from the scanner*;
just to the ESF, which is a high-precision, floating point function that
I've calculated *from* the scanner data.
It's not made of pixels: it's made for x's and y's, in double precision
floating point. I assure you that I'm already doing so much more
(necessary) evil to these functions, that shifting them around a bit
isn't going to lose anything.

> I really think the best way is to simply do each channel separately
> and then see what the results are. In theory, they should be pretty
> equal. If you want a single number I would then just average those
> three results.

Yes, in theory. In practice, my red channel has a visibly worse MTF than
the green channel, for one.

>>>[snip]
>>>
>>>No, the answer is not based on any one individual person. The answer
>>>is quite clear if you read out the gray values. Whether one person can
>>>see those grays and the other can't doesn't really matter in the
>>>context of objective measurements.
>>
>>But then why were 50% and (expecially) 10% chosen as standard?
>>Because of some physical reason? No, because they make perceptual sense:
>>10% is the boundary where the average human eye stops seeing contrast.
>
> No, there is physical reason why those luminance percentages were
> chosen. It's to do with how our eyes are built and the sensors for
> individual colors.

Did you just say "with how our eyes are built"? Now that's perceptual!
Ok, not necessarily perceptual in the sense that it has to do with our
brain, but it has to do with the observer.

MTF10 is chosen *because the average observer can't see less than 10%
contrast* (because of how his eyes are built, or whatever; it's still
the observer, not the data).

> I mean, if you're measuring how fast a car is going, are you going to
> change the scale because of how you perceive speed or are you going to
> ignore your subjective perception and just measure the speed?

Hmm, we definitely base units and scales of measurements on our
perception. We don't use light-years, we use kilometers; some weird
peoples even use "standardized" parts of their bodies (like my "average
observer", you see), such as feet, inches and funny stuff like that ;-P

Sure, we do use light-years now when we measure things that are
*outside* our normal perception.

> This is the same thing. You measure the amounts of gray the scanner
> can't resolve. How you perceive this gray is, is totally irrelevant to
> the measurement.

But the problem is that there is *no* amount of gray the scanner can't
resolve! It can resolve everything up to half Nyquist. I mean *my*
scanner. It's just that it resolves frequencies near Nyquist with such a
low contrast that they're hardly distinguishable.

Where do you draw the line? Just how much uniformely gray your test
pattern must be before you say "ok, this is the point after which my
scanner has no useful resolution"?

I don't see a choice other than the perceptual choice. Which also has
the advantage of being a farily standard choice.

> [snip]


>
> They may be testing a different thing, though. BTW, why don't you just
> use Imatest?

Because they're asking money for it :-) I've had my trial runs, finished
them up, and I'm now left with SFRWin and no intention to buy Imatest
(not that it's a bad program, it's just that I don't buy much of
anything in general).

I'm not sure I would call myself a "free software advocate", but I
definitely do like free software. And certainly the fact that my program
might be useful to other people gives me more motivation to write it,
than if it were only useful to myself.
Not necessarily altruism, mind you, just seeing a lot of downloads of a
program I've written would probably make me feel a star :-) hey, we're
human.

> Anyway, as I said on the outset. I'm just kibitzing here and threw in
> that luminance note because it seemed contradictory to the task.
>
> But instead of wasting time on replying carry on with programming! :o)

I can't keep programming all day anyway! -- well, I've done that
yesterday, and the result was one of those headaches you don't quickly
forget.

Anyway, have you tried out ALE yet? I don't think it can re-align
*single* rows or columns in an image, but it does perform a lot of
geomtry transformation while trying to align images. And it works with
16 bit images and all, which you were looking for, weren't you? It's
just so terribly slow.


by LjL
ljl...@tiscali.it

john rehn

unread,
Oct 2, 2005, 7:12:18 AM10/2/05
to
Hi !

I did not saw this thread before I started my own.
But may I ask you: What sfr do you actually get from your
scanners ??

regards

john rehn

Bart van der Wolf

unread,
Oct 2, 2005, 8:30:49 AM10/2/05
to

"john rehn" <john....@gmail.com> wrote in message
news:1128251538....@g49g2000cwa.googlegroups.com...

> Hi !
>
> I did not saw this thread before I started my own.
> But may I ask you: What sfr do you actually get from your
> scanners ??

http://www.xs4all.nl/~bvdwolf/main/foto/Imatest/SFR_DSE5400_GD.png

Bart

Don

unread,
Oct 2, 2005, 8:46:40 AM10/2/05
to
On Sun, 02 Oct 2005 03:23:42 +0200, "Lorenzo J. Lucchini"
<ljl...@tiscali.it> wrote:

>By the way, I see that the levels (or perhaps the gamma) are different
>if I scan at 16-bit and if I scan at 8-bit, with otherwise the same
>settings. Actually, the 16-bit scan clips. Wonderful, another bug in my
>fine scanner driver!

If could be that 8-bit clips as well but you just can't see it.
Another common problem when looking at 16-bit images with an 8-bit
histogram is that the programs don't calculate correctly. Even
Photoshop "massages" the histogram data before it shows it, resulting
in some really weird artefacts. Because of all those reasons I wrote
my own 16-bit histogram program.

>> Yes, 8-bit image is inadequate which results in inadequate metrics.
>
>Let's agree on terms. I took the "metrics" as meaning the slanted edge
>test results, and the "image" is just the image, that is the picture to
>be sharpened (or whatever).

Yes, metrics simply means results of a measurement. In the above
context, image is anything you used to make these measurements on.

>No wait -- my understanding is that, by definition, "optimal sharpening"
>is the highest amount you can apply *without* causing haloes.
>Perhaps unsharp mask in particular always causes them, I don't know, but
>there isn't only unsharp mask around.
>
>Haloes show quite clearly on the ESF graph, and I assure you that I
>*can* apply some amount of sharpening that doesn't cause "hills" in the
>ESF graph.

As I mentioned last time it's all about how the sharpening is done. It
simply means localized increase of (edge) contrast resulting in an
optical illusion i.e. we perceive such an image as sharp.

Now, whether you get ESF peaks is not really what I was addressing but
the fact that the whole concept of sharpening is based on this
selective contrast. So whether this causes ESF peaks or not, the image
has been (in my view) "corrupted". It may look good, and all that, but
I just don't like the concept.

>>>>[snip: the ruler test]


>>>
>> Of course, the key question is, is it worth it? In my case, in the
>> end, I decided it wasn't. But it still bugs me! ;o)
>
>I know. By the way, changing slightly the topic, what about two-pass
>scanning and rotating the slide/film 90 degrees between the two passes?
>I mean, we know the stepper motor axis has worse resolution than the CCD
>axis. So, perhaps multi-pass scanning would work best if we let the CCD
>axis get a horizontal *and* a vertical view of the image.
>
>Of course, you'd still need to sub-pixel align and all that hassle, but
>perhaps the results could be better than the "usual" multi-pass scanning.
>Clearly, there is a disadvantage in that you'd have to physically rotate
>your slides or film between passes...

And it's also nearly impossible to rotate exactly 90 degrees, at least
not to satisfy the accuracy of the scanner. So there will be problems
with that too. Also, due to stretching the pixels are no longer
perfectly rectangular so that will have to be fixed. Etc.

It's a very clever idea, though!

Another option (for lower resolutions) is to simply take a picture
with a high resolution digital camera. This causes many other
problems, of course, but at least as far as horizontal vs vertical
distortion goes it could be much more regular than a scanner.

>>>What I'm saying is, well, this will be no issue, as the channels will be
>>>re-aligned *before* taking either average or luminance.
>>
>> I would *not* align them because that would change the values!!! And
>> those changes are bound to be much more than what you're measuring!
>
>Hm? I don't follow you. When you have got the ESF, you just *have* your
>values. You can then move them around at your heart's will, and you
>won't lose anything. Which implies that you can easily move the three
>ESFs so that they're all aligned (i.e. the "edge center" is found in the
>same place), before taking any kind of average.

I'm not talking about ESF per se but in general. If you align the
channels (using some sort of sub-pixel interpolation) you will be
changing the actual sampled values. This may work visually but it will
throw off any measurements or calculations based on such data.

>> In principle, you should never do anything to the data coming from the
>> scanner if the goal is to perform measurements. That's why even gamma
>> is not applied but only linear data is used for calculations.
>
>Yes, and I'm not doing anything to the data *coming from the scanner*;
>just to the ESF, which is a high-precision, floating point function that
>I've calculated *from* the scanner data.
>It's not made of pixels: it's made for x's and y's, in double precision
>floating point. I assure you that I'm already doing so much more
>(necessary) evil to these functions, that shifting them around a bit
>isn't going to lose anything.

I don't know exactly what you're doing and it may very well not be
important but it's an easy trap to fall into. That's all I was saying.

>> I really think the best way is to simply do each channel separately
>> and then see what the results are. In theory, they should be pretty
>> equal. If you want a single number I would then just average those
>> three results.
>
>Yes, in theory. In practice, my red channel has a visibly worse MTF than
>the green channel, for one.

That's *very* interesting!!! I wonder why that is?

>>BTW, why don't you just use Imatest?
>
>Because they're asking money for it :-)

Oh, really! That's disgusting!!

Like I said, I'm not really into all that, but aren't there free
versions available? Surely, others must have done this many times by
now? Especially if Imatest is so greedy!

>I've had my trial runs, finished
>them up, and I'm now left with SFRWin and no intention to buy Imatest
>(not that it's a bad program, it's just that I don't buy much of
>anything in general).
>
>I'm not sure I would call myself a "free software advocate", but I
>definitely do like free software. And certainly the fact that my program
>might be useful to other people gives me more motivation to write it,
>than if it were only useful to myself.

As you know, in GNU sense "free" doesn't refer to cost but to the fact
that the software is not "imprisoned".

>Not necessarily altruism, mind you, just seeing a lot of downloads of a
>program I've written would probably make me feel a star :-) hey, we're
>human.

That's one of the main motivations for some of the best free software
out there. Or just simply because people are curious and don't believe
the martektroids so they do things themselves.

>Anyway, have you tried out ALE yet?

No, unfortunately not! It's still sitting on top of my "X-files" (I
have a temporary "x" directory where I keep all my current stuff).

I got sidelined because I ran out of disk space. You see, I've done
all my programming and I'm now heavily into scanning. It's complicated
to explain but I want to scan everything to disk first before I start
offloading the images to DVDs. The reason is because the chronology is
unclear, so until I finish scanning *all* of them I will not be able
to re-order them correctly. (Looking at slides with a naked eye is not
good enough.) And I don't want to start burning DVDs only to find out
later, the images are actually out of chronological order. I'm just
being silly, but that's the workflow I chose.

So I was forced to get a new drive. And then "just for fun" I decided
to format it as NTFS (the first time I did that). Long story short,
I'm still running tests and "playing" with it...

>I don't think it can re-align
>*single* rows or columns in an image, but it does perform a lot of
>geomtry transformation while trying to align images. And it works with
>16 bit images and all, which you were looking for, weren't you? It's
>just so terribly slow.

I have my own alignment program and it does what I need, but I was
just interested to see what they did in ALE. In the end, I not only
sub-pixel align in my program but actually transform the image. I do
this with 4 anchor points instead of going with a full mesh exactly
because it is so slow.

Don.

Lorenzo J. Lucchini

unread,
Oct 2, 2005, 9:30:26 AM10/2/05
to
Bart van der Wolf wrote:
>

Yes, "the guy" has some resolution graphs on xs4all :-)

You can see the figures for my Epson RX500 here:
http://ljl.150m.com/scans/fig-blade2.gif

But please notice that I might have made some mistakes scanning:
somehow, the edge image looks color-corrected and possibly
gamma-corrected, even though I thought I told the driver to disable that.

Still, the actual MTF doesn't look too different from the ones I've got
with certainly good scans.

by LjL
ljl...@tiscali.it

Lorenzo J. Lucchini

unread,
Oct 2, 2005, 10:07:04 AM10/2/05
to
Don wrote:
> On Sun, 02 Oct 2005 03:23:42 +0200, "Lorenzo J. Lucchini"
> <ljl...@tiscali.it> wrote:
>
> [my 16-bit scans having different colors from my 8-bit scans]

I don't really know, I'll have to do some tests on this. Yeah, it could
be that Photoshop is messing up something, but the images do *look* very
different, too, with the 16-bit image having the whitepoint at 255,
while the 8-bit scan is around 230 or so.

> [snip]


>
>>Haloes show quite clearly on the ESF graph, and I assure you that I
>>*can* apply some amount of sharpening that doesn't cause "hills" in the
>>ESF graph.
>
> As I mentioned last time it's all about how the sharpening is done. It
> simply means localized increase of (edge) contrast resulting in an
> optical illusion i.e. we perceive such an image as sharp.
>
> Now, whether you get ESF peaks is not really what I was addressing but
> the fact that the whole concept of sharpening is based on this
> selective contrast. So whether this causes ESF peaks or not, the image
> has been (in my view) "corrupted". It may look good, and all that, but
> I just don't like the concept.

I see, but I'm not sure sharpening can be dismissed as an optical illusion.
From all I've understood, scanners (expecially staggered array ones)
soften the original image, and sharpening, when done correctly, is
simply the inverse operation.

Actually, "softening" and "sharpening" are just two specific case, the
general concept being: if your optical system *corrupts* the original
target it's imaging, you can *undo* this corruption, as long as you know
exactly the (convolution) function that represents the corruption.

Look at these images, for example:
http://refocus-it.sourceforge.net/

All I know is that I can't read what's written in the original image,
while I can quite clearly read the "restored" version(s).
Yes, there is much more noise, that's unavoidable (expecially in such an
extreme example)... but I have a problem calling the technique "corruption".

Or look at the first example image here:
http://meesoft.logicnet.dk/Analyzer/help/help2.htm#RestorationByDeconvolution

Sure, the "restored" image is not as good as one that was taken without
motion blur to begin with, but still the result is quite impressive.

And note that both programs, Refocus-it and Image Analyzer, *guess* (or
let the user guess) the kind of blurring function *from* the image --
which does result in artifacts, as guessing is hard (the same that
happens with unsharp masking).

But if you know instead of guess, I'm convinced the sharpened result
will not only be more pleasing to the eye, but more mathematically close
to the original target.

>>>>>[snip: the ruler test]
>>>>
>>>Of course, the key question is, is it worth it? In my case, in the
>>>end, I decided it wasn't. But it still bugs me! ;o)
>>
>>I know. By the way, changing slightly the topic, what about two-pass
>>scanning and rotating the slide/film 90 degrees between the two passes?
>>I mean, we know the stepper motor axis has worse resolution than the CCD
>>axis. So, perhaps multi-pass scanning would work best if we let the CCD
>>axis get a horizontal *and* a vertical view of the image.
>>
>>Of course, you'd still need to sub-pixel align and all that hassle, but
>>perhaps the results could be better than the "usual" multi-pass scanning.
>>Clearly, there is a disadvantage in that you'd have to physically rotate
>>your slides or film between passes...
>
> And it's also nearly impossible to rotate exactly 90 degrees, at least
> not to satisfy the accuracy of the scanner. So there will be problems
> with that too. Also, due to stretching the pixels are no longer
> perfectly rectangular so that will have to be fixed. Etc.

Yes, but these things have to be done (though perhaps to a lesser
extent) with "simple" multi-pass scans, as well, because of the problems
we know -- stepper motor and all.
I'm not sure just *how much* increased complexity my idea would add to
the game.

> [snip]


>
>>>>What I'm saying is, well, this will be no issue, as the channels will be
>>>>re-aligned *before* taking either average or luminance.
>>>
>>>I would *not* align them because that would change the values!!! And
>>>those changes are bound to be much more than what you're measuring!
>>
>>Hm? I don't follow you. When you have got the ESF, you just *have* your
>>values. You can then move them around at your heart's will, and you
>>won't lose anything. Which implies that you can easily move the three
>>ESFs so that they're all aligned (i.e. the "edge center" is found in the
>>same place), before taking any kind of average.
>
> I'm not talking about ESF per se but in general. If you align the
> channels (using some sort of sub-pixel interpolation) you will be
> changing the actual sampled values. This may work visually but it will
> throw off any measurements or calculations based on such data.

Ok, I see.
But don't worry then, I don't have to do any sub-pixel interpolation in
the ESF case (or, you could say, I *do* have to do some, but I have to
do it no matter whether I have to re-align or not).

>>>In principle, you should never do anything to the data coming from the
>>>scanner if the goal is to perform measurements. That's why even gamma
>>>is not applied but only linear data is used for calculations.
>>
>>Yes, and I'm not doing anything to the data *coming from the scanner*;
>>just to the ESF, which is a high-precision, floating point function that
>>I've calculated *from* the scanner data.
>>It's not made of pixels: it's made for x's and y's, in double precision
>>floating point. I assure you that I'm already doing so much more
>>(necessary) evil to these functions, that shifting them around a bit
>>isn't going to lose anything.
>
> I don't know exactly what you're doing and it may very well not be
> important but it's an easy trap to fall into. That's all I was saying.

Ok. Just to explain briefly: imagine scanning a sharp edge. You now want
to obtain the function that describes how pixel values change on the
edge (the edge spread function = ESF).

So you take any single row of the scanned edge's image, and look at how
pixels change.

This function looks like the one I had uploaded here:
http://ljl.150m.com/scans/fig-blade2.gif (the first graph)


But, how can the function be so precisely defined, when there are only a
few pixels representing the edge transition in any one row of the edge
image?

Interpolation? No. You simply take more than just *one* row: you take
all of them.
And you scan an edge that's tilted by some degrees with respect to the
scanner axis you want to measure.

This way, you get oversampled data, just as if you were doing many
misaligned scan passes -- only, you know quite precisely what the
misalignment of each is (as you can measure where the edge *is* with
some decent precision).

Once you've done this, and you have the ESF, you don't need to do
anything sub-pixel anymore; you already have an oversampled, "sub-pixel"
function that you've obtained not by interpolation, but by clever use of
real data.

>>>I really think the best way is to simply do each channel separately
>>>and then see what the results are. In theory, they should be pretty
>>>equal. If you want a single number I would then just average those
>>>three results.
>>
>>Yes, in theory. In practice, my red channel has a visibly worse MTF than
>>the green channel, for one.
>
> That's *very* interesting!!! I wonder why that is?

Well, for one, who's to say that my scanner's white light source is white?
If red is less well represented in the light source than the other
primaries, there will be more noise in the red channel.

Though noise should directly affect the MTF, AFAIK.

But there are other possibilities: being a flatbed, my scanner has a
glass. Who says the glass "spreads" all wavelengths the same way?

>>>BTW, why don't you just use Imatest?
>>
>>Because they're asking money for it :-)
>
> Oh, really! That's disgusting!!

:-) It's their right. It's a fine program after all. Imagine what? A guy
on an Italian newsgroup just posted an *executable-only* Visual Basic
program for calculating resistor values from colors.
He was asking for advice about how to improve the program.
But when people told him they couldn't be of much help without the
source code, he reply he wouldn't post it on the net.

My reaction was to write a similar (but hopefully better) program, send
it to him, and tell him I transfered the copyright to him ;-)

> Like I said, I'm not really into all that, but aren't there free
> versions available? Surely, others must have done this many times by
> now? Especially if Imatest is so greedy!

There is SFRWin, which is free, though not open source; and it only
outputs the MTF, while Imatest also gives you the ESF and the LSF (which
have to be calculated to get to the MTF, anyway), as well as some other
useful information.

Also, both Imatest and SFRWin only work under Windows (a version of
SFRWin, called SFR2, runs under Matlab, which *might* mean it could work
under Octave, for all I know, but I doubt it).

> [snip]

by LjL
ljl...@tiscali.it

Don

unread,
Oct 3, 2005, 8:47:26 AM10/3/05
to
On Sun, 02 Oct 2005 16:07:04 +0200, "Lorenzo J. Lucchini"
<ljl...@tiscali.it> wrote:

>> Now, whether you get ESF peaks is not really what I was addressing but
>> the fact that the whole concept of sharpening is based on this
>> selective contrast. So whether this causes ESF peaks or not, the image
>> has been (in my view) "corrupted". It may look good, and all that, but
>> I just don't like the concept.
>
>I see, but I'm not sure sharpening can be dismissed as an optical illusion.

It can, because the image is not sharpened only the contrast at both
sides of the border between dark and light areas is enhanced locally.

To really sharpen the image one would need to "shorten" the transition
from dark to light i.e. eliminate or reduce the "fuzzy" part and
generally that's not what's being done.

One simple proof of that is halos. If the image were truly sharpened
(the fuzzy transition is shortened) you could never get haloes! In the
most extreme case of sharpening (complete elimination of gray
transition) you would simply get a clean break between black and
white. That's the sharpest case possible.

The fact that you get halos shows that so-called sharpening algorithms
do not really sharpen but only "fudge" or as I would say "corrupt".

> From all I've understood, scanners (expecially staggered array ones)
>soften the original image, and sharpening, when done correctly, is
>simply the inverse operation.

But that's my point, exactly, it does not really reverse the process
but only tries to and that just adds to the overall "corruption".

>Actually, "softening" and "sharpening" are just two specific case, the
>general concept being: if your optical system *corrupts* the original
>target it's imaging, you can *undo* this corruption, as long as you know
>exactly the (convolution) function that represents the corruption.

In theory but not in practice. And certainly not always. You can't
reverse a lossy process. You can "invent" pixels to compensate
("pretend to reverse") but you can never get the lossy part back.

Now, some of those algorithms are very clever and produce good results
while others just corrupt the image even more (e.g. anti-aliasing).

Whether the result is acceptable or not depends on each individual
because it's a subjective call, really.

>Or look at the first example image here:
>http://meesoft.logicnet.dk/Analyzer/help/help2.htm#RestorationByDeconvolution
>
>Sure, the "restored" image is not as good as one that was taken without
>motion blur to begin with, but still the result is quite impressive.

Which only confirms what I said: Some processes are very clever but
you can never really get the lossy part back.

>>>>I really think the best way is to simply do each channel separately
>>>>and then see what the results are. In theory, they should be pretty
>>>>equal. If you want a single number I would then just average those
>>>>three results.
>>>
>>>Yes, in theory. In practice, my red channel has a visibly worse MTF than
>>>the green channel, for one.
>>
>> That's *very* interesting!!! I wonder why that is?
>
>Well, for one, who's to say that my scanner's white light source is white?
>If red is less well represented in the light source than the other
>primaries, there will be more noise in the red channel.
>
>Though noise should directly affect the MTF, AFAIK.
>
>But there are other possibilities: being a flatbed, my scanner has a
>glass. Who says the glass "spreads" all wavelengths the same way?

But none of that should affect the results because you're dealing with
*relative* change in brightness along the edge. Now, in *absolute*
terms there may be difference between channels but if, for example,
red receives less light than other channels the *relative* transition
should still be the same, only the red pixels will be a bit darker.

I don't think noise enters into this because red would need to receive
considerably less light for noise to affect the measurements. If that
were the case you would notice this in the scans as they would get a
cyan cast.

Don.

Lorenzo J. Lucchini

unread,
Oct 3, 2005, 9:49:15 AM10/3/05
to
Don wrote:
> On Sun, 02 Oct 2005 16:07:04 +0200, "Lorenzo J. Lucchini"
> <ljl...@tiscali.it> wrote:
>
>
>>>Now, whether you get ESF peaks is not really what I was addressing but
>>>the fact that the whole concept of sharpening is based on this
>>>selective contrast. So whether this causes ESF peaks or not, the image
>>>has been (in my view) "corrupted". It may look good, and all that, but
>>>I just don't like the concept.
>>
>>I see, but I'm not sure sharpening can be dismissed as an optical illusion.
>
> It can, because the image is not sharpened only the contrast at both
> sides of the border between dark and light areas is enhanced locally.
>
> To really sharpen the image one would need to "shorten" the transition
> from dark to light i.e. eliminate or reduce the "fuzzy" part and
> generally that's not what's being done.
>
> One simple proof of that is halos. If the image were truly sharpened
> (the fuzzy transition is shortened) you could never get haloes! In the
> most extreme case of sharpening (complete elimination of gray
> transition) you would simply get a clean break between black and
> white. That's the sharpest case possible.
>
> The fact that you get halos shows that so-called sharpening algorithms
> do not really sharpen but only "fudge" or as I would say "corrupt".

But my point is that sharpening algorithms should not necessarily
produce haloes. I don't have proof -- actually, proof is what I'm hoping
to obtain if I can make my program work! --, but just note that my
hypothesis is just that: halos need not necessarily occur.

By the way - not that it's particularly important, but I don't think the
"sharpest case possible" is a clean break between black and white, as at
least *one* gray pixel will be unavoidable, unless you manage to place
all of your "borders" *exactly* at the point of transition between two
pixels.

>>From all I've understood, scanners (expecially staggered array ones)
>>soften the original image, and sharpening, when done correctly, is
>>simply the inverse operation.
>
> But that's my point, exactly, it does not really reverse the process
> but only tries to and that just adds to the overall "corruption".

Make a distinction between unsharp masking and similar techniques, and
processes based on knowledge of the system's point spread function,
which is what I'm trying to work on.

Unsharp masking just assumes that every pixel is "spread out" in a
certain way (well, you can set some parameters), and bases its
reconstruction on that.

*That*, I think, is its shortcoming. But if you knew *exactly* the way
every pixel is "spread out" (i.e., if you knew the point spread
function), my understanding is that you *could* then really reverse the
process, by inverting the convolution.

Read below before you feel an urge to say that it's impossible because
the process is irreversible...

>>Actually, "softening" and "sharpening" are just two specific case, the
>>general concept being: if your optical system *corrupts* the original
>>target it's imaging, you can *undo* this corruption, as long as you know
>>exactly the (convolution) function that represents the corruption.
>
> In theory but not in practice. And certainly not always. You can't
> reverse a lossy process. You can "invent" pixels to compensate
> ("pretend to reverse") but you can never get the lossy part back.

Now, this time, yes, what we're talking about is a lossy process, and as
such it cannot be completely reversed.

But before giving up, we should ask, *what is it* that makes it lossy?
Well, I'm still trying to understand how this all really works, but
right now, my answer is: noise makes the process lossy. If you had an
ideal scanner with no noise, then you could *exactly* reverse what the
sensor+optics do.

In real life, we have noise, and that's why you can't just do a
deconvolution and get a "perfect" result. The problem you'll have is
that you also amplify noise, but you won't be otherwise corrupting the
image.

Sure, amplifying noise is still something you might not want to do...
but pretend you own my Epson staggered CCD scanner: you have a scanner
that has twice less noise than equivalent linear CCD scanners, but a
worse MTF in exchange. What do you do? You improve the MTF, at the
expense of getting noise to the levels a linear CCD scanner would should.
And, in comparison with a linear CCD scanner, you've still gained
anti-aliasing.

Kennedy would agree :-) So let's quote him, although I can't guarrantee
the quote isn't a bit out of context, as I've only just looked it up
quickly.

--- CUT ---

[Ed Hamrick]
> The one thing you've missed is that few (if any) flatbed scanners
> have optics that focus well enough to make aliasing a problem when
> scanning film. In this case, staggered linear array CCD's don't
> help anything, and just reduce the resolution.

[Kennedy McEwen]
If this was the situation then any 'loss' in the staggered CCD spatial
response would be more than adequately recovered by simple boost
filtering due to the increased signal to noise of the larger pixels

--- CUT ---

> [snip]


>
>>>>Yes, in theory. In practice, my red channel has a visibly worse MTF than
>>>>the green channel, for one.
>>>
>>>That's *very* interesting!!! I wonder why that is?
>>
>>Well, for one, who's to say that my scanner's white light source is white?
>>If red is less well represented in the light source than the other
>>primaries, there will be more noise in the red channel.
>>
>>Though noise should directly affect the MTF, AFAIK.

Ehm, note that I meant to say "shouldn't" here.

>>But there are other possibilities: being a flatbed, my scanner has a
>>glass. Who says the glass "spreads" all wavelengths the same way?
>
> But none of that should affect the results because you're dealing with
> *relative* change in brightness along the edge. Now, in *absolute*
> terms there may be difference between channels but if, for example,
> red receives less light than other channels the *relative* transition
> should still be the same, only the red pixels will be a bit darker.

Not darker: the scanner calibration will set the light as the
whitepoint, so channels will still have the same brightness.
I agree on a second thought that the red source should be *really*
dimmer than the other, for this to produce noticeably more noise.

But I think the glass hypothesis still stands: if the glass blurs red
more than it blurs the other colors, well, here you have a longer edge
transition, and a worse MTF.

> [snip]

by LjL
ljl...@tiscali.it

Don

unread,
Oct 4, 2005, 11:29:50 AM10/4/05
to
On Mon, 03 Oct 2005 15:49:15 +0200, "Lorenzo J. Lucchini"
<ljl...@tiscali.it> wrote:

>But my point is that sharpening algorithms should not necessarily
>produce haloes. I don't have proof -- actually, proof is what I'm hoping
>to obtain if I can make my program work! --, but just note that my
>hypothesis is just that: halos need not necessarily occur.

"Sharpening" by increasing contrast of transition areas always
produces halos. It's the basis of the algorithm. You may not perceive
them but they're there. The optical illusion which makes you perceive
this contrast in transition areas as sharpness has a threshold. Step
over it and halos become perceptible. Stay below it and they don't.

>By the way - not that it's particularly important, but I don't think the
>"sharpest case possible" is a clean break between black and white, as at
>least *one* gray pixel will be unavoidable, unless you manage to place
>all of your "borders" *exactly* at the point of transition between two
>pixels.

It's theoretically the sharpest which, as you indicate, can also be
achieved in practice sometimes by lining up the image and the sensors.


Anyway, have to keep it short because I'm real busy today. With the
new drive I decided to re-organize everything and that takes a lot of
time. Haven't scanned anything in 3 days and I'm falling behind my
original schedule... Why are days always too short? ;o)

Don.

Bart van der Wolf

unread,
Oct 5, 2005, 8:38:52 AM10/5/05
to

"Lorenzo J. Lucchini" <ljl...@tiscali.it> wrote in message
news:zm0%e.4303$133....@tornado.fastwebnet.it...
SNIP

> Try with this command line:
>
> slantededge.exe --verbose --csv-esf esf.txt --csv-lsf
> lsf.txt --csv-mtf mtf.txt testedge.ppm

Yep, got it running.

Bart

Bart van der Wolf

unread,
Oct 6, 2005, 8:43:02 AM10/6/05
to

"Lorenzo J. Lucchini" <ljl...@tiscali.it> wrote in message
news:CGa0f.9459$133....@tornado.fastwebnet.it...
SNIP

> But my point is that sharpening algorithms should not necessarily
> produce haloes. I don't have proof -- actually, proof is what I'm
> hoping to obtain if I can make my program work! --, but just note
> that my hypothesis is just that: halos need not necessarily occur.

That's correct, halo can be avoided while still boosting the high
spatial frequencies' MTF. The boost however may be not too
spectacular, it's just restoring some of the capture process losses.
Some losses are inherent to the sampling process (e.g. area sampling
versus point sampling will produce different MTFs from the same
subject). Maybe it is more accurate to classify those as system
characteristics rather than losses.

Sharpening on the other end, with further anticipated losses in mind
(e.g. printing) should introduce small halos in order to trick human
vision, but the halo should not be visible (IOW smaller than visual
resolution). What *is* visible is the contrast boost (without halo) of
the spatial frequencies we *can* resolve.

Capture loss restoration can be tackled by using a high-pass filter.
Convolving the image with a smallish HP-filter kernel is rather fast
and simple to implement. The best result can be achieved if the HP
filter is modeled after the PSF. This is what it can look like on your
(odd looking) "testedge.tif":
<http://www.xs4all.nl/~bvdwolf/main/foto/Imatest/testedge.zip>
The Luminance channel was HP-filtered in "Image Analyzer" with a "user
defined filter" of 7x7 support.

The mean S/N ratio has decreased from 241.9:1 to 136.3:1, while the
10-90% edge rise went from 4.11 to 2.64 pixels. Unfortunately the scan
suffers from some CA like aberration (especially the Red channel is of
lower resolution), which may become more visible as well.

Bart

Lorenzo J. Lucchini

unread,
Oct 6, 2005, 9:23:05 AM10/6/05
to
Bart van der Wolf wrote:
>
> "Lorenzo J. Lucchini" <ljl...@tiscali.it> wrote in message
> news:CGa0f.9459$133....@tornado.fastwebnet.it...
> SNIP
>
> [snip]

>
> This is what it can look like on your (odd
> looking) "testedge.tif":
> <http://www.xs4all.nl/~bvdwolf/main/foto/Imatest/testedge.zip>
> The Luminance channel was HP-filtered in "Image Analyzer" with a "user
> defined filter" of 7x7 support.

Why is my edge odd-looking? Does it still look like it's not linear gamma?
The behavior of my driver is puzzling me more and more, expecially wrt
the differences between 8- and 16-bit scans.

> The mean S/N ratio has decreased from 241.9:1 to 136.3:1, while the
> 10-90% edge rise went from 4.11 to 2.64 pixels. Unfortunately the scan
> suffers from some CA like aberration (especially the Red channel is of
> lower resolution), which may become more visible as well.

Note that I had disabled all color correction, and the three channels
look much more consistent when my driver's standard color correction
coefficients are used.


By the way - I'm experimenting a bit with the Fourier method for
reconstructing the PSF that's explained in the book's chapter you
pointed me to (I mean the part about tomography).

I don't think I have much hope with that, though, as there is
interpolation needed, and it appears that interpolation in the frequency
domain is a tough thing.

OTOH, I think I've understood the way you're trying to reconstruct the
PSF; I'm not sure I like it, since as far as I can understand you're
basically assuming the PSF *will be gaussian* and thus try to fit a
("3D") gaussian on it. Now, perhaps the inexactness due to assuming a
gaussian isn't really important (at least with the scanners we're
using), but it still worries me a little.

Also, the book says that gaussian PSFs have gaussian LSFs with the same
parameters -- i.e. that a completely simmetrical gaussian PSF is the
same as any corresponding LSF.

Our PSFs are generally not symmetrical, but they *are* near-gaussian, so
what would you think about just considering the two LSFs we have as
sections of the PSF?

I think in the end I'll also try implementing your method, even though
there is no "automatic solver" in C, so it'll be a little tougher. But
perhaps some numerical library can be of help.


by LjL
ljl...@tiscali.it

Bart van der Wolf

unread,
Oct 6, 2005, 1:37:14 PM10/6/05
to

"Lorenzo J. Lucchini" <ljl...@tiscali.it> wrote in message
news:7A91f.15406$133....@tornado.fastwebnet.it...
SNIP

> Why is my edge odd-looking?

The pixels "seem" to be sampled with different resolution
horizontally/vertically. As you said earlier, you were experimenting
with oversampling and downsizing, so that may be the reason. BTW, I am
using the version that came with the compiled alpha 3.

SNIP


> OTOH, I think I've understood the way you're trying to reconstruct
> the PSF; I'm not sure I like it, since as far as I can understand
> you're basically assuming the PSF *will be gaussian* and thus try to
> fit a ("3D") gaussian on it.

In fact I fit the weighted average of multiple (3) Gaussians. That
allows to get a pretty close fit to the shape of the PSF. Although the
PSFs of lens, film, and scanner optics+sensor all have different
shapes, the combination usually resembles a Gaussian just like in many
natural processes. Only defocus produces a distinctively different
shape, something that could be added for even better PSF approximation
in my model.

This is how the ESF of your "testedge" compares to the ESF of my
model:
http://www.xs4all.nl/~bvdwolf/main/foto/Imatest/ESF.png

> Now, perhaps the inexactness due to assuming a gaussian isn't really
> important (at least with the scanners we're using), but it still
> worries me a little.

That's good ;-) I also don't take things for granted without some
soul searching (and web research).

> Also, the book says that gaussian PSFs have gaussian LSFs with the
> same parameters -- i.e. that a completely simmetrical gaussian PSF
> is the same as any corresponding LSF.

The LSF is the one dimensional integral of the PSF. If the PSF is a
Gaussian, then the LSF is also a Gaussian, but with a different shape
than a simple cross-section through the maximum of the PSF.
The added benefit of a Gaussian is that it produces a separable
function, the X and Y dimension can be processed separately after one
an other with a smaller (1D) kernel. That will save a lot of
processing time with the only drawback being a very slightly less
accurate result (due to compounding rounding errors, so negligible if
acurate math is used).

> Our PSFs are generally not symmetrical, but they *are*
> near-gaussian, so what would you think about just considering the
> two LSFs we have as sections of the PSF?

Yes, we can approximate the true PSF shape by using the information
from two orthogonal resolution measurements (with more variability in
the "slow scan" direction). I'm going to enhance my (Excel) model,
which now works fine for symmetrical PSFs based on a single ESF input
(which may in the end turn out to be good enough given the variability
in the slow scan dimension). I'll remove some redundant functions
(used for double checking), and then try to circumvent some of Excel's
shortcomings.

> I think in the end I'll also try implementing your method, even
> though there is no "automatic solver" in C, so it'll be a little
> tougher. But perhaps some numerical library can be of help.

My current (second) version (Excel spreadsheet) method tries to find
the right weighted mix of 3 ERF() functions
(http://www.library.cornell.edu/nr/bookcpdf/c6-2.pdf page 220, if not
present in a function library) in order to minimize the sum of squared
errors with the sub-sampled ESF. The task is to minimize that error by
changing three standard deviation values.
I haven't analyzed what type of error function this gives, but I guess
(I can be wrong in my assumption) that even an iterative approach
(although not very efficient) is effective enough because the
calculations are rather simple, and should execute quite fast. One
could consider (parts of) one of the methods from chapter 10 of the
above mentioned Numerical Recipes book to find the minimum error for
one Standard Deviation at a time, then loop through them again for a
number of iterations until a certain convergence criterion is met.

This is basically the model which is compared at the original ESF
sub-sample coordinates:
ESFmodel = (
W1*(1+IF(X<0;-Erf(-X/(SD1*Sqrt(2)));Erf(X/(SD1*SQRT(2)))))/2
+ W2*(1+IF(X<0;-Erf(-X/(SD2*Sqrt(2)));Erf(X/(SD2*SQRT(2)))))/2
+ W3*(1+IF(X<0;-Erf(-X/(SD3*Sqrt(2)));Erf(X/(SD3*SQRT(2)))))/2 )
/ (W1+W2+W3)

That will ultimately give, after optimization (minimizing the error
between samples and model), three Standard Deviations (SD1,SD2,SD3)
which I then use to populate a two dimensional kernel with the
(W1,W2,W3) weighted average of three symmetrical Gaussians. The
population is done with symbolically pre-calculated (with Mathematica)
functions that equal the 2D pixel integrals of 1 quadrant of the
kernel. The kernel, being symmetrical, is then completed by
copying/mirroring the results to the other quadrants.

That kernel population part is currently too inflexible for my taste,
but I needed it to avoid some of the Excel errors with the ERF
function. It should be possible to make a more flexible kernel if the
ERF function is better implemented.

Bart

Lorenzo J. Lucchini

unread,
Oct 6, 2005, 8:01:48 PM10/6/05
to
Bart van der Wolf wrote:
>
> "Lorenzo J. Lucchini" <ljl...@tiscali.it> wrote in message
> news:7A91f.15406$133....@tornado.fastwebnet.it...
> SNIP
>
>> Why is my edge odd-looking?
>
>
> The pixels "seem" to be sampled with different resolution
> horizontally/vertically. As you said earlier, you were experimenting
> with oversampling and downsizing, so that may be the reason. BTW, I am
> using the version that came with the compiled alpha 3.

Maybe I see what you mean: it seems that every pixel in the edge has a
vertical neighbour that has the same value.
But if I look at the noise, this doesn't seem to hold true anymore (and
you mentioned this before, I think).

Look... now that I think of it, I once scanned an edge where every pixel
on the edge was *darker* than the one below it (think of an edge with
the same orientation as testedge.tif).

Now, I don't really remember what settings I used on that one, so this
doesn't mean much, but I'm really sure that I've used all the "right"
settings for the testedge.ppm and testedge.tif I've included in alpha 3.

I can't quite explain this.

> [snip]

Before I try to digest what you wrote... :-) Have you heard of the Abel
transform -- whatever that is, of course, don't assume I know just
because I mention it! -- being used to reconstruct the PSF from the LSF?
(yes, unfortunately I've only read about "LSF", singular, upto now)

I ask just to be sure I'm not following a dead end, in case you already
looked into this.


by LjL
ljl...@tiscali.it

Bart van der Wolf

unread,
Oct 7, 2005, 9:27:40 AM10/7/05
to

"Lorenzo J. Lucchini" <ljl...@tiscali.it> wrote in message
news:FWi1f.16530$133....@tornado.fastwebnet.it...

> Bart van der Wolf wrote:
>>
>> "Lorenzo J. Lucchini" <ljl...@tiscali.it> wrote in message
>> news:7A91f.15406$133....@tornado.fastwebnet.it...
SNIP
> Maybe I see what you mean: it seems that every pixel in the edge has
> a vertical neighbour that has the same value.
> But if I look at the noise, this doesn't seem to hold true anymore
> (and you mentioned this before, I think).

Correct, that looks a bit strange.

Of course, for testing purposes only, one could make a well behaved
CGI slanted edge and apply several Gaussian blurs to it, and even add
a little Poisson noise. That won't solve things for your scanner, but
it does provide a known response for testing the program.

SNIP


> Before I try to digest what you wrote... :-) Have you heard of the
> Abel transform -- whatever that is, of course, don't assume I know
> just because I mention it! -- being used to reconstruct the PSF from
> the LSF? (yes, unfortunately I've only read about "LSF", singular,
> upto now)

No, I hadn't heard of it (or I wasn't paying attention when I did
;-)).
http://mathworld.wolfram.com/AbelTransform.html describes it, but I'm
not enough of a mathematician to immediately grasp its usefulness.

> I ask just to be sure I'm not following a dead end, in case you
> already looked into this.

I'll have to see myself if it can be of use, too early to tell.
However, do keep in mind that I am also considering the final
deconvolution or convolution step, which will take a very long time on
large images (e.g. 39 Mega-pixels on a full 5400 ppi scan from my film
scanner).

There is a lot of efficiency to be gained from a separable function
(like a Gaussian, or a polynomial(!)) versus one that requires a
square/rectangular kernel. It's roughly the difference between e.g. 18
instead of 81 multiplications per pixel when convolving with a 9x9
kernel, times the number of pixels.

What I'm actually suggesting, is that I'm willing to compromise a
little accuracy (:-() for a huge speed gain in execution. If execution
speed is unacceptable in actual use, then it won't be used. But I'm
willing to be surprised by any creative solution ...

One final remark for now, I think that for large images the
deconvolution path may prove to be too processing intensive (although
the CGLS method used by "Image Analyzer" seems rather efficient). It
is probably faster to convolve in the Spatial domain with a small
kernel than to deconvolve in the Frequency domain, which is why I
often mention the High-Pass filter solution. There are also free image
processing applications, like ImageMagick <http://www.imagemagick.org>
(also includes APIs for C or C++), that can use arbitrarily sized
(square) convolution kernels, so the final processing can be done (in
16-bit/channel, or I believe even in 32-b/ch if need be).

Bart

Lorenzo J. Lucchini

unread,
Oct 7, 2005, 10:02:58 AM10/7/05
to
Bart van der Wolf wrote:
>
> "Lorenzo J. Lucchini" <ljl...@tiscali.it> wrote in message
> news:FWi1f.16530$133....@tornado.fastwebnet.it...
>
>> Bart van der Wolf wrote:
>
> [snip]

>
> There is a lot of efficiency to be gained from a separable function
> (like a Gaussian, or a polynomial(!)) versus one that requires a
> square/rectangular kernel. It's roughly the difference between e.g. 18
> instead of 81 multiplications per pixel when convolving with a 9x9
> kernel, times the number of pixels.
>
> What I'm actually suggesting, is that I'm willing to compromise a little
> accuracy (:-() for a huge speed gain in execution. If execution speed is
> unacceptable in actual use, then it won't be used. But I'm willing to be
> surprised by any creative solution ...

You're right about speed of course.

One thing: by "separable function" you mean one that can be split into
two, which in turn are applied to the horizontal and vertical axes,
aren't you?

If so... are we really sure that there isn't a way to directly apply the
two LSFs for "deconvolution" (well, it'll have to be something slightly
different of course), instead of somehow reconstructing a PSF and then
splitting it again?

> One final remark for now, I think that for large images the
> deconvolution path may prove to be too processing intensive (although
> the CGLS method used by "Image Analyzer" seems rather efficient). It is
> probably faster to convolve in the Spatial domain with a small kernel
> than to deconvolve in the Frequency domain, which is why I often mention
> the High-Pass filter solution. There are also free image processing
> applications, like ImageMagick <http://www.imagemagick.org> (also
> includes APIs for C or C++), that can use arbitrarily sized (square)
> convolution kernels, so the final processing can be done (in
> 16-bit/channel, or I believe even in 32-b/ch if need be).

Indeed, I've been considering linking to ImageMagick, as well as to the
NetPBM library.

ImageMagick is probably more refined than NetPBM, and judging from your
article about resizing algorithms, it definitely has some merits.

Also, if I want to support more formats than just PNM (which I'm only
half-supporting right now, anyway), I'll have to use some kind of
library -- I'm definitely not going to manually write TIFF loading code,
not my piece of cake :-)


by LjL
ljl...@tiscali.it

Bart van der Wolf

unread,
Oct 8, 2005, 5:52:29 PM10/8/05
to

"Lorenzo J. Lucchini" <ljl...@tiscali.it> wrote in message
news:yfv1f.17515$133....@tornado.fastwebnet.it...
SNIP

> One thing: by "separable function" you mean one that can be split
> into two, which in turn are applied to the horizontal and vertical
> axes, aren't you?

Yep.

> If so... are we really sure that there isn't a way to directly apply
> the two LSFs for "deconvolution" (well, it'll have to be something
> slightly different of course), instead of somehow reconstructing a
> PSF and then splitting it again?

I'm working on that, but my method currently starts with finding a
match
to the ESF, there's no need to make a PSF for that.

For now the PSF is still useful for existing applications that require
a rectangular/square PSF as input for deconvolution, and the FIR
(Finite Impulse Response) filter support of many existing applications
is
often limited to 7x7 or 9x9 kernels. Also, calculating a PSF from an
ESF is not too much effort, although the final excecution of a PSF is
slower than
applying two 'separated' functions.

SNIP


> ImageMagick is probably more refined than NetPBM, and judging from
> your article about resizing algorithms, it definitely has some
> merits.

I have no experience with NetPBM, but ImageMagick is quite (too?)
potent and it also covers many file formats.

Bart

0 new messages