Welcome to Doom9's Forum, THE in-place to be for everyone interested in DVD conversion.

Before you start posting please read the forum rules. By posting to this forum you agree to abide by the rules.

 

Go Back   Doom9's Forum > Capturing and Editing Video > Avisynth Usage

Reply
 
Thread Tools Search this Thread Display Modes
Old 2nd April 2014, 21:14   #1  |  Link
D9JK
Registered User
 
Join Date: Feb 2010
Posts: 41
How does one get the average color of the frame?

Hello,

I thought this would be a simple task, but it's giving me a bit of trouble. I need a filter that averages the entire (current) frame into a single color, can be grayscale as well. If you've used Photoshop, I'm after an effect that is similar to "Filter/Blur/Average".

Some background (not necessary to read):

First I tried simply general blur filters with obscenely high values, but where doing this seemed to produce a flat color, it was simply gray across all frames, which was wrong because the average brightness should clearly have varied across the video frames. Additionally, applying excessive blurring seems to pick up some blackness from outside the image frame, but this may depend on which blur filter is being used.

Next I tried a slightly hacky way; resizing a frame to 1x1 (in image editing, this works as average blur filter), and then bringing it back to the original size. But the lowest resolution the resize filters allow is 4x4, so that didn't work.

Then I found a mention of a filter called "AverageLuma". As this sounded promising, I gave it a try. Apparently simply entering AverageLuma() causes an error message about invalid parameters for the filter... but I cannot find any helpful documentation about it. The filter is not listed neither in the internal nor external filters of Avisynth.

Perhaps I'm missing something.
D9JK is offline   Reply With Quote
Old 2nd April 2014, 21:44   #2  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
Suggest take a look at Showchannels.#
http://forum.doom9.org/showthread.php?t=163829
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???

Last edited by StainlessS; 2nd April 2014 at 22:20.
StainlessS is offline   Reply With Quote
Old 2nd April 2014, 22:14   #3  |  Link
D9JK
Registered User
 
Join Date: Feb 2010
Posts: 41
Your filter is a useful analyzing tool, but currently I'm looking for a filter that averages the entire frame into a single, flat color. That is, the filter should actually modify the frame contents.

Thank you anyway.
D9JK is offline   Reply With Quote
Old 2nd April 2014, 22:32   #4  |  Link
poisondeathray
Registered User
 
Join Date: Sep 2007
Posts: 5,375
Quote:
Originally Posted by D9JK View Post

Next I tried a slightly hacky way; resizing a frame to 1x1 (in image editing, this works as average blur filter), and then bringing it back to the original size. But the lowest resolution the resize filters allow is 4x4, so that didn't work.
If you work in RGB, you can use pointresize(1,1)
poisondeathray is offline   Reply With Quote
Old 2nd April 2014, 22:49   #5  |  Link
Gavino
Avisynth language lover
 
Join Date: Dec 2007
Location: Spain
Posts: 3,431
Quote:
Originally Posted by poisondeathray View Post
If you work in RGB, you can use pointresize(1,1)
But that won't average the pixels, it will just replicate the centre one.
EDIT: Not the centre pixel, but the corner one (bottom left for RGB).

Quote:
Originally Posted by D9JK View Post
Then I found a mention of a filter called "AverageLuma". As this sounded promising, I gave it a try. Apparently simply entering AverageLuma() causes an error message about invalid parameters for the filter... but I cannot find any helpful documentation about it. The filter is not listed neither in the internal nor external filters of Avisynth.
AverageLuma() is not a filter - it is a run-time function that gives a numeric result, and it can only be used inside a run-time filter such as ScriptClip(). This should give you what you want (assuming a YUV source):
Code:
ScriptClip("""
  y = round(AverageLuma())
  u = round(AverageChromaU())
  v = round(AverageChromaV())
  BlankClip(last, color_yuv=65536*y + 256*u + v)
""")
__________________
GScript and GRunT - complex Avisynth scripting made easier

Last edited by Gavino; 3rd April 2014 at 09:52. Reason: clarify PointResize behaviour
Gavino is offline   Reply With Quote
Old 2nd April 2014, 23:29   #6  |  Link
D9JK
Registered User
 
Join Date: Feb 2010
Posts: 41
Thanks Gavino, and sorry for my ignorance, but how do I use it exactly? I've written a few custom functions, but ScriptClip looks a bit different.
D9JK is offline   Reply With Quote
Old 2nd April 2014, 23:39   #7  |  Link
Gavino
Avisynth language lover
 
