Log in

View Full Version : RemoveGrain


Pages : 1 2 3 [4] 5

Heini011
23rd March 2005, 11:00
hi kassandro,

i have an athlon xp and have the same problem. ssetools and the current RemoveGrain.dll doesn't work. RemoveGrainS.dll is ok.

system: win 2k, avisynth 2.55

VirtualDub Error

Avisynth open failure:
LoadPlugin: unable to load "C:\Programme\Avisynth 2.5\plugins\SSETools.dll"

greetings.

kassandro
23rd March 2005, 11:42
Originally posted by Heini011
hi kassandro,

i have an athlon xp and have the same problem. ssetools and the current RemoveGrain.dll doesn't work. RemoveGrainS.dll is ok.

system: win 2k, avisynth 2.55

VirtualDub Error

Avisynth open failure:
LoadPlugin: unable to load "C:\Programme\Avisynth 2.5\plugins\SSETools.dll"

greetings.
The Athlon XP certainly has floating point SSE. Thus the problem is a missing DLL. I think you need msvcp71.dll (but I am not sure about it). Until the end of 1004 I had Visual Studio 2002 and it required msvcp70.dll. As I have now moved to Visual Studio 2003 also the DLL has changed. Each version of the C++ compiler has its own DLL.

Probably the them is true for Bexley's Athlon Thunderbird.

Leak
23rd March 2005, 11:57
Originally posted by kassandro
The Athlon XP certainly has floating point SSE. Thus the problem is a missing DLL. I think you need msvcp71.dll (but I am not sure about it). Until the end of 1004 I had Visual Studio 2002 and it required msvcp70.dll. As I have now moved to Visual Studio 2003 also the DLL has changed. Each version of the C++ compiler has its own DLL.

Probably the them is true for Bexley's Athlon Thunderbird.

For those missing a DLL:

http://www.dependencywalker.com/ is a good tool to check for missing DLLs - it's free and it's not hard to use... :)

np: Funkstörung - Captured In Tones (ft. Sarah Jay) (Disconnected)

Bexley
23rd March 2005, 15:53
I may provide a version without checking for full SSE next weekend. It will of course crash if some of the floating point SSE filters is used, but they aren't yet documented either.
Thanks, kassandro. I checked and the DLL isn't my problem, so that would be awesome. :)

kassandro
23rd March 2005, 18:25
I have uploaded a new inofficial.zip. It contains a staticly linked SSEToolsS.dll.

@Bexley:
Did you copy several versions of SSETools in the plugin directory. Only one version of SSETools (in the future the SSE2 version will be called SSE2Tools and the SSE3 version will be called SSE3 Tools) and RemoveGrain should be in the plugin directory. Otherwise it is not predictable, which plugin is chosen be Avisynth. If the SSE2 or SSE3 is chosen, then Athlon32 owner will have troubles. Actually, the old SSETools did only check for integer SSE and not full SSE.

Bexley
24th March 2005, 17:49
Ugh... I have a big problem, then. :(

I only have one version of SSETools.dll and RemoveGrain.dll in my plugins directory. I wonder if some other plugin might be causing a conflict... I'll try removing all unnecessary plugins when I get home and see if that helps.

kassandro
24th March 2005, 20:51
Originally posted by Bexley

I only have one version of SSETools.dll and RemoveGrain.dll in my plugins directory. I wonder if some other plugin might be causing a conflict... I'll try removing all unnecessary plugins when I get home and see if that helps.
You also need Repair.dll from the official RemoveGrain.zip on www.RemoveGrain.de.tf (http://www.RemoveGrain.de.tf). I am sorry for that mess, but it will take a while until I can return to RemoveGrain.

Bexley
25th March 2005, 03:54
No joy. :(

I removed all unnecessary plugins and made sure I have the most current versions of everything, and VDub still throws an error. The only way to load a script is to remove SSETools from the plugin directory. Oh well.... I'm still having fun with LRemoveDust, so I'll keep playing with that for a while. ;)

kassandro
25th March 2005, 07:11
Originally posted by Bexley
No joy. :(

I removed all unnecessary plugins and made sure I have the most current versions of everything, and VDub still throws an error. The only way to load a script is to remove SSETools from the plugin directory. Oh well.... I'm still having fun with LRemoveDust, so I'll keep playing with that for a while. ;)
You may also use Didde's original version. It doesn't require LimitChange. YV12LUTxy is used instead. On the other hand it would be nice to know the reason for failure. Avisynth's error message are unfortunately not very informative.

kassandro
9th April 2005, 22:34
I just have uploaded a new version of my RemoveGrain plugin. It became necessary because in the thread http://forum.doom9.org/showthread.php?s=&threadid=91823
a bug in the YUY2 version of TemporalRepair was discovered. Rather than fixing the YUY2 code, I dropped the interleaved YUY2 support altogether and replaced it by planar YUY2 (this is the reason why I have included inofficial versions of SSETools, which contain the filters Interleaved2Planar and Planar2Interleaved). The above thread contains also a claim by scharfis_brain, that the deinterlacer RGDeinterlace contructed with RemoveGrain is a "superblurrer", which blurs static areas. This is false as the test scripts in the above thread show, but scharfis_brain is not willing to withdraw his claim.
I have added also new bob modes 15,16 which are slightly better than modes 13,14 but also slightly slower.
However, the most import change is the new mode 17. It is a denosing mode for truely progressive film only, just like modes 1-10. I really love it. When the very aggressive mode 4 doesn't destroy thin lines, mode 17 uses this mode for denoising. If mode 4 is destructive, then mode 17 denoises more conservatively such that thin lines are preserved. The first test results with a b&w video clip (3962 frames) are impressive:

no cleaning 32.463.010 Bytes
RemoveGrain(mode=8) 29.964.964 Bytes
RemoveGrain(mode=9) 29.994.246 Bytes
RemoveGrain(mode=17) 28.221.649 Bytes
RemoveGrain(mode=4) 28.043.482 Bytes

Thus mode 17 clearly beats my old favorite mode 8 and comes quite close to the very aggressive mode 4. Of course, these results have to be confirmed by more extensive tests. Mode 17 seems to be ideal for any kind of postprocessing as, for instance, in RemoveDust. Previously mode 4 was used for this purpose and to avoid excessive softness it had to be corrected by TemporalRepair. This correction is no more necessary with mode 17. Compression should improve slightly while softness is reduced.

There are also substantial changes for the Repair filter. Modes 5-9 have now become useful by including the center pixel. Mode 9 repairs all thin lines, mode 5 now behaves similaroutput files to mode 2 and modes 6-8 are between mode 5 and 9. Of course, if mode 9 is used in RemoveDust, it has negative impact on compression (are 5-20% larger). However, mode 9 is ideal for the new RemoveDirt. It is used for cleaning the non-static areas, which are identified by the filter RestoreMotionBlocks of the new RemoveDirt plugin, and keeps these areas quite sharp, while for the static areas Repair isn't applied at all. My first tests with this new RemoveDirt script function show slightly better compression than with RemoveDust (with Repair(mode=2)) with significantly sharper non-static areas.

scharfis_brain
9th April 2005, 23:09
The above thread contains also a claim by scharfis_brain, that the deinterlacer RGDeinterlace contructed with RemoveGrain is a "superblurrer", which blurs static areas. This is false as the test scripts in the above thread show, but scharfis_brain is not willing to withdraw his claim.

I dislike, when poeple do big assumptions like I
would lie about test results (1) or my will to answer again (2).

1) I now DLed the new version an now with the new version rgdeinterlace dosen't do the overall superblurring.
But with the versions before, it definitely did!
But now it also leaves some combing behind.
If you want to, I can send you the my all purpose test clip with this cute asian girl.

2) The only thing I saw was: superblurring.
no matter what I did. so I decided to gave up to discuss this and went to non-computerized holidays
(oh, and they were really nice. Driving my Folding bike and so :) )

