Log in

View Full Version : New Filter: GrainOptimizer (2.02 -- Bug fixed with certain temporal denoisers)


Pages : [1] 2 3 4

Dark Shikari
7th October 2007, 06:44
>>>GrainOptimizer 2.02<<<

The only temporal-only grain reducer!

Simple summary:

This filter "slows down" the progression of grain over time to vastly decrease the bits required to encode that grain. On a per-frame basis, the filtered clip will look almost exactly the same as the original.

Pros: Huge bitrate drop over unfiltered clip (up to 40-50%+), and often higher image quality due to better bit distribution in encoding. Keeps the grainy look of the original source.

Cons: Temporal grain pattern isn't exactly the same as the original. Not as effective at lowering bitrate as a real, strong denoiser, if used alone. Less effective in very high-motion scenes; doesn't usually have negative effects but doesn't reduce the grain as effectively as in stationary scenes. Requires a powerful denoiser to input the denoised clip, so while fast alone, it isn't as fast in practice.

Full information:

One of the main problems with film grain is it is completely uncorrelated with the grain from the previous frame. This means that in low-detail blocks, such as the background of a frame (usually most of the blocks), the encoder is forced to use intra blocks instead of inter blocks, since the current frame's block is almost completely unrelated to the previous frame's block.

This filter resolves that by removing grain temporally but not spatially, in a manner in which the visual difference between the result and the original is minimal, and not even necessarily a negative difference. Using a combination of heuristics, it decides which areas of the frame should be acted on, and then which blocks should be retained between frames. As far as I have found in my testing, no visual artifacts are created by this technique as long as the proper heuristics are used.

This filter is somewhat motion-adaptive but not motion-compensated, and as a result it is quite fast (real-time on SD footage easily, even though it has no assembly code and is completely unoptimized). However, this also means it is not very effective in moving areas. This isn't really what the filter was meant to do to begin with though: its goal is to deal with background grain eating up bits, and that's what it does.

The end result is a basically "free" bitrate reduction of up to 50% at the same CRF/QP for high-grain sources, assuming that your bitrate is high enough that the encoder actually does attempt to preserve the grain--this is particularly important in x264, known for decimating grain at all but the lowest CRFs. Note that theoretically this filter will work for all encoders, not just x264--the benefits aren't as large in non-H.264 codecs, but both VC-1 and Xvid have shown bitrate drops of nearly 25% in my tests.

Note that you should have at least a few bframes and p4x4 blocks enabled to take full advantage of this filter. If it isn't clear at this point, the GrainOptimizer is intended as a preprocessing algorithm for a video encoder.

Syntax: GrainOptimizer(clip,denoisedclip,blocksize,strength,tdist,minrep)
Colorspaces supported: YV12 only (YUY2 and YV24 are possible in the future, RGB24/32 are not possible without drastically changing the algorithm.)

denoisedclip is the clip used for most of the internal heuristics and as such is very important. The better the denoiser you use, the better results you will get. A strong denoiser is recommended--losing details doesn't matter in this case, what matters is temporal stability. Inspect your denoised output if the filter doesn't seem to be working as well as it should; the denoised clip should have no noticable grain at all for maximum effectiveness. FFT3DGPU with a very high sigma (10+ for strong grain) + TTempSmooth works quite well, though I assume others like RemoveGrain(19) will work well also. Note this clip must be YV12.

blocksize is the size of the block (width/height) used for the block retention algorithm. 4 and 8 are the values currently supported, and 4 is the recommended default.

strength is by default 1 and is a decimal value. Note that as of version 2.0 the strength is automatically determined on a frame-by-frame basis--this number is simply a multiplier for the value determined internally. Don't change it unless the default has problems.

tdist is the maximum temporal distance, in frames, over which a block can remain static for due to the retention algorithm. It is by default 6: higher values will make the grain seem to move "slower", and lower values will make it seem to move "faster". A value as low as 2 will reduce the effectiveness of the filter somewhat but keep the grain's appearance almost exactly the same as the original. Higher values result in slower and slower grain, making it appear more like a static dither.

