PDA

View Full Version : PixieDustPP by Didée (was: Dust and blocks, or making dust even slower)


mg262
30th June 2004, 13:58
Edit: Go down here (http://forum.doom9.org/showthread.php?p=727667#post727667) to get Didée's new script, which alleviates a lot of the quirks of PixieDust.
________________________________________________________

Original (very old) post...

For those of you that can bear to spend the time, I've found that the following is quite effective against the artefacts of dust on a very noisy source:

Split the source into four copies, shifted like this:

a=last
b=crop(2, 0, -2, 0)
c=crop(0, 2, 0, -2)
d=crop(2, 2 ,-2, -2)

Dust each one separately, and recombine. (For the source in question, which is extremely noisy, I use peachsmoother on the result.)

The most annoying thing about the process is that you can't run multiple copies of dust in one script. I had thought that 2.55's dllname_functionname calling syntax might allow you to get round the problem by duplicating the dust DLL, but I can't get that the work. (See here http://www.avisynth.org/AviSynthPlugins for the calling syntax.)

I've resorted to using a preprocessing script, four dust scripts and a combining script, but usually one of the dust scripts crashes. I doesn't anyone knows of a lightweight program that will duplicate the Vdub direct stream copy (or even ->huffy) but that retries a script if there's a crash?

Malcolm
30th June 2004, 14:13
well, i guess that's because of some global variables in Dust.
if we only had the sources of Dust... :rolleyes:

can you provide some screenshots that shows which artefacts are eliminated by using dust this way?

how do you combine the 4 results of Dust?

A workaround to the inability to call Dust multiple times could be the following:
- don't crop but shift the 4 clips. (crop + addBorders) -> same size
- append them together to one clip
- call Dust
- split them to their original length (trim)
- combine them

like this you have called Dust only once.

Greetings,
Malcolm

Didée
30th June 2004, 15:00
Yep - it was scharfis_brain who came up with that nice little idea yesterday. "Scharfi for President!" :D

I was suspicious if it would work, because Dust still has to access the same frame multiple times. But now I can confirm: yes, this method indeed works!

Just be reminded that you have to keep your frame at a resolution of MOD16 horizontal and MOD8 vertical - otherwise Dust will give you nice artefacts. Pink ones, mostly ;)

And more: by adding black borders in order to keep MODs, Dust's ME will most likely fail to use the border blocks as references. Padding the borders with mirrors of themselves before cropping is - still not optimal, but supposingly better than adding black borders.

- Didée

mg262
30th June 2004, 15:09
I tried the idea on the assumption that dust divided the screen into cells and found the best match for each cell in the previous frame by motion compensation... so that cells did not necessarily match up on boundaries. So removing a couple of pixels from the left (say) shifts the cell boundaries, and averaging removes the boundary affect

I haven't put that very well, but what I mean is that I was hoping that the artefacts (squares) in each version would be slightly offset so that averaging them basically cancelled them out. Whether or not that explanation is correct, the process certainly seemed to yield a benefit.

A workaround to the inability to call Dust multiple times could be the following: ...

That is a good idea! Thanks.

The noise is mostly a sense of squares appearing in disappearing over time, so it's hard to see the difference in a static shot, but I'll try and find one that shows it and post it up later...
I will post screenshots in a bit, although it's

mg262
30th June 2004, 15:12
Didee - just caught your reply. So that's where the pink junk comes from! Luckily I'm going to be cropping everything anyway, so it doesn't matter too much about the border effects.

Does anyone have any idea what size blocks dust works with? I found it hard to tell from stills... offsetting by 2 was really just a guess.

Didée
30th June 2004, 15:42
Accidentialy, I've made myself a little function some time ago :)

Function BorderMirror( clip clp, int "hh", int "vv")
{
hh = default( hh, 8 )
vv = default( vv, 8 )

top=clp.crop(0,0,-0,vv)
bot=clp.crop(0,clp.height-vv,-0,-0)

stackvertical( top.flipvertical(),clp,bot.flipvertical() )

left=last.crop(0,0,hh,-0)
right=last.crop(last.width-hh,0,hh,-0)

stackhorizontal(left.fliphorizontal(),last,right.fliphorizontal())

return last
}

Just call "BorderMirror()" to expand all sides 8-pixel-wide with mirrors, or call i.e. "BorderMirror(16,16)" to define the width & height on your own.

BTW, I like to use this function for visualizing if my general cropping is tight enough, or if there are any serious artefacts around the borders in the source itself. If so, they become much more obvious this way.

***

I think Dust uses 8-pixel cells internally. (But don't nail me down on that!).

Then, I think you can get a pretty nice artefact reduction already with only 2 offsetted sources, instead of 4. Just in case you're in a hurry :D
In that case, make the 2 copies offset by 2 pixel horizontally + 2 pixel vertically. Speak, offset them diagonal to each other.

And my final note: Although I know about these artefacts, and usually find them myself in my encodings, I hardly can spot any of them when actually watching my stuff as a normal spectator ;)


- Didée

mg262
30th June 2004, 16:01
Alternate idea for multidusting:

The order in which function names take precedence is as follows:

1. user-defined function (always have the highest priority)
2. plugin-function (have higher priority than built-in functions - they will override a built-in function)
3. built-in function

Inside those groups the function loaded at last takes precedence, there is no error in a namespace conflict.


Assuming that this documentation should read "last" rather than "at last", it should be possible to load a copy of the DLL and thus effectively reinitialise it... I'm going to try when this (very slow) vdub job finishes.

Didée - thanks again. I'm going to try changing the offset to 4 and seeing how that looks in a bit...

Wilbert
30th June 2004, 16:04
And my final note: Although I know about these artefacts, and usually find them myself in my encodings, I hardly can spot any of them when actually watching my stuff as a normal spectator :)
Could someone post a bunch of screenshots with these artefacts?

Soulhunter
30th June 2004, 18:57
Originally posted by Wilbert
Could someone post a bunch of screenshots with these artefacts?
Source

http://img39.imageshack.us/img39/8705/Source_1937.jpg


PixieDust

http://img39.imageshack.us/img39/7882/PixieDusted_1937.jpg

____________________

Source

http://img39.imageshack.us/img39/7717/Source_2481.jpg


PixieDust

http://img39.imageshack.us/img39/9579/PixieDusted_2481.jpg

____________________

Source

http://img39.imageshack.us/img39/6875/Source_3564.jpg


PixieDust

http://img39.imageshack.us/img39/1387/PixieDusted_3564.jpg

Didée
30th June 2004, 21:41
Yes, that's exactly the kind of problem.

BUT:

(Ah, one more chance to go into lenghts about my beloved Dust :D )

Soulhunter, I'm pretty sure you've called PixieDust(limit) with a relative high value for "limit". Greater than 2 or 3, that is.

There's one *VERY* important thing about Dust's "limit" parameter - and a assume many people are not aware of it:

The "limit" parameter of Dust is NOT a conventional threshold as used in most other filters! Exclamation!

Most conventional filters use thresholds in the meaning of:

IF ( |test_pixel-reference_pixel| <= threshold )
THEN do_processing
ELSE do_nothing

Or in words: only do any processing if the neighbor pixel is not more different from the center pixel than (threshold).

Now ... Dust works different than the rest of the world. It uses no thresholds at all - at least not any that we know of.

The "limit" parameter describes how much any pixel may be changed maximally.

I.e. when calling PixieDust(limit=2), than no pixel will be changed more than +/- 2 maximally.
There is no reason of upping the "limit" in order to catch more noise. Dust will always reckognize all noise it is able to reckognize, no matter what value for "limit" one sets.

And in fact, a limit of "2" is fully sufficient for most sources. "1" is not a ridiculous low value - it is a very good value for "calming down" the noise, for people that prefer to let some noise in the source for encoding. "3" is already suited for strong noise, IMHO.
And the more you allow it a pixel to change, the stronger the artefacts, and the higher the risk to get them.