And now, the day I am back at home,
you seem to have solved the blurring problem yourself.

Didée
10th April 2005, 02:01
Thanks for the new version, kassandro! Mode=17 was a good idea.

... I do have a question. One might call it a request.

These days I've come across an application where the following is desireable to do:

> IF { Repair(clip1, clips, mode=1) does change a pixel }
> THEN { apply Repair(clip1, clip2, mode=3) to that pixel }

where the actual values might change. Would it be possible to implement a version of RemoveGrain with a *pair* of modes as arguments, like e.g.

> TestRepair(clip1, clip2, TestMode, RealMode )

or perhaps (since RealMode > TestMode must be true anyways, and probably easier to integrate into the current framework of the plugin)

> TestRepair(clip1, clip2, mode, mode_offset)

Because, basically the operation is extremely simple. However, if it has to be simulated through scripting, things become annoyingly slow:

> test = Repair(clip1, clip2, mode=1)
> real = Repair(clip1, clip2, mode=3)
> test_diff = difference(source,test)
> test_diff = test_diff.binarize()
> MaskedMerge(source, test, test_diff)

This is pretty much work for a close-to-trivial operation. And to make things worse: In the given case of application, this operation has to be done several times (2, 4, 6 or even 8 times), and therefore is not really practical.
But I assume when done by a plugin itself, it should be breezingly fast, since all work is still done on 3*3 pixels only.

BTW, it's not intended for some obscure special operation. A nice & handy all-purpose application, probably of public interest, is what I have in mind ;)


EDIT:

Seems I hadn't my brain with me at 3 o'clock in the night.
Functionally, the description was correct, but I'm aiming at Repair(), not at RemoveGrain() ... :o

Corrected.

Boulder
10th April 2005, 08:43
I can't get the new RemoveGrain working.

SegmentedAVISource("e:\temp\captures\lapparit_2.avi",pixel_type="YUY2")
LeakKernelBob(order=1,sharp=true,threshold=10)
Interleaved2Planar()
RemoveGrain(mode=17)
Planar2Interleaved()


---------------------------
VirtualDub Error
---------------------------
Avisynth open failure:
RemoveGrain: only planar color spaces are supported
(E:\Temp\Captures\testi.avs, line 4)
---------------------------
OK
---------------------------

I also tried the SSE versions of the plugins but no luck.

kassandro
10th April 2005, 11:23
Since Boulder's problem can be answered quickly, I do it first. The posts of scharfis_brain and Didée will be answered in about an hour.

Boulder, if you want to use RemoveGrain (and all the other filters which do not accept interleaved color spaces) you have to use this filters with "planar=true". The reason for this extra work is explained in the section "Color Spaces" at the end of the RemoveGrain documentation. Here is the corrected script:

SegmentedAVISource("e:\temp\captures\lapparit_2.avi",pixel_type="YUY2")
LeakKernelBob(order=1,sharp=true,threshold=10)
Interleaved2Planar()
RemoveGrain(mode=17, planar=true)
Planar2Interleaved()

