Log in

View Full Version : Skip pixel filter, a larger radius, sandwicher to enhance degrainers


Ponder
13th June 2011, 20:51
A clip with pixel values layout as

1 2 3 4 5
A B C D E
6 7 8 9 0
F G H i j
u v x y z

For example, execute this line, clip.medianfilter()
Normally, a median filter will calculate "new 8" from these 9 pixels

B C D
7 8 9
G H i

If Clip.Skip_ Pixel_Filter(by 1 spatial offset).medianfilter() is executed,

a "skip pixel filter" sandwich will allow medianfilters to calculate a "new 8" from

1 3 5
6 8 0
u x z

instead to get a more realistic median. When replacing medianfilter with a denoise filter
for HD source, a better denoised clip is likely.

Why is it useful? For large dimension clips, the effects of your filters chain will be more
accurate (give your clip a larger radius to operate), and faster (simplify your script).

Skip pixel simulation, using script is like 20+ operations with crop, addborder, reduceby2,
turnleft, weave... working on it, just wish something like it exist.

Didée
13th June 2011, 23:50
mt_luts(clp,clp,mode="median",pixels="-2 0 0 -2 0 0 0 2 2 0",expr="y",Y=3,U=2,V=2)

That should what you want, but could be that it's already slower than a simple

MedianBlur(2,0,0)

which in turn would be more precise anyway.

For radii 3 and above, kassandro's RemoveGrainHD is faster than MedianBlur.


But, somehow, it's the wrong picture anyway.
instead to get a more realistic median. When replacing medianfilter with a denoise filter
for HD source, a better denoised clip is likely.

The fact is that with HD resolutions, spatial filters simply need to work with a bigger 'radius' (or 'window'), in order to achieve the "same" effect as on SD sources.

Picking single pixels from a larger neighborhood is a rather crude way to increase the radius. It definetly will give less precise results than operating on all pixels of the increased neighborhood.

Ponder
14th June 2011, 06:29
@Didée, Thank you for the very informative suggestions.

Let take a case where noisy pixels are more or less evenly spread (spatially), let say
8 is a clean pixel, 1,3,5,B,D,G,i,u,x,z will be likely cleaner or clean pixels as well.
The other pixels are noisier then. A new "8" median calculation of radius 1 will use 4 clean
and 4 noisier neighbor pixels.

B D
G i are clean pixels

C
7 9
H are noisier

Now if the old "8" is a noisier pixel, A new "8" median calculation
of radius 1 will also use 4 clean and 4 noisier neighbor pixels, same 8 pixels.

On the other hand, when skip_ Pixel_Filter is used, If old "8" is clean, A new "8" median calculation
of radius 1 will use 8 cleaner pixels, If old "8" is noisy, A new "8" median calculation
of radius 1 will use 8 noisy pixels to do so. So the average of 8 (larger sample size) noisy pixels
is more middle(stable), if radius=2, 24 noisier pixels will be average out instead of 12 clean and
12 noisier pixels. The half clean and half noisier pixels bundle calculation does not seem too
right. ie. Why let half of the noisy pixels influent the calculation of a clean median pixel!

The above analysis is for Clip.Skip_ Pixel_Filter(by 1 spatial offset).medianfilter() to get a
cleaner median by differential grouping, cleaner group vs. noisier group as an illustration.

A denoiser may have some 3x3 or 5x5 median filter inside, Natively, it will take half clean and
half noisy pixels from our noisy source to calculate its median internally.

when one use " Source.Skip_ Pixel_Filter(radius=1 or 2).denoisers()", for every pixel it works
on, either a relate group of cleaner, or a group of noisier pixels will be sent to the denoiser for
its internal analysis. It will probably do no worse in general.

Feeding these grouped pixels to denoisers, the noisier the source ,the bigger the effect of
skip_ Pixel_Filter will be. It has a sense of, give the denoisers, a better selection of pixels.
whatever churn out at the other end, which denoiser has more positive or no, or worse effect,
that is another story.

Even if one denoiser has positive effect from skip pixel filter, that would make lot of its users
happy. Meanwhile I keep my finger cross for such plugin from the programming community to try it
out. Say, it does not work out, one can always use it to decorate clips into a Xmas tree, Bright
green every 5th pixel, bright yellow every 10th pixel by stringing the filters a couple times.

@Didée, Totally unrelate question, try to speed up scene detection using 1/4 size clip

prev = last.Filter.subtitle("scene_end")
next = last.Filter.subtitle("scene_beg")
SCSelect(next.reduceby2(),prev.reduceby2(),last.reduceby2(),dfactor=3.5)

Definitely will not work, even though SCSelect is quite fast, is there a way to trick SCSelect
to use a small control clip?

Didée
14th June 2011, 08:10
is there a way to trick SCSelect
to use a small control clip?
None that I knew of.


Keep in mind that a median filter acts "keep it or kill it". Now consider that you're only using 4 pixels out of 24 available neighbor pixels. 16.6% considerd, 83.3% not considered.