(Heavy noise as i.e. in analog capturing is another story - but that's the domain of GoldDust, not PixieDust. Think about the name: if the noise has a "per-pixel-characteristic", then you need ... which Dust flavour?)

Now, if anyone thinks "limit" would be a "normal" parameter, and uses it in some "normal" range like 4~~7, then ... he gets blocking for no benefit.

Personally, I use PixieDust with a limit of "2" in 99% of all cases. And I have very little problems with blocking. ;)

End of schoolmastering (sorry). But if at least one person out there in the wide world has had an "AHA!" effect now, then it was worth it.


- Didée

niiyan
30th June 2004, 21:44
An idea for multidusting.

1.Use two (or more) DustV5.dlls.

Put original DustV5.dll in your plugins' directory, and copy it into another directoy.

or

Rename DustV5.dll (eg.Renamed_Dust.dll). In this case, you can place this renamed dll in your plugins' directory, even though there is also original DustV5.dll, too.


2.Make the function for multidusting and use it like this:


#LoadPlugin("your_directory\DustV5.dll")
AviSource("hoge.avi") #your source
SeparateFields()
even = SelectEven().FaeryDust(...)
odd = SelectOdd().MultiDust(...)
InterLeave(even, odd).Weave()

function MultiDust(clip clip, int "limit", string "output")
{
LoadPlugin("another_path\DustV5.dll")
#or
#LoadPlugin("(maybe)your_directory\Renamed_Dust.dll")
clip = FaeryDust(clip, limit, output)
return clip
}


You use original dll for even field, and copied dll in another directory (or renamed dll) for odd field, by calling it in your function.

Soulhunter
30th June 2004, 21:59
Originally posted by Didée
Soulhunter, I'm pretty sure you've called PixieDust(limit) with a relative high value for "limit". Greater than 2 or 3, that is.
No, I used the default values -> PixieDust()

But to tell the truth, I dont know what are PixieDust's defaults... :o


Bye

Didée
30th June 2004, 22:15
Originally posted by Soulhunter
But to tell the truth, I dont know what are PixieDust's defaults... :o
Dust Version 5 by Steady 01/23/2003

New parameters added. All are optional.

output="YUY2/RGB/RGB32/RGB24"

The default is to output the same format as the input. RGB is the
same as RGB32. Dust works internally on YUV 4:4:4 planar
(One Y,U, and V for each pixel). Future versions may have the option
of working in RGB space.


-------------------------------------

limit=5

Sets the strength of the temporal filtering. (How much it can change the
original pixel).Note that high settings (> ~8) will be 'overridden'
by other internal settings. The default settings are:

FaeryDust 2
PixieDust 5
GoldDust 8
SpaceDust Does not apply

-----------------------------------------------------------------------

FaeryDust uses temporal filtering only. It should preserve the maximum
detail. (Not really true yet with strong settings but will be :)
Recommended limit settings 1-5

SpaceDust is just the spatial filter from PixieDust. It is for those
who want the April version speed from Dust now :) It can improve the
visual quality quite a bit. However unlike PixieDust, It can only reduce
noise - not remove it. So the compression gains (and compressed quality)
will be less.

PixieDust is essentially FaeryDust + SpaceDust (with some twists). It is
probably the best to use for medium noise and those who shoot for
1-CD encodes. Recommended limit settings 3-8.

GoldDust uses heavier filtering. Not really very developed yet.

mg262
30th June 2004, 22:27
Didée - I always work with VHS captures, some of which are very noisy... I spent a couple of weeks last Christmas testing every smoother I could get my hands on and dust was definitely the best.

I typically use Pixiedust at 5 (& yup, I know what limit is) because beyond that the artefacts become very noticeable. That won't clean off all the junk, but using another smoother (spatial?) at light settings fixes most things.

I haven't seen much difference between Golddust and high values of Pixie, but I haven't looked extensively -- if you think Gold is better, then I'll run another set of tests...

