## ConditionalFilter

`ConditionalFilter` (clip testclip, clip source1, clip source2, string expression1, string operator, string expression2, bool "show")

`ConditionalFilter` (podmínkový filtr) vrací source1 , když je splněna podmínka ''expression1+operator+expression2'' pro aktuální snímek, jinak vrací source2. Pokud není žádná funkce v expression1 nebo v expression2 jasně použita na nějaký klip, použije se filtr na testclip . Audio se bere ze source1.

Příklad. Vybereme snímky z klipu vid_blur když je střední jas snímku menší než 20, jinak bereme snímky z výchozího klipu.

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

Přidáním show= "true" zobrazíme aktuální hodnoty parametru na obrazovce.

Řetězce expression1 a expression2 mohou být jakékoliv číselné nebo logické výrazy, a smí zahrnovat vnitřní nebo uživatelské funkce, stejně tak některé přídavné funkce, které jsou předdefinovány ( Runtime Funkce) a speciální runtime proměnnou current_frame (číslo žádaného snímku).
Řetězec operator může být "equals", "greaterthan" nebo "lessthan". Nebo lze použít odpovídající symboly "=", ">" nebo "<" .

## ScriptClip

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

`ScriptClip` vrací klip vrácený funkcí function použité na každý snímek. Řetězec filter může být libovolný vnitřní filtr, ale mohou to být také některé preferované filtry, které jsou předdefinovány ( Runtime Funkce). Přidáním show= "true" zobrazíme aktuální hodnoty parametru na obrazovce.

Několik příkladů:

    # Toto tiskne rozdíl mezi předchozím a aktuálním snímkem:
    clip = AviSource("c:\file.avi")
    ScriptClip(clip, "Subtitle(String(YDifferenceFromPrevious))")

    # Toto používá rozmazání každého snímku v závislosti na rozdílu od předchozího snímku.
    # Toto také zobrazí jaké chyby se oznamují na některých snímcích:)
    clip = AviSource("c:\file.avi")
    ScriptClip(clip, "Blur(YDifferenceFromPrevious/20.0)")

    # Toto použije časové změkčení značně statické scény a proměnné rozmazání na pohyblivé scény.
    # Také rozmazání je zde řádně uzavreno. Také přiřadíme proměnnou - a proto je vloženo přerušení řádku:
    function fmin(float f1, float f2) {
      return (f1<f2) ? f1 : f2
    }
    clip = AviSource("c:\file.avi")
    T = clip.TemporalSoften(2, 7, 7, 3, 2)
    ScriptClip(clip, "diff = YDifferenceToNext()"+chr(13)+"diff>2.5 ? Blur(fmin(diff/20, 1.5)) : T")

    #Zobrazí číslo snímku v klipu:
    ScriptClip("subtitle(string(current_frame))")

    #Zobrazí řetězec 'frame =    the frame-number':
    ScriptClip("""subtitle("frame = " + string(current_frame))""")

Ve v2.55 je přidán parametr after_frame=true/false . Určuje má li skript vyhodnocovat před (což je základní nastavení) nebo až potom, kdy bude snímek doručen od výše stojících filtrů.

"Omezení": Výstup skriptu musí být stejného formátu jako vstup do filtru `ScriptClip` (stejné barevné prostředí, šířka a výška). Vracený klip může mít jinou délku, ale bude použita délka výchozího klipu "clip". Audio ze vstupu "clip" zustává nedotknuto. Pro dva velmi rozdílné zdroje (MPEG2DEC3 a AviSource) - může nastat nesoulad barevných prostredí. To je známý špek.

## FrameEvaluate

`FrameEvaluate` (clip clip, script filter, bool "after_frame")

Podobný jako `ScriptClip`, kromě toho, že výstup z filter je ignorován. To může být užitečné například pro přiřazení proměnných, atd. Vrací se snímky přímo ze vstupního klipu.
Ve v2.53 je přidán parametr after_frame=`true/false` . Určuje má li skript vyhodnocovat před (což je základní nastavení) nebo až potom, kdy bude snímek doručen od výše stojících filtrů.

## ConditionalReader

Tento filtr umožní import libovolné informace ze souboru do některé funkce.

Viz stránky o ConditionalReader .

## Runtime Functions

Jsou vnitřní funkce, vyhodnocované na každém snímku.