If there is e.g. a 3-high pixel cluster
. . . . . . .
a a a a a a a
b b b b b b b
c c c c c c c
. . . . . . .

then a median filter with your proposed 4+1 pixel positions will result in
. . . . . . .
a a a a a a a
. . . . . . .
c c c c c c c
. . . . . . .

Funny, isn't it.

Gavino
14th June 2011, 09:10
Let take a case where noisy pixels are more or less evenly spread (spatially), let say
8 is a clean pixel, 1,3,5,B,D,G,i,u,x,z will be likely cleaner or clean pixels as well.
But most types of noise are not evenly spread.
The very nature of noise is that it is random.

Didée
14th June 2011, 09:59
Noise might not be evenly spread. It's the detail that often comes along in regular patterns.

I came up with ^that^example because I actually tried the posted mt_luts(median), and saw exactly the mentioned defect on the shirt of an actor.

/me points once more to RemoveGrainHD. It is full of spatial filters that are designed to deal with the spatial requirements of HD content.

Didée
14th June 2011, 10:26
For what it's worth: 5-sample-median of ( pixel, [x-2], [x+2], [y-2], [y+2] ), like requested by OP.

Fastest possible script implementation, ~200% the speed of MedianBlur(2,0,0). (Only short splash-test with an SD file.)
Requires pre-v1.0 of RemoveGrain. (Old-style 'clense')

mpeg2source("sample.d2v")

o = last
ox = o.width
oy = o.height

lft = o.pointresize(ox,oy,-2, 0,ox+.001,oy)
rgt = o.pointresize(ox,oy, 2, 0,ox+.001,oy)
top = o.pointresize(ox,oy, 0,-2,ox,oy+.001)
bot = o.pointresize(ox,oy, 0, 2,ox,oy+.001)

Median2(lft,rgt,o,top,bot)

return(last)

#=============================================
# median of 5 clips from Helpers.avs by G-force
Function Median2(clip "input_1", clip "input_2", clip "input_3", clip "input_4", clip "input_5", string "chroma")
{

chroma = default(chroma,"process") #default is "process". Alternates: "copy first" or "copy second"

#MEDIAN(i1,i3,i5)
Interleave(input_1,input_3,input_5)
chroma == "process" ? Clense(reduceflicker=false) : Clense(reduceflicker=false,grey=true)
m1 = selectevery(3,1)

#MAX(MIN(i1,i3,i5),i2)
m2 = input_1.MT_Logic(input_3,"min",chroma=chroma).MT_Logic(input_5,"min",chroma=chroma).MT_Logic(input_2,"max",chroma=chroma)

#MIN(MAX(i1,i3,i5),i4)
m3 = input_1.MT_Logic(input_3,"max",chroma=chroma).MT_Logic(input_5,"max",chroma=chroma).MT_Logic(input_4,"min",chroma=chroma)

Interleave(m1,m2,m3)
chroma == "process" ? Clense(reduceflicker=false) : Clense(reduceflicker=false,grey=true)
selectevery(3,1)

chroma == "copy first" ? last.MergeChroma(input_1) : chroma == "copy second" ? last.MergeChroma(input_2) : last

Return(last)
}

TheProfileth
15th June 2011, 11:18
The filter Didée posted didn't really produce usable/satisfactory results. I found that this on the other hand did. It is actually a usable filter and is very fast.
Function fastmedian(clip o){
ox = o.width()
oy = o.height()

lft = o.pointresize(ox,oy,-1, 0,ox+.001,oy)
rgt = o.pointresize(ox,oy, 1, 0,ox+.001,oy)
top = o.pointresize(ox,oy, 0,-1,ox,oy+.001)
bot = o.pointresize(ox,oy, 0, 1,ox,oy+.001)

output=Median2(lft,rgt,o,top,bot)

return(output)
}
Some comparisons
http://screenshotcomparison.com/comparison/59664
http://screenshotcomparison.com/comparison/59665

Ponder
15th June 2011, 20:26
The following will illustrate better how Skip_ Pixel_Filter interact with degrainers
All the A's belong to "a feature", hence their value are very close, so are B,C,D...K

Lot of "2 Pixels wide" features 1920x HD movie.

A1 A2 B1 B2 C1 C2 == 70 72 21 25 13 17 42 43
A3 A4 B3 B4 C3 C4 == 74 71 21 23 12 15 40 40
D1 D2 E1 E2 F1 F2 == 41 41 82 84 66 69 23 21
D3 D4 E3 E4 F3 F4 == 41 41 81 83 67 64 21 23
G1 G2 H1 H2 I1 I2 == 50 53 35 32 02 05 99 92
G3 G4 H3 H4 I3 I4 == 52 52 33 34 04 05 99 92
J1 J2 J3 J4 J5 J6 == 11 12 11 11 11 13 72 75
K1 K2 K3 K4 K5 K6 == 55 55 53 55 55 54 03 03

Mostly 1 Pixels wide features SD same movie.