Boulder
10th April 2005, 11:27
Oh damn, missed that one:o Thanks, I've got some 4hrs of VHS sources to torture with a revised LRemoveDust;)

EDIT: To be 100% sure, could you confirm that this function is OK? (I left TemporalRepair out as you said it can be removed with mode=17)

function LRemoveDust_planar(clip input, int _mode, int "limit")
{
limit=default(limit,4)
repmode = 2
clensed = Clense(input,grey=true)
rep=Repair(clensed, input, mode=repmode, planar=true, modeU=-1)
rg = RemoveGrain(rep, mode=_mode, planar=true, modeU=-1)
return LimitChange(rg, input, limit)
}

YV12 input and the original chroma merged back after the function call, hence the greyscale mode and no Interleaved2Planar/Planar2Interleaved calls.

kassandro
10th April 2005, 13:02
@scharfis_brain:
I wanted to be a little bit aggressive but not offensive. Firstly, I never the said that you lied. Instead I claimed that you were wrong, which is a big difference. In the above thread I did concede that you were right, if the color space was not YV12. Actually, my own tests fail, if the ImageReader clip is not converted to YV12. Since your opinion has considerable weight (which is well deserved) in this forum, I wanted you to make some reasonable YV12 tests, in order to get rid of this "superblurrer" branding, which was justified then only for non-YV12. The YV12 code didn't change at all - at least as far as RGDeinterlace is concerned. As you didn't answer my latest contribution in this thread for quite a while, I did launch this little attack. The sole purpose was to make it clear, that your reputation in this forum will be reduced, if you are not able to withdraw from statements, which have turned out to be false. Unfortunately, I had to withdraw many times from some of my statements, because they were wrong. But it is better to withdraw from a statement rather than to hope that it will be forgotten.

As far as residual combs are concerned you are probably right. I would rather prefer to say that there are deinterlacing artifacts. Most smart deinterlacers exhibit some kind of artifacts under 400% magnification in Vdub. On the other hand, The compression results speak for themselves. If the residual combs or artifacts would be significant, these results would be impossible. I claim that except my earlier Deinterlacer AlignFields no other Deinterlacer, which doesn't blur static areas, comes even close to RGDeinterlace (I mean the iterated version of jstelly in the above thread) as far as compression is concerned.


@Didée:
There are three ways to implement your request and before doing it. Clearly the fasted way is to implement for any two modes a routine, which does exactly what you want. If you n modes, then this results in a whopping (n-1)*n routines. That is simply too much. Of course, you may do it for a few selected combinations. But for each mode I use a substantial amount of mmx/sse registers. In order, to avoid unpleasant reloading from the cache, I would have to do both modes simultaneously, which is currently not possible for most mode combinations, because there are not enough mmx/sse registers. This problem will be gone, once we have moved to the Athlon64 platform. On this platform, there are a whopping 16 sse registers, twice as much as we have now. Avisynth may well be the only occassion, where one could really use that many sse registers. Nevertheless, I would have preferred 8 256-bit sse registers instead of 16 128-bit registers.
Altogether I would say that this first and fasted solution to your request, is not feasible right now.
The second approach is to use only one mode but two input clips. If the pixel of the first clip is changed by the specified mode, then the pixel is replaced by the same pixel in the second clip, which may be processed with RemoveGrain(mode=secondmode) or something completely different. This approach is quite feasible right now and the memory access costs are twice as much as with the first approach. With this approach the execution time should be 40-80% longer.
And then there is a third very general approach. It is bases on a filter with three input clips. If the same pixel is different in the first and the second clip, then this pixel in the first clip is replaced by the same pixel in the third clip. This is similar to MaskedMerge, but instead of a mask it uses the difference of two clips. The memory access costs are now three times as high as with the first optimal solution. On the other hand, I can exploit SSE2 much better. Thus the execution time penalty should be only 50-90% with SSE2, if the frames are properly aligned.

