Prev: Canon 1250U2
Next: driver
From: Don on
On Wed, 28 Sep 2005 02:00:41 +0200, "Lorenzo J. Lucchini"
<ljlbox(a)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.
From: Lorenzo J. Lucchini on
Don wrote:
> On Wed, 28 Sep 2005 02:00:41 +0200, "Lorenzo J. Lucchini"
> <ljlbox(a)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
ljlbox(a)tiscali.it
From: Lorenzo J. Lucchini on
Bart van der Wolf wrote:
>
> "Lorenzo J. Lucchini" <ljlbox(a)tiscali.it> wrote in message
> news:%ib_e.38$U13.8(a)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
ljlbox(a)tiscali.it
From: Lorenzo J. Lucchini on
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
ljlbox(a)tiscali.it
From: Lorenzo J. Lucchini on
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
ljlbox(a)tiscali.it
First  |  Prev  |  Next  |  Last
Pages: 1 2 3 4 5 6 7 8 9 10 11
Prev: Canon 1250U2
Next: driver