RemoveDirt
é assim chamado um limpador temporal para
Avisynth 2.5x. Se você não quiser passar pela documentação, use sem fixar
qualquer variável. Para um filme comum isto deve tirar cerca da metade da
sujeira sem criar artefatos visíveis. Embora o ajuste padrão seja bastante
conservador, movimento muito rápido tolera um risco de artefato moderado. Porém,
como o pós processar remove todos os artefatos não suaves, eles são raros e
normalmente suaves e muito curtos, difícil de captar pelo olho humano. Clipes são
muito diferentes e acertando as variáveis que controlam o comportamento de
RemoveDirt podem fazer uma grande diferença. Duas ferramentas de depuração
diferentes podem ser usadas para este propósito. As próprias variáveis podem
ser explicadas melhor pela discussão do fundamento do algoritmo. Se você não
entender uma variável, não mude seu valor padrão e poste uma pergunta no RemoveDirt
thread do foro de
doom9 em vez de me enviar um e-mail.
Nenhum limpador automático pode capturar toda a sujeira sem a destruição do filme pelos artefatos. A quantia da limpeza depende muito da quantia do movimento. Para evitar a limpeza dos artefatos devem ser suprimidos nas áreas de movimentos de um clipe. Uma câmera móvel é claramente o pior caso. O primeiro e o último quadro de um clipe nunca são limpados e deverá haver uma limpeza numa troca de cena aguçada, porque RemoveDirt requer que o prévio e o subseqüente quadro sejam existentes e bem ajustados. E ainda, RemoveDirt – diferente de outros limpadores - tenta remover sujeira mas nunca borrar, é prudente usar com um leve suavizador na sujeira restante, para obter melhor compressão (tal filtro deve ser RemoveDirt). Se você usa divx 5.1.1 o filtro do pré-processo interno é uma boa escolha, mas baseado em meus testes pessoais eu recomendaria só o suave pré-processo. Em sua configuração padrão RemoveDirt pode remover quaisquer grandes pedaços de sujeira, mas geralmente remove muita sujeira pequena e pó e depois de ser processado por RemoveDirt o clipe deve parecer significativamente mais limpo.
RemoveDirt
suporta os dois mais importante espaços YV12 e
YUY2 de cor. Suporte para outro YUV espaço de cor pode ser incluído, mas o
projeto torna impossível suportar espaços de cor RGB (converte a YUY2 com o
filtro interno ConvertToYUY2 do Avisynth se você tropeçar nos tais espaços de
cor). A largura e a altura do clipe devem ser um múltiplo de 8.
Como pode ser visto no código fonte e nas descrições abaixo, RemoveDirt é bastante sofisticado. Para alcançar desempenho razoável era necessário programar todas as rotinas de baixo nível em linguagem assembly que usa intensivamente as instruções de inteiro SSE da Intel. Assim uma CPU moderna com capacidade de inteiro SSE é necessária para usar este plugin.
Começando com a versão 0.5 o pacote binário de RemoveDirt contém duas versões do plugin. RemoveDirt.dll (lincada dinamicamente, então pequena) e RemoveDirtS.dll (lincada estaticamente, por isso grande). Tente primeiro a dll pequena e copie-a ao diretório de plugin do Avisynth. Se não trabalhar, provavelmente se deve à biblioteca msvcr70.dll perdida. Instale essa biblioteca em C:\windows\system32 ou apague RemoveDirt.dll e substitua por RemoveDirtS.dll. Por favor, não ponha as duas dlls no mesmo diretório de plugin. Se você encher o diretório de plugins com todos os tipos de dlls supérfluas, só reduz a velocidade do início de qualquer aplicação que usa o Avisynth. RemoveDirt é seguro com respeito a "multithreading" (multi-tarefas) e pode ser usado muitas vezes e arbitrariamente num único escrito de Avisynth. Não haverá nenhum conflito com outros filtros.
1. Uma mancha suja ou arranhão só acontece em um
quadro e nunca numa seqüência inteira. Esta propriedade básica é explorada por
qualquer limpador temporal. Assim arranhões causados por projetores de
filme ruins na mesma posição em uma série de quadros não podem ser
corrigidos por um limpador temporal. Em nosso projeto de programa a propriedade
básica é feita preciso como segue: um píxel está potencialmente sujo
se cf[x,y] não está entre min(pf[x,y],nf[x,y]) e max(pf[x,y],nf[x,y]), onde
cf[x,y] denota o valor do píxel cinzento com coordenadas x e y no quadro atual
e pf[x,y similar] e nf[x,y] denota o valor cinzento do mesmo píxel no prévio e
do quadro subseqüente. Em outras palavras um píxel potencialmente sujo está
fora da gama medida pelo prévio e o quadro subseqüente. Nós usamos a palavra
potencialmente, porque infelizmente, não só sujeira mas também algum tipo de
movimento está causando um píxel a sair do alcance. Se não distinguir entre
ambos, a remoção de sujeira arruinará em lugar de limpar um clipe. Este fato
desagradável faz verdadeira remoção de sujeira automática com baixo risco de
artefato desafiando assim. O exemplo extremo é uma fina linha de preto com um
fundo branco que se move. Por causa do movimento qualquer píxel preto é branco
no prévio e no quadro subseqüente, que neste exemplo todos os píxeis pretos
estão sempre fora do alcance. Por outro lado, se a largura do objeto comovente
é grande na direção de movimento (esta é a razão por que a linha tem que
ser fina no exemplo anterior) e se os píxeis dos objetos que se movem tiverem
cor semelhante, então os píxeis do objeto comovente não estão
significativamente fora do alcance. Conseqüentemente do ponto de vista da
limpeza, há movimento bom e ruim. A limpeza de movimento ruim causa artefatos,
movimento bom não.
2. Se um bloco limpo tem uma margem em comum com um
bloco que não foi limpado por alguma razão, então a limpeza não deve
aumentar muito a diferença das duas bordas adjacentes de ambos os blocos,
caso contrário a limpeza tem que ser considerada como incorreta e deve ser
desfeita. Em outras palavras os blocos limpados devem se ajustar razoavelmente
bem aos blocos que não são limpados. Esta é uma técnica de pós
processamento. Tão técnica quanto pode parecer, é uma idéia extremamente
poderosa para evitar artefatos feios. Francamente, penso que a verdadeira remoção
de sujeira automática com baixo risco de artefato é dificilmente possível sem
esta idéia. Para pós processamento RemoveDirt usa as variáveis pthreshold e
cthreshold.
Se a diferença luma total das duas bordas adjacentes aumenta mais que o
pthreshold, então a limpeza do bloco fica inacabada por RemoveDirt. Similar, a
limpeza fica inacabada, se a diferença croma excede cthreshold. A máxima
diferença de 8 píxeis é 8*255. Se cthreshold for maior que este valor, então
o pós processamento de croma fica desativado. Para o pós processamento croma
YUY2 sempre é desativado porque ainda não está implementado. Se ambos,
pthreshold e cthreshold, são maiores que o máximo valor, então o pós
processamento é completamente desativado. pthreshold = 20 é
o valor padrão
e se nada mais é especificado, cthreshold tem
o mesmo valor de pthreshold.
Claramente o pós processamento luma é muito mais importante que o croma. Se cthreshold e especialmente pthreshold, então os artefatos maciços bem desagradáveis ficam visíveis. Estes são muito mais provável em áreas com muito pouco contraste. Claro que deve haver bom movimento para ter tais artefatos. Se você ver estes tipos de artefatos maciços, você deve abaixar os percentuais. O pós processamento só deve ser desativado se todos os quadros limpados são conferidos como artefatos. Pela mesma natureza do algoritmo nenhum pós processamento acontecerá se todos os blocos foram limpados. Deve haver pelo menos um bloco não limpado para ativar o pós processamento. O algoritmo de pós processamento dá volta em todos os blocos para achar blocos que possam ser restabelecidos, apesar disso é bastante eficiente. É a filosofia básica de RemoveDirt, que a detecção de movimento necessita descobrir pelo menos um e não todos os blocos de objetos em movimento. O resto então é cuidar do pós processamento.
Qualquer procedimento que permite distinguir entre sujeira e movimento pode ser considerado como algum tipo de detecção de movimento. Deste ponto de vista a seção prévia contém já dois procedimentos. Ambos são sujeira específica e podem ser consideradas como não convencional. Nesta seção consideramos detecção de movimento de sujeira independente geral. A idéia básica para decidir se um bloco é de movimento ou não, é medir a diferença deste bloco com sua contraparte no quadro prévio ou no subseqüente. Porém, como a finalidade de limpar isto não é apropriada, porque se a diferença com sua contraparte em um quadro vizinho for baixa, não pode conter muita sujeira. Ao invés a idéia principal é medir a diferença dos blocos no quadro prévio e subseqüente mas não no quadro atual.
Assim para a detecção de movimento básica, o quadro atual (o quadro a ser limpado) não é usado, só o prévio e o subseqüente são usados para este propósito. No RemoveDirt o comportamento de detecção de movimento básica é principalmente controlado pela variável mthreshold. Embora um bloco só contenha 64 píxeis a função de diferença usada por RemoveDirt retorna só valores entre 0 (blocos idênticos) e 8*255 (diferença entre um bloco absolutamente preto e um absolutamente branco). Se esta diferença exceder o valor de mthreshold, então o bloco é marcado como de movimento. mthreshold=150 é o valor padrão. Quanto mais alto o valor mthreshold, mais limpeza (mas também com um risco mais alto de artefato). Além do percentual absoluto representado pela variável mthreshold, RemoveDirt pode usar também variável percentual que varia de bloco para bloco (de fato RemoveDirt só usa um bloco de percentual específico se for menor que mthreshold). Não descrevemos o algoritmo, um pouco complicado aqui.
Os percentuais adaptáveis são controlados pela variável athreshold. Pode muito bem alcançar valores negativos, mas se athreshold < -mthreshold/2, então não haverá nenhuma limpeza. athreshold=50 é o valor padrão. Quanto mais alta a variável athreshold mais blocos são limpados e mais alto o risco de artefato. Se mthreshold e athreshold são > 8*255, então todos os blocos são limpados. Na presença de movimento ruim esta escolha vai criar artefatos volumosos e só deveria ser usada para quadros selecionados que usam a gama de arquivos como descritos abaixo. Há duas variáveis adicionais dist e tolerance que controlam detecção de movimento básica. dist=1 e tolerance=12 são os valores padrões. Um bloco B é considerado vizinho de um bloco A por RemoveDirt, se os blocos horizontal e vertical são só dist separadamente. Para dist=0 um bloco tem só um vizinho, o próprio bloco. Se dist=1, então um bloco tem 9 vizinhos, se não fica situado ao limite. Se dist=2, então cada bloco interno tem 25 vizinhos e se dist=3 então tem 49 vizinhos, etc.. Agora por um determinado bloco RemoveDirt conta todos os blocos vizinhos que são marcados como blocos de movimento. Se a porcentagem dos blocos de movimento entre todos os blocos vizinhos exceder o valor tolerance, então o bloco não é limpado.
Assim no caso padrão de 9 blocos vizinhos e tolerance=12 um bloco de movimento é permitido e a limpeza será permitida, não obstante. Em particular, um bloco de movimento é limpado, se não tem nenhum outro bloco de movimento como vizinho. Isto é razoável, porque movimento raramente acontece em um só bloco minúsculo. No outro, se os blocos de movimento têm uma certa densidade então também os vizinhos não devem ser limpados. Esta é a idéia por trás das variáveis dist e tolerance. Um valor mais alto de dist resulta em menos limpeza. Quanto mais alto o valor de tolerância, mais limpeza. Se tolerance >= 100 então todos os blocos são limpados. Usando o valor padrão, RemoveDirt poderá distinguir uma fina linha preta movente suja, se não se move muito rapidamente. Detecção de movimento só precisa pegar partes de uma área que se move. Então o resto normalmente é tomado cuidado através de pós processamento. A desvantagem da detecção de movimento básica é que não distingue entre movimento bom e ruim. Na realidade, movimento bom é mais fácil pegar que movimento ruim. Eu espero aquele bom dia para que possa fazer algo melhor a respeito.
O método acima de detecção de movimento tem uma desvantagem séria, entretanto. Se um bloco em um quadro tem uma quantia significativa de sujeira, então o mesmo bloco no prévio e no subseqüente quadro será detectado falsamente como um bloco de movimento. Por conseguinte, se muita sujeira pequena espalha uma sucessão de quadros por toda parte, o desempenho de limpeza de RemoveDirt pode degradar. A idéia para fixar este problema é pegar os dois quadros vizinhos, mas não o quadro atual, de uma versão já limpada do clipe. Um escrito de Avisynth com este tipo de duplo processo parecerá assim:
input = MPEG2Source("input.d2v") firstpass = RemoveDirt(input) cleaned = RemoveDirt(input, neighbour=firstpass)
Aqui neighbour é uma variável que pega clipes como valores (o valor padrão
é o clipe especificado no primeiro argumento). Esta técnica pode ser reiterada
mais adiante, mas claro que o escrito executa cada vez mais lento em cada repetição.
Normalmente o número de blocos limpados aumenta sem dúvida menos que 1% com a
repetição e pode não compensar por dobrar o tempo de execução. Todo o tipo
de depuração deve ser desativado para a primeira passagem se o caos de depuração
não é desejado. Todas as outras variáveis devem ter valores idênticos
provavelmente, mas há lugar para muitas experiências. Claro que é possível
fazer muita tolice com a variável neighbour. RemoveDirt só rejeita um
clipe neighbour, se seu formato for muito diferente
do clipe primário, tal que chegaria a
comprometer a
execução estável do plugin.
Atualmente três modos de limpeza em RemoveDirt estão implementados. Eles são acessados pela variável mode. mode = 0 é um modo de calcular a média muito simples. Se um bloco for marcado como limpável, então os píxeis deste bloco são substituídos pela média do píxel correspondente dentro do prévio e o quadro subseqüente. Se o pós processamento for desativado, gera artefatos muito facilmente. O modo padrão = 2 é muito mais inteligentes mas também um pouco mais lento. Se cf[x,y] é o valor de um píxel cinzento num bloco limpável e se pf[x,y], nf[x,y] são os valores cinzentos correspondentes dentro do prévio e os quadros subseqüentes, então cf[x,y]is ficam inalterados se min(pf[x,y],nf[x,y]) <= cf[x,y] <= max(pf[x,y],nf[x,y]). Se cf[x,y] < min(pf[x,y],nf[x,y]) então cf[x,y] é substituído por min(pf[x,y],nf[x,y]). Finalmente, se cf[x,y] > max(pf[x,y],nf[x,y]), então cf[x,y] é substituído por max(pf[x,y],nf[x,y]). Os valores croma são controlados da mesma maneira. Este é o método que estou usando sempre e provavelmente rende os melhores resultados. Devido a SSE não é muito mais lento que o método de calcular a média simples. Finalmente há o modo experimental = 1 que está nalgum lugar entre o modo 0 e 2 mas mais próximo ao modo 2. Modo 1 é o modo mais complicado e mais lento. Inicialmente eu esperava obter melhor compressão com modo = 1, mas um primeiro teste foi desencorajador. Mais adiante testes mostrarão, se este modo deve ser abandonado ou não.
Se você tem um filme que requer limpeza é provável que seja velho e freqüentemente preto e branco. Claro que o croma de clipes p&b não precisa ser processado e o tempo da cpu pode ser economizado. Para realizar isto, RemoveDirt deve ser usado com a variável grey = true (o padrão é grey = false). Então em vez de simplesmente copiar o croma velho ao novo, o croma novo é simplesmente nomeado o valor constante 128. Isto é mais rápido que a cópia e como um subproduto, apaga todo o ruído do croma. Em outras palavras, se havia qualquer cor antes, é apagada (o filtro interno do Avisynth greyscale tem exatamente o mesmo efeito). grey = true desabilita pós processo croma que não faz sentido em clipes p&b. Como não vai haver nenhum pós processo de croma, pthreshold pode ser um pouco baixo, entre 30 ou 40.
A variável boolean depura e a variável de inteiro mostra como é usado para depurar. Se RemoveDirt é usado com show = 1, então todos os blocos que são limpados são coloridos de vermelho. Se RemoveDirt é usado com show = 2, então todos os blocos que não são limpados são coloridos de vermelho. O valor padrão show = 0 indica que nenhuma coloração é feita. O modo show só pode ser usado para prever e pode ser útil para ver rápido quais áreas são pegas por RemoveDirt e as que não pode limpar. Usando a tecla F5 de VirtualDubMod, pode-se ver bem como a mudança de variáveis afeta a limpeza. O modo show só trabalha para clipes YUY2. Porém, esta é uma inconveniência em lugar de restrição. Deve-se simplesmente pôr o filtro interno de Avisynth ConvertToYUY2 na frente de RemoveDirt. Claro que isto só deveria ser feito para prever. Se o escrito estiver comprimido, ConvertToYUY2 deve ser removido para evitar conversões de cores espaciais desnecessárias.
Se debug = true então RemoveDirt
produz os seguintes
tipos ao utilitário debugview:
[1120] [36536] RemoveDirt: 5779 blocks cleaned (93%), 229 motion blocks (3%), 0 blocks restored, 1 loops [1120] [36537] RemoveDirt: 5745 blocks cleaned (93%), 246 motion blocks (3%), 3 blocks restored, 2 loops [1120] [36538] RemoveDirt: 5348 blocks cleaned (86%), 378 motion blocks (6%), 17 blocks restored, 5 loops [1120] [36539] RemoveDirt: 4772 blocks cleaned (77%), 778 motion blocks (12%), 0 blocks restored, 1 loops [1120] [36540] RemoveDirt: 4396 blocks cleaned (71%), 1028 motion blocks (16%), 1 blocks restored, 2 loops [1120] [36541] RemoveDirt: 4695 blocks cleaned (76%), 820 motion blocks (13%), 3 blocks restored, 2 loops [1120] [36542] RemoveDirt: 5362 blocks cleaned (86%), 384 motion blocks (6%), 48 blocks restored, 3 loops [1120] [36543] RemoveDirt: 4038 blocks cleaned (65%), 1275 motion blocks (20%), 6 blocks restored, 2 loops [1120] [36544] RemoveDirt: 3780 blocks cleaned (61%), 1522 motion blocks (24%), 3 blocks restored, 2 loops [1120] [36545] RemoveDirt: 3943 blocks cleaned (63%), 1359 motion blocks (22%), 6 blocks restored, 2 loops [1120] [36546] RemoveDirt: 4104 blocks cleaned (66%), 1225 motion blocks (19%), 3 blocks restored, 2 loops [1120] [36547] RemoveDirt: 4287 blocks cleaned (69%), 1099 motion blocks (17%), 1 blocks restored, 2 loops [1120] [36548] RemoveDirt: 4041 blocks cleaned (65%), 1261 motion blocks (20%), 0 blocks restored, 1 loops [1120] [36549] RemoveDirt: 3901 blocks cleaned (63%), 1409 motion blocks (22%), 2 blocks restored, 3 loops [1120] [36550] RemoveDirt: 3757 blocks cleaned (60%), 1507 motion blocks (24%), 4 blocks restored, 2 loops [1120] [36551] RemoveDirt: 3799 blocks cleaned (61%), 1502 motion blocks (24%), 6 blocks restored, 2 loops
O primeiro número ao lado esquerdo é o id do processo que roda o escrito, o segundo é o número de quadro, os números blocks cleaned se explicam, o número motion block é o número de blocos de movimento, que foi achado pelas várias rotinas de detecção de movimento, blocks restored é o número que foi restabelecido pela rotina de pós processamento e o número loops é o número repetições que foram feitas pela rotina de pós processamento para completar sua tarefa. Se Dist = 0 e tolerance < 100, então a relação,
blocks cleaned + motion blocks + restored blocks = total number of blocks = (frame width / 8) * (frame height / 8)
[blocos limpados + blocos de movimento + blocos restabelecidos = número total de blocos = (largura do quadro / 8) * (altura do quadro / 8)]
segura. Se um bloco é limpado, não significa que havia sujeira. Também seria o tempo consumido para excluir blocos limpos da limpeza e usar toda a proteção de artefato discutida antes, porque limpar um bloco limpo não deveria fazer um diferença visual e deveria melhorar ligeiramente a compressão. O número blocks restored é de importância particular. O número médio dos blocos restabelecidos deveria ser 1-2% de todos os blocos. Se for mais alto, a colocação é provavelmente muito agressiva, se mais baixo, uma colocação mais agressiva pode ser usada. Se um interruptor de cena aguçada acontecer, então sempre há dois quadros com números muito baixos de blocks cleaned . O primeiro quadro é o último da cena velha e o segundo é o primeiro quadro da cena nova. Este é um padrão bastante característico. Em geral os números são totalmente dependente de movimento. Aqui estão alguns quadros extraordinários que eu observei recentemente, ao processar um velho filme p&b bastante sujo:
[1008] [2652] RemoveDirt: 5495 blocks cleaned (89%), 13 motion blocks (0%), 587 blocks restored, 32 loops [1008] [22269] RemoveDirt: 4196 blocks cleaned (68%), 729 motion blocks (11%), 445 blocks restored, 20 loops [1008] [24016] RemoveDirt: 1783 blocks cleaned (29%), 1957 motion blocks (32%), 1017 blocks restored, 16 loops
O quadro 2652 é especialmente notável: entretanto havia só 13 blocos de movimento, pós processamento pegou uns 587 blocos gritantes com umas 32 voltas gritantes. Eu nunca tinha visto tais números antes e eu pensei que eles só são teoricamente possíveis. Embora valha algum tempo, eu ainda rodo sempre RemoveDirt com debug = true e se eu ver números excepcionais como acima, então eu sempre faço uma inspeção visual de tais quadros excepcionais. No caso, todos os quadros estavam sem artefatos visuais.
Infelizmente a quantia de sujeira por quadro
costuma variar ao longo de um filme. Por exemplo, os primeiros minutos de um
filme são particularmente sujos, porque ficam situados no lado de fora do rolo
do filme. Também muitos quadros particularmente ruins se espalham por toda
parte num filme. Estas situações não podem ser bem controladas por uma única
variável de colocação. Para este propósito range files - arquivos de gama foi implementado em RemoveDirt. Pode-se
gastar 9 arquivos de gama que são especificados com a variável range1
range2,... , range9. Cada arquivo de gama tem seu próprio grupo de variáveis
com o mesmo nome das variáveis globais mas com o número de gama preso no fim.
Por exemplo, se RemoveDirt
é usado com
RemoveDirt(range3= "myrange", mthreshold3=200, athreshold3=300, tolerance3=0, dist3=2)
então RemoveDirt usa mthreshold = 200, athreshold = 300 etc. para todas os quadros especificadas no arquivo de gama "myrange" que se espera seja localizado no diretório do escrito do Avisynth, mas também locais diferentes podem ser usados especificando o caminho completo. Para todos os outros quadros RemoveDirt usa o valor padrão, porque nenhuma das variáveis globais foi mudada. Um arquivo de gama como "myrange" contém qualquer número de quadros únicos como 13054 ou gamas de quadros como 13756-64 que são um atalho para 13756-13764 (estes números podem ser achados prevendo o clipe no VirtualDubMod). Os números dos quadros em um arquivo de gama tem que estar aumentando. Este acordo faz certos atalhos possíveis, que podem ser vistos do exemplo subseqüente. As várias gamas também devem ser separadas por um espaço em branco. Aqui nós temos um exemplo típico:
0-43 67 287 9 1211-39 387 1432-544 11780-2833
Os anteriores arquivos de gama cobrem os seguintes quadros: 0-43, 67, 287, 289, 1211-1239, 1387, 1432-1544, 11780-12833,. Se um quadro é especificado em mais de um arquivo de gama, então o arquivo de gama com o número de gama mais alto tem precedência. Por exemplo, se um quadro é especificado em range2 e range4, então as variáveis para range4 são usadas. No futuro, usarei valores um pouco mais agressivo que o padrão para as variáveis globais. Então eu terei um arquivo de gama com valores significativamente mais agressivos pelos primeiros minutos e talvez algumas outras cenas, se não há muito movimento e finalmente eu terei um arquivo de gama com variáveis fixadas para limpeza total, que serão usadas em quadros extremamente sujos ou estragados. Embora eu já use RemoveDirt para o trabalho real (com o passar do tempo eu enchi um disco rígido inteiro de 120 Gb, trocável, de filmes p&b velhos e sujos de origem de DVB e este disco rígido está agora gradualmente trabalhado abaixo), testar ainda é um assunto importante e esta é a única razão, por qual ainda não estou usando arquivos de gama.
1. Nunca apare depois de RemoveDirt. Codecs modernos dividem os quadros da mesma maneira que RemoveDirt em uma grade de blocos de píxel 8x8 (peritos de codecs, vocês poderiam confirmar isso, por favor?) para executar o crucial transformar o co-seno discreto para tais blocos. Agora se o clipe é aparado depois de RemoveDirt, então é provável que o grid de RemoveDirt e o codec estejam dando resultados diferentes na compressão subpar. Há uma exceção, entretanto: aparando depois não dói, se todos os quatro lados são aparados por um múltiplo de 8. Por exemplo, Crop(8,64,0,-72) está ok.
2. Apare apenas com "align=true".
RemoveDirt
usa pesadamente as instruções SSE.
Se você aparar sem "align=true" antes de
RemoveDirt, então os dados nos quadros podem não serem alinhados corretamente e RemoveDirt
executará substancialmente mais lento. Como conseqüência você deve aparar
sempre com Avisynth e não com DVD2AVI.
3. Filmes Telecinados devem ser telecinados
invertidos antes de RemoveDirt. Se um filme é telecinado alguns campos são
duplicados para aumentar a taxa de quadro de 24 fps a 30 fps. Conseqüentemente
em tais campos a propriedade básica de sujeira, descrita acima, não é mais válida
e nenhum limpador temporal pode mais limpar em tais campos duplicados. Por outro
lado, um telecine inverso todo quarto quadro é composto de campos que originam
de dois quadros diferentes. Visualmente estes dois campos se ajustam bem mas
ambos são de um contexto de compressão diferente que pode enganar RemoveDirt
à falsa detecção de movimento. Em casos extremos, um campo pode ser de um I- ou
P-quadro, enquanto o outro é de um B-quadro. Mas até mesmo se os campos forem
de quadros de tipo idêntico, o contexto de compressão diferente tem um efeito
significativo. Por conseguinte RemoveDirt
executa menos bem em filmes de telecine inversos
que em filmes progressivos. Também pela mesma razão a compressão de filmes de
telecines inversos é pior que filmes progressivos. Nós na Europa devemos agradecer a Deus
diariamente por não termos telecinados. Porém, aqui na Alemanha temos
locutores de rádio de tv digitais que gostam de pentear filmes progressivos
(aproximadamente 5% de filmes todo progressivos de ARD e especialmente ZDF são
penteados). Felizmente estes idiotas não podem duplicar campos, assim
RemoveDirt deve trabalhar, mas em filmes penteados a sujeira é sempre dividida
em mais de dois quadros, que claramente ferem RemoveDirt
. Por outro lado, se estes filmes penteados
estiverem despenteados, então nós temos o problema de contexto de compressão
para qualquer quadro e não só para qualquer quarto quadro. Esta também é a
razão por que o filtro de uncomb (despentear) de Trbarry não trabalha bem na
prática. A mesma pergunta surge para filmes entrelaçados. Devemos desentrelaçar
antes ou depois de RemoveDirt
? Por outro lado, sujeira e arranhões
normalmente só acontecem em fotografia, conseqüentemente, filme progressivo.
Assim esta pergunta não deveria importar muito.
Da discussão acima, deve ficar claro que para medir a qualidade de RemoveDirt
devem ser usados só clipes progressivos, que
nunca foram telecinados e que nunca foram confundidos por provedores de tv
digitais estúpidos. Meu plugin AlignFields pode ser usado para decidir
com certeza absoluta, se um clipe preenche esses constrangimentos de qualidade
ou não.
4. Ponha outros filtros depois de RemoveDirt. Exceto esses filtros mencionados antes, como aparo e telecine inverso, todos os outros filtros devem ser postos depois de RemoveDirt no escrito de Avisynth, porque a maioria dos filtros têm um impacto negativo em vez de positivo em detecção de sujeira.
Nome | Tipo | Valor Padrão | Notas | Seção |
neighbour | Clip | primary clip | Motion Detection | |
dist | Integer | 1 | >=0 | Motion Detection |
mthreshold | Integer | 150 | >=0 | Motion Detection |
athreshold | Integer | 50 | Motion Detection | |
pthreshold | Integer | 20 | >=0 | Dirt Detection |
cthreshold | Integer | pthreshold | >=0, só para clipes YV12 | Dirt Detection |
tolerance | Integer | 12 | 0<=tolerância<=100 | Motion Detection |
mode | Integer | 2 | apenas 0,1,2 | Cleaning Modes |
grey | Boolean | false | Black&White | |
debug | Boolean | false | Debugging | |
show | Integer | 0 | apenas 0,1,2, apenas para clipes YUY2 | Debugging |
Todas estas variáveis podem ser especificadas para arquivos de gama juntando o número do arquivo de gama no fim da variável. Por exemplo, mode5 é a variável de modo para range5.
Para um filtro com muitas variáveis como RemoveDirt (junto com todas as variáveis para arquivos de gama, RemoveDirt tem mais de 100 variáveis), onde as colocações dependem fortemente do clipe de entrada, isto desejável ter mais de uma colocação padrão. Em lugar de passar estas colocações padrão ao binário, são colocadas no arquivo RemoveDirt.ini. Agora, se temos RemoveDirt(default="anime") no escrito, RemoveDirt procura o arquivo RemoveDirt.ini no diretório do escrito. Se não pode achar este arquivo termina com uma mensagem de erro. Claro que, sem a opção padrão, não é necessário RemoveDirt.ini. Então RemoveDirt procura pela string anime. Se não puder achar esta string, termina com uma mensagem de erro. Finalmente lê todas as variáveis depois de anime e substitui os valores internos padrões pelos valores em RemoveDirt.ini. O formato é
name of variable = value of variable
Se a variável for uma string, então o valor tem que ser incluído entre aspas. A string não deve conter o caractere " de aspas. Se o caractere de comentário # aparece no escrito (fora de um valor de string, claro), então tudo depois de # até o fim da linha é considerado como um comentário. Vamos ver o exemplo concreto de RemoveDirt.ini seguinte:
clensing # Clensing total, só para quadros selecionados especificados em clensing.rmd,
range1 = "clensing.rmd"
pthreshold1 = 5000
mthreshold1 = 5000
grey = false
bw # modo preto & branco
grey = true
pthreshold = 20
mthreshold =180
anime # modo para vídeos anime
pthreshold = 40
cthreshold = 30
mthreshold = 200
Neste exemplo RemoveDirt.ini contém três modos padrões: clensing, bw, anime. O clensing de modo padrão define um arquivo de range1 clensing.rmd (tem que existir se este modo padrão for usado) e as variáveis pthreshold1 e mthreshold1 são escolhidas para todos os quadros especificadas em clensing.rmd todos os píxeis são limpados. Também usa grey = false, pthreshold = 20, mthreshold = 180 e cthreshold = 30 para os outros quadros, porque estas variáveis são especificadas depois de clensing. Para todas as outras variáveis os valores padrões internos são levados. No caso RemoveDirt(default="bw") grey = true, pthresholdd = 20, mthreshold =180 e cthreshold = 30 são usados (claro que cthreshold é ignorado porque grey = true). No caso RemoveDirt(default="anime") os valores pthreshold = 40, cthreshold = 30 e mthreshold = 200 são usados. Se houver erros de sintaxe no RemoveDirt.ini, então RemoveDirt termina com uma mensagem de erro que exibe o número de linha com o primeiro erro de sintaxe.
Pela
mesma natureza do algoritmo subjacente RemoveDirt não pode limpar em
interruptores de cena aguçadas. Só muitos poucos blocos fortuitos são
limpados. Por outro lado o primeiro quadro depois que um interruptor de cena
deve ser codificado como uma I-quadro, e se este I-quadro é particularmente
sujo, a compressão tem prejuízo. Similar, o último quadro antes de um
interruptor de cena deve ser codificado como um P-quadro e a sujeira será
negativa para compressão. Mais outros filtros temporais têm problemas em
interruptores de cena aguçada. ImproveSceneSwitch é
um filtro simples para melhorar esta situação.
A diferença d(n) do quadro n e n+1 tem um papel
fundamental para este filtro. Está baseado na psadbw instrução SSE. Se
YV12 é o espaço de cor do clipe, então só o luma é usado para calcular a
diferença, caso contrário luma e croma são usados. A razão para esta diferença
é conveniência computacional. Se field = 0 (este é o padrão) então o quadro inteiro é usado para
calcular d(n). Se campo = 1, só então o campo de topo é usado para calcular a
diferença. Se campo = 2, só então o campo de fundo é usado para calcular a
diferença. Esta variável é importante para desentrelaçadores como
AlignFields. Nós determinamos um interruptor de cena (aguçada) entre quadro n e n+1 se d(n) >
ratio*d(n-1) e d(n)>ratio*d(n+1). Aqui a relação é uma variável de
inteiro > 1 (ratio = 7 é o padrão).Esta
variável determina a sensibilidade do interruptor de cena de
ImproveSceneSwitch. Não deve ser maior que 100 para evitar estouro aritmético.
Agora, se tivermos uma seqüência n-1,,n,n+1,n+2 de quadros com um interruptor
de cena entre n e n+1, então ImproveSceneSwitch substitui a seqüência
n-1,n,n+1 por n-1,n-1,n+2,n+2. Claro que este tipo de quadro duplo só deve
acontecer a interruptores de cena aguçada e então o espectador não deve notar
o truque. ImproveSceneSwitch é
usado como segue
ImproveSceneSwitch
(clip, orig, ratio = integer, extrapolate = boolean,
first = boolean, last = boolean, field=0,1,2, debug = boolean)
Aqui clip é
a produção e orig é a entrada do filtro
temporal, que deve ser melhorado por ImproveSceneSwitch.
orig só é usado para determinar trocas de cena.
Flash e efeitos semelhantes (muito comum em vídeos de música) pode enganar ImproveSceneSwitch.
Para tais clipes ImproveSceneSwitch não deve ser
usado ou uma relação muito alta acima de 10 deve ser escolhida. Como padrão,
o último quadro da cena velha e o primeiro quadro da cena nova é substituído
por ImproveSceneSwitch
. Porém,
para alguns filtros temporais como AlignFields só
um desses quadros deve ser substituído. Para este propósito temos as variáveis
boolean first e last. Se first =
false, então o quadro permanece inalterado, até mesmo se é detectado
como o primeiro quadro de uma cena nova. Similar, se last =
false, então o quadro permanece inalterado até mesmo se é detectado
como o último quadro de uma cena. first = true
e last = true
são os valores
padrões. ImproveSceneSwitch deve ser
aplicado como segue:
input = MPEG2Source("input.d2v") dein = RemoveDirt(input) ImproveSceneSwitch(dein, input)
Se debug = true, então informação de troca de cena é enviar a debugview. Se extrapolate = true (false é o padrão), então em vez de quadro simples que duplica a extrapolação é usado para calcular os quadros de troca de cena. Embora SSE possa ser muito bem usado para este propósito, extrapolação é óbvio muito mais lento que a duplicação de quadro e a compressão não é tão boa. Porém, o movimento é controlado melhor pela extrapolação. Conseqüentemente a relação pode ser escolhida um pouco abaixo se extrapolate = true. Por outro lado, se a relação não for muito pequena, então o espectador quase não deve perceber a duplicação de quadro. Eu apreciaria muito a avaliação no foro sobre a pergunta, se extrapolar ou não extrapolar. Assim que uma nova versão AlignField for liberada, ImproveSceneSwitch será removido de RemoveDirt e movido ao plugin AlignField. No AlignField será removido o código de troca de cena, porque ImproveSceneSwitch é melhor e mais rápido. Atualmente eu combino ImproveSceneSwitch com AlignFields pela função de Avisynth seguinte
function AF3(clip input) { dein = AlignFields(input,mode=3, scene=0, topfield=true, tff=true) return ImproveSceneSwitch(dein, input, ratio=5, first=true, last=false, field=2, debug=true) }
Se topfield = true e tff =
false, então first = false, last = true, field
= 2 têm que ser escolhidos ao invés. Se topfield = false e tff
= true, então then first = false, last = true, field
= 1têm que ser escolhidos. Finalmente, se topfield = false e tff
= false, então first = true, last = false, field
= 1 têm que ser escolhidos. Para determinar os valores corretos para outros
desentrelaçadores, deve-se olhar para o código de fonte. Pela
natureza do algoritmo, os primeiros dois e os últimas dois quadros sempre ficam
inalterados. ImproveSceneSwitch
é aperfeiçoado para a situação, quando os
quadros do clipe são pedidos
em seqüência.
Isto é típico para um processo de codificação.
É quase 4 vezes mais lento se os quadros são pedidos fortuitamente ou em ordem
inversa.
Por Rainer Wittmann "gorw em gmx.de"
$Date: 2006/03/26 18:11:53 $ Portuguese translation by RoLon