## ConditionalFilter

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

`ConditionalFilter` retorna source1 quando a condição formada por ''filter+operator+value '' é conhecida, caso contrário retorna source2. Se filter não é aplicado explicitamente a um clipe, será aplicado em testclip. O áudio é pego de source1.

Um exemplo. Isto escolherá quadros de vid_blur quando o valor luma médio de um quadro é menos que 20. Caso contrário serão retornados os quadros vid.

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

Incluindo show="true" exibirá os valores atuais na tela.

A string filter pode ser qualquer filtro interno, mas também alguns filtros pré-definidos (funções Runtime).
A string operator pode ser "equals", "greaterthan" ou "lessthan". Ou "=", ">" ou "<" respectivamente.

## ScriptClip

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

`ScriptClip` retorna o clipe devolvido pela função avaliada em cada quadro. A string filter pode ser qualquer filtro interno, mas também alguns filtros pré-definidos (funções Runtime). Incluindo show="true" exibirá os valores atuais na tela.

Alguns exemplos:

    # Isto imprimirá a diferença do quadro prévio sobre o atual:
    clip = AviSource("c:\file.avi")
    ScriptClip(clip, "Subtitle(String(YDifferenceFromPrevious))")

    # Isto aplicará borrado em cada quadro baseado na diferença do prévio.
    # Isto também mostrará como os erros são informados em alguns quadros :)
    clip = AviSource("c:\file.avi")
    ScriptClip(clip, "Blur(YDifferenceFromPrevious/20.0)")

    # Isto aplicará temporalsoften a cenas muito estáticas e aplica um _variable_ blur em cenas de movimento.
    # O borrado agora fica corretamente coberto. Também designamos uma variável - e por que uma quebra de linha é inserida:
    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)")

    # Exibe o número do quadro em um clipe:
    ScriptClip("subtitle(string(current_frame))")

    # Exibe 'frame = the frame-number' em um clipe:
    ScriptClip("""subtitle("frame = " + string(current_frame))""")

Na v2.55 está incluída uma opção after_frame=true/false. Isto determina se o escrito deve ser avaliado antes (operação padrão) ou depois que o quadro viesse dos filtros acima.

"Restrições": a produção do escrito DEVE ser exatamente como o clipe entregue ao ScriptClip (mesma largura e altura de colorspace). Seu clipe retornado pode ter comprimento diferente - mas o comprimento do "clipe" sempre é usado. O áudio do "clipe" é passado intacto. Para duas fontes muito diferentes (MPEG2DEC3 e AviSource) - você pode colidir com colorspace. Este truque é conhecido.

## FrameEvaluate

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

Semelhante a `ScriptClip`, e xceto que a produção do filtro é ignorada. Isto pode ser usado para designar variáveis, etc. Os quadros são passados diretamente do clipe dado.
Na v2.53 uma opção after_frame=`true/false` está incluída. Isto determina se o escrito deve ser avaliado antes (operação padrão) ou depois que o quadro viesse dos filtros acima.

## ConditionalReader

Este filtro permite importar informação arbitrária em uma variável selecionável.

Veja a página dedicada ConditionalReader.

## Funções Runtime (em tempo de execução)

Estas são as funções internas nas quais todo quadro é avaliado.

Estes retornarão média do valor do píxel de um plano (requer YV12, ISSE):
`AverageLuma` (clip)
`AverageChromaU` (clip)
`AverageChromaV` (clip)

Estes retornarão um valor flutuante entre 0 e 255 da diferença absoluta entre dois planos (requer YV12, ISSE):
`RGBDifference` (clip1, clip2)
`LumaDifference` (clip1, clip2)
`ChromaUDifference` (clip1, clip2)
`ChromaVDifference` (clip1, clip2)

Ao usar estas funções há um último clipe "implícito" (o primeiro parâmetro não precisa ser especificado), assim o primeiro parâmetro é substituído pelo testclip.

Estes devem ser muito úteis para detecção de transições de mudanças de cena:
`RGBDifferenceFromPrevious` (clip)
`YDifferenceFromPrevious` (clip)
`UDifferenceFromPrevious` (clip)
`VDifferenceFromPrevious` (clip)
`RGBDifferenceToNext` (clip)
`YDifferenceToNext` (clip)
`UDifferenceToNext` (clip)
`VDifferenceToNext` (clip)

    # Isto substituirá o último quadro antes de uma mudança de cena
    # com o primeiro quadro depois dessa mudança:
    ConditionalFilter(last, last, last.trim(1,0), "YDifferenceToNext()", ">", "10", true)

#### Outras funções internas:

