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, exceto 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 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: 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:

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

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