Log in

View Full Version : Averaging pixels (by downsizing image?) - solved


redfordxx
16th March 2005, 19:34
*********************EDIT:
If you happen to need average pixel like this, look directly at posts
17th March 2005 00:29
27th March 2005 21:47
There is also a function ShrinkBy2 in SSETools plugin which "sounds" like it could work, but I didn't check and AFAIK no docs are available.
**********************
Hi,
I want to make average of each block of 4x4 pixels (in YV12) on mod4 sized clip. I thought a way is via downsizing. More exactly, when I have block like this (numbers are colors)
0011
0011
4433
4433
I want to get
2222
2222
2222
2222 etc.

Via downsizing it would be
22
22
and then PointResize back to original size.

But I never achieved it. I tried different resizers.. these aliasing or sharpening or whatever effects cause sometimes result like this:
0000
0000
0000
0000
into
11
11
when there was some value in nearby block. Similar for 8x8.

Thanx
R.

E-Male
16th March 2005, 20:27
maybe none of the avbisynth resizers is blockbased

a blockbased downsizer or averager shouldn't be hard if you give some more details on what you want

redfordxx
16th March 2005, 22:01
Originally posted by E-Male
...on what you want When I have frame of a clip and I downsize it by two, I would like to have in each pixel of the downsized clip
average of colors of the four relevant pixels of original clip, which were merged by downsizing.

E-Male
16th March 2005, 22:56
what does "relevant" mean for you?
what colorspace?
"by 2" means halfing width AND hight each?

redfordxx
16th March 2005, 23:12
Originally posted by E-Male
what does "relevant" mean for you?
what colorspace?
"by 2" means halfing width AND hight each?
When downsizing by 2 both width AND height, for each pixel in the new smaller picture, there were exactly four pixels (2x2) in the original. These pixels I meant are relevant to the new one. Bad expression.

YV12
The same priciple as for Y sould work for U,V --- only doublesized

Manao
16th March 2005, 23:25
Just do :

bilinearresize(half_width, half_height).bilinearresize(quarter_width, quarter_height).pointresize(width, height)

It'll work

redfordxx
16th March 2005, 23:58
Originally posted by Manao
Just do :

bilinearresize(half_width, half_height).bilinearresize(quarter_width, quarter_height).pointresize(width, height)
It'll work
No it doesnot.

Look (I'm testing it only in one channel, so don't be scared by the color;))
http://img18.exs.cx/img18/7460/original8ug.th.png (http://img18.exs.cx/my.php?loc=img18&image=original8ug.png)
http://img18.exs.cx/img18/6855/averaged6di.th.png (http://img18.exs.cx/my.php?loc=img18&image=averaged6di.png)
the second one is with higher contrast, to see the difference.
Just try swithing the images fast. You will easily find blocks on the second pic, where the same block on first image is 100% clear. E.g. top left one and the one below...

Mug Funky
17th March 2005, 00:52
reduceby2()

Si
17th March 2005, 01:05
Just to fully clarify - do you want this

A B W X
C D Y Z
J K P Q
L M R S

made into

E E V V
E E V V
I I N N
I I N N

Where E is Average(A,B,C,D), V= Average(W,X,Y,Z) etc

or something else

regards
Simon

redfordxx
17th March 2005, 01:16
Originally posted by Mug Funky
reduceby2()
Again, No, also already tried.

redfordxx
17th March 2005, 01:18
Originally posted by Si
Just to fully clarify - do you want this

A B W X
C D Y Z
J K P Q
L M R S

made into

E E V V
E E V V
I I N N
I I N N

Where E is Average(A,B,C,D), V= Average(W,X,Y,Z) etc

or something else

regards
Simon Etc... YES.

redfordxx
17th March 2005, 01:21
I wonder if bicubic resize is the solution with setting these extra parameters... I don't know what they mean.

Didée
17th March 2005, 01:29
DEdgeMask(0,255,0,255,"0 0 0 0 1 1 0 1 1",U=3,V=3).PointResize(50%).PointResize(100%)

Not sure which points actually are taken by PointResize, though. Eventually the kernel has to be flipped u/d or l/r.

Manao
17th March 2005, 06:41
Edited : i'll wait to be fully awaken...