A B C X = 72 21 13 44
D E F Y = 41 82 66 22
G H I Z = 50 35 02 95
J J J W = 11 11 11 72
K K K V = 55 55 55 03

When above SD souce is used
A script using Removegrain() 3x3 hard coded algorithm when encounter the a pixel 82 it uses
72 21 13
41 82 66
50 35 02 for picking to output a final pixel

At pixel 66 it uses

21 13 44
82 66 22
35 02 95

These samples have very distinctive 9 elements(features). So Removegrain() has more choices,
ie a sample of 9.

Since Removegrain() is 3x3 matrice hard coded (assembly optimized, not possible at 5x5,cpu registers
are too few.

When 1920x source is used, at pixel 82, Removegrain() uses

71| 21 23
---------
41| 82 84
41| 81 83

it looks like a sample 4 small groups of pixel values

70ish 20ish
40ish 80ish

this has the effect of reducing the "sample size" from a 9 features to 4, hence reduce the
usefulness of Removegrain().

At pixel 66 it uses

23 12 15
84 66 69
83 67 64

Again it looks like a sample size of 4 features with pixel values of

20ish 10ish
80ish 60ish

The more 2 pixels wide features (or noise) in a clip, the more the above structure will appear.
I can not expect Removegrain() produce best picking on a 4ish sample size. If we have 2560x1440+
source with feature pixel size of 3. A 3x3 sample sent to Removegrain() will look 1x1 sample size.
Removegrain is done.

So, here we get 1 full feature 2x2 size(60ish), 2 half 2x1 size features and 1 quarter feature(20ish).
Somewhat like replacing 9 marbles by 1 apple, 2 eggs and a marble.

This is why your excellent script below work very well on SD, but reduce its power a lot
on 1920 noisy source. So it is a HD scaling problem.

o = last
f = o.MinBlur(1,2).MinBlur(2,2).RemoveGrain(11,-1)
f.FluxSmoothT(7).mt_AddDiff(mt_MakeDiff(o,f,U=2,V=2),U=4,V=4)
mt_LutXY(o,last,"x 2 + y < x 2 + x 2 - y > x 2 - y ? ?",U=2,V=2)

To fully utilize above script on 2 pixels wide sources, Removegrain() have to use a 6x6 matrice,
even a 5x5 matrice miss a little here and there. kassandro's RemoveGrainHD is too slow for me,
he did mention it to use on pictures instead.;-) I don't believe we will have enough CPU registers
in the next ten years to allow assembly optimization on a 6x6 matrice in RemovegrainHD().

A HD-SD scaling problem can infact be dealt (workable solution) with by unscaling it.
Downsizing is one, Skip a pixel is another. Thus

At pixel 66, Skipping a pixel we get

21 13 42
82 66 23
35 02 99

Now we have 9 distinctive elements, similar structure like the SD source, feeding these
9 elements to a SD type Removegrain() with hardcoded 3x3 engine. I would expect "on average", the
result will be better. At pixel 82, another 9 distinctive elements will be generated through
Skipping a pixel method.

When a noisy pixel is 2 pixels wide(2x2), Skip_pixel will allow Removegrain() by chisel a quarter
of the noisy pixel at a time. One corner,2nd, 3rd, 4th corner later, hopefully remove most of it.

When to use Skip_ Pixel_Filter(1), as follow:

"Feature Pixel Size"(average) vs. theoretical effectiveness Chart

2.2 -- sort of 1.8 pixel size
2 ------------ Skip_ Pixel_Filter(1) theoretically work best here
1.8 -- more better
1.6 ---- better
1.5 --------- Skip_ Pixel_Filter(0.5)=skip half a pixel, theoretically break even here
1.4 ---- worse
1.2 -- more worse
1.0 -- SD source --- Worst, Skip_ Pixel_Filter() should not be used

Math speculation, harmful if read twice:
"Rough" estimation, 720x480 Feature Pixel Size is 1, then 1440x960 is Pixel Size about 2.
so 1280p is Roughly 1.78. In reality, visual inspection is the most reliable guide to decide
what resolution is better for Skip_ Pixel_Filter(offset=1).

What if one want Skip_ Pixel_Filter(0.5) for size of 1080x720 source. not Skip_ Pixel_Filter(1)?
At 66=F1, value at location C1 should be (c1+c3)/2 etc. Now Skip_ Pixel_Filter will need to do some
calculations using a traditional 5x5 matrice to prepare a (3x3) with nine quarter-features for
Removegrain() or other degrain plugins. So Skip_ Pixel_Filter(0.5) has an effect of a 4x4 matrice,
this could be interesting to see, as it will benefit HD with Feature Pixel Size from around 1.4 to
1.6.

With different weight at matrice radius=1 to 2, we can actually get a 4x4 matrice effects for
Skip_ Pixel_Filter(from 0 to < 1.00). This sound good, A degrainer with hardcoded 3x3 engine
can actually use 5x5 information. Skip_ Pixel_Filter not only can skip pixel at setting=1,
it can melt info from a 5x5 matrice into a 3x3 matrice when setting is between 0 to 1.