Join Date: Dec 2007
Location: Spain
Posts: 3,431
Just add that code after your source filter, eg

AviSource("mysource.avi") # or whatever you are using
ScriptClip("""
... as shown earlier ...
""")
__________________
GScript and GRunT - complex Avisynth scripting made easier
Gavino is offline   Reply With Quote
Old 2nd April 2014, 23:49   #8  |  Link
D9JK
Registered User
 
Join Date: Feb 2010
Posts: 41
Ah, I see. I'm usually using filters this way:

Code:
Changed = Original.Grayscale().Invert()
The script is a bit long when I have other filters in there already, but I suppose I can put it in a new custom function, then give it a name short enough.

Thanks a bunch!
D9JK is offline   Reply With Quote
Old 3rd April 2014, 16:43   #9  |  Link
pandy
Registered User
 
Join Date: Mar 2006
Posts: 1,049
Perhaps resize will work for you? (1 pixel probably not).
Bilinear work to 2x2 then 4 - 5 time in series Blur (1.5, 1.5) should solve your problem (at least from my perspective looks like all 4 pixels have same value - obviously this is RGB space, for YCbCr can be else, probably limit is 4x4 and multiple pass Blur (16 times or more) is required).

Last edited by pandy; 3rd April 2014 at 16:59.
pandy is offline   Reply With Quote
Old 4th April 2014, 16:09   #10  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
This will also work with RGB & YUY2, Need Gavino's Grunt() plugin for the "After_frame=True" arg.
EDIT: No you dont, see next post.


Code:
ShowChannels(SetVar=True,Show=False)
ScriptClip("""
  SC_Ave_1 = (SC_Ave_1<0.0) ? 0.0 : SC_Ave_1      # If Avisynth v2.6, convert Y8 channels 1 and 2 to 0 (will be -1.0)
  SC_Ave_2 = (SC_Ave_2<0.0) ? 0.0 : SC_Ave_2
  z = (256*Round(SC_Ave_0)+Round(SC_Ave_1))*256+Round(SC_Ave_2)
  IsRGB ? BlankClip(last, color=z) : BlankClip(last, color_yuv=z)
""",after_frame=True)
EDITED: Added Y8 guard.

You can even select an area of the frame to examine via ShowChannels x,y,w,h args.

Code:
Changed = Original.Grayscale().Invert()
will work equally well as here (you dont need to have everything on one line)
Code:
Original.Grayscale()
Invert()
ShowChannels(SetVar=True,Show=False)
ScriptClip("""
  SC_Ave_1 = (SC_Ave_1<0.0) ? 0.0 : SC_Ave_1      # If Avisynth v2.6, convert Y8 channels 1 and 2 to 0 (will be -1.0)
  SC_Ave_2 = (SC_Ave_2<0.0) ? 0.0 : SC_Ave_2
  z = (256*Round(SC_Ave_0)+Round(SC_Ave_1))*256+Round(SC_Ave_2)
  IsRGB ? BlankClip(last, color=z) : BlankClip(last, color_yuv=z)
""",after_frame=True)
Changed=Last
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???

Last edited by StainlessS; 5th April 2014 at 08:58.
StainlessS is offline   Reply With Quote
Old 4th April 2014, 23:12   #11  |  Link
Gavino
Avisynth language lover
 
Join Date: Dec 2007
Location: Spain
Posts: 3,431
Quote:
Originally Posted by StainlessS View Post
Need Gavino's Grunt() plugin for the "After_frame=True" arg.
The built-in ScriptClip() also supports the after_frame arg.
__________________
GScript and GRunT - complex Avisynth scripting made easier
Gavino is offline   Reply With Quote
Old 6th April 2014, 20:29   #12  |  Link
D9JK
Registered User
 
Join Date: Feb 2010
Posts: 41
Although my original intention was something else, I also wrote a crude automatic white balance function as a test:
Code:
function AutoWB(clip X, float O)
 {
  X
  ConvertToYV12()
  ScriptClip(""" u=round(AverageChromaU()) v=round(AverageChromaV()) BlankClip(last, color_yuv=65536*128 + 256*u + v) """)
  Invert()
  Overlay(X, mode="softlight")
  Overlay(X, mode="chroma", opacity=1-O)
 }
I'm probably not going to use it very much, as automatic white balance functions would have to be much more sophisticated to be practical. But out of curiosity: is ScriptClip limited to working on one frame at a time, or would it be possible to somehow take nearby frames into consideration? I'm asking this because the AutoWB function above can of course produce very abrupt adjustments on the WB, and averaging the color of eg. 10-30 neighboring frames would help in making the effect less apparent.
D9JK is offline   Reply With Quote
Old 6th April 2014, 22:58   #13  |  Link
Gavino
Avisynth language lover
 