redfordxx
17th March 2005, 11:45
Originally posted by Didée
DEdgeMask(0,255,0,255,"0 0 0 0 1 1 0 1 1",U=3,V=3).PointResize(50%).PointResize(100%)

Not sure which points actually are taken by PointResize, though. Eventually the kernel has to be flipped u/d or l/r.
Thanx Didée, it works --- I only had to add borders, for the DEdgeMask gave incorrect results, when part of the matrix is outside the frame.

Well, honestly, I didn't expect the solution is so complicated...
(I mean the idea is nice. Probably more CPU time demanding than I thought...)

Kernel=the matrix in "", isn't it?

redfordxx
17th March 2005, 11:50
Originally posted by Manao
Edited : i'll wait to be fully awaken... ?????????????????????

Manao
17th March 2005, 11:53
I got up too early this morning and gave a wrong answer. I deleted it quickly, but i can't delete the whole post, hence the message.

Didée
17th March 2005, 12:19
Manao: Good moaning, erh, morning ... :D

Originally posted by redfordxx
Well, honestly, I didn't expect the solution is so complicated...
(I mean the idea is nice. Probably more CPU time demanding than I thought...)A specialised plugin could do the job in a fraction of the time. We just don't have such a one.
Basically, BilinearResize would do the very same thing. But if it were coded so as to average every 2*2 pixels (as you need here), then the resizer would shift the frame around during downsizing+upsizing combos. For a resizer, that's of course not acceptable.

Kernel=the matrix in "", isn't it? Yes. The string "1 2 3 4 5 6 7 8 9" in DEdgeMask normally would be written1 2 3
4 5 6
7 8 9

BTW, in case you want to get the average out of 8*8 blocks, the simplest way is to use Tom's DCTFilter() with

DCFilter(1,0,0,0,0,0,0,0)

Manao
17th March 2005, 12:29
> BilinearResize would do the very same thing.

No, and that's why I deleted my post : when downsizing by a factor two, the bilinear algorithm takes 4 pixels into accounts ( weighting them 0.25 0.75 0.75 0.25 ). When upsizing, however, it takes only two pixels into account ( 0.5 0.5 ), so the following :

Bilinearresize(double_width, double_height).pointresize(half_width, half_height).pointresize(width, height)

Should give a similar result to your script ( there again, we don't know which pixel is used by pointresize, and an offset is needed )

BTW, Didee, you often use DEgdeMask where i'd use YV12Convolution, especially when i'm not building a mask.

Didée
17th March 2005, 12:39
Ah, yes. Thanks for the correction on the bilinear thingie.

Originally posted by Manao
BTW, Didee, you often use DEgdeMask where i'd use YV12Convolution, especially when i'm not building a mask. Yes indeed. That's a behaviour coming from the fact that there are lots of kernels that cannot be build through the vectorial approach of yv12convolution. Examples:
1 1 1 2 3 2 -1 -1 -1 1 0 0
1 0 1 3 2 3 -1 9 -1 0 1 0
1 1 1 2 3 2 -1 -1 -1 0 0 1
So, sometimes I spare the time for thinking about "is it seperateable?", and quickly type DEdgeMask instead.

But of course here you're right: In this case, on could as well use

yv12convolution("0 1 1","0 1 1")

Mind I was pretty tired as well when writing that post above ;)

redfordxx
17th March 2005, 13:28
Originally posted by Didée
BTW, in case you want to get the average out of 8*8 blocks, the simplest way is to use Tom's DCTFilter() with
DCFilter(1,0,0,0,0,0,0,0) And for U,V colors it makes only 4x4 pixel average (as there is half resolution)?

IDEA: how about for 2x2 average(separately for each color - e.g. Y)?clip
FitY2U
UtoYor it has same problem as just resize?

redfordxx
17th March 2005, 13:31
Originally posted by Didée
use Tom's DCTFilter() with
DCFilter(1,0,0,0,0,0,0,0)
Can you write the formula which is used here?
Can't remember what is (I)DC Transformation...

redfordxx
17th March 2005, 22:05
Originally posted by Didée
DCFilter(1,0,0,0,0,0,0,0)
Well, almost works...

almost means that some blocks look like:22222222
22222222
22222222
11111111
11111111
22222222
22222222
222222221 or 2 represent different colors, 1 always little darker than 2.