Tyto vrací střední hodnotu pixelu na ploše - jasové, nebo barevné (vyžaduje YV12, ISSE):
`AverageLuma` (clip)
`AverageChromaU` (clip)
`AverageChromaV` (clip)

Tyto vrací desetinnou hodnotu mezi 0 a 255 absolutního rozdílu mezi plochami (jasovými, nebo barevnými) dvou klipů (vyžaduje YV12, ISSE):
`RGBDifference` (clip1, clip2)
`LumaDifference` (clip1, clip2)
`ChromaUDifference` (clip1, clip2)
`ChromaVDifference` (clip1, clip2)

Při použití těchto funkcí je aktivní "implicit last" (pokud není specifikován první parametr), takže za první parametr je dosazen testclip (což je poslední zmíněný klip), předávaný filtrům ConditionalFilter, ScriptClip, FrameEvaluate.

Tyto filtry jsou užitečné pro stanovení změny scény:
`RGBDifferenceFromPrevious` (clip)
`YDifferenceFromPrevious` (clip)
`UDifferenceFromPrevious` (clip)
`VDifferenceFromPrevious` (clip)
`RGBDifferenceToNext` (clip)
`YDifferenceToNext` (clip)
`UDifferenceToNext` (clip)
`VDifferenceToNext` (clip)

    # Nahrazuje poslední snímek před změnou scény
    # prvním snímkem z nové scény
    ConditionalFilter(last, last, last.trim(1,0), "YDifferenceToNext()", ">", "10", true)

#### Další vnitřní funkce:

`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 je v procentech, určuje jaký procentuální podíl pixelů může být větší nebo menší než dané minimum. Threshold (prahová hodnota) je volitelná a její výchozí hodnota je 0.

Pokud rozumíte předchozímu oddílu, můžete přejít ke kapitole "rozšířeného podmíněného filtrování", ve které se dozvíte trochu víc o podmíněném filtrování.

## Rozšířené podmíněné filtrování: část I

Pro pochopení této kapitoly je potřeba vědět jak pracuje AviSynth:
Skripty se vytváří od shora dolů, ale když videoeditor žádá snímek, jeho vyhodnocení začíná od posledního snímku a pokračuje k prvnímu nahoru po řetězci filtrů. Například:

    AviSource("myfile.avi")
    ColorYUV(analyze=true)
    Histogram()

Při otevření skriptu ve VirtualDubu se stane následující:

- Když Vdub požaduje snímek, AviSynth požaduje tento snímek z Histogramu.
- Histogram požaduje snímek z ColorYUV,
- ColorYUV žádá snímek od AviSource, který vytváří snímek, a doručí ho ke ColorYUV.
- ColorYUV zpracuje obraz a posílá ho do Histogramu, který ho vrací VirtualDubu.

Tedy řetězec filtrů pracuje v zásadě pozpátku (výstup je spíše 'vytažen' ze spodu než 'protlačen' z hora) což dává možnost použít několik snímků i z výše položených filtrů pro obdržení žádaného snímku.

Nicméně Podmíněné filtry, potřebují vyhodnocovat skripty před tím, než žádají o snímky z výše položených filtrů, proto potřebují vědět, který filtr volat. Další důležitá zvláštnost spočívá v tom, že pouze globální proměnné v 'prostředí' podmíněného filtru, lze použít uvnitř i vně podmíněného filtru . Podívejte se na následující skript

    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)

Tento řetězec filtrů pracuje následovně:

- Při žádosti Vdubu o snímek, AviSynth žádá snímek z g().
- g() žádá snímek z AviSource():
  - AviSynth žádá snímek z druhého operátoru FrameEvaluate.
  - Druhý FrameEvaluate vyhodnotí YDifferenceFromPrevious(w) a přiřadí tuto hodnotu proměnné text , po obdržení žádaného snímku z AviSource. Potom se žádá snímek u prvního operátoru FrameEvaluate.
  - První FrameEvaluate žádá snímek ze ScriptClip po 'vyhodnocení String(text) a přiřazení této hodnoty proměnné t'.
  - ScriptClip žádá snímek z ConvertToYV12(), a vyhodnocení Subtitle(t) v tomto snímku.
  - ConvertToYV12() žádá snímek z AviSource().
- AviSource() vytváří snímek a posílá ho ke g(), který ho vrací VirtualDubu.

Jak je vidět, w je definováno jako globální proměnná. Tímto způsobem ji můžeme později použít ve skriptu v podmíněných filtrech. Pokud chceme použít proměnné t a text v různých funkcích (uvnitř nebo vně podmíněných filtrů) musí být také zadány jako globální proměnné. Tak například:

    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)

Toto je pouze ilustrace pro demonstraci r;zm7ch mo6nost9. Většina skriptu je napsána zbytečně, a může být odstraněna. Následující dvaskripty dají stejný výstup.

    v = AviSource("c:\clip.avi")
    # ScriptClip přijímá víceřádkové skripty:
    scriptclip(v,"
    	text = YDifferenceFromPrevious()
    	t = string(text)
    	subtitle(t)
    ")

    v = AviSource("c:\clip.avi")
    ScriptClip(v, "Subtitle(String(YDifferenceFromPrevious))")

V následující kapitole se naučíme zapisovat do textového souboru informace, patřící ke snímku.

## Rozšířené podmíněné filtrování: část II

V následujícím příkladu, se do textového souboru zapisují některé informace, patřící ke snímku. První proměnná "a" říká, že snímek je prokládaný-zjistí se použitím filtru IsCombed z balíku `Decomb` (pro určitou mezní hodotu (threshold)). Druhá proměnná "b" říká kolik je ve snímku pohybu.

    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)

Můžeme upravit tyto dvě funkce, a odstranit globální proměnné, jejich následujícím zápisem:

    function IsMoving(float diff)
    {
     return (diff >= 1.0)
    }

    function CombingInfo(clip c)
    {
     file = "F:\interlace.log"

     c = WriteFile(c, file, "a", "sep", "b")
     c = FrameEvaluate(c,"
           diff = 0.50*YDifferenceFromPrevious() + 0.25*UDifferenceFromPrevious() + 0.25*VDifferenceFromPrevious()
           b = IsMoving(diff)
           a = IsCombed(combedthreshold)
         ")

     return c
    }

V následující kapitole si prohlédneme příklad adaptivní pohybové filtrace zvětšní (resizing).

## Rozšířené podmíněné filtrování: část III

Na fórech se objevilo několik pohybově adaptivních filtrů pro zvětšování a vyhlazování. Tyto filtry rozlišují malé, střední a velké množství pohybu v klipu (na základě srovnání snímků). Podle toho mohou být použity různé druhy filtrů pro různý druh pohybu. Obecně, časové vyhlazování se použije pro statické scény s malým pohybem, prostorové vyhlazení se použije pro scény s velkým pohybem a ve scénách se středním pohybem se používají prostorově-časové vyhlazovače.
Níže se nahází zjednodušená verze filtru QUANTIFIED MOTION FILTER v1.5 b1 (10/07/2003) by HomiE FR, :

    ----------------------------------------------------
    # QUANTIFIED MOTION FILTER v1.3
    # NAČÍTÁME PLUGIN AVISYNTHU
    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")

    # NAČÍTÁME SKRIPT - QUANTIFIED MOTION FILTER

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

    # FILTRACE PRO MÁLO POHYBU
    # -> ZMĚNA VELIKOSTI SE ZOSTŘENÍM + ČASOVÁ FILTRACE
    function Low_Motion_Filter(clip c)
    {
      c = TemporalCleaner(c, 5, 10)
      c = LanczosResize(c, 512, 272)
      return c
    }

    # FILTRACE PRO STŘEDNÍ MÍRU POHYBU
    # -> NEUTRÁLNÍ BIKUBICKÁ ZMĚNA VELIKOSTI + ČASOVÁ & PROSTOROVÁ FILTRACE
    function Medium_Motion_Filter(clip c)
    {
      c = FluxSmooth(c, 7, 7)
      c = BicubicResize(c, 512, 272, 0.00, 0.50)
    return c }

    # FILTRACE PRO VELKÉ MNOŽSTVÍ POHYBU #
    -> ZMĚKČOVACÍ ZMĚNA VELIKOSTI + PROSTOROVÁ FILTRACE
    function  High_Motion_Filter(clip c)
    {
      c = FluxSmooth(c, -1, 14)
      c = UnFilter(c, -30, -30)
      c = BilinearResize(c, 512, 272)
      return c
    }

    #  OTEVÍRÁNÍ VIDEO ZDROJE
    AviSource("E:\temp\QMF\britney-I_love_rock_'n_roll.avi")
    ConvertToYV12(interlaced = true) Telecide(0)
    # POUŽITÍ ADAPTIVNÍHO FILTRU PRO ZMĚNU VELIKOSTI (S POUŽITÍM QMF)
    QMF()

    ----------------------------------------------------
    text souboru gmf.avs
    ----------------------------------------------------

    # QUANTIFIED MOTION FILTER (17/08/2003) by HomiE FR (homie.fr@wanadoo.fr)
    # FUNKCE URČENÍ MÍRY POHYBU function ME()
    {
      # NASTAVUJEME MÍRU POHYBU V SOULADU SE STŘEDNÍM ROZDÍLEM SNÍMKŮ [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
    }

    # FUNKCE ADAPTIVNÍ FILTRACE
    function QMF(clip c, float "threshold_lm", float "threshold_hm", bool "debug")
    {
      # NASTAVUJEME PRAHOVÉ HODNOTY PRO MNOŽSTVÍ POHYBU[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

      # POVOLUJEME/ZAKAZUJEME VÝSTUP  LADÍCÍ INFORMACE[3]
      debug = default(debug, false)

      # INICIALIZUJEME PROMĚNNOU, OBSAHUJÍCÍ MNOŽSTVÍ POHYBU
      global motion_level = 0

      # NASTAVENÍ PŘÍTOMNÉHO KLIPU[4]
      global clip = c

      # DOSTÁVÁME VÝSTUPNÍ ROZLIŠENÍ[5]
      width = Width(Low_Motion_Filter(c))
      height = Height(Low_Motion_Filter(c))
      global c_resized =  PointResize(c, width, height)

      # POUŽÍVÁME POHYBOVÝ FILTR V SOULADU S MNOŽSTVÍM POHYBU[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]

      # TISKNEME LADÍCÍ INFORMACE [7]
      c = (debug == true) ? ScriptClip(c, "Debug()"): c

      # DOSTÁVÁME MÍRU POHYBU Z ANALÝZY SNÍMKŮ [8]
       c = FrameEvaluate(c, "ME()")

      # DOSTÁVÁME ROZDÍL MEZI PŘEDCHOZÍM A SOUČASNÝM SNÍMKEM [9]
      c = FrameEvaluate(c, "global diff = 0.50*YDifferenceFromPrevious(clip) + 0.25*UDifferenceFromPrevious(clip) + 0.25*VDifferenceFromPrevious(clip)")
      return c
    }

    # FUNKCE LADÍCÍ INFORMACE
    function Debug(clip c)
    {
      # INFORMACE O VERZI[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= "lucidaconsole", size= 14, text_color= $FFFFFF)

      # TISK INFORMACE O MÍŘE POHYBU [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="lucidaconsole", size= 16, text_color=$FFCCCC)

      # TISK INFORMACE O REŽIMU PRÁCE Quantified Motion Filter [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
    }
    ----------------------------------------------------

Tento řetězec filtrů pracuje následovně:

- Když Vdub žádá snímek, AviSynth žádá snímek z QMF.
  - QMF žádá snímek z FrameEvaluate [9].
  - Poté se vyhodnotí skript [9] , a globální proměnné diff se přiřadí hodnota po žádosti o snímek z AviSource. FrameEvaluate [9] žádá snímek z FrameEvaluate [8].
  - Ještě jednou je skript [8] vyhodnocen:
    - při vyhodnocení me(), dostává globální proměnná motion_level hodnotu pro tento snímek [1]
  - Je-li debug= true, snímek je žádán ze ScriptClip [7], a proto i z Debug().
  - Poté (a také když je debug nastaveno na false) je snímek žádán z posledního ConditionalFilter [6c], který ho žádá z [6b], a ten zase žádá snímek z [6a].
    - Ve výsledku se snímek žádá buď z High_Motion_filter, Medium_Motion_filter, nebo Low_Motion_filter v závislosti na hodnotě motion_level.
- QMF žádá snímek z Telecide, Telecide z ConvertToYV12 a nakonec ConvertToYV12 z AviSource.
- AviSource vytváří snímek a posílá ho ke ConvertToYV12, atd.

Některé detaily byly vynechány, ale je to ukázka jak skript v podstatě pracuje.

`$English Date: 2008/12/21 09:23:02 $`

`Český překlad:12.2.2009`