Prev: Canon 1250U2
Next: driver
From: Don on 28 Sep 2005 09:16 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 28 Sep 2005 09:28 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 28 Sep 2005 10:55 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 28 Sep 2005 11:04 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 28 Sep 2005 11:11
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 |