Welcome to Doom9's Forum, THE in-place to be for everyone interested in DVD conversion. Before you start posting please read the forum rules. By posting to this forum you agree to abide by the rules. |
1st November 2010, 22:54 | #44 | Link |
Registered User
Join Date: Sep 2010
Location: Austin, TX
Posts: 40
|
autolevels() improvements
I sent a pm to the author, but his profile says he joined doom9 in order to post his filter, then last posted a few months later, in the fall of 2007, so I suspect he won't notice it.
I've had a look at the code and it is something I could pick up and generalize, and perhaps improve it in other ways. It would be a good way for me to get my feet wet. However, the whole reason I started using avisynth was in order to transfer and restore about 35 8mm films to DVD in time for Christmas, as a present to my siblings. I may not have time to work on the plugin until that task is done. However, I will mention a few weaknesses (other than blindly assuming YV12 format pixels) I see in the code, in order of difficulty. (1) The average luma is computed by looking +/- N frames from the current frame (settable as a parameter). It starts its average from either frame -N or the most recent scene change before the current frame. It ends its average either at frame +N or at the frame before the last scene change before frame +N. This is all perfectly good unless there is more than one scene change detected after the current frame. This is cured by adding one "break;" after noticing a scene change after the current position, and is a very minor point. (2) Once the rolling time averaged min/max luma for the current frame is computed, the luma distribution is shifted to map to 16 .. 235. This is desirable for some purposes, other times mapping to 0..255 is desirable. Perhaps this should be a parameter. (3) The scene detection logic is very simple minded, although it probably works most of the time. The "min" and "max" luma for the frame are computed by ignoring roughly the outer 1% of the brightest/darkest pixels, so outliers don't have undue influence. If either the min or max for frame N has changed by more than a threshold value as compared to the previous frame, it is considered to be a new frame. This is probably pretty easy to produce false positives as well as false negatives. Just from thought experiments, no actual data gathering, I think this can be improved. Using changes in the min/max is OK, but the threshold needs to be higher to avoid false positives, at the expense of false negatives. We can add other tests to help fix this. Each frame in the averaging window has already exhaustively (and expensively) measured the luma histogram, but only the min/max are cached for the frame. It would be better save the whole histogram as well (only 256 ints). In addition to detecting whether the min/max changed significantly, with the histogram we could add tests for whether the mean (or median) has changed, and whether the autocorrelation between the histograms of successive frames has changed much. Further, rather than just considering whether frames n-1 and n correlate, look at the correlation for each successive pair. If there is a sudden change in the correlation it would be less prone to false positives. That is, even if the correlation changes a lot between frames n-1 and n, it is meaningful only if the correlation has been somewhat stable either before or after frame n. This will avoid a situation I've seen where in the middle of an ordinary scene the luma flashes rapidly up and down a few times. |
3rd November 2010, 06:45 | #45 | Link | |
Registered User
Join Date: Sep 2010
Location: Austin, TX
Posts: 40
|
new version of autolevels
Well, I couldn't resist, and I downloaded msvc++ 2010 express and set up virtualdub and avisynth on a virtual xp machine.
I now have a 0.4alpha version of autolevels. It fixes a couple small bugs, is probably measurably faster, supports yuy2, planar yuv, and interleaved rgb24/32 surfaces. Great. The problem is that I take this dll which works fine in the virtual 32b xp machine and bring it to my real windows 7 64b box. It is running a 32b version of avisynth and 32b version of virtualdub too. When I try to load my newly minted autolevels, I get this bland error: Am I overlooking something obvious, or is this where things start to get difficult? |
|
4th November 2010, 00:13 | #47 | Link |
Registered User
Join Date: Sep 2010
Location: Austin, TX
Posts: 40
|
kemuri-_9 -- you seem to be right. In the project properties for C/C+ code generation, I used to have "Runtime Library: Multi-threaded DLL (/MD)". Changing that to "Multi-threaded (/MT)" now allows my dll to run on my native machine.
However, the dll size went from 32 KB (similar to the size of the existing autolevels.dll) to a whopping 138 KB. Debugging info is disabled and optimization is enabled, as this is a release build. I tried comparing my .vcxproj file to a 2006-era .vcproj file (from AddGrain) to find the difference, but despite being related, I can't correlate many of the options. Are there any visual studio wizards that can spot the option which isn't set right? Meanwhile, I'll keep fiddling... code generation command line: /Zi /nologo /W3 /WX- /O2 /Oy- /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_USRDLL" /D "AUTOLEVELS_EXPORTS" /D "_WINDLL" /Gm- /EHsc /MT /GS /fprecise /Zc:wchar_t /Zc:forScope /Fp"Release\autolevels.pch" /Fa"Release\" /Fo"Release\" /Fd"Release\vc100.pdb" /Gd /analyze- /errorReport:queue linker command line: /OUT:"C:\jim\video\autolevels\Release\autolevels.dll" /INCREMENTAL:NO /NOLOGO /DLL "kernel32.lib" /MANIFEST /ManifestFile:"Release\autolevels.dll.intermediate.manifest" /ALLOWISOLATION /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /PDB:"C:\jim\video\autolevels\Release\autolevels.pdb" /SUBSYSTEM:WINDOWS /OPT:REF /OPT:ICF /PGD:"C:\jim\video\autolevels\Release\autolevels.pgd" /TLBID:1 /DYNAMICBASE /NXCOMPAT /MACHINE:X86 /ERRORREPORT:QUEUE |
4th November 2010, 00:49 | #48 | Link |
Compiling Encoder
Join Date: Jan 2007
Posts: 1,348
|
what are you asking a question about?
the size increase with statically linking in the MSVC runtime into the DLL is normal. the original size is small because it requires the use of an environment located MSVC runtime. personally though, a ~100KB increase from statically linking in the MSVC runtime is extremely small. |
4th November 2010, 04:21 | #49 | Link |
Registered User
Join Date: Sep 2010
Location: Austin, TX
Posts: 40
|
kemuri-_9 -- that is reassuring, but I have looked at a bunch of the other plugins on warpenterprises. some come with source code, fewer still contain their msvc project files. It seems that people do usually specify /MT (multithreaded) instead of /MD (multithreaded DLL), yet all of the dlls weigh in under 40KB. In the grand scheme of things an extra 100KB isn't a whole lot these days, but it still seems to indicate I have some setting wrong.
|
4th November 2010, 08:26 | #50 | Link |
͡҉҉ ̵̡̢̛̗̘̙̜̝̞̟̠͇̊̋̌̍̎̏̿̿
Join Date: Feb 2009
Location: No support in PM
Posts: 712
|
It depends on which parts of the runtime library you are using. As kemuri said, no need to worry about these few extra kilobytes. Older MSVC versions may also produce lighter binaries given the same settings.
__________________
dither 1.28.1 for AviSynth | avstp 1.0.4 for AviSynth development | fmtconv r30 for Vapoursynth & Avs+ | trimx264opt segmented encoding |
4th November 2010, 13:53 | #51 | Link |
Compiling Encoder
Join Date: Jan 2007
Posts: 1,348
|
you still have some debugging on with the /Zi compilation option, other than that i don't see anything.
after fixing that i would say that you're being overly paranoid about the filesize. most other plugins are not using msvc 2010 either, you could probably get a different (possibly smaller) filesize using an older verison. |
6th November 2010, 10:48 | #52 | Link |
Registered User
Join Date: Sep 2010
Location: Austin, TX
Posts: 40
|
Autolevels 0.4 released
It took a couple days, but I set up a web page for my version of autolevels, which is now revision 0.4
http://www.thebattles.net/video/autolevels.html There are a number of ways this filter could be improved, but for now I need to set it aside so I can get back to my 8mm film conversion project. If you have any ideas, criticisms, or or questions, I'll be monitoring this thread, or you can email me at the address located on the web page I've just set up. Edit 11/11/2010 I recommend not using this version, as the RGB path is too hacky, and the YUV path has only minor improvements over the 0.3 version. I'll release a better version soon. Last edited by frustum; 11th November 2010 at 11:38. |
8th November 2010, 16:45 | #55 | Link |
Registered User
Join Date: Dec 2004
Location: Terneuzen, Zeeland, the Netherlands, Europe, Earth, Milky Way,Universe
Posts: 689
|
I have done some testing with the modified filter.
In RGB color space, autolevels works like it should, now. Stretching the histogram to 0-255 is perfect. I have tested it with VDubs levels filter, just to be sure. The whites are a bit blown out both in YUY2 and in YV12 color space. The colors are much better in RGB color space, even if I convert back to YV12 afterwards. I have disabled the scene change detection because this sometimes fails and then we have unwanted level changes in the middle of a scene. The filter works fine without the scene change detection. It needs a few frames (set with FilterRadius) to re-adjust at scene change, but that's not a problem for me. I have even tried FilterRadius=20 and this gives a very smooth levels adjustment. Here are the test results, it is all transfered 8mm film. Please notice the big difference in the red channel! There might be some color shift, but I can live with that. Fred.
__________________
About 8mm film: http://www.super-8.be Film Transfer Tutorial and example clips: https://www.youtube.com/watch?v=W4QBsWXKuV8 More Example clips: http://www.vimeo.com/user678523/videos/sort:newest |
10th November 2010, 18:15 | #56 | Link |
Registered User
Join Date: Jan 2008
Posts: 12
|
I can confirm that stretching not working correctly in YV12. And also the red color problem described above. I used common VHS source not 8mm, not that it should matter..
Last edited by boondoggle; 10th November 2010 at 18:18. Reason: Stretching works in Yuy2 |
11th November 2010, 11:26 | #57 | Link |
Registered User
Join Date: Sep 2010
Location: Austin, TX
Posts: 40
|
Fred --
In your chicken picture, I'm not surprised that the whites are blown out, as they are a small percentage of the pixels. This is a feature of the algorithm that autolevels 0.3 uses, and which I didn't change in 0.4. The algorithm is to ignore the darkest and brightest 1/256th of all pixels (~ 0.4%) when determining the min/max luma for a frame. The intent is to avoid outliers in the distribution such that a stray noise pixels doesn't throw things off. If this feature didn't exist, if you had even one pixel with luma <= 16 and one with luma >= 235, autolevels would be a no-op. Perhaps the best approach for this would be to add a parameter which specifies what fraction of outliers to ignore, and have it default to 1.0/256.0 for backwards compatibility. Another approach would be to still ignore outliers, but to clamp them to 16/235. Any opinion on which is better? The color shift issue you see is no doubt due to the very hacky implementation of luma mapping for RGB I added. While it is infinitely better than what was there in 0.3 (which was to silently accept RGB as if it was YUV), it still leaves a lot to be desired. I spent only one evening on it and it seemed OK for the videos I tried, but I regret rushing it out now that I've seen some of the problems that occur. A great torture test is to try "somevideo.tweak(cont=0.05).converttoXXX.autolevels()" and see what happens beyond the expected heavy quantization. Tonight I tried some less hacky but still hacky schemes to do the luma mapping in RGB space while still keeping the RGB proportions (in the just release 0.4, each of r,g,b are clipped independently). They all suffered from different failing corner cases. So, I stole the yuv2rgb and rgb2yuv conversion routines from avisynth's guts (convert.h) and did the most direct code I could: one pixel at a time, convert rgb to yuv, remap the y using the same table I use in the yv12 code path, then convert back to rgb. That gives a nice image and isn't nearly as slow as I had feared it would be. If I go this route, I'd like to drop the "matrix" parameter, which I copied from the greyscale() filter. It is probably overkill as converttoyv12() from rgb is hardcoded for just one mapping function, not a choice of three. Overall, I recommend not using 0.4 and getting tied into rgb (mis)behavior that I will fix soon. BTW, I picked up this tip from a thread from a couple years ago. If you suspect that your components exceeding legal bounds, which is likely with autolevels' output, you can confirm it with limiter(), like this: autolevels.limiter(show="luma") Boondoggle -- Can you try your case with the 0.3 autolevels dll? I haven't changed yv12 processing, other than a very small fix to the scene detection logic. |
11th November 2010, 15:29 | #58 | Link | |
Big Bit Savings Now !
Join Date: Feb 2007
Location: close to the wall
Posts: 1,545
|
Many thanks for the polishing of autolevels, frustrum !
Yesterday i had a short play with your autolevels 0.4 Quote:
For high resolution stills I tend to let some 0.05% of pixels go clamped. For SD video it may be different and other people may have different needs, so it would be nice to have a luma range and a clamp percentage to specify. If we only could have autolevels controlling LaTo's Smooth Curve, Smooth Levels, Smooth Tweak, it would be awesome. Since steady histograms come out there I find myself wanting no more histogram "holes".
__________________
"To bypass shortcuts and find suffering...is called QUALity" (Die toten Augen von Friedrichshain) "Data reduction ? Yep, Sir. We're that issue working on. Synce invntoin uf lingöage..." |
|
11th November 2010, 22:56 | #60 | Link |
Avisynth Developer
Join Date: Jan 2003
Location: Melbourne, Australia
Posts: 3,167
|
The original code when used with RGB24 was almost doing the right thing (just wrong limits). In RGB each colour channel can range from 0 to 255. The colour depicted is related to the ratio of the R, G and B channels. This ratio must be maintained. You should just be looking for the Maximum and Minimum values of any channel and then scaling and biasing all RGB channels equally, the A channel should be ignored.
Like most filters that fiddle with brightness and contrast in YUV colour space we cheat and only process the Luma channel. The 2 chroma channels are not adjusted. The hue of the colour is related to the ratio of the U and V chroma channels. The saturation of the colour is related to the ratio of the U and V channels to the Luma channel. The luma only cheat may lead to noticable changes in saturation when the adjustment is not small. Expect different results when processing RGB compared to YUV. The RGB results can be strictly correct, the YUV results will be a compromise. You can see the effect easily in VirtualDub with the inbuilt Levels filter by toggling the "Operate in luma instead of RGB" option. And all YUV results should be the same. YV12 and YUY2 being different is a bug. |
|
|