Soulhunter - those clips are brilliant and show the effect much more clearly than anything I have. Is any chance you could try the 4xdust method on the first of those clips for comparison? (Or I'll do it if you like.)

kassandro
1st July 2004, 06:15
Originally posted by Didée
The "limit" parameter describes how much any pixel may be changed maximally.

I.e. when calling PixieDust(limit=2), than no pixel will be changed more than +/- 2 maximally.

Changing a pixel only by 2 is virtually invisible. Even changing it by 10 is hard to see. Thus your interpretation of the limit parameter cannot be correct or I simply misunderstand you.

Didée
1st July 2004, 13:03
Originally posted by kassandro
Changing a pixel only by 2 is virtually invisible. Even changing it by 10 is hard to see. Thus your interpretation of the limit parameter cannot be correct or I simply misunderstand you.
My interpretation were correct if it was one. But that's exactly what Dust does, and what Steady is mentioning in the readme - so it is no "interpretation".
You can easily verify this by taking the difference between the source and source.dust(x) - the maximal difference will be +/- x. Maybe with some outliers.

Of course, such small differences are very hard to see - *generally*.
But, if you run it with a limit 5 (default), then the maximum possible delta in two neighbor blocks is 10 - and on flat, gradient-like areas, this results in the mentioned problem. Check Soulhunters screenshots.

edit: What Dust would need is an internal postprocessing step, similar to what you are doing in RemoveDirt, kassandro. A pity that Steady didn't do that.

- Didée

Malcolm
1st July 2004, 13:22
Does anyone know what's up with the Author (Steady)? Why has he stopped development? Why didn't he release the sourcecode to the public? Why has he left the forum?

Greetings,
Malcolm

kassandro
1st July 2004, 17:31
Didée,
you would be right, if for a whole line there would be difference of 10 between neighbouring pixels, then you would see blockiness like in Soulhunter's screen shots. However, if he really cleans everywhere, but with change limitation to avoid artifacts, then blockiness would hardly be possible. Blockiness is possible, if he would use dct/idct filtering like trbarry, or he would clean only some blocks, like RemoveDirt, which has no change limitation, or if he would use a block rather than a pixel dependent cleaning routine. For me personally change limitation is a very primitive kind of artifact protection, because such kind of cleaning has very little effect on sharp dirt. On the other hand, change limitation can be nicely combined with minmax clipping, which I employ in RemoveDirt. Consequently I could get a temporal change limited cleaner with 200-400 fps on my 1.3 GHZ Celeron, which doesn't require any deblocking. It should be very similar to Faerydust.
Now spatial cleaning is a very different subject. Firstly, there are the convolution based denoisers, which I deeply hate. Secondly, there is trbarry's dct filter and vaguedenoiser, which seems to use a dwt (= discret wavelet transform) instead of dct. Unlike convolution based filters these filters are based on very sound mathematical ideas. Nevertheless they do not make sense to me, because any advanced codec does such kind of filtering all the time and in a more compression efficient way. Thus instead of using such filters one should better raise the quantiser of the codec. Then finally there is trbarry's Undot, which uses some kind of spatial minmax clipping. This is a fast, simple, virtually artifact free, spatial denoiser, which makes sense for any progressive clip but unfortunately takes out only very little noise. I pushed the idea of Undot a lot further and RemoveGrain is the result. An inofficial release can be found by searching for RemoveGrain in this forum. It is stable but slow. The official release will be SSE turbo charged. Because of the above variety Pixiedust's spatial cleaning method is hard to guess, but temporally with change limitation (change limitation does not make sense for Undot like denoisers) I can certainly do better.
Dust was written before Avisynth went yv12. As we can read from the above documentation, it converts internally the interleaved yuy2 color space to a planar color space, processes the frame and then converts it back to yuy2. Thus yv12 would have been the ideal color space for Dust, because all these conversion would not have been necessary.

Soulhunter
1st July 2004, 18:31
Originally posted by mg262
Soulhunter - those clips are brilliant and show the effect much more clearly than anything I have. Is any chance you could try the 4xdust method on the first of those clips for comparison? (Or I'll do it if you like.) Cant get it work... :(

# Multidust AVS

Function MultiDust(clip clip, int "limit", string "output")
{
LoadPlugin("C:\Programme\AviSynth 2.5\x\dustv6.dll")
Clip = PixieDust()
Return clip
}


LoadPlugin("C:\Programme\AviSynth 2.5\plugins\dustv5.dll")
Import("C:\Programme\AviSynth 2.5\x\Multidust.avs")

mpeg2source("C:\Blah\test4.d2v")

SeparateFields()
Even = SelectEven().PixieDust()
Odd = SelectOdd().MultiDust()
InterLeave(even, odd).Weave()

mg262
1st July 2004, 19:45
What's the error message? Should it be

Clip = clip.PixieDust()

?

I wasn't really talking about fields, but this...


a = Pixiedust(5)
LoadPlugin("C:\Capture\AviSynth 2.5\plugins\old\Dust2.dll")
b = crop(2, 0, -2, -0).BorderMirrorH(2).Pixiedust(5)
LoadPlugin("C:\Capture\AviSynth 2.5\plugins\old\Dust3.dll")
c = crop(0, 2, -0, -2).BorderMirrorV(2).Pixiedust(5)
LoadPlugin("C:\Capture\AviSynth 2.5\plugins\old\Dust4.dll")
d = crop(2, 2 ,-2, -2).BorderMirror(2,2).Pixiedust(5)
ab = layer(a, b, "add", 127, 2, 0)
cd = layer(c, d, "add", 127, 2, 0)
layer(ab, cd, "add", 127, 0, 2)


which does work, with bordermirror as above (Didée) and BorderMirrorH having the obvious meaning.

Mohan

Soulhunter
1st July 2004, 20:27
Originally posted by mg262
What's the error message?
Only a "error in module blah-blah n' some dizzy numbers that tell me nothing" message... :D

Does it work for you ???


Bye

mg262
1st July 2004, 20:33
It essentially works... at least, this does:


Function MultiDust(clip c, int "limit", string "output")
{
LoadPlugin("Dust2.dll")
Clip = c.PixieDust()
Return clip
}

avisource("e:\cp\boat in sun.avi")

SeparateFields()
Even = SelectEven().PixieDust()
Odd = SelectOdd().MultiDust()
InterLeave(even, odd).Weave()

Soulhunter
1st July 2004, 20:56
@ mg262

Ok, I solved the problem... ;)

I will post some MuliDust samples later!
____________________

@ Didée

The effect is much less annoying now!

But It is still visible... :\


Bye

Soulhunter
1st July 2004, 21:28
Sorry, but the MultiDust processing seems not to look much better... :(

IMO even a bit worse !!!


Source

http://img13.exs.cx/img13/1729/Sourcey_3564.jpg


PixieDust

http://img12.exs.cx/img12/1387/PixieDusted_3564.jpg


MultiDust

http://img12.exs.cx/img12/7606/MultiDusted_3564.jpg


Bye

Soulhunter
1st July 2004, 21:45
Only a small n00b'ish play-around... ^^


Blah1 = LanczosResize(1024, 576).PixieDust().LanczosResize(720, 576)
Blah2 = LanczosResize(720, 1024).MultiDust().LanczosResize(720, 576)
Layer(Blah1, Blah2,"fast")

http://img17.exs.cx/img17/8079/LayerDust_3564.jpg


Bye

niiyan
1st July 2004, 22:33
Originally posted by mg262
I wasn't really talking about fields, but this...
I wasn't talking about fields, too... MultiDust is an idea to run multiple copies of dust in one script. My code is only a sample how to use MultiDust script. I don't know how it's effective to blocks.

Didée
2nd July 2004, 11:09
There is a very simple key to the "problem". I just found it.

Wait a little.

(to be edited]

edit: (while uploading screenshots)

I think I'll stop with these "hold your breath - this post will be edited" posts. Everytime someone springs in, so that I JUST have to make a new post, to keep the thread's flow. Well, I'm just too slow, I assume ;)

To mg262 (post below):

Your efforts are without any effect! You crop left/right 4 pixels andthen add 4 pixels again left/right. The respective for vertikal.
That's not the way to shift a frame around ...


- Didée

mg262
2nd July 2004, 12:58
Didée - waiting eagerly.

Soulhunter - by multidusting, I didn't mean separating fields, etc (which produces 8*16 blocks instead of 8*8, which is why yr Multidust shot looks worse). Is there any chance you could try the script I posted (with 4s instead of 2s as below...):

a = Pixiedust(5)
LoadPlugin("C:\Capture\AviSynth 2.5\plugins\old\Dust2.dll")
b = crop(4, 0, -4, -0).BorderMirrorH(4).Pixiedust(5)
LoadPlugin("C:\Capture\AviSynth 2.5\plugins\old\Dust3.dll")
c = crop(0, 4, -0, -4).BorderMirrorV(4).Pixiedust(5)
LoadPlugin("C:\Capture\AviSynth 2.5\plugins\old\Dust4.dll")
d = crop(4, 4 ,-4, -4).BorderMirror(4,4).Pixiedust(5)
ab = layer(a, b, "add", 127, 4, 0)
cd = layer(c, d, "add", 127, 4, 0)
layer(ab, cd, "add", 127, 0, 4)

Edit:

Didée - d'oh - I'm being a complete idiot, as you point out. In the original post I had the above w/o BorderMirror, which did of course result in some very pink borders!

Didée
2nd July 2004, 14:53
Well, to draw the conclusion right at the start:

I won't lie it away - Dust indeed produces blocking on its own. But by far *not as much* as it is mostly supposed to produce!
In fact and in contrary, a lot of the produced blocking does not show a weakness of Dust - it shows (alas) how good its denoising is!

There were several points that made me wonder - e.g.

(1) Why do I get so much less blocking than other people who are reporting the issue?
(2) Why did e.g. Wilbert ask "what blocks are you guys talking about", despite having tested Dust thoroughly (capture & denoising comparison)
(3) Why is it sometimes so obvious, and sometimes it is no issue at all?


The miracle's solution:

For a big amount of those blocks it is not Dust who is responsible, but ... THE SOURCE!

I came to the conclusion that indeed Dust's denoising is sometimes so good, that after its processing, blocks already present in the input source suddenly become visible - beforehand, they were only hidden by the noise. (!)

Then, we still have the fact of Dust producing blocks on its own. Here comes the second problem:

Block Alignment.

If the source is a) not resized and b) either not croped at all, or cropped at MOD8, then Dust's own blocking potential will fall together with the revealed blocks from the source. This is where the blocking becomes really obvious and annoying.

I experimented a little, and found out that the "overall" blocking gets indeed noticeably less if the source frame is shifted to be no more block-aligned, before feeding it to Dust.

Here are three screenshots. Please note that I have currently no source on this PC that shows the problem *really* good (the worse the source, the more obvious the problem) - so I made two small tricks to emphasize the problem.
Below I'll post a script, which can be used to track the problem. (Also, find the two "emphasizing tricks" commented in it.)


Source:
http://img40.exs.cx/img40/3981/ttt_source.png

PixieDust(5), block-aligned:
http://img40.exs.cx/img40/3941/ttt_dust_normal.png

PixieDust(5), offset by 4 pixels:
http://img33.exs.cx/img33/1647/dust_offset4.jpg


Obvious, isn't it? There are blocks in the offset-4 frame, too - but they are much less in number, and in strength as well.

That everyone can test this for her/himself, this script may come handy:
Mpeg2Source("I:\_UnderWork\LOTR_TTT\_DVD1\vts_01.d2v",idct=7) #,cpu=4,moderate_h=45,moderate_v=55)
crop(8,80,-8,-80,true)

# I activated the following to worse the blocking already present in the source:
#mergeluma( dctfilter(1.0,.0,.0,.0,.0,.0,.0,.0), 0.0626 )

orig=last
length=framecount(orig)
orig_8 = orig.addborders(8,8,8,8)
off_4 = orig.addborders(4,4,12,12)

temp = orig_8 + off_4
dust = temp.converttoyuy2().PixieDust(5).converttoyv12()
dust_blockaligned = dust.trim(0,length).crop(8,8,-8,-8)
\ .subtitle("PixieDust, block-aligned", size=12)
dust_offset_4 = dust.trim(length, 0).crop(4,4,-12,-12)
\ .subtitle("PixieDust, 4 pixels offset", size=12)