@Gavino, definitely not fix distant, but have pattern, distant of fluctuation are well contained.
The 2 groups are statistically noisier or cleaner.

@Didee, Thank you for the script. I'll need to digest it first.

Skip_ Pixel_Filter() is not suppose to be used on SD.:-(). It is for big pixel, preferrably
the size of an orange. No wonder the line is replaced. We can get the line back in HD using some
repair script, so I am not too worry about it. The median example I used can be little misleading
it looked like a SD matrice. Sorry about that, even though I mention "large dimension", but was
not clear enough, should have mention large feature pixel size too.

@TheProfileth, can't spot difference between 2 pics yet...

In summary:
The goal of Skip_ Pixel_Filter() is to give any spatial degrainers which are 3x3 hard coded
(can not be changed to 5x5 without multifolds speed slowdown) a different set of 3x3 with more
distinctive elements (more accurate on average, SD like structure) to work with.

An explanatory name for Skip_ Pixel_Filter() could be "Big_Pixel_Matrice_Transformer_Plugin"
or "5x5_to_3x3_Matrice_Transformer_for_Degrainer_Plugin"
or "Big_Pixel_Quarterized_Noise_Chisel_Pounder"

An easier name to say is probably just "Big_Pickle_Quarter_Pounder" filter.
So this is how one remove some dancing pickles from a video.

TheProfileth
15th June 2011, 20:36
"Feature Pixel Size"(average) vs. theoretical effectiveness Chart

2.2 -- sort of 1.8 pixel size
2 ------------ Skip_ Pixel_Filter(1) theoretically work best here
1.8 -- more better
1.6 ---- better
1.5 --------- Skip_ Pixel_Filter(0.5)=skip half a pixel, theoretically break even here
1.4 ---- worse
1.2 -- more worse
1.0 -- SD source --- Worst, Skip_ Pixel_Filter() should not be used


I can do that pretty easy

@TheProfileth, can't spot difference between 2 pics yet...

Try zooming in :P
The difference is pretty noticable, not to mention the several hundred Kilobyte size drop.


An easier name to say is probably just "Big_Pickle_Quarter_Pounder" filter.
So this is how one remove some dancing pickles from a video.
Dancing pickles??? That is awesome :D

Function depickledancer(clip o,float "pixelskip"){
ox = o.width()
oy = o.height()
pixelskip=default(pixelskip,1.5)

lft = o.pointresize(ox,oy,-pixelskip, 0,ox+(pixelskip/2000),oy)
rgt = o.pointresize(ox,oy, pixelskip, 0,ox+(pixelskip/2000),oy)
top = o.pointresize(ox,oy, 0,-pixelskip,ox,oy+(pixelskip/2000))
bot = o.pointresize(ox,oy, 0, pixelskip,ox,oy+(pixelskip/2000))

output=Median2(lft,rgt,o,top,bot)

return(output)
}

that should work if I am correct

Didée
15th June 2011, 21:01
Edit @TheProfileth: You cannot force "half" or "fractional" pixel shifts with PointResize.

_____

separatefields().turnleft()
assumeframebased().separatefields()
Spatial_Denoiser_of_Choice()
weave().turnright()
assumefieldbased().weave()
This extends the 8+1 pixels of a 3x3 working area to the 8 edge/midside pixels, +center, of a 5x5 working area.

Not-recommended for the same reasons as my previously posted script. It boils down to the simple fact that the working area is not continuous when such a method is used. When the working area is not continuous, then so might the result be, potentially.

There's roughly 2 different cases:

a) The HD source has good detail that justifies its resolution. In this case, filtering with discontinuous working area will produce problems.

b) If the HD source is smooth enough for the discontinuous working area not to produce any artifacts, then the HD source is too blurry to justify its resolution. You can simply reduce it to half size, because that's all that it really deserves.

TheProfileth
15th June 2011, 21:27
Edit @TheProfileth: You cannot force "half" or "fractional" pixel shifts with PointResize.

Yea I realized that, as soon as I tested it as the only changes came from rational integers.


There's roughly 2 different cases:

a) The HD source has good detail that justifies its resolution. In this case, filtering with discontinuous working area will produce problems.

b) If the HD source is smooth enough for the discontinuous working area not to produce any artifacts, then the HD source is too blurry to justify its resolution. You can simply reduce it to half size, because that's all that it really deserves.

