ConditionalFilter

ConditionalFilter (clip testclip, clip source1, clip source2, string filter, string operator, string value, bool ''show'')

ConditionalFilter restituisce il clip source1 quando si verifica la condizione costituita da ''filter+operator+value'' , in caso contrario restituisce source2. Se filter non è esplicitamente applicato ad un clip, esso sarà applicato a testclip. L' audio è preso da source1.

Un esempio. Scegliere frames da vid_blur quando il valore medio del luma di un frame è < 20. In caso contrario i frames saranno presi da vid . Aggiungendo alla fine "true" si evidenzieranno sullo schermo i valori effettivi:

vid = AviSource("file")
vid_blur = vid.Blur(1.5)
ConditionalFilter(vid, vid_blur, vid, "AverageLuma()", "lessthan", "20")

La stringa filter può essere un qualsiasi filtro interno, ma anche alcuni filtri predefiniti (vedere sotto).
La stringa operator può essere "equals", "greaterthan" o "lessthan". O rispettivamente "=", ">" o"<" .

ScriptClip

ScriptClip (clip, string function, bool ''show', bool "after_frame")

ScriptClip restituisce il clip elaborato dalla function applicata ad ogni frame.

Alcuni esempi :
# Questo mostra le differenze tra il frame precedente ed il corrente:
clip = AviSource("c:\file.avi")
ScriptClip(clip, "Subtitle(String(YDifferenceFromPrevious))")

# Questo applica ad ogni frame un blur  basato sulle differenze rispetto al precedente.
# E in più mostra come vengono comunicati gli errori rilevati su alcuni frames :)
clip = AviSource("c:\file.avi")
ScriptClip(clip, "Blur(YDifferenceFromPrevious/20.0)")

# Questo applica temporalsoften alle scene statiche ed un blur _variabile_ alle scene movimentate.
# Blur è ora completato correttamente. In più viene assegnata una variabile - e questo giustifica il line break
che è stato inserito:
function fmin(float f1, float f2) {
  return (f1<f2) ? f1 : f2
}
clip = AviSource("c:\file.avi")
ScriptClip(clip, "diff = YDifferenceToNext()"+chr(13)+"diff > 2.5 ? Blur(fmin(diff/20,1.5)) : TemporalSoften(2,7,7,3,2)")

#Mostra il frame-number in un clip:
ScriptClip("subtitle(string(current_frame))")

#Mostra 'frame = frame-number' in un clip:
ScriptClip("""subtitle("frame = " + string(current_frame))""")

Nella v2.55 è stata aggiunta un'opzione after_frame=true/false . Questa stabilisce se lo script debba essere elaborato prima (default) o dopo che il frame sia stato preso dai filtri precedenti.

"Limitazioni": l' output dello script DEVE essere esattamente simile al clip trasferito a ScriptClip (stesso colorspace, larghezza ed altezza). Il clip restituito può avere lunghezza diversa - ma quella che vuiene usata è sempre la lunghezza di "clip" . L'Audio di "clip" rimane inalterato. Usando sorgenti molto diverse (MPEG2DEC3 e AviSource) - è possibile incorrere in errori di colorspace . Questo è un problema conosciuto.

FrameEvaluate

FrameEvaluate (clip clip, script function, bool "after_frame")

Simile a ScriptClip, eccetto che l'output del filter è ignorato. Questo è utile per assegnare variabili, etc. I frames sono passati direttamente partendo dal clip fornito.
Nella v2.53 è stata aggiunta un'opzione after_frame=true/false . Questa stabilisce se lo script debba essere elaborato prima (default) o dopo che il frame sia stato preso dai filtri precedenti.

ConditionalReader

Questo filtro consente di importare qualsiasi informazione dentro una variabile selezionabile.

Vedere la pagina dedicata a ConditionalReader .

Runtime Functions

Queste sono funzioni interne che sono calcolate ad ogni frame.

Queste restituiscono il valor medio dei pixel di un plane (richiedono YV12, ISSE):
AverageLuma (clip)
AverageChromaU (clip)
AverageChromaV (clip)

Queste restituiscono un valore float compreso tra 0 e 255 del valore assoluto delle differenze tra 2 planes (richiedono YV12, ISSE):
RGBDifference (clip1, clip2)
LumaDifference (clip1, clip2)
ChromaUDifference (clip1, clip2)
ChromaVDifference (clip1, clip2)

Usando queste funzioni viene definito un clip "implicit last" (il primo parametro può non essere specificato), sicchè il primo parametro è sostituito dal testclip.

Questo dovrebbe essere veramente funzionale per determinare i cambi di scena:
RGBDifferenceFromPrevious (clip)
YDifferenceFromPrevious (clip)
UDifferenceFromPrevious (clip)
VDifferenceFromPrevious (clip)
RGBDifferenceToNext (clip)
YDifferenceToNext (clip)
UDifferenceToNext (clip)
VDifferenceToNext (clip)
 

# Questo sostituisce l'ultimo frame prima di un cambio di scena
# col primo frame dopo il cambio di scena:
ConditionalFilter(last, last, last.trim(1,0), "YDifferenceToNext()", ">", "10", true)

Altre funzioni interne:

YPlaneMax (clip, float threshold)
UPlaneMax (clip, float threshold)
VPlaneMax (clip, float threshold)
YPlaneMin (clip, float threshold)
UPlaneMin (clip, float threshold)
VPlaneMin (clip, float threshold)
YPlaneMedian (clip)
UPlaneMedian (clip)
VPlaneMedian (clip)
YPlaneMinMaxDifference (clip, float threshold)
UPlaneMinMaxDifference (clip, float threshold)
VPlaneMinMaxDifference (clip, float threshold)

Threshold è una percentuale che stabilisce quanti pixels sono consentiti sopra o sotto il minimo. Questa soglia è opzionale e vale 0 di default.

Se avete capito quanto esposto sopra, potete procedere con "advanced conditional filtering", che vi svelerà qualcosa in più sul conditional filtering.

Advanced conditional filtering: part I

Per capire questa sezione è necessario conoscere alcune cose sulle funzionalità di AviSynth :
Gli scripts sono esaminati dall'alto al basso, ma quando viene richiesto un frame, viene chiamato per primo l'ultimo filtro ed il frame procede all'insù nella catena dei filtri . Ad esempio:

AviSource("myfile.avi")
ColorYUV(analyze=true)
Histogram()
Aprendo lo script in Vdub ecco quello che succede In questo modo la catena di filtri lavora all'indietro cosa che consente ai filtri di richiedere alla sorgente più di un frame contemporaneamente.

I Conditional filters tuttavia, hanno bisogno di elaborare gli scripts prima di richiedere frames ai filtri che stanno prima, perchè necessitano conoscere quale filtro chiamare. Altro importante problema è che solo le variabili definite global nel conditional filter 'environment' possono essere usate all'esterno (e vice versa). Date un'occhiata al seguente script

v = AviSource("E:\Temp\Test3\atomic_kitten.avi").ConvertToYV12

function g(clip c)
{
  global w = c
  c2 = ScriptClip(c, "subtitle(t)")
  c3 = FrameEvaluate(c2, "t = String(text)")
  c4 = FrameEvaluate(c3, "text = YDifferenceFromPrevious(w)")
  return c4
}

g(v)
Questa catena di filtri lavora in questo modo: Come si può vedere , w è definita come "variabile globale". In questo modo la si può usare successivamente nello script nel conditional environment. Se si volessero usare le variabili t e text in una diversa function (dentro o fuori il conditional environment),anch'esse devono essere definite come global variables. Allora ad esempio:
v = AviSource("E:\Temp\Test3\atomic_kitten.avi").ConvertToYV12

function g(clip c)
{
  global w = c
  c2 = ScriptClip(c, "subtitle(t)")
  c3 = FrameEvaluate(c2, "me()")
  c4 = FrameEvaluate(c3, "global text = YDifferenceFromPrevious(w)")
  return c4
}

function me()
{
  global t = String(text)
}

g(v)
Buona parte dello script precedente è ridondante e può essere eliminato. Lo script seguente produce lo stesso output
v = AviSource("c:\clip.avi")
ScriptClip(v, "Subtitle(String(YDifferenceFromPrevious))")
In the following section some frame dependent info will be written to a text-file.

Advanced conditional filtering: part II

Nel seguente esempio alcune informazioni che dipendono dal frame saranno scritte in un text-file. La prima variabile "a" indica se il frame è combed (per una certa soglia "threshold"). Notare che IsCombed è un filtro del plugin Decomb . La seconda variabile "b" indica se nel frame c'è "molto" movimento.

global sep="."
global combedthreshold=25

function IsMoving()
{
global b = (diff < 1.0) ? false : true
}

function CombingInfo(clip c)
{
file = "F:\interlace.log"
global clip = c
c = WriteFile(c, file, "a", "sep", "b")
c = FrameEvaluate(c, "global a = IsCombed(clip, combedthreshold)")
c = FrameEvaluate(c, "IsMoving")
c = FrameEvaluate(c,"global diff = 0.50*YDifferenceFromPrevious(clip) + 0.25*UDifferenceFromPrevious(clip) + 0.25*VDifferenceFromPrevious(clip)")
return c
}

v = mpeg2source("F:\From_hell\from_hell.d2v").trim(100,124)
CombingInfo(v)

Nella sezione seguente considereremo un esempio di "adaptive motion/resizing filter".

Advanced conditional filtering: part III

Eccovi alcuni filtri "adaptive motion/resizing" apparsi nei forums. Questi filtri discriminano tra low, medium ed high motion presente in un clip (sulla base dei frames). Per fare ciò, si possono usare filtri diversi per diversi tipi di movimento presenti nel clip. In generale, si dovrebbe usare temporal smoothing nelle scene a basso movimento, spatial smoothing nelle scene ad alto movimento e spatio-temporal smoothing nelle scena a movimento medio.
Di seguito, una versione semplificata del QUANTIFIED MOTION FILTER v1.5 b1 (10/07/2003) di HomiE FR:

----------------------------------------------------
# QUANTIFIED MOTION FILTER v1.3
# LOADING AVISYNTH PLUGINS
LoadPlugin("C:\PROGRA~1\GORDIA~1\mpeg2dec3.dll")
LoadPlugin("C:\PROGRA~1\GORDIA~1\TemporalCleaner.dll")
LoadPlugin("C:\PROGRA~1\GORDIA~1\FluxSmooth.dll")
LoadPlugin("C:\PROGRA~1\GORDIA~1\UnFilter.dll")

# LOADING QUANTIFIED MOTION FILTER SCRIPT

Import("E:\temp\QMF\qmf.avs")

# LOW MOTION FILTER FUNCTION
# -> SHARP RESIZING + TEMPORAL ONLY
function Low_Motion_Filter(clip c)
{
  c = TemporalCleaner(c, 5, 10)
  c = LanczosResize(c, 512, 272)
  return c
}

# MEDIUM MOTION FILTER FUNCTION
# -> NEUTRAL BICUBIC RESIZING + TEMPORAL & SPATIAL
function Medium_Motion_Filter(clip c)
{
  c = FluxSmooth(c, 7, 7)
  c = BicubicResize(c, 512, 272, 0.00, 0.50)
  return c
}

# HIGH MOTION FILTER FUNCTION
# -> SOFT RESIZING + SPATIAL ONLY
function High_Motion_Filter(clip c)
{
  c = FluxSmooth(c, -1, 14)
  c = UnFilter(c, -30, -30)
  c = BilinearResize(c, 512, 272)
  return c
}

# OPENING VIDEO SOURCE
AviSource("E:\temp\QMF\britney-I_love_rock_'n_roll.avi")
ConvertToYV12(interlaced=true)
Telecide(0)

# APPLYING ADAPTATIVE RESIZING FILTER (USING QMF)
QMF()
----------------------------------------------------

# QUANTIFIED MOTION FILTER (17/08/2003) by HomiE FR (homie.fr@wanadoo.fr)
# MOTION ESTIMATION FUNCTION
function ME()
{
  # SETTING MOTION LEVEL ACCORDING TO AVERAGE DIFFERENCE [1]
  global motion_level = (diff < threshold_lm) ? 0 : motion_level
  global motion_level = (diff >= threshold_lm && diff <= threshold_hm) ? 1 : motion_level
  global motion_level = (diff > threshold_hm) ? 2 : motion_level
}

# QUANTIFIED MOTION FILTER FUNCTION
function QMF(clip c, float "threshold_lm", float "threshold_hm", bool "debug")
{
  # SETTING MOTION LEVELS THRESHOLDS [2]
  threshold_lm = default(threshold_lm, 4.0)
  threshold_hm = default(threshold_hm, 12.0)
  global threshold_lm = threshold_lm
  global threshold_hm = threshold_hm

  # ENABLING/DISABLING DEBUG INFORMATION [3]
  debug = default(debug, false)

  # INITIALIZING MOTION LEVEL
  global motion_level = 0

  # SETTING PRESENT CLIP [4]
  global clip = c

  # GETTING OUTPUT RESOLUTION [5]
  width = Width(Low_Motion_Filter(c))
  height = Height(Low_Motion_Filter(c))
  global c_resized = PointResize(c, width, height)

  # APPLYING MOTION FILTER ACCORDING TO MOTION LEVEL [6]
  c = ConditionalFilter(c, Low_Motion_Filter(c), c_resized, "motion_level", "=", "0")  # [6a]
  c = ConditionalFilter(c, Medium_Motion_Filter(c), c, "motion_level", "=", "1")       # [6b]
  c = ConditionalFilter(c, High_Motion_Filter(c), c, "motion_level", "=", "2")         # [6c]

  # PRINTING DEBUG INFORMATION [7]
  c = (debug == true) ? ScriptClip(c, "Debug()") : c

  # GETTING MOTION LEVEL THROUGH MOTION ESTIMATION [8]
  c = FrameEvaluate(c, "ME()")

  # GETTING DIFFERENCES BETWEEN PAST/PRESENT FRAMES [9]
  c = FrameEvaluate(c, "global diff = 0.50*YDifferenceFromPrevious(clip) + 0.25*UDifferenceFromPrevious(clip) + 0.25*VDifferenceFromPrevious(clip)")
  return c
}

# DEBUG INFORMATION FUNCTION
function Debug(clip c)
{
  # PRINTING VERSION INFORMATION [10]
  c = Subtitle(c, "Quantified Motion Filter", x=20, y=30, font="lucida console", size=18, text_color=$FFFFFF)
  c = Subtitle(c, "by HomiE FR (homie.fr@wanadoo.fr)", x=20, y=45, font="lucida console", size=14, text_color=$FFFFFF)

  # PRINTING MOTION ESTIMATION INFORMATION [11]
  c = Subtitle(c, "motion estimation", x=20, y=85, font="lucida console", size=18, text_color=$FFFFFF)
  c = Subtitle(c, "diff = "+string(diff), x=20,y=110, font="lucida console", size=16, text_color=$FFCCCC)

  # PRINTING QUANTIFIED MOTION FILTER INFORMATION [12]
  c = Subtitle(c, "quantified motion filter", x=20, y=135, font="lucida console", size=18, text_color=$FFFFFF)
  c = (motion_level == 0) ? Subtitle(c, "scene type = low motion", x=20, y=160, font="lucida console", size=16, text_color=$66FF66) : c
  c = (motion_level == 1) ? Subtitle(c, "scene type = medium motion", x=20, y=160, font="lucida console", size=16, text_color=$66FF66) : c
  c = (motion_level == 2) ? Subtitle(c, "scene type = high motion", x=20, y=160, font="lucida console", size=16, text_color=$66FF66) : c
  return c
}
----------------------------------------------------
La catena di filtri lavora così:

Alcuni dettagli sono stati omessi, ma lo script in definitiva lavora in questo modo.

$Date: 2004/09/26 19:49:40 $