# Compare all simultaneously:
stackvertical( orig.subtitle("Input source", size=12).addborders(orig.width/2,0,orig.width/2,0)
\ ,stackhorizontal(dust_blockaligned, dust_offset_4 ))

# Compare one after another:
#interleave(orig.subtitle("Input source", size=12), dust_blockaligned, dust_offset_4 )

# I activated the following to quickly emphasize blocking in all output images:
#sharpen(1.0)

return last


Finally, the obvious answers to the 3 questions at the beginning:

(1) Not only that I mostly use small limits for Dust - very often I process Mpeg-2 input with PP settings like those (outcommented) in above script. This lessens the blocking of the input, and therefore for Dust, too.

(2) Wilbert is, AFAIK, mostly doing analog capturing. Hence no DCT blocks on the input, hence no problem through Dust. Simple as that.

(3) Obvious. Dust after resizing - little problems. Dust after cropping "through" DCT cells - little problems. Dust after cropping "on" DCT cells - potentially big problems.


Lastly, I've made a Wrapper-Function for PixieDust, that works around this block-alignment problem. I'll post it within short time, if no contradicting objections come up.


In case I've made an error or have drawn false conclusions, please point it out.

Thanks to mg262 for bringing up the topic again, and also to everyone contributing into this thread. It's always nice to finally improve on a long-term issue. (Although I'm really ashamed that I didn't find out this one earlier).
The power of the community.


- Didée

Didée
2nd July 2004, 16:01
The Wrapper-Function for PixieDust. It should behave exactly like the original function, except for the "output=colorspace" option. (I was too lazy- is anyone using that at all?)

An additional benefit is, that one needs to worry no more if the clip's actual size is MOD16/MOD8 or not - the input gets padded accordingly, if needed.