`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 é uma porcentagem, em quanto por cento de píxeis é permitido acima ou abaixo do mínimo. O percentual é opcional e o padrão é 0.

Se você entendeu os materiais acima, pode prosseguir com "Filtragem Condicional Avançada", que vai lhe contar um pouco mais.

## Filtragem Condicional Avançada: parte I

Você terá que saber alguns coisas sobre a funcionalidade do AviSynth para entender esta seção:

Os escritos são analisados de cima para baixo, mas quando um quadro é pedido o último filtro é invocado antes, para pedir os quadros de cima, na cadeia de filtro. Por exemplo:

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

Ao abrir o escrito no Vdub acontece o seguinte

- Quando Vdub pedir um quadro, AviSynth pede o quadro do Histograma.
- O histograma pede um quadro do ColorYUV,
- ColorYUV do AviSource, que produz quadro, entrega-o ao ColorYUV.
- ColorYUV processa a imagem e a envia para o Histograma, que a devolve ao Vdub.

Assim a cadeia do filtro trabalha basicamente para trás, dando ao filtro a possibilidade de pedir vários quadros da fonte acima.

Os filtros condicionais porém, devem avaliar os escritos antes deles pedirem quadros do filtro acima, porque precisam saber qual filtro chamar. Um outro assunto importante é que só variáveis globais definidas no filtro condicional 'environment' podem ser usados fora (e vice-versa). Dê uma olhada neste escrito:

    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)

Esta cadeia de filtro trabalha assim:

- Quando Vdub pede um quadro, AviSynth pede outro de g().
- g() pede um de AviSource():

- AviSynth pede um quadro do segundo FrameEvaluate.
- O segundo FrameEvaluate avalia YDifferenceFromPrevious(w) e designa este valor para a variável text, depois de pedir um quadro do AviSource. Depois deste um quadro é pedidO do primeiro FrameEvaluate.
- O primeiro FrameEvaluate pede um quadro de ScriptClip, depois a avaliação deString(text) e designando este valor à variável t'.
- ScriptClip pede um quadro de ConvertToYV12 () e avalia Subtitle(t) nesse quadro.
- ConvertToYV12() pede um quadro de AviSource().

- AviSource() produz o quadro e o envia a g(), que o retorna para Vdub.

Como pode ser visto, w está definido como uma variável global. Deste modo podemos usá-lo depois no escrito, no ambiente condicional. Se nós queremos usar as variáveis t e text em uma função diferente (dentro ou fora do ambiente condicional), elas também devem ser definidas como variáveis globais. Assim por exemplo:

    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)

Muito do escrito acima é redundante e pode ser removido. O escrito seguinte produz o mesmo

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

Na seção seguinte alguma info do quadro dependente será escrita a um arquivo de texto.

## Filtragem Condicional Avançada: parte II

No exemplo seguinte, alguma info do quadro dependente será escrita num arquivo de texto.A primeira variável "a" indica se o quadro é pente (a um certo percentual). Note que IsCombed é um filtro do plugin Decomb. A segunda variável "b" indica se há muito movimento no quadro.

    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)

Na seção seguinte um exemplo de "adaptive motion/resizing filter" - filtro de movimento / redimensionar adaptável - será considerado.

## Filtragem Condicional Avançada: parte III

Alguns filtros de motion/resizing adaptáveis apareceram nos foros. Estes filtros distinguem movimento em baixo, médio e alto num clipe (em base de quadro). Ao fazer, diferentes filtros podem ser usados para cada tipo diferente de movimento no clipe. Em geral, deve-se usar suavização temporal em cenas de pouco movimento, espacial em cenas de grande movimento e espacial-temporal em cenas de movimento médio.
Abaixo, uma versão simplificada de FILTRO de MOVIMENTO QUANTIFICADO v1.5 b1 (10/07/2003) por HomiE FR, é dado:

    ----------------------------------------------------
    # FILTRO DE MOVIMENTO QUANTIFICADO V1.3
    # CARREGANDO PLUGINS DO AVISYNTH
    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")

    # CARREGANDO ESCRITO DE FILTRO DE MOVIMENTO QUANTIFICADO

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

    # FUNÇÃO DE FILTRO DE POUCO MOVIMENTO
    # -> REDIMENSIONAMENTO AGUÇADO + SÓ TEMPORAL
    function Low_Motion_Filter(clip c)
    {
      c = TemporalCleaner(c, 5, 10)
      c = LanczosResize(c, 512, 272)
      return c
    }

    # FUNÇÃO DE FILTRO DE MÉDIO MOVIMENTO
    # -> REDIMENSIONAMENTO BICÚBICO NEUTRO + TEMPORAL & ESPACIAL
    function Medium_Motion_Filter(clip c)
    {
      c = FluxSmooth(c, 7, 7)
      c = BicubicResize(c, 512, 272, 0.00, 0.50)
      return c
    }

    # FUNÇÃO DE FILTRO DE GRANDE MOVIMENTO
    # -> REDIMENSIONAMENTO SUAVE + SÓ ESPACIAL
    function High_Motion_Filter(clip c)
    {
      c = FluxSmooth(c, -1, 14)
      c = UnFilter(c, -30, -30)
      c = BilinearResize(c, 512, 272)
      return c
    }

    # ABRINDO FONTE DE VÍDEO
    AviSource("E:\temp\QMF\britney-I_love_rock_'n_roll.avi")
    ConvertToYV12(interlaced=true)
    Telecide(0)

    # APLICANDO FILTRO DE REDIMENSIONAMENTO ADAPTÁVEL (USANDO QMF)
    QMF()
    ----------------------------------------------------

    # FILTRO DE MOVIMENTO QUANTIFICADO (17/08/2003) por HomiE FR (homie.fr@wanadoo.fr)
    # FUNÇÃO DE ESTIMAÇÃO DE MOVIMENTO
    function ME()
    {
      # FIXANDO NÍVEL DE MOVIMENTO DE ACORDO COM A DIFERENÇA DA MÉDIA [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
    }

    # FUNÇÃO DO FILTRO DE MOVIMENTO QUANTIFICADO
    function QMF(clip c, float "threshold_lm", float "threshold_hm", bool "debug")
    {
      # FIXANDO PERCENTUAIS DE NÍVEIS DE MOVIMENTO [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

      # ATIVANDO/DESATIVANDO INFORMAÇÃO DE DEBUG [3]
      debug = default(debug, false)

      # INICIALIZANDO NÍVEL DE MOVIMENTO
      global motion_level = 0

      # FIXANDO PRESENTE CLIPE [4]
      global clip = c

      # PEGANDO A RESOLUÇÃO DA PRODUÇÃO [5]
      width = Width(Low_Motion_Filter(c))
      height = Height(Low_Motion_Filter(c))
      global c_resized = PointResize(c, width, height)

      # APLICANDO O FILTRO DE MOVIMENTO DE ACORDO COM O NÍVEL DE MOVIMENTO [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]

      # IMPRIMINDO A INFORMAÇÃO DE DEBUG [7]
      c = (debug == true) ? ScriptClip(c, "Debug()") : c

      # PEGANDO O NÍVEL DE MOVIMENTO POR ESTIMAÇÃO DE MOVIMENTO [8]
      c = FrameEvaluate(c, "ME()")

      # PEGANDO DIFERENÇAS ENTRE QUADROS PASSADOS/PRESENTES [9]
      c = FrameEvaluate(c, "global diff = 0.50*YDifferenceFromPrevious(clip) + 0.25*UDifferenceFromPrevious(clip) + 0.25*VDifferenceFromPrevious(clip)")
      return c
    }

    # FUNÇÃO DE INFORMAÇÃO DE DEBUG
    function Debug(clip c)
    {
      # IMPRIMINDO A INFORMAÇÃO DA VERSÃO [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)

      # IMPRIMINDO A INFORMAÇÃO DA ESTIMAÇÃO DE MOVIMENTO [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)

      # IMPRIMINDO A INFORMAÇÃO DO FILTRO DE MOVIMENTO QUANTIFICADO [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
    }
    ----------------------------------------------------

Esta cadeia de filtro trabalha assim:

- Quando Vdub pede um quadro, AviSynth pede outro de QMF.

- QMF pede um quadro de FrameEvaluate [9].
- Depois de fazer este escrito [9] é avaliado e a variável global diff é nomeada depois de pedir um quadro de AviSource. FrameEvaluate [9] pede um quadro de FrameEvaluate [8].
- Uma vez mais o escrito [8] é avaliado:

- ao avaliar me(), a variável global motion_level é nomeada para aquele quadro [1]

- Se debug=true, um quadro é pedido de ScriptClip [7] e do Debug().
- Depois disso (e também quando debug seja false) um quadro é pedido do último ConditionalFilter [6c] que pede um quadro de [6b], o qual em troca pede um de [6a].

- Note que no fim, um quadro de High_Motion_filter, Medium_Motion_filter, ou Low_Motion_filter é pedido, dependendo do valor de motion_level.

- QMF pede um quadro de Telecide, Telecide de ConvertToYV12 e finalmente ConvertToYV12 de AviSource.
- AviSource produz o quadro e o envia a ConvertToYV12, etc.

Foram omitidos alguns detalhes, mas isto é basicamente como o escrito trabalha.

`$Date: 2006/03/26 18:11:19 $ Portuguese translation by RoLon`