Before implementing one of these solutions, some additional consideration are in order. The above "alternative" processing produces similar effects as thresholds. Didée, you and I, we are the only ones to stress repeatedly the principle "use as few thresholds as possible", because of threshold artifacts and there negative impact on compression. I therefore would suggest the following "smooth" version of your request: let y1, y2, y3 be the value of a pixel in three different clips and 0 < M < 256 a fixed constant (chosen as an Argument in the Avisynth script. Letting a = min(|y1 - y2|, M), then y1 is replaced by (y1*(M-a) + a*y3)/M. In other words, if the difference between y1 and y2 is very larger ( >= M ), then y1 is replaced by y3. If it is 0, y1 remains unchanged. Otherwise some "smooth" intermediate values are chosen. In this way, you clearly avoid the nasty threshold like effects. If M is a power of 2, i.e. 1,2,4,8,16,32,64,128,256, then such a general purpose filter can be implemented fairly efficiently with SSE2 being quite helpful.

Actually, in my first version of mode=17, I did implement the following: If for a single pixel mode=4 destroys thin lines, then use mode 1 for this pixel. Although about 2/3 of the mode 4 changes were done exactly the same way also by this unofficial mode 17, the compression results were shocking and this "threshold like" effect must be the sole reason for it. Earlier I was already quite careful, to avoid such effects in Repair and TemporalRepair.

kassandro
10th April 2005, 13:20
Originally posted by Boulder
Oh damn, missed that one:o Thanks, I've got some 4hrs of VHS sources to torture with a revised LRemoveDust;)

EDIT: To be 100% sure, could you confirm that this function is OK? (I left TemporalRepair out as you said it can be removed with mode=17)

function LRemoveDust_planar(clip input, int _mode, int "limit")
{
limit=default(limit,4)
repmode = 2
clensed = Clense(input,grey=true)
rep=Repair(clensed, input, mode=repmode, planar=true, modeU=-1)
rg = RemoveGrain(rep, mode=_mode, planar=true, modeU=-1)
return LimitChange(rg, input, limit)
}

YV12 input and the original chroma merged back after the function call, hence the greyscale mode and no Interleaved2Planar/Planar2Interleaved calls.
Yes, it is ok. Actually, Interleaved2Planar/Planar2Interleaved also support grey=true and then only the luma is processed (I didn't test it, though). Being purely temporal, LimitChange works also for
planar YUY2 as long as you do not specify values for LimitU, LimitV, which are different from Limit. LimitChange with LimitU=256 processes only the luma (at least I think so), but this works currently only with YV12. Once SSETools is moved to planar color spaces, it will do so also for planar YUY2, RGB24, RGB32. LimitChange will continue to support interleaved color spaces as well, because it costs only very little additional work. Because Interleaved2Planar/Planar2Interleaved is much faster than ConvertToYV12/ConvertToYUY2 (especially with grey=true), it would be nice if you would try it. Of course, if you use YV12, you don't need "planar=true".

Boulder
10th April 2005, 13:43
I think the culprit is RemoveGrain and it's YUY2 performance.

At first I tried feeding YUY2 in that function (with the appropriate changes, of course) and noticed that the process is considerably slower than converting to YV12, processing and then going back to YUY2 and merging the original chroma back. I didn't make any accurate measures, but the difference was something in the region of 25-30%.

I'll make another test as soon as my current encode finishes to verify this, I'll also do a compressibility and a quick artifact comparison between mode=4+TemporalRepair and mode=17 without TR.

Boulder
10th April 2005, 15:16
I did the tests and I'm puzzled:D

1)YV12->RD(17,4) operating in b/w->YUY2->MergeChroma : 0.37RT , 22 922 588 bytes
2)YV12->RD(4,4) operating in b/w->TemporalRepair->YUY2->MergeChroma : 0.35RT , 22 273 212 bytes
3)YUY2->RD(17,4) limiting chroma as well : 0.25RT , 26 192 444 bytes

What the heck happens with YUY2 input? I did the same chroma denoising in all cases so that can't cause the difference. The third case looks a bit noisier though.

Based on quick examination, there's not much difference between 1 and 2.

Didée
10th April 2005, 15:32
@ kassandro

Sorry, I had one stupid error in my last post: I meant to speak about Repair(), but somehow wrote RemoveGrain() instead ... probably it was too late in the night ;)

I've to think a little about your three suggestions, to not miss arising aspects.

But to make the task easier: Since in fact a clip shall be repaired by another one, the only modes in question are the modes 1 to 4, i.e. full evaluation of the 3*3 square. The higher "line" modes are of no use in this very case.
Therefore (and for the fact I've only little clue about that lowlevel coding you do ;)), I thought it should be not too hard to implement:

For each pixel being processed:

a = source
b = repair( mode = mode1 )
c = repair( mode = mode2 )

(b != a) ? c : a

In words: do two repairs, and if the first did something, use the second one instead.

Your lastly proposed, alternative method here is not suited, I think. What I'm actually doing is post-processing frames that have been motion compensated. Generally, Repair(MC_frame,orig_frame) does an awesome job in removing blocks in those places where MC has failed, and makes the MC'ed frame perfectly suited to be included in the aftercoming temporal processing. In fact, the "repaired" blocks become like the original, but with some sort of "noise-on-their-own", which is an side-effect that appears like a gift :)
The downside is: The MC'ed clip has to be Repair()'ed by at least mode=3, to sufficiently remove the block artefacts. But when working with a fixed mode=3, then all those areas where MC was successful are processed way too strong, and the end result of MC'ed denoising therefore turns out too soft, to not say blurry.

Currently, things like turning this (http://img156.exs.cx/img156/2999/01thenoise3hl.png) into this (http://img156.exs.cx/img156/3091/092xltsmc4au.png) are possibe: Insane amount of noise can be removed, and the result is *calm*. But when working on rather clean sources with only little noise, things get too soft if a fixed repair mode of 3 is used.

That's the problem I'm currently facing.

kassandro
10th April 2005, 19:43
Originally posted by Boulder
I think the culprit is RemoveGrain and it's YUY2 performance.

At first I tried feeding YUY2 in that function (with the appropriate changes, of course) and noticed that the process is considerably slower than converting to YV12, processing and then going back to YUY2 and merging the original chroma back. I didn't make any accurate measures, but the difference was something in the region of 25-30%.

25-30% of the frame serving process would be acceptable, but 25-30% of the encoding process would be a lot. If you use grey=true, then in both cases the same amount of pixels is processed in the same way. From this point of view, there should be no difference. However, in the planar YUY2 case 720 Y values are followed by 360 U Values, then 360 V values and then again 720 Y values, while in the YV12 case 720 Y values are followed by 720 Y values etc. (the clip width is 720). Thus in the planar YUY2 you have always an L1 cache miss at the end of each line, which you don't have in the YV12 case, but this slight L1 cache inferiority cannot cause such a huge performance difference. The YUY2 version uses also more memory, because the YUY2 frames are 33% larger than the YV12 frames. But with 512MB this should be irrelevant. There must be other causes.


1)YV12->RD(17,4) operating in b/w->YUY2->MergeChroma : 0.37RT , 22 922 588 bytes
2)YV12->RD(4,4) operating in b/w->TemporalRepair->YUY2->MergeChroma : 0.35RT , 22 273 212 bytes
3)YUY2->RD(17,4) limiting chroma as well : 0.25RT , 26 192 444 bytes