Actually, this function runs about ~3% slower than the original. No wonder, Dust has to process a bigger image, because of the padding. (So this time, it's not "Didée & his slow scripts" :p )

Hope i didn't forget anything.

function PixieDust2( clip clp, int "limit" )
{
lim = default(limit, 5)
ox = clp.width
oy = clp.height
xcorr = int( 16. - ox%16 - 4. )
ycorr = int( 8. - oy%8 - 4. )
top = clp.crop( 0, 0,-0, 4).flipvertical()
bot = ycorr > 0
\ ? clp.crop( 0,oy-ycorr,-0,-0).flipvertical()
\ : top
ycorr > 0 ? stackvertical( top, clp, bot)
\ : stackvertical( top, clp)
left = last.crop(0, 0, 4,-0).fliphorizontal()
right = xcorr > 0
\ ? last.crop(ox-xcorr,0,-0,-0).fliphorizontal()
\ : left
xcorr > 0 ? stackhorizontal(left,last,right)
\ : stackhorizontal(left,last)

clp.isYV12() ? ConvertToYUY2() : NOP
PixieDust(lim)
clp.isYV12() ? ConvertToYV12() : NOP
crop(4,4,-xcorr,-ycorr)
return last
}


- Didée

mg262
2nd July 2004, 16:38
Didée, you're a genius. That would also explain why (working only with analogue sources) I see only very subtle effects.

Mohan

MrTibs
2nd July 2004, 22:21
I've been using Dust on my analog tv captures for some time and have noticed the blocks there also. There seems to be be some "total movement" threshold that causes the blocks to increase suddenly. The effect is worse on frames that have static or near static areas along with fast moving areas. (i.e. someone walks in front of the camera or looking out a car window)

To get around this problem I've used 2DClearner (at low levels) before Dust to remove some of the noise. It seems that by removing some of the noise first, Dust is able to do a proper temperal blend and nulify the negative effects of 2DCleaner.

To further stabilize the frame, I use an experimental filter called StaticFreeze that freezes static parts of the frame of long ranges. (Static freeze can create some unplesent artifacts so I haven't released it.)

For noisy sources, this produces the best results but I wouldn't say that the results are excelent. A new filter is needed that can do temporal blending with motion compensation over long frame ranges (5 frames on each side of the active frame).

Soulhunter
2nd July 2004, 22:36
Source

http://img13.exs.cx/img13/1729/Sourcey_3564.jpg


PixieDust

http://img12.exs.cx/img12/1387/PixieDusted_3564.jpg


PixieDust2

http://img15.exs.cx/img15/8383/PixieDust2.jpg

Didée
3rd July 2004, 01:53
Soulhunter!! Shall I owe you the the title "Destroyer of Hopes", or what ...

You have simply everything: sources for which Dust always blocks out, halos that can't be removed, eyes that can't be reckognized, ...

I give up on you, really :D


But MrTibs, you have a very good point there. In fact, I also use temporal denoising before PixieDust, for sources with stronger noise. My home-brewed variant is named "WickedDenoiser", but still gets changed too frequently to be posted ...
It seems generally a good idea to "calm down" the noise beforehand, just a little, to make Dust's life a bit easier.


Soulhunter - any chance to get a couple of frames from one of your posted sources? They show the problem so wonderfully ugly ... good playground that would be.


- Didée

Soulhunter
3rd July 2004, 02:22
Originally posted by Didée
You have simply everything...Except a real life... :D


Bye

Didée
4th July 2004, 00:46
Hi,

new results - but not the mood of doing big typing.

I correct myself: It seems not-blockaligned Dust has only little effect. Some image features get better, but some may even go worse. It's kind of the "you win here, you loose there" game ...

However: Averaging of two offset'ed Dust processings is *very* effective. Consider the following screenshots:

Source:
http://img28.exs.cx/img28/6146/sword_source.png

Dust(5), block-aligned:
http://img28.exs.cx/img28/7829/sword_dust5_blockaligned.png

Dust(5), offset by 4 pixel:
http://img28.exs.cx/img28/2654/sword_dust5_offset4.png

Averaging Dust(5)-offset-2 with Dust(5)-offset-6:
http://img28.exs.cx/img28/7383/sword_dust5_off2off6avg.png


Ah! Much better. Averaging of 4 offset'ed Dust versions would be even better, of course. But it's not really worth the time, IMHO. I consider the averaging of 2 Dust versions as "sufficiently free of artefacts". Mind you, for the above screenshots Dust(limit=5) was used - a mostly too strong setting, as already mentioned. These are with limit=2:

Dust(2):
http://img28.exs.cx/img28/3262/sword_dust2.png

Average of Dust(2)-offset-2 & Dust(2)-offset-6:
http://img28.exs.cx/img28/6848/sword_dust2_off2off6avg.png


You see, with limit=2, blocking for "normal" Dust is much weaker. And the averaged one is definetly fine.

Now, do one last comparison: Take the screenshot "Source", and that with averaging Dust(2) (the last one). Zoom in by 500%, and look at the actresses face.

Seems Dust is suited for de-blocking. Oh my Lord :D

I'll make the wrapper function somewhen later - but not now.

Code snipplet:
str = 2
length= framecount(last)
off_2 = last.addborders(2,2,14,6)
off_6 = last.addborders(6,6,10,2)
tmp = off_2 + off_6
dust = tmp.converttoyuy2().PixieDust(str).converttoyv12()
dust_offset_2 = dust.trim(0, length).crop(2,2,-14,-6)
dust_offset_6 = dust.trim(length*2, 0).crop(6,6,-10,-2)

dust_multi2 = overlay(dust_offset_2,dust_offset_6,opacity=0.5)
dust_multi2


- Didée

malkion
4th July 2004, 11:59
Not sure if this input will help you guys to brainstorm...

I've used blockbuster (block_size=4) after pixiedust, and sure enough,
the blocks appearing after pixiedust is called appears to shrink from 8x8 blocks to 4x4 blocks.

[edit]
Or, rather, the original 8x8 blocks are then divided into 4x4 blocks.
[\edit\]

Just more info for you.

kassandro
4th July 2004, 16:17
I used an enhanced version of the difference filter, which is part of the AlignFields (http://www.alignfields.de.tf) plugin. difference(clip1, clip2) prints for each frame the total absolute difference (SAD) of both clips and the number of pixel changes to debugview. I used it to check, whether a deinterlacer adhere to the "no motion no change" and whether it keeps one field unchanged. In order to validate Didée claims, I had to enhance the difference filter with the additional variable tolerance. If the change is less or equal tolerance, then it is ignored. Thus difference(clip1, clip2, tolerance=0) behaves just as the old version.
I used the following script:

LoadPlugin("C:\programme\Avisynth\plugins2\LoadPluginEx2.dll")
LoadPlugin("C:\programme\Avisynth\plugins2\DustV5.dll")
MPEG2Source("napoleon.d2v", cpu=4)
input=ConvertToYUY2()
output=PixieDust(input,limit=2)
difference(output, input, tolerance=2)
trim(83892, 83902)

I first explored PixieDust(limit=2). With tolerance=0 difference reported the following results:
[2140] [83892] total difference = 291992, different Pixels 253633
[2140] [83893] total difference = 301347, different Pixels 262219
[2140] [83894] total difference = 301654, different Pixels 262283
[2140] [83895] total difference = 311644, different Pixels 269620
[2140] [83896] total difference = 298786, different Pixels 260138
[2140] [83897] total difference = 302328, different Pixels 262725
[2140] [83898] total difference = 314595, different Pixels 271635
[2140] [83899] total difference = 298442, different Pixels 260893
[2140] [83900] total difference = 303879, different Pixels 265411
[2140] [83901] total difference = 319431, different Pixels 274940
[2140] [83902] total difference = 293773, different Pixels 258982
It was a 720x576 clip. Thus about 800000 different pixels were possible (luma and chroma are counted seperately). The above results show that Pixiedust, even with limit=2, changes very many pixels, about 30%, but the changes are very small, indeed only about 1.15 per pixel (divide the total difference by the number of different pixels). Now let's see, whether Didée assertion, that the changes made by Pixiedust are smaller than the value of limit. To this end I changed tolerance to 2 and got the following results:
[2140] [83892] total difference = 10507, different Pixels 3470
[2140] [83893] total difference = 10908, different Pixels 3596
[2140] [83894] total difference = 10626, different Pixels 3498
[2140] [83895] total difference = 10887, different Pixels 3587
[2140] [83896] total difference = 9496, different Pixels 3141
[2140] [83897] total difference = 9600, different Pixels 3168
[2140] [83898] total difference = 10656, different Pixels 3521
[2140] [83899] total difference = 9269, different Pixels 3065
[2140] [83900] total difference = 8848, different Pixels 2922
[2140] [83901] total difference = 10755, different Pixels 3561
[2140] [83902] total difference = 7605, different Pixels 2517
Thus Didée claim is definitely false. There are always several thousand pixels with change > 2. With tolerance=3 I got:
[2140] [83892] total difference = 382, different Pixels 95
[2140] [83893] total difference = 480, different Pixels 120
[2140] [83894] total difference = 528, different Pixels 132
[2140] [83895] total difference = 498, different Pixels 124
[2140] [83896] total difference = 292, different Pixels 73
[2140] [83897] total difference = 375, different Pixels 93
[2140] [83898] total difference = 372, different Pixels 93
[2140] [83899] total difference = 296, different Pixels 74
[2140] [83900] total difference = 328, different Pixels 82
[2140] [83901] total difference = 288, different Pixels 72
[2140] [83902] total difference = 216, different Pixels 54
and with tolerenace=4 I finally got
[2140] [83892] total difference = 10, different Pixels 2
[2140] [83893] total difference = 0, different Pixels 0
[2140] [83894] total difference = 0, different Pixels 0
[2140] [83895] total difference = 6, different Pixels 1
[2140] [83896] total difference = 0, different Pixels 0
[2140] [83897] total difference = 7, different Pixels 1
[2140] [83898] total difference = 0, different Pixels 0
[2140] [83899] total difference = 0, different Pixels 0
[2140] [83900] total difference = 0, different Pixels 0
[2140] [83901] total difference = 0, different Pixels 0
[2140] [83902] total difference = 0, different Pixels 0
Thus essentially there are no changes > 4.
Next I turned to PixieDust(limit=5). With tolerance=0 I got
[2140] [83892] total difference = 357225, different Pixels 274051
[2140] [83893] total difference = 373233, different Pixels 282202
[2140] [83894] total difference = 373293, different Pixels 281910
[2140] [83895] total difference = 379065, different Pixels 288598
[2140] [83896] total difference = 363810, different Pixels 278881
[2140] [83897] total difference = 368866, different Pixels 281190
[2140] [83898] total difference = 376551, different Pixels 288929
[2140] [83899] total difference = 361892, different Pixels 279224
[2140] [83900] total difference = 367931, different Pixels 283356
[2140] [83901] total difference = 377721, different Pixels 290473
[2140] [83902] total difference = 350757, different Pixels 275460
Thus with a higher limit value Pixiedust changes somewhat more pixels and the average difference increases to about 1.25. With tolerance=2
I got:
[2140] [83892] total difference = 48747, different Pixels 15004
[2140] [83893] total difference = 57812, different Pixels 17681
[2140] [83894] total difference = 59092, different Pixels 18077
[2140] [83895] total difference = 55337, different Pixels 17022
[2140] [83896] total difference = 50058, different Pixels 15373
[2140] [83897] total difference = 51480, different Pixels 15806
[2140] [83898] total difference = 50371, different Pixels 15578
[2140] [83899] total difference = 47033, different Pixels 14552
[2140] [83900] total difference = 48346, different Pixels 14993
[2140] [83901] total difference = 48375, different Pixels 15024
[2140] [83902] total difference = 39594, different Pixels 12302
With tolerance=3 I got:
[2140] [83892] total difference = 13050, different Pixels 3105
[2140] [83893] total difference = 16400, different Pixels 3877
[2140] [83894] total difference = 16849, different Pixels 3996
[2140] [83895] total difference = 14954, different Pixels 3561
[2140] [83896] total difference = 13788, different Pixels 3283
[2140] [83897] total difference = 14142, different Pixels 3360
[2140] [83898] total difference = 12751, different Pixels 3038
[2140] [83899] total difference = 11894, different Pixels 2839
[2140] [83900] total difference = 11821, different Pixels 2818
[2140] [83901] total difference = 11586, different Pixels 2761
[2140] [83902] total difference = 9312, different Pixels 2208
With tolerance=4:
[2140] [83892] total difference = 3038, different Pixels 602
[2140] [83893] total difference = 4260, different Pixels 842
[2140] [83894] total difference = 4065, different Pixels 800
[2140] [83895] total difference = 3406, different Pixels 674
[2140] [83896] total difference = 3172, different Pixels 629
[2140] [83897] total difference = 3334, different Pixels 658
[2140] [83898] total difference = 2839, different Pixels 560
[2140] [83899] total difference = 2642, different Pixels 526
[2140] [83900] total difference = 2601, different Pixels 513
[2140] [83901] total difference = 2602, different Pixels 515
[2140] [83902] total difference = 2328, different Pixels 462
With tolerance=5:
[2140] [83892] total difference = 168, different Pixels 28
[2140] [83893] total difference = 300, different Pixels 50
[2140] [83894] total difference = 390, different Pixels 65
[2140] [83895] total difference = 216, different Pixels 36
[2140] [83896] total difference = 162, different Pixels 27
[2140] [83897] total difference = 259, different Pixels 43
[2140] [83898] total difference = 234, different Pixels 39
[2140] [83899] total difference = 72, different Pixels 12
[2140] [83900] total difference = 216, different Pixels 36
[2140] [83901] total difference = 162, different Pixels 27
[2140] [83902] total difference = 108, different Pixels 18
Thus with limit=5 Didée claim is much more accurate than with limit=2. Finally with tolerance=6 I got
[2140] [83892] total difference = 0, different Pixels 0
[2140] [83893] total difference = 0, different Pixels 0
[2140] [83894] total difference = 0, different Pixels 0
[2140] [83895] total difference = 0, different Pixels 0
[2140] [83896] total difference = 0, different Pixels 0
[2140] [83897] total difference = 7, different Pixels 1
[2140] [83898] total difference = 0, different Pixels 0
[2140] [83899] total difference = 0, different Pixels 0
[2140] [83900] total difference = 0, different Pixels 0
[2140] [83901] total difference = 0, different Pixels 0
[2140] [83902] total difference = 0, different Pixels 0
Altogether I conclude that Pixiedust makes many small changes, but I can't explain myself, how Pixiedust can creat the slight blockiness displayed in Soulhunter's pics. The clip with which I did my test did not show any visible blockiness, even with limit=5.

Didée
4th July 2004, 18:07
malkion:

Have no time right now to try that - but your findings :confused: me.
With Blockbuster you can either blur, sharpen, or add noise to cells found to be "flat". Filter's default is to add noise.
Even when Blockbuster is run with a cell size of "4" - I can't see how this should result in breaking up Dust's 8*8 blocks into 4*4 blocks??

Please explain. Exact script, and perhaps some screenshots, would help.


kassandro:

Yeah, I've not the slightest clue what I'm talking about. I just try to keep you all busy, since the forum's activity is currently so low ;)

Seriously. I just cannot make myself quickly some enhanced analyzing tools like you can do. All I have available is one pair of eyes, some common sense, and a little Avisynth scripting. That is my complete toolkit.

But I have a (possible) explanation for the effect you discovered.
I assume that Dust's "limit" is used to *only* limit the maximal change for the *temporal denoising* Dust is doing, after motion compensation, and without spatial denoising.
(Read last sentence twice.)

There are several other things going on in Dust, especially in PixieDust, which probably are not taken into account, regarding "limit":

- PixieDust uses spatial denoising (SpaceDust) *before* any ME/MC is performed. Perhaps not exactly "before", but fiddled "inbetween", since Steady is speaking of "some twists" - but that's detail.
However: Supposingly the changes of the spatial denoising are not taken into account when applying "limit".

- Dust uses subpixel accuracy for motion estimation/compensation (AFAIK quarter pixel - Steady was thinking of even 1/8th pixel accuracy for later versions, but then he dissapeared.)
It was mentioned that he is only using bilinear interpolation for the subpixel calculations. This is an explanation for the fact why the output of Dust is always at tad softer then the input. And it could be a further explanation for differences being greater than expected, since the change of values due to the soft subpixel interpolations probably are not taken into account, either.

I even have the suspect that *every* single pixel gets replaced by Dust with the re-calculated pixel from the internally created subpixel cell.


I know this all is wild speculating about a filter we don't know about how it is *exactly* working.
But most times, my "feelings" about such things are not too way off. ;)


- Didée

malkion
4th July 2004, 21:55
@Didee, sorry, screen shots aren't my forte, and I'm not working on a source that produces blocks with pixiedust right now.

I only mentioned it knowing how smart you are, and maybe a new puzzle to help solve the equation, if it applies. :devil:

However, standard scripting should produce the results.

converttoyuy2().pixiedust().converttoyv12()
blockbuster(method="noise",block_size=4,variance=0.3,seed=1)

@Soulhunter, since you already have Gladiator with blocks from dust, could you do me a favor and try blockbuster afterwards with the
settings above, then post a sample screenshot if you reproduce the results I've mentioned?

Soulhunter
4th July 2004, 23:28
Originally posted by malkion
@Soulhunter, since you already have Gladiator with blocks from dust, could you do me a favor and try blockbuster afterwards with the
settings above, then post a sample screenshot if you reproduce the results I've mentioned? Can't see a difference @ the Gladiator sample... :(


Bye

Fizick
5th July 2004, 00:00
As a just-maked Senior member, :devil: I can say:
1. Besides one pair of eyes, some common sense, and a little Avisynth scripting , I have some photo-editing software. I measure intensity difference between blocks in bottom picture on first page (without tiger). It is about 5 max.

2. The Did?e's method of image shifting and summation is more general, it may be also applied for example to VagueDenoiser (which uses not shift-invariant wavelet transform).

3. Border mirror is very elegant! By the way, I have use it internally in new version my DePan filter, but still not release it (seems that nobody is interested in DePan).

4. Dust's "limit" is used to *only* limit the maximal change for the *temporal denoising* Dust is doing, after motion compensation, and without spatial denoising.
Yes, it is probably so.

malkion
5th July 2004, 00:29
Must be my mistake then. Thanks for the trial Soulhunter.

Soulhunter
5th July 2004, 01:03
Originally posted by malkion
Must be my mistake then. Thanks for the trial Soulhunter. Maybe this apply's only to my "hardest-nut" sample... :confused:


Bye

malkion
5th July 2004, 01:06
Nah, it's my bad. Knowing stupid me, I prolly was streching the preview window in the latest Vdub. :stupid:

mg262
5th July 2004, 11:25
Thanks for all the help/thoughts, guys... I thought I'd post up the exact script I was using in case anyone else finds this thread + wants to test quad-dusting... it's basically what I referred to in the first post but with Didée's reflection idea incorporated. Hopefully no stupid error this time!


cutright = stackhorizontal( crop(2, 0, -2, -0), crop(last.width-4, 0, 4, -0).fliphorizontal() )
cutbottom = stackvertical( crop(0, 2, -0, -2), crop(0, last.height-4, -0, 4).flipvertical() )
cutboth = stackvertical( cutright.crop(0, 2, -0, -2), cutright.crop(0, cutright.height-4, -0, 4).flipvertical() )
a = Pixiedust(5)
LoadPlugin("C:\Capture\AviSynth 2.5\plugins\old\Dust2.dll")
b = cutright.Pixiedust(5)
LoadPlugin("C:\Capture\AviSynth 2.5\plugins\old\Dust3.dll")
c = cutbottom.Pixiedust(5)
LoadPlugin("C:\Capture\AviSynth 2.5\plugins\old\Dust4.dll")
d = cutboth.Pixiedust(5)
ab = layer(a, b, "fast", 127, 2, 0)
cd = layer(c, d, "fast", 127, 2, 0)
layer(ab, cd, "fast", 127, 0, 2)

Soulhunter
7th July 2004, 02:34
mpeg2source("C:\Tests\Test4.d2v").converttoyuy2()

cutright = stackhorizontal( crop(2, 0, -2, -0), crop(last.width-4, 0, 4, -0).fliphorizontal() )

cutbottom = stackvertical( crop(0, 2, -0, -2), crop(0, last.height-4, -0, 4).flipvertical() )

cutboth = stackvertical( cutright.crop(0, 2, -0, -2), cutright.crop(0, cutright.height-4, -0, 4).flipvertical() )

LoadPlugin("C:\Programme\AviSynth 2.5\plugins\Dusty0.dll")
a = Pixiedust(5)

LoadPlugin("C:\Programme\AviSynth 2.5\plugins\Dusty1.dll")
b = cutright.Pixiedust(5)

LoadPlugin("C:\Programme\AviSynth 2.5\plugins\Dusty2.dll")
c = cutbottom.Pixiedust(5)

LoadPlugin("C:\Programme\AviSynth 2.5\plugins\Dusty3.dll")
d = cutboth.Pixiedust(5)

ab = layer(a, b, "fast", 127, 2, 0)
cd = layer(c, d, "fast", 127, 2, 0)

Layer(ab, cd, "fast", 127, 0, 2)

http://img34.exs.cx/img34/1424/QuadDusted_3564.jpg

Still visible, but much less than before !!!

Now I wanna test if your script is "speed -vs- quality wise" better than my "ResizeDustLayer" try... :D


Bye

Didée
7th July 2004, 17:07
That is not my script. That is your interpretation of my script ;)

There's nothing wrong with that script, but ... you don't honestly want to do a speed comparison between this and your previously posted "resize"-method, no?
I mean ... your resize-method uses 2 instances of dust, whereas above shifting-method uses 4 of them instead. That's a tiny little bit unfair. One script with 4 big iron balls tied to the legs, the other one with only 2 ...
Guess what you'll get with quadrouple-dust? I estimate roughly 1 fps ~ 2 fps, depending on CPU power. (1 fps for me).

BTW, if you use quadrouple'd Dust anyway, then I'd use 4 shifted clips - your above script uses 3 shifted variants & the not-shifted original.

BTW2: Since the blocking is only going on in the Y channel, the fastest method for the layering would be through masktools:

yv12layer( clip1, clip2, "fast", 127, chroma=false, offX, offY, Y=3,U=1,V=1)

When I played with multi-dusting last weekend, that made still a difference of ~ 6% (for double-dust, not quadrouple).


- Didée



P.S. (off-topic)

Anyone interested in a scripted alternative to "MSU smart sharpen"? :D

Soulhunter
7th July 2004, 19:48
Originally posted by Didée
That is not my script. That is your interpretation of my script ;)

No, its mg262's interpretation... :p

Originally posted by Didée
There's nothing wrong with that script, but ... you don't honestly want to do a speed comparison between this and your previously posted "resize"-method, no?

Nah, was just kidding there...

Only a small hint that the "resize-method" is faster (and visually pleasant IMO) !!!


Bye

Didée
8th July 2004, 17:02
Originally posted by Soulhunter
Only a small hint that the "resize-method" is faster
Veto.

It was not me who suggested to use 4 diferent dust'ed clips ...

My proposed method of averaging two offset'ed clips is "faster" (read: less slow) than your resize-method. :p

- Didée

Soulhunter
10th July 2004, 04:50
Originally posted by Didée
My proposed method of averaging two offset'ed clips is "faster" (read: less slow) than your resize-method. :p
But visually as well... :confused:


Bye

Didée
23rd October 2005, 18:33
Wow, this thread has become old. Nonetheless, here is where the following belongs:

# ================================
# PixieDustPP v0.1 (21 Oct 2005)
# ================================
#
# A wrapper & postprocessing function for PixieDust. The aim is to reduce the blocking artefacts that PixieDust may produce
# on image areas it can't motion-compensate correctly.
# Moreover, PixieDust has a tendency to make the overall output a tad too soft, caused by its spatial processing [SpaceDust].
# Then, the additional Deblocking doesn't exactly help on that matter ... so there is also the possibility to apply some very
# slight sharpening, in order to compensate for this softening.
#
# It's not the ultimate solution. But it helps very noticeably.
#
# Required Plugins:
# - MaskTools (at least v1.5.6, v1.5.8 recommended)
# - DGDecode (a recent version containing the "Deblock()" h.264 deblocking routine)
# - RemoveGrain (the pre-1.0 version!)
#
#
# Fiddled together by Didée, for your pleasure.
#

Didée
23rd October 2005, 18:35
The script:

# ================================
# PixieDustPP v0.1 (21 Oct 2005)
# ================================
#
# A wrapper & postprocessing function for PixieDust. The aim is to reduce the blocking artefacts that PixieDust may produce
# on image areas it can't motion-compensate correctly.
# Moreover, PixieDust has a tendency to make the overall output a tad too soft, caused by its spatial processing [SpaceDust].
# Then, the additional Deblocking doesn't exactly help on that matter ... so there is also the possibility to apply some very
# slight sharpening, in order to compensate for this softening.
#
# It's not the ultimate solution. But it helps very noticeably.
#
# Required Plugins:
# - MaskTools (at least v1.5.6, v1.5.8 recommended)
# - DGDecode (a recent version containing the "Deblock()" h.264 deblocking routine)
# - RemoveGrain (the pre-1.0 version!)
#
#
# Fiddled together by Didée, for your pleasure.
#

function PixieDustPP(clip clp, int "limit", int "q", int "s", int "smode", int "smode2", int "fullDB", bool "reduce")
{
limit = default( limit, 3 ) # limiter value for PixieDust
q = default( q, 24 ) # quant to use for Deblocking (h.264 deblocking routine provided by recent DGDecode)
s = default( s, 1 ) # subliminal sharpening to combat dulling due to PixieDust and Deblocking:
# 0->no sharpening 1-> before PixieDust 2-> after Deblocking 3->both
smode = default( smode, 4 ) # RemoveGrain blurring mode to use for sharpening before PixieDust
smode2 = default( smode2,20 ) # same for 2nd sharpening
fullDB = default( fullDB,51 ) # 0 -> reduce only PixieDust's blocking 100 -> reduce Source & PixieDust blocking
reduce = default( reduce,false) # when true: at the very end, for every pixel reduce the achieved effect by 1
rg1str = (s==3) ? 0.333 : 0.5

SHRP1 = "x y - abs 2 "+string(limit/3.0)+" - < x y - abs 24 > ° x x y - abs 4 < x y - abs 11 > ° x 1 x y - x y - abs / * + x 2 x y - x y - abs / * + ? ?"
SHRP2 = "x y - abs 2 < x y - abs 24 > ° x x y - abs 4 < x y - abs 7 > ° x 1 x y - x y - abs / * + x 2 x y - x y - abs / * + ? ?"
REDUC = "x y - abs 2 < x x x y - abs 1 - x y - x y - abs / * - ?"
DBALT = "x 128 - y 128 - * 0 < x x 128 - "+string(fullDB)+" * 100 / 128 + ?"

clp2 = isyv12(clp) ? clp : clp.converttoyv12()
clp2

(s==1 || s==3) ? yv12lutxy(last,last.removegrain(smode,-1), yexpr=SHRP1,U=2,V=2) : last
(s==1 || s==3) ? mergeluma(removegrain(1,-1), rg1str) : last

converttoyuy2()

dusted = pixiedust(limit).converttoyv12()
dustdiff = yv12lutxy(clp2,dusted,"x y - 128 +","x y - 128 +","x y - 128 +",U=3,V=3)

deblocked = dusted.deblock(q)
deblockdiff = yv12lutxy(dusted,deblocked, "x y - 128 +", "x y - 128 +", "x y - 128 +", U=3,V=3)
deblockdiffnew = yv12lutxy(deblockdiff,dustdiff, DBALT, U=2,V=2)

yv12lutxy(dusted,deblockdiffnew, "x y 128 - -", "x y 128 - -", "x y 128 - -",U=3,V=3)

(s==2 || s==3) ? yv12lutxy(last, last.removegrain(smode2,-1), yexpr=SHRP2, U=2,V=2) : last
(s==2 || s==3) ? mergeluma(removegrain(1,-1), rg1str) : last

reduce ? yv12lutxy(clp,last, REDUC,"y","y", U=3,V=3) : last

isyv12(clp) ? last : isRGB(clp) ? last.converttoRGB() : last.converttoyuy2()

return( last )
}

mg262
23rd October 2005, 20:36
:) Since Dust filters are my first response to... well, most things, this is extremely welcome! :) Thank you, Didée.