minrep sets the minimum number of grain replacements per macroblock. This is by default 8--higher values result in fewer blocks acted upon but more efficient action on those that are acted upon. Values cannot be above (256 / Blocksize^2) or below 0. The old behavior of the program, before this option existed, was equivalent to minrep=0.

Recommended: keep it at 8. Perhaps different values might be better with other codecs? Lowering the value will decrease efficiency but might make the result look more grainy.

This filter is experimental--report bugs and cases where it creates problems here, but don't complain about it doing so!

New version 2.02 (http://mirror05.x264.nl/Dark/force.php?file=./GrainOptimizer_2.02.zip)
New version 2.01 (http://www.mediafire.com/?5zgnzmp49gl)
Old version 1.2 (http://www.mediafire.com/?armdydnrwd1)

Version History:

2.02 -- Some temporal denoisers have very overly strong effects at scene changes, which tend to confuse the GrainOptimizer. This has been compensated for in most cases.
2.01 -- Bugs fixed with 2.0.
2.0 -- Rewrote over half the code. It now automatically determines the strength necessary on a frame-by-frame basis, to deal with changing grain patterns. The biggest change is that it requires a denoised clip as a second input, for much more accurate motion detection. Chroma option was removed for code simplicity.
1.2 -- Major improvements. Randomized starting array, resulting in slightly nondeterministic behavior but no "solid" appearance for the first few frames of an encode. A lot of improvements were made to considerably lower the bitrate by optimizing specifically for MPEG-4 ASP/AVC encoding styles and dealing with the residual costs of macroblocks. Additionally quality should be slightly improved, and some quality bugs fixed. New option added. Blocksize can now be 8, but is not recommended (though it should work).
Functional changes: the new version now should decrease bitrate on almost all input sources, including some reduction on already-denoised sources.
1.11 - Minor algorithm updates
1.1 - Major bugfix: GrainOptimizer now works correctly on longer sequences. Chroma heuristic added.
1.02 - Feature improvement: non-mod16 resolutions now supported.
1.01 - Minor bugfix: non-mod16 resolutions now correctly result in an error instead of a crash.
1.0 - Initial Release

Guest
7th October 2007, 06:48
What color spaces are supported?

Dark Shikari
7th October 2007, 06:52
What color spaces are supported?Added that info.

Adub
7th October 2007, 07:40
This certainly looks interesting. Do you mind if I ask were you go the 30% reduction numbers from? Just curious.

Unfortunately, I don't have any sources right now that would benefit from this filter, but as soon as I do, I will give it a try.

Unless you recommend using it on every single clip I might ever use? :)

woah!
7th October 2007, 07:52
mpc window crashes for me straight away :( script is ok without grainopt in it.

i see firsy frame and then mpc just closes itself with no error message.

check
7th October 2007, 08:00
I confirm it works.

@woah, are you running `GrainOptimizer()`?

Dark Shikari
7th October 2007, 08:09
This certainly looks interesting. Do you mind if I ask were you go the 30% reduction numbers from? Just curious.

Unfortunately, I don't have any sources right now that would benefit from this filter, but as soon as I do, I will give it a try.

Unless you recommend using it on every single clip I might ever use? :)
The 30% reduction is the max I got on some very very grainy sources given to me by Didee and Cruncher. The highest-motion, highest-detail sources with the least areas of flat background gave almost no improvement or none at all.

Adub
7th October 2007, 09:23
Huh. Good to know.

Theoretically, this might be a good filter for anime, no? They tend to have flat backgrounds and very little motion. I may have to try that out. I could also create some synthetic tests using addgrain() or something.

Ebobtron
7th October 2007, 09:28
@Dark Shikari
Thanks for the new filter.
With your filter in the AviSynth plug-in folder both VDub and avsFilmCutter crash without as much as a blink, wink or the famous request to phone home and tell mommy.

Both programs useAVSValue = env->GetVar("$PluginFunctions$");to load an AVSValue object full of the function names like "GrainOptimizer" and "GrainOpt_GrainOptimizer".

I am not much of a plug-in driver but as I remember it the trouble maybe in one of the following code examples. :)

// This is the function that created the filter, when the filter has been called.
// This can be used for simple parameter checking, so it is possible to create different filters,
// based on the arguments recieved.

AVSValue __cdecl Create_SimpleSample(AVSValue args, void* user_data, IScriptEnvironment* env) {
return new SimpleSample(args[0].AsClip(),env);
// Calls the constructor with the arguments provied.
}


// The following function is the function that actually registers the filter in AviSynth
// It is called automatically, when the plugin is loaded to see which functions this filter contains.

extern "C" __declspec(dllexport) const char* __stdcall AvisynthPluginInit2(IScriptEnvironment* env) {
env->AddFunction("SimpleSample", "c", Create_SimpleSample, 0);
// The AddFunction has the following paramters:
// AddFunction(Filtername , Arguments, Function to call,0);

// Arguments is a string that defines the types and optional names of the arguments for you filter.
// c - Video Clip
// i - Integer number
// f - Float number
// s - String
// b - boolean

return "`SimpleSample' SimpleSample plugin";
// A freeform name of the plugin.
}

:thanks:

Boulder
7th October 2007, 11:00
I can't get the dll to load at all.. I'm running WinXP SP2. Autoloading or LoadPlugin doesn't do the trick, with LoadPlugin I just get the error message "Cannot load grainopt.dll". When autoloading, the function GrainOptimizer is not available.

Daodan
7th October 2007, 11:23
Not working here either. The script loads in vdm, but when I try to scroll it crashes.
Been following the other thread about this filter and the examples seemed to be pretty good, especially considering x264 kinda detemporalizes the grain by itself at medium bitrates, so maybe this can do same thing while preventing other side effects x264 makes at medium quants (~21 and up).

Ebobtron
7th October 2007, 11:24
This filter is experimental--report bugs and cases where it creates problems here, but don't complain about it doing so!Sorry didn't see that or more like notice before. Ok, I promise. :)