Join Date: Dec 2007
Location: Spain
Posts: 3,431
Quote:
Originally Posted by D9JK View Post
is ScriptClip limited to working on one frame at a time, or would it be possible to somehow take nearby frames into consideration?
Each output frame can be derived from several input frames, although with the standard ScriptClip(), to get access to previous or future frames you have to construct additional clips via filters such as Trim() or SelectEvery().
It's easier with the GRunT version of ScriptClip() - for example, AverageChromaU(-2) gives the average U value of the frame two before the current one.
__________________
GScript and GRunT - complex Avisynth scripting made easier
Gavino is offline   Reply With Quote
Old 7th April 2014, 13:14   #14  |  Link
D9JK
Registered User
 
Join Date: Feb 2010
Posts: 41
Thanks Gavino, I'll take a look. That's a funny abbreviation, too. :-)
D9JK is offline   Reply With Quote
Old 11th August 2015, 14:33   #15  |  Link
Dogway
Registered User
 
Join Date: Nov 2009
Posts: 2,361
Gavino, do you know how to access every other frame? I am trying to compare YDifferenceToNext() between current and current+2, but I'm out of ideas, this is what I'm trying:

Code:
scriptclip("""Subtitle(c,string(YDifferenceToNext(Fmod(current_frame, 2.0)==0.0?even:odd)),align=7,size=30)""",
            \ args="c,even=selectevery(c,2,0,2),odd=selectevery(c,2,1,3)")
 }
What I get is a value of 0 every other frame as if they were repeated.
Dogway is offline   Reply With Quote
Old 11th August 2015, 14:48   #16  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
Code:
 RT_YDifference(clip,int "n"=current_frame,int "delta"=1,int "x"=0,int "y"=0,int "w"=0,int "h"=0,int "x2"=x,int "y2"=y,
      bool "interlaced"=false,int "Matrix"=(Width>1100||Height>600?3:2))
  Returns FLOAT value luma difference (0.0 -> 255.0) between frame n area x,y,w,h, and frame (n+delta) area x2,y2,w,h.
  Note, by default it will be equivalent to YDifferenceToNext as delta defaults to 1 and x,y,w,h defaults full frame.
  Note, 'x2' and 'y2' default to 'x' and 'y' respectively.

  Eg, RT_YDifference(clip,delta=0,y2=1,interlaced=true)
    Would difference the even and odd lines of the same frame,
RT_YDifference(delta=2)
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???
StainlessS is offline   Reply With Quote
Old 11th August 2015, 14:54   #17  |  Link
Dogway
Registered User
 
Join Date: Nov 2009
Posts: 2,361
If that means there's no way with built-in functions then thanks for the help.
Dogway is offline   Reply With Quote
Old 11th August 2015, 15:16   #18  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
Code:
Avisource("E:\v\avatar.avi")
target = Trim(2,0)
# target = SelectEvery(2,2,3) # EDIT: Added


SS="""
    x = LumaDifference(Target)
    y = RT_YDifference(delta=2)
    Subtitle(string(x) + " " + String(y),align=7,size=30)
"""

Last.scriptclip(SS, args="Target")
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???

Last edited by StainlessS; 11th August 2015 at 15:27.
StainlessS is offline   Reply With Quote
Old 11th August 2015, 15:19   #19  |  Link
Dogway
Registered User
 
Join Date: Nov 2009
Posts: 2,361
Yes, thank you, RT_Stats plugin. If possible I will try to keep using built-in function, if not possible I guess RT_YDifference() is fine.
Dogway is offline   Reply With Quote
Old 11th August 2015, 15:26   #20  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
Already given built-in ie LumaDifference, RT_ was just a check for valid.
can also use SelectEvery(2,2,3) instead of trim.

Or more like your original post

Code:
return Avisource("E:\v\avatar.avi").scriptclip("""Subtitle(string(LumaDifference(SelectEvery(2,2,3))),align=7,size=30)""")
EDIT: Or probably SelectEvery(1,2) better

Code:
return Avisource("E:\v\avatar.avi").scriptclip("""Subtitle(string(LumaDifference(SelectEvery(1,2))),align=7,size=30)""")
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???

Last edited by StainlessS; 11th August 2015 at 20:28.
StainlessS is offline   Reply With Quote
Reply

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 21:48.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.