(I shall set appropriate jobs to run overnight and tomorrow and then try to produce some intelligent feedback. Did I remember to say :) :) :) ?)

mg262
24th October 2005, 14:27
I took the liberty of updating the thread title -- hope that's okay, Didée.

MaskTools -- http://manao4.free.fr/
DGDecode -- http://www.neuron2.net/
RemoveGrain -- http://videoprocessing.11.forumer.com/viewtopic.php?t=9

Edit: Grrr... the thread title keeps reverting. Let me try again...
Edit: No luck. The first post is suitably altered, but it's not reflected in the AVISynth usage forum. :angry:

Wilbert
24th October 2005, 14:39
Edit: No luck. The first post is suitably altered, but it's not reflected in the AVISynth usage forum.
Here you go ;)

mg262
24th October 2005, 15:38
:thanks:

Didée
24th October 2005, 15:57
If you mean so, sure ... but you're shooting rather quickly, my friend. Until first feedback has come in, we're not even sure it isn't a hoax ;)
(Waiting for our famous block-spotter Soulhunter...)

Note the "v0.1" ... it's just "one try" of several possible. Following the same idea, things could be done in several slightly different ways - in the end, Dust's blocking issues are mostly a matter of pixel changes of +/-1 to +/-2. In this range, it's not trivially easy to seperate the good from the bad ...