I thought I should note that in addition to my above remarks, that the filter seems to work fine for me when using "loadplugin". And yes it is very fast.

Dark Shikari
7th October 2007, 11:32
I forgot something: BOTH WIDTH AND HEIGHT HAVE TO BE MOD16, and I forgot to check for this :rolleyes:

New version uploaded.

squid_80
7th October 2007, 11:51
The manifest seems to be missing from the .dll.

EDIT: or is it compressed? If so I'd suggest ditching the compression.

Dark Shikari
7th October 2007, 11:57
The manifest seems to be missing from the .dll.

EDIT: or is it compressed? If so I'd suggest ditching the compression.Its compressed using PECompact--whats the problem with it not having a manifest? It seems to load correctly.

squid_80
7th October 2007, 12:03
It seems to load correctly.
Apparently not for the four people who have already reported having problems. What's it compiled with?

Guest
7th October 2007, 13:25
I forgot something: BOTH WIDTH AND HEIGHT HAVE TO BE MOD16 That's a severe limitation. It doesn't have to be that way.

Dark Shikari
7th October 2007, 19:35
That's a severe limitation. It doesn't have to be that way.No, it doesn't, but the algorithm requires it. The only way to get around it is basically to pad the sides or similar. I could have my filter simply pad the sides, do the algorithm, and then unpad the sides, of course.

Wait... quick question. In x264, when a video isn't mod16, does it pad all sides of the video or just one? The problem is that if the macroblocks in the video are off from what my filter thinks are the macroblocks, the filter will be drastically less effective.
Apparently not for the four people who have already reported having problems. What's it compiled with?
VC++ 2005 Express.

I replaced it with a non-compacted version--try it out now.

Terranigma
7th October 2007, 20:04
Thanks for the new filter. It seems promising. :)

Boulder
7th October 2007, 20:37
I replaced it with a non-compacted version--try it out now.Nope, still won't load:(

Dark Shikari
7th October 2007, 20:54
Non-mod16 now supported. The algorithm just doesn't act on the extra pixels, simple as that.

Ebobtron
7th October 2007, 21:38
@Dark Shikari
Thank you,
With current version VirtualDubMod and FilmCutter start and id funcition names correctly. :) :thanks:
@squid_80If so I'd suggest ditching the compression.Do you have time to describe the relevant issue with the compressed version of the dll ? :thanks:

Mtz
8th October 2007, 01:28
I'm not good in avisynth, but I made a small test on a VOB source.
In the first 177 frames (the duration of a movie scene), the filter is working. At frame 178 and after this frame when the action of the movie is changed, the filter is not working anymore.
Screenshots:
Frame 177
http://i23.tinypic.com/10z7q85.jpg
http://i22.tinypic.com/if0kyu.jpg


Frame 178
http://i20.tinypic.com/1231p4x.jpg
http://i22.tinypic.com/28kuhpc.jpg

The first screenshot from 177 and 178 is the original.

enjoy,
Mtz

Dark Shikari
8th October 2007, 02:05
I'm not good in avisynth, but I made a small test on a VOB source.
In the first 177 frames (the duration of a movie scene), the filter is working. At frame 178 and after this frame when the action of the movie is changed, the filter is not working anymore.
Screenshots:
Frame 177
http://i23.tinypic.com/10z7q85.jpg
http://i22.tinypic.com/if0kyu.jpg


Frame 178
http://i20.tinypic.com/1231p4x.jpg
http://i22.tinypic.com/28kuhpc.jpg

The first screenshot from 177 and 178 is the original.

enjoy,
MtzYup, I found an algorithm bug dealing with the improper (lack of) resetting some internal arrays... fixing now.

rfmmars
8th October 2007, 03:48
Yup, I found an algorithm bug dealing with the improper (lack of) resetting some internal arrays... fixing now.

Here's what I am finding using it in AVS-p.........I only see a small numbers of pixals in the center changing shape. so this may be related to the other members post about after frame 177.

Richard

squid_80
8th October 2007, 04:02
@@squid_80Do you have time to describe the relevant issue with the compressed version of the dll ? :thanks:
Because it was compressed it wasn't telling the OS correctly about what .dll files it needed to run.

If anyone is still having problems install the Visual Studio 2005 SP1 Redistributable Package.

Dark Shikari
8th October 2007, 04:06
Here's what I am finding using it in AVS-p.........I only see a small numbers of pixals in the center changing shape. so this may be related to the other members post about after frame 177.

RichardYup, there is a MAJOR bug in the current version that drastically decreases its capability. I have a working version right now and I'm recording bitrate decreases of over 30% in some cases, and on longer clips also (the bug caused anything other than short clips to end up in uselessness). Updated version will be uploaded soon.

Dark Shikari
8th October 2007, 05:18
Results on Cruncher's source material, settings 4-25-10-true, 2484 frames, 1920x800, at CRF 18:

Without GrainOptimizer:
18301kbps
SSIM: 0.961

With GrainOptimizer:
13970kbps
SSIM: 0.959

This is with the new, fixed version. Uploaded and fixed :)

burfadel
8th October 2007, 05:57
Works great, the 4,25,10 setting is much more effective, or seems to be, than the default. The strength of 25 actually resulted in a smaller file size than that if it were set to 50! (only slight, 4kb on the clip I used but thats still significant). I did find a few other things, although this is with only testing on that one 30 second segment of video...

- It does not work well with other noise reducers. I tried a clip with a couple of different types, enabled and disabled, and with the grainoptimise above and below them. In all cases the grainoptimiser by itself seemed to be better... and resulted in a smaller file. The actualy quality would be better than the combined settings unless the source is chronic.

- The optimiser HAS to be run before the resize filter, not after. On the test clip I used having it before the resize filter increased its effectiveness close to 100 percent over that of when its placed after the resizer (its twice as effective if placed before). The clip Dark Shikari used for his test wasn't resized (from what I can tell), and hence he got his 30 percent effectiveness. I got 15 percent reduction with the filter right after the resizer (spline64resize) and 30 percent right before the resizer! :)

- Its quite fast, faster than most other noise reducers I've seen. Once optimised it will likely to be one of the fastest available! :)