Didée
17th March 2005, 23:55
Aaaah ... yes, of course. DCTFilter(1,0,...) keeps the topmost line and leftmost row /*slaps forehead*/.

DCTFilterD(14) should do the job.

Si
18th March 2005, 23:06
So, if using YV12 colourspace then each 4 pixel block shares the same U and V data -yes?

So all thats needed is a 2x2 block averager of the Y plane - yes?

regards
Simon

redfordxx
22nd March 2005, 00:09
Originally posted by Didée
Aaaah ... yes, of course. DCTFilter(1,0,...) keeps the topmost line and leftmost row /*slaps forehead*/.
DCTFilterD(14) should do the job.
Does not. Same result as that before --- 8x8 blocks with stripe in the middle as I described.
But, what is interesting:
Consequently I was experimenting with idct algo's using following script:LoadPlugin("C:\PROGRA~1\MULTIM~1\GORDIA~1\AviSynthPlugins\MaskTools.dll")
LoadPlugin("C:\PROGRA~1\MULTIM~1\GORDIA~1\AviSynthPlugins\dgdecode121.dll")

r=mpeg2source("D:\record\rip\lotr tt\1\tt1new.d2v", CPU=0, iDCT=4) # iDCT=4 is "Reference", right?!
r=r.trim(0,5000).crop(4,76,712,424)
d1=mpeg2source("D:\record\rip\lotr tt\1\tt1new.d2v", CPU=0, iDCT=1)
d1=d1.trim(0,5000).crop(4,76,712,424)
d2=mpeg2source("D:\record\rip\lotr tt\1\tt1new.d2v", CPU=0, iDCT=2)
d2=d2.trim(0,5000).crop(4,76,712,424)
d3=mpeg2source("D:\record\rip\lotr tt\1\tt1new.d2v", CPU=0, iDCT=3)
d3=d3.trim(0,5000).crop(4,76,712,424)
d7=mpeg2source("D:\record\rip\lotr tt\1\tt1new.d2v", CPU=0, iDCT=7)
d7=d7.trim(0,5000).crop(4,76,712,424)
s1=YV12Subtract(r,d1,Y=3,U=3,V=3)
s2=YV12Subtract(r,d2,Y=3,U=3,V=3)
s3=YV12Subtract(r,d3,Y=3,U=3,V=3)
s7=YV12Subtract(r,d7,Y=3,U=3,V=3)
StackHorizontal(Stackvertical(s1,s3),Stackvertical(s2,s7)).ColorYUV(cont_y=2048,cont_u=2048,cont_v=2048)The number 1 and 2 differed from 4=reference mostly in the shape I described. On the other hand, when 3 or 7 differed, it was always nice full blocks.

BTW: Although 4=reference, I tend to like 3 more...

redfordxx
22nd March 2005, 00:12
Originally posted by Si
So, if using YV12 colourspace then each 4 pixel block shares the same U and V data -yes?

So all thats needed is a 2x2 block averager of the Y plane - yes?Well I don't understand, whether this is inteded to be question or answer...

Si
22nd March 2005, 19:13
Its a question :)

I think what you want can be simply acheived by a simple average of the 4 bytes that make up the 2x2 pixel block of a Y plane in a YV12 image.

But I didn't want to code it up if it wasn't that easy.

I'm not called Simple Si for nothing ;)

regards
Simon

redfordxx
22nd March 2005, 19:25
Originally posted by Si
I think what you want can be simply acheived by a simple average of the 4 bytes that make up the 4x4 pixel block of a Y plane in a YV12 image.
Well, whatever plane you are speaking about...

... for this "simple average" I got many answers --- all wrong but the one by Didée: DEdgeMask

Si
27th March 2005, 21:47
I finally knocked up a simple filter (BlockAverage (http://www.geocities.com/siwalters_uk/blockaverage01.zip)) to see if this does what you originally expecting/wanted.



regards
Simon

redfordxx
28th March 2005, 20:29
Originally posted by Si
I finally knocked up a simple filter Well, I havent understood that you're gonna make a filter. Thanks and sorry for making you have effort... because I am already done with the method from Didée and I am averaging all planes 8x8 blocks.