Yup that pretty much sums up the issue at hand, the idea itself is atleast a applicable one but the problem is applicable to what? Maybe there is one situation where it DOES infact work but that will just be 1 off hand source and it sort of is a waste of effort to work up an idea that MIGHT work effectively on a source that MIGHT exist but probably doesn't. The whole thing with this is that Ponder you have been counting your chickens before they hatch, you talk about all the ways this filter should work and why it should, but no video source is gonna look or react as you explained, skipping pixels overlooks too much, you lump detail with noise, banding with texture, edges with flat areas, creating sort of a mass of smashed up pixels, but atleast it is fast right? Maybe if you want to make a motion detection clip for srestore this could be useful (maybe?) but even then I doubt that this would help maintain clarity of motion seeing as you could in theory blend a inbetween frame with a normal frame and end up with a blurred mess of a inbetween frame, I mean just think of what would happen to a crossfade or a fade to black or even a high motion scene, you start slicing and dicing pixels and you end up with less than half your sample size and nothing but speed to show for it. The only usable thing I got out of this was the
script I posted first
Function fastmedian(clip o){
ox = o.width()
oy = o.height()

lft = o.pointresize(ox,oy,-1, 0,ox+.001,oy)
rgt = o.pointresize(ox,oy, 1, 0,ox+.001,oy)
top = o.pointresize(ox,oy, 0,-1,ox,oy+.001)
bot = o.pointresize(ox,oy, 0, 1,ox,oy+.001)

output=Median2(lft,rgt,o,top,bot)

return(output)
}
This actually does a decent job of denoising and is amazingly fast, so atleast we can not call this venture without its gains.
Either way, good ideas are still good ideas even if they are not usable or applicable, sometimes the best ideas just are not possible, like world peace or the filter adddetail(settings="handdrawn",tweak="Studio Ghibli")

Ponder
16th June 2011, 02:37
@TheProfileth, both pictures look good, perhaps I need some zooming.

Thank for your effort of improve it. It is not that easy in script, perhaps impossible. This
is why I was hoping someone appreciate the logic and produce a plugin. It is easy, I belief
(may be I wrong on that), to intercept a pixel every other step, and send them out to the next
degrainer. You can not expect a fast median filter by itself to denoise dancing grains!!.
medianblur(2,0,0) or Didée's Median2 is very strong, you will get soup.

but no video source is gonna look or react as you explained, skipping pixels overlooks too much,
you lump detail with noise, banding with texture, edges with flat areas, creating sort of a mass
of smashed up pixels, but at least it is fast right?

The problems you describe are from separatefields() and weave. You must understand what commands
cause the problems, that is a very big blame on the wrong part.

separatefields() and weave are not meant to partition matrice this easy, there is a shift of 1
line during separatefields(), of course you get boundary mismatch problems. My 1st post, already
mentioned crop and addborder, guess what it is for?. to fix the shifting!.

Skipping a pixel is like cropping every other row and every other column!. You will never
get any overlap or blend problem from any cropping operations. Too bad, we do not have a crop
row or column commands here.

A true Skipping a pixel plugin will have ZERO boundary problem, acting just like a crop filter.
Nothing more or less or any artifacts. We may get nutty result because we try to simulate it
through script with many plugins or avisynth commands.

Please don't made up your mind too quickly, changing one pararmeter from Didee's script, or
pointresize to quickly get pixelskip=1.5 shows you are very enthusiastic, it is a good thing,
but also made lots of wrongful blames when thing didnt work out.

Skip_ Pixel_Filter() is not same as Median2. It interprets between your source and degrainer.
Skip_ Pixel_Filter() is a select pixels filter. it repacks 3x3 pixels, or process 5x5 matrice into
a new 3x3 if there is an average algorithm added to it, you get a 4x4 effect.

pixelskip=default(pixelskip,1.5) is also dangerous. you are assuming small Features(details) Pixel
Size is 2.5 pixels thick!. This is new stuff, anyone can make that mistake. I do, lot of times.

TheProfileth
16th June 2011, 10:25
The problems you describe are from separatefields() and weave. You must understand what commands
cause the problems, that is a very big blame on the wrong part.

I did not use the method Didee described using separatefields and weave, I am talking in general. The principle of your idea is that by skipping pixels we can speed up a degrainer and/or make it more accurate by giving it a farther reaching sample window while actually making it process less of the frame. You are mainly adding more VARIETY to the median and less ACCURACY.

Didée
16th June 2011, 11:18
The problems you describe are from separatefields() and weave. You must understand what commands
cause the problems, that is a very big blame on the wrong part.

separatefields() and weave are not meant to partition matrice this easy, there is a shift of 1
line during separatefields(), of course you get boundary mismatch problems. My 1st post, already
mentioned crop and addborder, guess what it is for?. to fix the shifting!.

Skipping a pixel is like cropping every other row and every other column!. You will never
get any overlap or blend problem from any cropping operations. Too bad, we do not have a crop
row or column commands here.
I'm not quite sure, for what or against what you're arguing here.
However, repetition: the separate/turn/separate//filter//weave/turn/weave sequence does exactly what you've asked for.

Here an example: left is a 512x512 part of a 1080p frame. Right is radius=1 median with 1-pixel-skipping.

http://www.abload.de/thumb/pixskip_sourcecnj3.png (http://www.abload.de/image.php?img=pixskip_sourcecnj3.png) http://www.abload.de/thumb/pixskip_rad1mediantuw5.png (http://www.abload.de/image.php?img=pixskip_rad1mediantuw5.png)

