Avisynth: Wavelet denoising?
After someone (blackprince?) posted a link about it I studied some references about wavelet noise reduction and it seems really promising.
The idea is the following (very simplified): At each level of a Wavelet transform, you split the image in two components: a "blured" component (low-pass) and a "detail" component (high-pass). If you look at the "detail" component, most of it should be zero, except where you have, well, details: edges, textures. When you have noise, instead of mostly zero, you have random small amplitude points (the noise) with the higher amplitude edges and textures. If you "gate" this "detail" component so that these small points due to noise are zeroed and the higher amplitude edges and textures are kept untouched, and then combine it with the "blured" component, the noise is killed but the edges and textures are as sharp as before! This is unlike traditional smoothing where all high frequencies are attenuated, and by the time noise is killed the edges and textures are also smoothed... Besides removing normal "white" noise, it is also impressive at removing block noise if your source is a low bitrate AVI or MPEG file :) One nice feature is that you can try to estimate an "optimal" threshold automatically from the variance of the "detail" component. I have programmed an implementation of it in Delphi (that works with still images), I'll try to translate it to C and compile as a AVISynth filter. (the original filter documentation is in Japanese and it won't work with my old Pentium II :(, it needs SSE). |
Hi GFR,
Is there a reference model or a definition in C, C++ ? I'm interested in looking at that 8) -kwag |
You can find some C/C++ or Matlab libraries on the web (try it in Google).
While there are many different wavelets you can try (each one with its pros and cons) the wavelet I'm trying to code is a very simple algorythm called "lifting". It's like this: 1) Split the image in two sub-images, one with the even colums, the other with the odd columns (the first column is column 0). 2) Make the odd image = odd - even. The odd image is now a high pass in the horizontal direction (note: it can be negative). 3) Make the even image = even + odd div 2 This makes the even image a low pass in the horizontal direction. 4) Split each of the two subimages into even and odd lines, and now calculate odd-odd as a high pass in horizontal and vertical directions ("corners" detail), odd-even is high pass in H and low pass in V (vertical edges), even-odd is low pass H high pass V (horizontal edges) and the even-even is a lower resolution version of the original image. 5) If you want you can run the even-even image through the algorythm again for another level of the transform and so on. You can estimate the variance of the noise using the highest resolution odd-odd image, because it is problably mostly noise. The median of the aboslute deviation to the median is said to be a good estimative. Now "gate" all the detail images with x=0 if abs(x)<thresh x=x-sign(x)*thresh if abs(x)>=thresh Or any other gating function you want (this one avoids creation of false oscillations). Use the thresh=k*(variance of the noise), k from 2 to 3 should be good enough (the optimal k is subject of many researches). You can also try a different thresh for each subimage. The inverse transform is straightforward, just make even=even-odd div 2, odd = odd+even and interleave the even with odd. Good things: 1) very fast, few operations, can be all integer. 2) no need for extra memory, the calculations can be in-place (you don't actually split the images just keep track of the pointers) Bad things: it's not the smoothest wavelet around and it is not the one that best decorrelates the low freq coeffs from the high freq ones. I hope the Delphi code is working today, I can post it to you if you want it. |
Hi GFR,
Sure!, post it. I would be nice if it can be ported to C. My Pascal (Dephi) programming is very (VERY) rusty, but I should be able to read the code and do an un-optimized working port to C, and then worry about optimizations. It would be very interesting if this would complement SansGrip "Blockbuster" filter :wink: -kwag |
Just the forward transform - I'm debugging the backward transform.
It seems long but it's repetitive and can problably be optimized. Nothing special, only you have to be careful so that you know which index is pointing to what! Code:
procedure TForm1.Button1Click(Sender: TObject); |
|
Hi kwag
Below: http://www.cs.kuleuven.ac.be/˜wavelets/ you can find a C++ wavelet library and some nice articles. I'm afraid you need some background in signal/image processing to understand these. |
Quote:
You're right :) I can read and write code, but I've never gone into signal processing ( DSP's, etc. ) algorithm's that deep :roll: To many things I want to do, not enough time :D The most I've done in digital coding is generating a Golay (23,12) encoder in software, using a 6522 PIA (Peripheral Interface Adapter ), for test encoding on paging equipment ( circa 1985 8O ) . Some info related to what I had to deal with here: http://www.math.uic.edu/~fields/Deco...roduction.html And that was ~15 years ago 8O . After that, my programming has been in the communications field ( more of I/O control, some embedded stuff ,etc ) but not on video. So I have a lot to learn, before I can start applying my programming concepts in this field ;) -kwag |
Re: wavelet denoising
Quote:
|
Hi SansGrip,
SansGrip wrote: Quote:
helps: http://www.kvcd.net/forum/viewtopic.php?t=1440 -black prince |
References:
http://www.cs.kuleuven.ac.be/˜wavelets/ Some publications, a C++ package. You can find the articles below with google: IEEE TRANSACTIONS ON IMAGE PROCESSING, VOL. 9, NO. 9, SEPTEMBER 2000 Adaptive Wavelet Thresholding for Image Denoising and Compression S. Grace Chang, Student Member, IEEE, Bin Yu, Senior Member, IEEE, and Martin Vetterli, Fellow, IEEE On Denoising and Best Signal Representation Hamid Krim, Senior Member, IEEE, Dewey Tucker, St´ephane Mallat, Member, IEEE, and David Donoho DE-NOISING BY SOFT-THRESHOLDING David L. Donoho Department of Statistics Stanford University Multimedia Applications of the Wavelet Transform (PHD thesis) Claudia Kerstin Schremmer Maarten Jansen pieflab - matlab package, some articles |
Copy this and paste in the browser's address bar (without http:// )
www.geocities.com/gfr.geo/smooth-lift.gif This looks horrible :( but it is very clear to illustrate the concept. I'm using the integer lifting wavelet (lazy wavelet) , then CLIPPING the high level details instead of killing the low-level details. Since this particular wavelet produces blocks when you eliminate details, it's very easy to see which portions of the the picture are "smoothed" (in fact "blocked") and which are kept intact. With a better choice of wavelet this can be a good selective edge blur filter. |
Experimental Avisynth wavelet filter
I threw together a quick filter using the algorithm posted above. I hope I got it right (it seems to reconstruct the image fine, but I'd be grateful if someone could check the source against the description of the algorithm). Currently it only does one pass, and only operates on luma.
You can specify a threshold for each of the detail components. See the readme for usage. Doesn't seem very effective to me, with low thresholds not really touching the noise and higher ones making the image blocky. Is this because it only does one pass? How many passes would be good to be effective against noise? Or is it just not a very good type of wavelet? If so, what would be more suitable for denoising? Incidentally, what would happen if one were to apply this to even/odd frames instead of pixels? |
Re: Experimental Avisynth wavelet filter
Quote:
I tested the wavelet filter. But as you said, the lower the values, the lower the filtering. But I still can see the artifacts. If I increase the values, they just get blured, but they are still present. I believe because it is applied on the input stage of the encoder, it won't be as usefull as if it was applied on a output stage of an encoder. Which in this case ( TMPEG, CCE, etc. ) , it's impossible to do. If the encoders had a "Pre filter" hook stage and a "Post filter" hook stage to plug filters, then I believe it would work on the output stage, just as it does on the still images samples presented earlier on this thread. Just my thought :roll: -kwag |
Re: Experimental Avisynth wavelet filter
@kwag, GFR, all:
Quote:
Theoretically speaking wavelets should be a very good technique for denoising. There are several key features of noise that I've identified: 1) Low amplitude 2) High frequency 3) Random The key features of the details we want to keep are: 1) Low amplitude 2) Mostly low frequency 3) Non-random Because dumb spatial/temporal softeners usually only pay attention to the first feature of noise (the characteristic low amplitude), they usually annihilate details too (because they're also low amplitude). In order for a filter to remove noise and nothing else, it needs to answer the following questions: Low amplitude? No -> Skip Low frequency? Yes -> Skip Random? No -> Skip Replace with (possibly weighted) average Only if all tests pass should the pixel be considered influenced by noise. Step 1 is easy, because low amplitude just means "how much does the actual value vary from the average?" If a lot, it's high amplitude. If very little, it's low. Step 2 is tricky in that it involves some kind of transformation of the signal. Generally to perform frequency analysis on a signal one must transform it into the frequency domain, i.e. using Fourier techniques. These are a pain to code and slow to run. The nice thing about wavelets is that they let you (with varying effectiveness based on the particular wavelet used) isolate the high-frequency and low-frequency parts of the signal without jumping through too many hoops. They're both (usually) easier to code and faster than Fourier methods. Step 3 is either very easy or very hard, I've not really thought about it enough yet ;). Randomness is the defining factor of noise, though, and it's becoming my opinion that any truly non-destructive denoiser must measure the (temporal) randomness of what it thinks is noise. Simply being within a variance threshold is not sufficient. Another complicating factor is motion. To properly account for motion it's necessary to use motion compensation (aka motion estimation), which is a very tricky thing to code. Motion adaption -- as used in NoMoSmooth -- is a step in the right direction, though it might be rendered redundant if the three steps outlined above are effective. Anyway, that's a summary of my thoughts over the last few days trying to improve NoMoSmooth. Differentiating between noise and detail is very hard, but wavelets might open an avenue to solving the puzzle. I'd be very interested to hear about various wavelets and their strengths/weaknesses, preferably without too many mathematical details, at least initially ;). |
Re: wavelet denoising
Quote:
|
Couldn't a FFT filter be used to get rid of those?
|
Quote:
|
Hi SansGrip,
This is not related to wavelets, but it might be worth a look. I found this in the file readpic.c, after studying some sources originally by the MPEG Group, and modified by John Schlichther as used in his program "AVI2MPG1". Here's the code: /* Settings for the softfilter: Maybe these should be adjustable from the commandline, but Tolearance 10 and Filtersize 6 are good defaults. - Tolerance: An absolute value (on a scale from 0 to 255), which determines, if the colour diffence should be exposed to filtering or not. This value needs to be bigger than the image noise peak to peak value. All small stuctures in the image, that have a contrast of less that this value are filtered down and might get lost. - Filtersize: The array used for every pixel for filtering. The larger this value is, the stronger the filter is, but also the longer will filtering take. doubling this value will take four time longer for filtering. */ const int Tolerance = 10; const int Filtersize = 6; #define MAX(a, b) ((a)>(b)?(a):(b)) #define MIN(a, b) ((a)<(b)?(a):(b)) /* Softfilter is an advanced blur filter, that will not blindly soften everything in the image, but will look at all pixels around the pixel to be modified, and will only use these pixels, that have almost the same value. By this simple rule, it will not soften down sharp edges, but only adjacent pixels of almost the same color. The effect of this is dramatic. It can eliminate almost all noise in large single colored areas of the image, without significantly decreasing sharpness in other areas, where there is high contrast. The code is not really highly optimised, but it produces good results. If you need speed badly, you can either not use it, or use some inline assembler. I assume, you should be able to get quite a speedup from using assembler, but I guess there is not more than 20% speedup possible by using C techniques. Thomas Hieber (thieber@gmx.net) */ void softfilter(unsigned char* dest, unsigned char* src, int width, int height) { int refval, aktval, upperval, lowerval, numvalues, sum, rowindex; int x, y, fx, fy, fy1, fy2, fx1, fx2; for(y = 0; y < height; y++) { for(x = 0; x < width; x++) { refval = src[x+y*width]; upperval = refval + Tolerance; lowerval = refval - Tolerance; numvalues = 1; sum = refval; fy1 = MAX(y-Filtersize, 0); fy2 = MIN(y+Filtersize+1, height); for (fy = fy1; fy<fy2; fy++) { rowindex = fy*width; fx1 = MAX(x-Filtersize, 0) + rowindex; fx2 = MIN(x+Filtersize+1, width) + rowindex; for (fx = fx1; fx<fx2; fx++) { aktval = src[fx]; if ((lowerval-aktval)*(upperval-aktval)<0) { numvalues ++; sum += aktval; } } //for fx } //for fy dest[x+y*width] = sum/numvalues; } } } Regards, -kwag |
Quote:
Unfortunately it's also significantly slower than just doing a straight average because you have to check each pixel within the radius to see if it's inside the threshold. |
Site design, images and content © 2002-2024 The Digital FAQ, www.digitalFAQ.com
Forum Software by vBulletin · Copyright © 2024 Jelsoft Enterprises Ltd.