The difference between 1) and 2) is too high compared with the very short benchmark done by myself. Remember that in my benchmark mode 17 and mode 4 were compared on an equal footing. In your case, mode 4 was tamed by temporalrepair while mode 17 was not restricted and nevertheless the difference is higher on a percentage level. On the hand, denoising truely static areas doesn't impact compression very much.
Now the difference between between 1) and 3) is dramatic. There must be something wrong either on my side or on your side. You can check this with difference filter, my main debugging tool, which is included in SSETools. I suggest the following test:

difference(YUY2Filter(input).greyscale(), YV12Filter(input).greyscale())

If non-zero differences are reported to debugview something must be wrong. Note, that you can only compare clips of the same kind with difference (same color space, width and height). It would also be nice to post both scripts here.

kassandro
10th April 2005, 21:17
Originally posted by Didée
@ kassandro

Sorry, I had one stupid error in my last post: I meant to speak about Repair(), but somehow wrote RemoveGrain() instead ... probably it was too late in the night ;)

That was a good mistake. Because the main point was the same, only the setup was somewhat simpler, which probably made it easier for me to understand, what is going on.



But to make the task easier: Since in fact a clip shall be repaired by another one, the only modes in question are the modes 1 to 4, i.e. full evaluation of the 3*3 square. The higher "line" modes are of no use in this very case.

The modes 5-9 also inspect to the full 3*3 square, but the neighbours are only used only as line pairs. Modes 3 and 4 are poor, because they ignore the most important pixel, the pixel in the center. However, I can change this. Probably you want mode 3, because mode 4 simply repairs too much and even generates softness like RemoveGrain(mode=4). If you want strong repair, you should try mode=9. It is the sole Repair mode, in my upcoming RemoveDirt script function and so far I like what I see, though the real visual test will come, when I burn all these RemoveDirt videos on a DVD and watch it with my DVD player. My very brilliant but also very slow plasma screen is not appropriate for such tests.



For each pixel being processed:

a = source
b = repair( mode = mode1 )
c = repair( mode = mode2 )

(b != a) ? c : a

In words: do two repairs, and if the first did something, use the second one instead.

The general filter, which I have proposed as the "third approach" can be used also here. But you have here the same "either or". In your very specific case, however, I probably can do also the very fast version and it won't be much slower than mode=3 (of course the center pixel must be included as well). On the other hand, the disadvantages of an "either or approach" remain and although your denoising result in your two pictures is very impressive (you obviously didn't use boring change limiting), but you won't be fully rewarded by the compressor. To make my point more clear, let's say that you have two pixel, which are close too each other. For the first pixel Repair(mode=1) makes no change, while for the second Pixel it makes only a change of 1. Then the first pixel is not touched by Repair(mode=3), while the second may be massively changed by Repair(mode=3). In other words, through your filtering you introduce new discontinuities (you certainly remove also a lot of discontinuities) and this is simply not DCT friendly. Thus you always should avoid such "either or techniques" and replace it by "smooth transition".
[/B][/QUOTE]

Boulder
10th April 2005, 21:37
I did the difference test, and there is a substantial amount of difference between the two versions. This is the script I used:

AVISource("i:\lapparit_1.avi",pixel_type="YUY2")
AssumeTFF()
Trim(82655,121925).FadeIn(5).FadeOut(25)
KillAudio()
LeakKernelBob(order=1,sharp=true,threshold=10).AssumeTFF()
yv12=ConverttoYV12().LRemoveDust_planar(17,4).ConverttoYUY2()
yuy2=Interleaved2Planar().LRemoveDust_planar(17,4).Planar2Interleaved()
difference(yv12.GreyScale(), yuy2.GreyScale())

function LRemoveDust_planar(clip input, int _mode, int "limit")
{
limit=default(limit,4)
repmode = 2
clensed = Clense(input, grey=true)
rep=Repair(clensed, input, mode=repmode, planar=true, modeU=-1)
rg = RemoveGrain(rep, mode=_mode, planar=true, modeU=-1)
return LimitChange(rg, input, limit)
}

This is a snippet of the debug log:

[3420] [46] total difference = 1356, different pixels = 1101
[3420] [47] total difference = 10954, different pixels = 7634
[3420] [48] total difference = 35615, different pixels = 21908
[3420] [49] total difference = 56094, different pixels = 35110
[3420] [50] total difference = 88070, different pixels = 53263
[3420] [51] total difference = 118387, different pixels = 74082
[3420] [52] total difference = 152732, different pixels = 90588

The output of the YUY2 one looks rather odd. See these screenshots:
YUY2
http://www.saunalahti.fi/sam08/rd_yuy2.jpg
YV12
http://www.saunalahti.fi/sam08/rd_yv12.jpg
Similar behaviour occurs even if I set mode to something else than 17. Looks like chroma is screwed up somehow but there's difference in the luma channel as well. This can be seen when the original chroma information is merged back to both YV12 and YUY2 branches. The YUY2 version is less aggressive and leaves a slightly noisier video.