See the artifacts? The cause is not because of some SeparateFields-related line shift oddity, or whatever. The cause is your "algorithm", Ponder. Nothing else.

(Yes, a median-1 is kind of a worst case here. General blurring filters will be much less catastrophic. But what is seen here is exactly the basic problem.)

With pixel_skip you're using only a small subset from the neighborhood that is not sufficiently representative for the neighborhood.

Ponder
17th June 2011, 22:53
@Didee
I have ImageSource ,imageReader problem, keep getting message on Avisynth 2.56 or 2.57.

Evaluation system: exception - interger overflow
aE" aE" Du Du..

So, I am wondering is this what was used to get that messy picture?
Are their any rounding off in pointresize below? ie. pixel losslessly preserved?


o = last
ox = o.width
oy = o.height

lft = o.pointresize(ox,oy,-1, 0,ox+.001,oy)
rgt = o.pointresize(ox,oy, 1, 0,ox+.001,oy)
top = o.pointresize(ox,oy, 0,-1,ox,oy+.001)
bot = o.pointresize(ox,oy, 0, 1,ox,oy+.001)

separatefields().turnleft()
assumeframebased().separatefields()
#Spatial_Denoiser_of_Choice()
Median2(lft,rgt,o,top,bot)
weave().turnright()
assumefieldbased().weave()

In fact, If

separatefields().turnleft()
assumeframebased().separatefields()
#Spatial_Denoiser_of_Choice()
weave().turnright()
assumefieldbased().weave()

is a lossless transformation, then it can be used as a diagostic tool on small feature(detail)'s
pixel size as well.

I ran some tests on 300's wheatfield scene.This has many fines features.

#RemoveGrain(18) #or 17,2
#hqdn3d(5) #hqdn3d(0,0,3,6)
#FFT3DFilter(sigma=6,sigma2=3,sigma3=2,sigma4=6)
#DeGrainMedian(mode=0)
#RemoveGrainHD()
#TemporalRemoveGrainHD()

Didee 's script
o = last
f = o.MinBlur(1,2).MinBlur(2,2).RemoveGrain(11,-1)
f.FluxSmoothT(7).mt_AddDiff(mt_MakeDiff(o,f,U=2,V=2),U=4,V=4)
mt_LutXY(o,last,"x 2 + y < x 2 + x 2 - y > x 2 - y ? ?",U=2,V=2)# or without

The results look fine, meaning the new 3x3 skip pixel matrice fit the degrainers well.

300 wheat field hqdn3d(5) Skip a pixel test
http://www.mediafire.com/?nc0yvdszm37z5yp

What dont look good? RemoveGrain(4,or 9). on the "queen cloths", Being the 2 most destructive
modes according to Kassandro, it destroy edges. Medianblur(radius=1) is also like RemoveGrain(4)
according to Tonny Petersen (tsp@person.dk).

To compare, I ran test on RemoveGrain(4,or 9) "without" pixel skip, it also look very ugly on the
queen cloth.

Didée
17th June 2011, 23:30
A median filter is always destructive. In "vanilla" usage, it is hardly ever suited for direct image processing.

The image comparison was made with removegrain(4), i.e. a spatial median with radius=1. And BTW, your Avisynth version is very outdated.

With your proposal of a 5-point median, in combination with 1-pixel-skipping, the pattern is

o o X o o
o o o o o
X o X o X
o o o o o
o o X o o

This means that the filter has good chances to be non-destructive on horizontal or vertical features
o o X o o o o X o o
o o o o o o o o o o
X o X o X X o X o X
o o o o o o o o o o
o o X o o o o X o o

but will necessairly fail, in a very similar way to the pixtures I posted, when it hits fine *diagonal* structures.

To be non-destructive to diagonal pictures, you'd need a median pattern like this:
X o o o X
o o o o o
o o X o o
o o o o o
X o o o X
Here, there are 3 samples located on diagonal structures, 2 samples outside. Diagonals are preserved. But now it will fail on horizontal & vertical structures.

There have been "smart" extensions to median filtering, by computing several such patterns in parallel, and [somehow] combining the results. But even then, it's far from being "impressive". It's still only median clamping.


BTW, it's only personal taste, but ... your sample "300 wheat hqdn3d5 Skip a pixel test" looks really poor to me. Spatial destruction galore, and plenty of grain still present.

Is all of meant to result in a "true" degrainer, or are you only after a pre-filter to feed a *reasonable* denoiser with?

TheProfileth
18th June 2011, 00:21
On a semi related note, would it be possible to take 3 medians one like
o o X o o
o o o o o
X o X o X
o o o o o
o o X o o
then another like
X o o o X
o o o o o
o o X o o
o o o o o
X o o o X
then a final one
o X o X o
X X X X X
o X o X o
X X X X X
o X o X o
Would it be possible to merge the medians of the first 2 (or instead just do a single median using the selected spaces on both, if this is faster/more accurate) and then use the last one as a guide to restore the first median(s) into the more complete last median?