Dark Shikari
8th October 2007, 06:18
- The optimiser HAS to be run before the resize filter, not after. On the test clip I used having it before the resize filter increased its effectiveness close to 100 percent over that of when its placed after the resizer (its twice as effective if placed before). The clip Dark Shikari used for his test wasn't resized (from what I can tell), and hence he got his 30 percent effectiveness. I got 15 percent reduction with the filter right after the resizer (spline64resize) and 30 percent right before the resizer! :) Now this is very interesting. I would have expected running it after the resize filter to be much better, since its meant to operate on the same macroblocks the encoder operates on. It would be interesting to figure out exactly why its so much better before the resizer. Perhaps because a resizer like Spline "spreads out" the effect of the grain a lot?

ToS_Maverick
8th October 2007, 10:35
i tested your filter with the suggested settings from above and got some artifacts:

normal, "optimized"
http://img73.imageshack.us/img73/6905/110origsmallzh2.th.png (http://img73.imageshack.us/my.php?image=110origsmallzh2.png) http://img522.imageshack.us/img522/5051/110optsmallbs6.th.png (http://img522.imageshack.us/my.php?image=110optsmallbs6.png)

http://img522.imageshack.us/img522/2149/330origsmallyg2.th.png (http://img522.imageshack.us/my.php?image=330origsmallyg2.png) http://img256.imageshack.us/img256/6541/330optsmallvj4.th.png (http://img256.imageshack.us/my.php?image=330optsmallvj4.png)

in the first example some horizontal lines got introduced, in the second example the background get's "optimized" away :D

Dark Shikari
8th October 2007, 15:24
i tested your filter with the suggested settings from above and got some artifacts:

normal, "optimized"
http://img73.imageshack.us/img73/6905/110origsmallzh2.th.png (http://img73.imageshack.us/my.php?image=110origsmallzh2.png) http://img522.imageshack.us/img522/5051/110optsmallbs6.th.png (http://img522.imageshack.us/my.php?image=110optsmallbs6.png)

http://img522.imageshack.us/img522/2149/330origsmallyg2.th.png (http://img522.imageshack.us/my.php?image=330origsmallyg2.png) http://img256.imageshack.us/img256/6541/330optsmallvj4.th.png (http://img256.imageshack.us/my.php?image=330optsmallvj4.png)

in the first example some horizontal lines got introduced, in the second example the background get's "optimized" away :DThat looks very good to me--what horizontal lines are you talking about? That looks like the filter actually made the result a bit sharper, which looks quite good IMO. Are these images after or before encoding?

Edit: Ah yes, I see the slight horizontal lines... I would suggest you use slightly weaker settings.

ToS_Maverick
8th October 2007, 15:29
first example the background wall, left of johnny's shoulder.

also there are 4x4 blocks during motion scenes, do you want a shot of it as well?

EDIT: oh, the images are from the avs-script, before encoding

Terranigma
8th October 2007, 15:33
I can attest to this as well. :stupid: What do you propose Shikari? This is coming from the default settings of just GrainOptimizer(). Perhaps you didn't thoroughly check the filter before submitting the newer build?

Dark Shikari
8th October 2007, 15:57
That looks really strange, because my code has something to specifically stop that sort of thing... can one of you upload a VOB/M2V sample for me to test on?