kassandro
10th April 2005, 22:37
Thanks for your test, Boulder. I see no problem with your script. The problem must be on my side. My first suspect is the YUY2 version of LimitChange. The low level routine is the same for both YUY2 and YV12, but I may have false arguments to the low level routine in the YUY2 case. Because Didee's LRemoveDust was based on YV12LUTxy, which unfortunately accepts only YV12 input, I could make comparisons only in the YV12 case.
I will make my own tests to reproduce the problem. I am too tired to make these tests now. If I am locked out by neuron2 tomorrow, I probably can say more.

kassandro
10th April 2005, 23:09
I just did reproduce the problem. My guess seems to be correct. I used the following script

function LRemoveDust_planar(clip input, int _mode, int "limit")
{
limit=default(limit,4)
repmode = 2
clensed = Clense(input, grey=true)
rep=Repair(clensed, input, mode=repmode, planar=true, modeU=-1)
rg = RemoveGrain(rep, mode=_mode, planar=true, modeU=-1)
return LimitChange(rg, input, limit)
}

input=MPEG2Source("input.d2v", cpu=4, ipp=false)
yv12=LRemoveDust_planar(input,17,4).ConverttoYUY2
yuy2=ConverttoYUY2(input).Interleaved2Planar().LRemoveDust_planar(17,4).Planar2Interleaved()
difference(greyscale(yv12), greyscale(yuy2), tolerance=4)

If tolerance=4, then the difference filter ignores differences <= 4. Note that limit=4!!!. If tolerance=4 then I get zero differences. If I lower the tolerance, then I get non-zero differences. Thus it is very likely that LimitChange messes up the clip. Since I did test the YV12 version, the problem must be in the YUY2 version. I will hunt this bug tomorrow more concretely. Now, if LimitChange messes up the clip, the encoding process slows down, because the input is less smooth. This would also explain the speed differences.

kassandro
11th April 2005, 09:10
I just have uploaded a new binary archive. It corrects a silly bug in LimitChange (contained in SSETools). I have also corrected a problem with Avisynth's PLANAR_ALIGNED flag in SSETools. The same problem is in Repair, TemporalRepair, MCClense, but it cannot cause damage. However, these filter may reject valid input clips because of this problem. Since there are no complaints, I will fix it later in version 0.8.1, which will improve Repair(mode=3) to include the center pixel, because Didee has a nice application of this mode.

Boulder
11th April 2005, 09:31
I still have the same problem with the fixed SSE2Tools.dll, I also tried SSETools.dll. The same script as above.

kassandro
11th April 2005, 10:09
Originally posted by Boulder
I still have the same problem with the fixed SSE2Tools.dll, I also tried SSETools.dll. The same script as above.

Sorry, I am really a fool. I simply ran the test with tolerance=4 and with this tolerance I had already zero differences before. I have to resume the bug hunt.

kassandro
11th April 2005, 11:24
Boulder, I hope that it's correct now.

Boulder
11th April 2005, 11:48
Yes, looks OK to me. The speed difference remains, YUY2 processing is ~30% slower but then again, there's 25% more data to process.

Chainmax
20th April 2005, 14:56
So the new chroma limiting LRemoveDust is now this:

function LRemoveDust_planar(clip input, int _mode, int "limit")
{
limit=default(limit,4)
repmode = 2
clensed = Clense(input, grey=true)
rep=Repair(clensed, input, mode=repmode, planar=true, modeU=-1)
rg = RemoveGrain(rep, mode=_mode, planar=true, modeU=-1)
return LimitChange(rg, input, limit)
}

? If TemporalRepair is removed from the script, shouldn't the new default limit mode be 17 instead of 4 so as to avoid unnecesary mistakes?

Boulder
20th April 2005, 15:02
Limit is limit, mode is mode. If you want to use mode=17, you could always set it in the function. Besides, that function is not for all purposes, it's for my YUY2 captures;) See the grey=true and modeU=-1 parameters, I only process the luma because I merge the original chroma back after the conversion YUY2->YV12->YUY2.

Chainmax
20th April 2005, 16:08
Sorry, I get mixed up with those. I know that the first parameter in LRemoveDust is the RemoveGrain mode, and since everyone seems to be using LRemoveDust(4,x), I assumed that was the default, and since the only default set to 4 is limit I concluded the wrong thing :o.

So, I could just use the old script and call it with LRemoveDust(17,2) then? Could repair cause issues trying to repair stuff that doesn't need repairing when using mode=17? Also, the inofficial plugins are no longer needed, right?

Boulder
20th April 2005, 16:22
You could try this for YV12, and (17,2) should be a good one to try:

function LRemoveDust(clip input, int _mode, int "limit")
{
limit=default(limit,4)
repmode = 2
clensed = Clense(input)
rep = Repair(clensed, input, mode=repmode)
rg = RemoveGrain(rep, mode=_mode)
return LimitChange(rg, input, limit)
}
You'll need SSETools from the latest RemoveGrain package. What comes to your question regarding Repair, the behaviour hasn't changed since the original function, that is, Repair deals with video that comes from brutal cleaning with Clense.

Chainmax
20th April 2005, 17:20
Oh, then it's TemporalRepair that deals with RemoveGrain's mode 4. So, what would be the effects of leaving its line on is using mode 17 instead of mode 4? By the way, aren't you forgetting the planar=true switches in the rep and rg lines?