Didée
18th June 2011, 00:44
Edit: Sure. Possible is (almost) everything. But when using something like the 3rd pattern, it will be VERY SLOW when done only via script. (That would require mt_luts(median), which seems more for "evaluation" rather than "real usage".)
A reasonable attempt could be to comput both the "X" and the "+" pattern median, and use that one that actually causes the smaller change.

-------

@Ponder

And just to mention it: it is pretty hard to make head or tail out of your latest post. Quote:
I ran some tests on 300's wheatfield scene.This has many fines features.

#RemoveGrain(18) #or 17,2
#hqdn3d(5) #hqdn3d(0,0,3,6)
#FFT3DFilter(sigma=6,sigma2=3,sigma3=2,sigma4=6)
#DeGrainMedian(mode=0)
#RemoveGrainHD()
#TemporalRemoveGrainHD()

Didee 's script
o = last
f = o.MinBlur(1,2).MinBlur(2,2).RemoveGrain(11,-1)
f.FluxSmoothT(7).mt_AddDiff(mt_MakeDiff(o,f,U=2,V=2),U=4,V=4)
mt_LutXY(o,last,"x 2 + y < x 2 + x 2 - y > x 2 - y ? ?",U=2,V=2)# or without

The results look fine, meaning the new 3x3 skip pixel matrice fit the degrainers well.
What are you trying to say or show? There's a few lines of out-commented denoisers. Then there's a quoted script of a different purpose (keep grain, remove low-frequency flicker).

None of these lines are related to pixel skipping.

But at the bottom of this, you conclude: "The results look fine, meaning the new 3x3 skip pixel matrice fit the degrainers well."


And worse ...

right above that, you have posted the script
o = last
ox = o.width
oy = o.height

lft = o.pointresize(ox,oy,-1, 0,ox+.001,oy)
rgt = o.pointresize(ox,oy, 1, 0,ox+.001,oy)
top = o.pointresize(ox,oy, 0,-1,ox,oy+.001)
bot = o.pointresize(ox,oy, 0, 1,ox,oy+.001)

separatefields().turnleft()
assumeframebased().separatefields()
#Spatial_Denoiser_of_Choice()
Median2(lft,rgt,o,top,bot)
weave().turnright()
assumefieldbased().weave()
This script is faulty and not valid. If it doesn't crash, then it produces nonsense.


Here's an example what your 5-point-median-(X-distribution)-with-1-pixel-skipping actually produces (1st frame of Zep's sample):

orig:
http://www.abload.de/thumb/300sourcenfm2.png (http://www.abload.de/image.php?img=300sourcenfm2.png)

5-point-median (X-distribution)
http://www.abload.de/thumb/300destroyedeful.png (http://www.abload.de/image.php?img=300destroyedeful.png)


Look at that closely. Is it crap? Yes it is. And big time so.

What am I trying to tell since the start of this thread?

Ponder
18th June 2011, 03:22
@Didee, all these times, we talked about 2 different things!.
from
ooooo
oxxxo
oxxxo
oxxxo
ooooo

to

x o x o x
o o o o o
x o x o x
o o o o o
x o x o x