And some mysterious oracling: PixieDustPP is a little child ... little childs love to ride a SeeSaw :)

mg262
24th October 2005, 17:48
Well, I was worried that it might slide away unseen... threads turn up in the AVISynth Usage forum so fast that I only read about half of them -- and I'm reasonably active. (And I unhelpfully made the presence of your post rather less visible by replying to it...) I hope you didn't mind.

Note the "v0.1" ... it's just "one try" of several possible. Following the same idea, things could be done in several slightly different waysDon't worry, I'm not expecting perfection on a first attempt... I'm just glad you've turned your attention to this problem.

In this range, it's not trivially easy to seperate the good from the bad ...And this is why I'm glad you've turned your attention to this problem ;) . My previous attempts would have been on the order of PixieDust.LtdSharpen (on my sources blurring is a problem much more often than blocks, though both do occur...)

Still testing... NB using limit > 5 causes black spots to appear all over the picture. (Wraparound?)

SeeSaw... makes me think of up and down...

Edit: The stuff my hard disk is full of doesn't seem to produce blocks in Dust... there is some loss of sharpness, and I think the script may help a little, but the effect is very subtle. (Look at the brown face on the second step up.)

http://people.pwf.cam.ac.uk/mg262/posts/pixiecomparison617.png

The material that spawned this thread is long gone from my HDD, but I'm hunting for something more suitable to test it with...