P.S: from reading the penultimate page, it seems that you and kassandro have different results on wether M17 and M4+TR are really the same or not. Have you got any more tests? Maybe I can try testing it on my X-Men sample...

Boulder
20th April 2005, 18:05
Mode 17 should keep the thin lines whereas mode 4 is much more brutal. Putting TR would make the filter a bit less aggressive but I don't know if it would be noticable. The hard limiting already helps so I've left TR out with mode 17.

With YV12 input planar=true is assumed already so no need to put it there.

kassandro
21st April 2005, 10:48
Originally posted by Chainmax

P.S: from reading the penultimate page, it seems that you and kassandro have different results on wether M17 and M4+TR are really the same or not. Have you got any more tests? Maybe I can try testing it on my X-Men sample...
M17 and M4+TR are quite different. TR removes any changes made by m4, if there is no motion or temporal noise. This is necessary because m4 destroys thin lines, which the human eye simply doesn't like. M17, on the other hand, should preserve thin lines. Thus there is no need to apply TR. Of course, M17 effects also static areas.

Originally posted by Boulder
Mode 17 should keep the thin lines whereas mode 4 is much more brutal. Putting TR would make the filter a bit less aggressive but I don't know if it would be noticable. The hard limiting already helps so I've left TR out with mode 17.

M17 is remarkably close to M4 as the following script shows:

input=avisource("my.avi")
M17=RemoveGrain(input, mode=17)
M4=RemoveGrain(input, mode=4)
difference(difference(M17, input), M4)

Then for each frame first the difference between M17 and input and then the difference between M17 and M4 is reported in debugview. Thus M17 performs just like M4 as long as thin lines are not affected.
Keeping thin lines seems to be also the basic denoising strategy of digicams. I have two digicams, a Canon A70 and a Ricoh Caplio GX, which are antipodal. The Canon performs very aggressive denoising, while the Ricoh does a very poor denoising job. While the Canon sometimes shows very visable denoising artifacts, it is nevertheless always getting good reviews. The Ricoh, on the other hand, is getting battered for its noise performance in reviews.
Thus one should not minimise the changes with respect to the original, rather it all about deceiving the human eye. Of course, M17 generates also some softness, but it is not the destructive sofftness of M4.
I will perhaps write a scientific paper about the ideal properties of M17, because it involves some mathematical reasoning to actually show that thin lines preserved. This mode would be ideal for digicams.

Boulder
21st April 2005, 11:20
Originally posted by kassandro
Of course, M17 generates also some softness, but it is not the destructive sofftness of M4.

What I noticed when trying M17 in RemoveGrain only instead of LRemoveDust, is that it's way too blurry for my taste. In fact, M2 already started softening the image noticably. Since then, I've used M5 for DVD sources, M17 within LRemoveDust for captures and M2 for the rare MPEG4 clips I've processed.

kassandro
21st April 2005, 19:12
Originally posted by Boulder
What I noticed when trying M17 in RemoveGrain only instead of LRemoveDust, is that it's way too blurry for my taste. In fact, M2 already started softening the image noticably. Since then, I've used M5 for DVD sources, M17 within LRemoveDust for captures and M2 for the rare MPEG4 clips I've processed.
I'm quite surprised, that you see already softness coming from M2. If you look at the difference with the original, it is relatively small compared with M17. It would be interesting if you could post some pictures (with and without M17). Digicam manufacturers usually do some sharpening after denoising to get rid of softness. I usually turn off sharpening by chosing the softest mode, which also preserves the most details.

Boulder
21st April 2005, 20:09
I'll get some screenshots for you a bit later tonight. The difference between 2 and 5 isn't big but 2 appeared to affect the brightness of small objects which then looks like they were softened considerably. I can't explain it better but the screenshots should show the behaviour. The DVD I tested it on was Star Wars Episode 4 which has a sharp and clear video so it'll reveal any excessive detail loss well.

Boulder
21st April 2005, 21:22
All right, here are the screenshots. I didn't attach them to the post but posted the links, eight large pictures per post is not nice;)