9 pixels! not 5 pixels. skip every other row and skip every other column. All the matrices I showed
had 9 pixels. How did you get a 5 pixels impression. When you post 5-pixels median, I was quite
confused about the title but thought it was just a title. Holly Hell on earth, this is big time
miscommunication.:-(

For skipping half a pixel, actually 17 pixels are needed to get the final 9 pixels.

Ponder
18th June 2011, 08:07
Is all of meant to result in a "true" degrainer, or are you only after a pre-filter to feed a

*reasonable* denoiser with?

Right now, a variable pre-filter to feed a *reasonable* denoiser. For skipping 1 pixel, 9 pixels

mapping from 5x5 matrice into a new 3x3 matrice, shrink by delete every other row or column.
That why I called it a sandwhich, or interpreter.. I am not after a skip-pixel-median at all.
When you posted the 5-median script, I thought maybe pre-filter can not be done in script, so you

posted 5-median script instead. So I went on to illustrate a much more (babbling)details on how
and when such filter work and when it "won't" work so that if any programmer interest enough to

produce such matrice transformation plugin will have enough info not to misuse it, this is the
least I can do.

With more analysis and testing, I suspect even on HD source, Lot of small detail features are

probably around 1.5 +/- 0.2 pixel wide. If that is the average case. skip "HALF" pixel
is way better than skip 1 pixel. I never belief any fix parameter tool is useful. a size variable
skip_pixel plugin is much better, is definite what I am after.

Small detail features pixel size - 1 = Skip pixel size
Thus 1.5 - 1= 0.5 = skip "HALF" pixel

Removegrain use 9 pixels, However
skip "HALF" pixel use 17 nearest pixels from from a 5x5 matrice, then transform it to a 9 pixels
3x3 matrice. Since any hard code 3x3 degrainers can only see 3x3, there is no way we can feed
a 5x5 to it. Skip_pixel_plugin is needed to shrink it to 3x3.


Need all 17 pixels A,x and w from source as below

x o x o x
o w w w o
x w A w x
o w w w o
x o x o x

same as

x1 o9 x2 o9 x3
o9 w1 w2 w3 o9
x4 w4 Aa w5 x5
o9 w6 w7 w8 o9
x6 o9 x7 o9 x8

to get new 3x3

y1 y2 y3
y4 Aa y5 ---> what degrainers see
y6 y7 y8


The Y is calculate by any nearest "pair" of w,x
y1 = (w1 + x1)/2,...., y8 = (w8 + x8)/2.

This being a 17 pixels sample size used, thus have 4x4 matrice + 1 pixel effects.
Much more accurate than a basic 3x3 or a 3x3 skip 1 pixel matrice. It has best of both world

feature.

So if skip_pixel(0.5) can be assembly optimized. It will be a big plus to the old degrainers.

Can anyone with thorough CPU registers knowledge enlight me if present day CPU have enough physical
registers to allow such assembly optimization. ie. just a (A+B)/2 routine on 8 pairs of
pixels. ATM, My hunch is yes.

TheProfileth
18th June 2011, 08:29
So is something akin to
x o x o x
o o o o o
x o x o x
o o o o o
x o x o x
which compresses down to

x x x
x x x
x x x
Well I can see this being slightly more useful than what was previously mentioned but still it is going to be inaccurate mainly just due to the massive pixel reduction via the row and column deterioration.

Ponder
18th June 2011, 09:48
What are you trying to say or show? There's a few lines of out-commented denoisers.

I uncommented those Denoisers to run test to see if I get "messup pic effect".
I did not see the same "big messup effect", hence I replied "results look fine". Yes,
there are tons of dancing left on hqdn3d(5), but that was not purpose of the test.

DirectShowSource("b:\wheat.mkv", fps=23.976)
separatefields().turnleft()
assumeframebased().separatefields()

#Spatial_Denoiser_of_Choice()
#RemoveGrain(18) #or mode 17,2
#hqdn3d(5)
#hqdn3d(0,0,3,6)
#FFT3DFilter(sigma=6,sigma2=3,sigma3=2,sigma4=6)
#DeGrainMedian(mode=0)
#RemoveGrainHD()
#TemporalRemoveGrainHD()

weave().turnright()
assumefieldbased().weave()
return last

With your proposal of a 5-point median, in combination with 1-pixel-skipping
Now I know what you are getting at. No,no.., "not combination". Mega misunderstand from
thread 1.

Source.Skip_ Pixel_Filter(1).5-point_median.RemoveGrain(4) Guarantee an sort of end of the world
scenario.

RemoveGrain(4) or (9), by itself already means no edges.

From the 1st thread.
Clip.Skip_ Pixel_Filter(by 1 spatial offset).medianfilter()

medianfilter() here is like RemoveGrain(18), not destructive mode like RemoveGrain(4).

it is like Source.Skip_ Pixel_Filter(1).RemoveGrain(18) for 1920px1080.

When replacing medianfilter with a denoise filter
for HD source,...

it is then like Source.Skip_ Pixel_Filter(1).DeGrainMedian() or
Source.Skip_ Pixel_Filter(0.5).DeGrainMedian() if we have a variable Skip_ Pixel_Filter.

Ponder
18th June 2011, 10:23
@TheProfileth
Look like everyone misunderstood my illustration. no downsizing, just remap mainly for sources
that are big eg.1920x1080, ie for big pixel, center point preserve. for 1280p, my deduction chart
suggest skip half pixel is much better. Remember this eg. Removegrain "ONLY" see and grab 9 pixels
to compare when it chooses a center pixel. skip_pixel(1) also sends 9 pixels to Removegrain, no more
and no less but with more statistically accuracy "IF" you source dimension big like 1920x1080.
1440p is not even safe for skip pixel(1), just break even point, no margin of safety from my chart.
So no false hope here.

skip_pixel(0.5) sends 17 pixels by melting it into 9 pixels, so Removegrain actually
get info from 17 pixels but through 9 pixels. So that is not a bad thing at all.

Didée
18th June 2011, 11:09
Oh. Meanwhile we've arrived at halfpel interpolation. How long until quarterpel or 16th-pel ....


It's not that I would've misunterstood you ...

@Didee, all these times, we talked about 2 different things!

[...]

9 pixels! not 5 pixels. skip every other row and skip every other column. All the matrices I showed
had 9 pixels. How did you get a 5 pixels impression.
It basically doesn't matter too much if a 5-sample or 9-sample median is calculated. With pixel skipping, it's only 2 different variants of a flawed concept.

The picture I posted was done with 9 samples. And very obviously, this 5samples->9samples change was not the rescue.

- Theory says there should arise problems.

- Practice was done and has proven theory.

= Case closed.


Spatial filters have a certain scope and aptitude. Once the thereby-implied limits are understood, it becomes obvious that changing the sampling pattern is like ...

"re-inventing the wheel, but this time with a rectangular shape!"