Mtz
8th October 2007, 17:55
Also bad encodes with the file from attachment. I uploaded the file to test yourself your plugin because I don't want to post here too many screenshots. On this source I think xvid encode will look better than x264 with or without grainoptimizer.
The vob is here. (http://www.mytempdir.com/2036161)

enjoy,
Mtz

Dark Shikari
8th October 2007, 18:03
first example the background wall, left of johnny's shoulder.

also there are 4x4 blocks during motion scenes, do you want a shot of it as well?

EDIT: oh, the images are from the avs-script, before encoding4x4 blocks.. can you please upload the source? I'll need to update my heuristic to fix this.

Dark Shikari
8th October 2007, 18:13
It seems some of the problems seem to be caused by using GrainOptimizer with another denoiser, which seems to always give negative results. I've noted this in the original post.

Sagittaire
8th October 2007, 18:40
Encoder like VC1 PEP or Cinevision encoder use particular HVS masking filter for grain: spatial/temporal filtering in dark area.

ToS_Maverick
8th October 2007, 19:04
@Dark Shikari:
here is a still active link (http://forum.doom9.org/showthread.php?p=1028047#post1028047) to the source.

as Sagittaire suggested, you could include something like that to x264, so that x264 behaves like XviD with grain, if somebody is interested in such behaviour. maybe the more you compress, the less random the grain gets.

burfadel
8th October 2007, 19:05
Now this is very interesting. I would have expected running it after the resize filter to be much better, since its meant to operate on the same macroblocks the encoder operates on. It would be interesting to figure out exactly why its so much better before the resizer. Perhaps because a resizer like Spline "spreads out" the effect of the grain a lot?

I did another lot of tests regarding this, and came up with the same result. Putting the grain optimiser right before the resizer always came up with a smaller file (I haven't checked the measured quality, my post is about final file size alone) - although the files seem identical.

This is not just confined to the spline64 resizer. I tried the spline36 resizer, Lanczos resizer (with 3 taps, 4 taps, and 6 taps), and Bicubic resizer. All of these were reducing the resolution of the encode. I also tried an encode with the enlarged, and still it came up with a better result with the grain optimiser before the resizer!

The difference isn't overly large, but there is a difference. On one encode it yielded a better difference than that of between using a Subme of 6 and subme of 7!

It may be because the resizer affects the grain in a negative way, reducing the effectiveness of the removal? ... I guess the only thing is to try it for yourself! lol

Terranigma
8th October 2007, 19:18
@Dark Shikari:
here is a still active.
Tos, are you using grainoptimizer after denoising? If so, then that's your problem.

ToS_Maverick
8th October 2007, 19:38
nope, no denoising.

Dark Shikari
8th October 2007, 21:10
@Dark Shikari:
here is a still active link (http://forum.doom9.org/showthread.php?p=1028047#post1028047) to the source.

as Sagittaire suggested, you could include something like that to x264, so that x264 behaves like XviD with grain, if somebody is interested in such behaviour. maybe the more you compress, the less random the grain gets.I'll try this source next and see if I can replicate the problem.

ToS_Maverick
8th October 2007, 21:36
thank you, that's the script i'm using for comparison:

DGDecode_mpeg2source("Black.Pearl.Sample.d2v", idct=7)
opt=last.GrainOptimizer(blocksize=4,strength=25,tdist=10,chroma=true).crop(4,58,712,360).LanczosResize(768,320)
crop(4,58,712,360).LanczosResize(768,320)
interleave(last,opt)

Dark Shikari
8th October 2007, 22:38
I've made some modifications but I'm not even sure if they're positive or not--I think the simple conclusion is that your source isn't grainy enough for the filter to be useful.

Dark Shikari
8th October 2007, 23:13
I managed to fix the main artifacting issues, but the main problem is with the source itself--its covered in artifacts! Look at the first frame that contains a close-shot of Orlando Bloom's face--its a complete mess of blocks.

Dark Shikari
9th October 2007, 00:59
Updated to 1.11 with some slight algorithm changes to fix some of the previously found artifacts. Here's a frame comparison with Elecard Streameye of a B-frame in a max-setting Mainconcept-encoded clip, at 12000kbps.

(click for full)

Key: Red/orange = intra, blue = inter, yellow = skip, green = direct

Without GrainOptimizer:

http://i22.tinypic.com/97pfkk.png (http://i22.tinypic.com/97pfkk.png)

With GrainOptimizer:

http://i24.tinypic.com/rmmlhz.png (http://i24.tinypic.com/rmmlhz.png)

:cool:

Terranigma asked me to do a test with artificial grain, so I denoised that same clip with mocomp'd fft3dfilter and then used addgrain(20,0.2,0.2). The result was 25 megabits at CRF18 without GrainOpt, and 14.5 megabits with GrainOpt, a massive difference. Moreover, GrainOpt actually looked slightly better--though the background grain moved slower, as a result more bits were available to keep the grain in moving areas, and so the grain looked much more accurate to the original (original output of the script that is) IMO.

Dark Shikari
9th October 2007, 04:59
A test on Xvid shows that the latest version decreases bitrate by 18% at CQ3 on max settings. an almost exactly equivalent decrease was measured in VC-1 on Quality 90 (15.2mbps -> 12.5 mbps).

burfadel
9th October 2007, 11:54
Anyone else found the optimsier works better (for example) right before the resizer instead of right after?