Scene 1, original (http://www.saunalahti.fi/sam08/norg_1.jpg)
Scene 1, mode=5 (http://www.saunalahti.fi/sam08/mode5_1.jpg)
Scene 1, mode=2 (http://www.saunalahti.fi/sam08/mode2_1.jpg)
Scene 1, mode=17 (http://www.saunalahti.fi/sam08/mode17_1.jpg)
Scene 2, original (http://www.saunalahti.fi/sam08/norg_2.jpg)
Scene 2, mode=5 (http://www.saunalahti.fi/sam08/mode5_2.jpg)
Scene 2, mode=2 (http://www.saunalahti.fi/sam08/mode2_2.jpg)
Scene 2, mode=17 (http://www.saunalahti.fi/sam08/mode17_2.jpg)

The second scene shows that mode=2 affects small details a little too much whereas mode=5 is almost unnoticable.
The script contains only MPEG2Source and cropping the black borders off before RemoveGrain.

kassandro
21st April 2005, 22:25
Thanks, Boulder, for the pictures. I will discuss a few details tomorrow. In the first picture clearly the space ship gets softened a lot by M17. You see some slight softening already with M2, but it is much closer to the original then to M17. When I say "thin lines are preserved", then I have to add "but not the end points of these lines" at least for M17. Thus M17 may shorten thin lines by two pixels. If these thin lines are very short as in the fine details of the space ship, then details are lost. M2 even preserves the end points of thin lines. In my tests I always had longer thin lines, hair, for instance, but if a thin line is only 3 pixels long, only the pixel in the middle is safe, while the other two may be erased.

vcmohan
22nd April 2005, 03:31
Originally posted by Boulder
All right, here are the screenshots.

For experienced users the comparison may be understandable but for me to flit from one photo to other and remembering details is too much. Possibly horizontal stacking original with the intended compare image will be more easily appreciated. For one seeing the images individually I could not appreciate the differences.

Boulder
22nd April 2005, 06:03
Stacking them doesn't do much good because the images are large in resolution. Use IrfanView for example, or any other program that can do slideshows. That way you'll see the differences very clearly when switching fast from image to another.

kassandro
22nd April 2005, 07:56
Originally posted by Boulder
Stacking them doesn't do much good because the images are large in resolution. Use IrfanView for example, or any other program that can do slideshows. That way you'll see the differences very clearly when switching fast from image to another.
I have no problem to see the differences. In fact, Irfanview is my only picture viewer. It has the advantage, that one retrieve the exact RGB values of a pixel by clicking on it, which is quite important in order to make a very fine analysis.

Yesterday I mentioned, that M17 may destroy the two endpoints of a thin line. I must say also that Repair(mode=9) restores thin lines - but again without the two endpoints. Thus, if you have a moving white line with a black background, clense erases this line, Repair(Mode=9) restores this line without the two endpoints and M17 erases also the new endpoints. Thus altogether, you may loose 4 pixels with this kind of filtering. TemporalRepair would not help at all, because it restores only static areas and the line is moving. But, of course this is a rather exceptional situation.

However, in my view line shorting is only responsible for the smaller part of the softening. Most of softening of M17 and virtually all of the softening of M2 is due to the YV12 effect. If we apply these filters to the YV12 chroma the aggressiveness of these filters is quadrupling. All the edge softening should be caused by this effect. Already a conversion from RGB to YV12 softens the edges quite a bit.

I have used the lossless jpegcrop to extract some small parts of the original second picture for discussion.
In the first two pics you see how well M17 preserves thin lines. In the second you already see the line shortening effect a little bit, though.
http://home.pages.at/kassandro/pics/Boulder1.jpg http://home.pages.at/kassandro/pics/Boulder2.jpg
In the third, you can see quite a few small details, which are shortened by M17:
http://home.pages.at/kassandro/pics/Boulder3.jpg
Finally, in the fourth pic you a cluster of sprayed black pixels, which is softened strongly by M17, but the human eye will not really see this as a negative.
http://home.pages.at/kassandro/pics/Boulder4.jpg
You can't really do anything here, because these pixels look very much like noise. Any reasonable denoiser will do some destruction here.

Boulder
22nd April 2005, 12:33
Yes, I made similar observations, and that's why I've decided to stick to M5 followed by TemporalSoften(2,3,4,6,2) with DVD sources as they are usually already quite clean.

For analog captures LRemoveDust with M17 and limit 4 is a very good choice, it leaves just enough noise in the video to make it look good. My eyes stand slight (or even moderate) noise much better than oversmoothed video, this applies especially to human skin which looks horrible when there's even a slightest amount of smearing.

Chainmax
23rd April 2005, 05:18
kssandro: if Mode5 really is that similar to Mode2 while producing less smoothing, could Mode17 be altered so its secondary mode is based on Mode5 instead?

Boulder: it makes no sense for me to have two almost identical scripts, one for YUY2 and one for YV12, so I will use the following one for both cases:

function LRemoveDust_planar(clip input, int _mode, int "limit")
{
limit=default(limit,4)
repmode = 2
clensed = Clense(input)
rep=Repair(clensed, input, mode=repmode, planar=true)
rg = RemoveGrain(rep, mode=_mode, planar=true)
return LimitChange(rg, input, limit)
}

Boulder
23rd April 2005, 07:59
The reason why I have two functions is that the one I use for my YUY2 captures deals only with luma and is a little faster because chroma processing is disabled.

My process is to convert to YV12, use LRemoveDust, convert back to YUY2 and merge the original chroma information back. This way I get a lossless YUY2->YV12->YUY2 conversion and faster processing. I've tried feeding YUY2 data directly into LRemoveDust but it's a lot slower because the amount of data to process is 25% larger.

kassandro
23rd April 2005, 12:30
Boulder,
I initially wanted to release a new version of RemoveGrain, but I postpone to the next weekend to implement some ideas - mostly for Repair - to improve "thin line shortening" at least a little. I still don't understand, why YUY2 is so slow. On the other hand, I can reuse the low level functions for Interleaved2Planar(grey=true), Planar2Interleaved(grey=true), to extract the luma of a YUY2 frame into an YV12 frame with a random chroma and then the way back from an YV12 frame into a YUY2 frame with the chroma set to no color. Both routines should be much faster than ConvertToYUY2 and ConvertToYV12.

Boulder
23rd April 2005, 13:00
The speed difference is quite likely just because of the 25% of increase in the data that needs to be processed - as it probably means less cache (L1/L2) hits and a larger amount of memory and disk access, it's not surprising the difference can be 35%.

Your plan sounds interesting, hopefully I'll have some time to test it as I'll have a very busy month ahead with my studies as we have to design and implement a database :scared: If it works as planned, it should definitely be much faster since all the chroma processing can be forgotten, all that needs to be done is merging the original chroma back.