Edit: just noticed I typed DD instead of PP... subliminal associations :p

FlimsyFeet
24th October 2005, 22:32
Huffyuv cap from analogue source:

PixieDust(limit=5)
http://img419.imageshack.us/img419/4662/pixie0kp.png

PixieDustPP(limit=5, fullDB=0)
http://img419.imageshack.us/img419/9062/pixiepp3mp.png

Didée
25th October 2005, 13:07
Quite possible. On the other hand:

source:
http://img474.imageshack.us/img474/1595/28401source2qo.png

PixieDust():
http://img474.imageshack.us/img474/6974/28402pixie4gb.png

PixieDustPP(s=1,q=35,fullDB=49)
http://img474.imageshack.us/img474/2968/28403pixiepps1q35db490rh.png

Look at the background, on the right ...


edit: compared to a simple PixieDust().Deblock(quant=30):

http://img474.imageshack.us/img474/5324/28404pixiedeblock306kx.png

, which is obviously softer ... after compression, quite muddy.

Soulhunter
25th October 2005, 13:16
Waiting for our famous block-spotter Soulhunter...
Hehe, still have this Gladiator chapter on my HDD... ^^

If I find the time I post some samples in the course of the day, or night!?


Bye

Didée
25th October 2005, 15:11
Sure, Soulhunter, go on. Much appreciated. Only practice can (dis)prove theory ... ;)


Some notes for testing:

s=1 should be always good, against "PixieDust softness" (minor enhancement before PD, max. change is +/- 2).

s=2 (and 3, which is 1 + 2) is meant to combat "Deblocking softness" (small enhancement after deblocking, max. change is +/- 2). Seems not always that good, probably better to use it only when fullPP >= 51.

fullPP = 0 --> Only those pixel changes achieved by Deblock() are used that have different "sign" than the pixel changes achieved by PixieDust. Consequently, this will (should) do nothing to a frame except for reversing changes PixieDust has made. (Assuming that PixieDust has not left any noise that Deblock could reduce any further, it should only be blocking created by PixieDust that will be reverted, while the achieved noise reduction should be kept.)

when fullPP>0 then: all changes from Deblock() that would not be used with fullPP=0 (i.e. those changes having the same "sign" as PixieDust's changes) are applied with a percentage of [fullPP].

Since most changes of (reasonable) Deblocking will be very small (numerically), the rule of thumb is: (simple matter of rounding)

fullPP=100 -> full deblocking of PixieDust & Source (propably too blurry)

fullPP=49 -> full deblocking of PixieDust. Source deblocking results will be applied as 1->0, 2->1, 3->1, 4->2

fullPP=51 -> full deblocking of PixieDust. Source deblocking results will be applied as 1->1, 2->1, 3->2, 4->2


"reduce" parameter: probably not worth to use. (Perhaps on strong grained sources with fullPP=100.)

Soulhunter
25th October 2005, 19:28
Source
http://img485.imageshack.us/img485/4590/2984source5oh.jpg (http://imageshack.us)

PixieDust(5)
http://img110.imageshack.us/img110/7/2984pix50jo.jpg (http://imageshack.us)

PixieDustPP(Limit=5,FullDB=75)
http://img485.imageshack.us/img485/1812/2984pixiedustpplimit5fulldb755.jpg (http://imageshack.us)

Well, seems to work... ^^

Next I try to find a sharp scene with blocks!


Bye

Soulhunter
25th October 2005, 19:55
Source
http://img429.imageshack.us/img429/3897/1496source7eu.jpg (http://imageshack.us)

PixieDust(5)
http://img429.imageshack.us/img429/3759/1496pix52dk.jpg (http://imageshack.us)

PixieDustPP(Limit=5,S=2)
http://img448.imageshack.us/img448/4461/1496pixiedustpplimit5s22xz.jpg (http://imageshack.us)

Dallemon
19th January 2006, 05:16
ehm im getting some weird artefacts using this filter/script combo :/

AVS-script:
loadplugin("C:\Programmer\AviSynth 2.5\plugins\old\loadpluginex.dll")
loadplugin("C:\Programmer\AviSynth 2.5\plugins\old\dustv5.dll")
mpeg2source("d:\fc1080i.d2v",cpu=0,ipp=false)
crop(2,0,-0,-8,align=true)
lanczos4resize(1488,1080)
pixiedustpp(limit=5,s=3,smode=19,smode2=19,fulldb=0)
limitedsharpenfaster(dest_x=1280,dest_y=720)

Screenshot:
http://img483.imageshack.us/img483/9043/snapshot200601190502590oh.jpg (http://imageshack.us)

hartford
19th January 2006, 05:27
Pixie will do a "pre-ghost" frame at times; ie, it's temporal compensation will
show itself by "ghosting" in a "previous" frame.

I have seen it do this, but whenplayed on TV, it is not noticable. However, your requirements may differ.

I cannot say with certainty that the artifacts that you see are as a result of the way that the filter works without posting some "without Pixie" frame.

Dallemon
19th January 2006, 05:47
well i've also tried using iip for resizing and that gives the same result :/ (if i just use limitedsharpen then i dont get the lines)

EDIT: requirements are 1280x720 projector without scaling =)

Didée
19th January 2006, 09:10
PixieDust will start to behave strangely on big framesizes above a certain limit, and will totally b0ork out on even bigger framesizes.
I'm not sure anymore what the exact limits are, but IIRC it gets dangerous above 1024x1024.

BTW, although technologically absolutely different, FFT3DFilter is a (more than) adequate alternative to PixieDust.

zlab
25th March 2006, 15:41
Hi,
I hv a problem of loading dustv5.dll in the script, it response with ... not a avisynth 2.5 plugin, any solution? it there any possible link to dustv6.dll?
Thanks.

Didée
25th March 2006, 16:14
dustv6 does not exist. (Not that we knew of.)

dustv5 has to be loaded via LoadPluginEx or LoadPluginEx2.

zlab
25th March 2006, 16:26
Thanks a lot, now working like a fluid.

_leech_
23rd June 2006, 03:51
PixieDustPP works great, but not perfectly...

http://img58.imageshack.us/img58/2551/artifact3cf.jpg

:(

DeepDVD
23rd June 2006, 05:12
@ _ leech_

Look on upper side. There's a screenshot with the same problem.

PixieDust will start to behave strangely on big framesizes above a certain limit, and will totally b0ork out on even bigger framesizes.
I'm not sure anymore what the exact limits are, but IIRC it gets dangerous above 1024x1024.

jeffy
24th February 2008, 17:42
Correction for PixieDustPP (Division by zero):
http://forum.gleitz.info/showpost.php?p=329781&postcount=26

Amateur
3rd February 2011, 16:15
is pixiedust still a useful filter? has it been updated/improved? if so, what is its successor?