# Blockbuster

## Abstrato

autor: Ross Thomas
versão: 0.7
download: http://www.avisynth.org/warpenterprises/
categoria: Miscelânea de Plugins
requisitos: YV12 & YUY2 Colorspace

## Descrição

Blockbuster é um filtro Avisynth projetado para reduzir ou eliminar blocos DCT de um "enocode"(?). Os blocos DCT, também conhecido como "blocos escuros" quando aparecem em áreas de um quadro de baixo luma, são feios, atrapalhando os artefatos que os codificadores de MPEG gostam de espalhar liberalmente ao contrário do nosso que codifica sem defeito.

Enquanto a severidade do problema varia entre as versões diferentes de MPEG com MPEG-1 que exibe a maioria dos blocos DCT e MPEG-4 a menor, eles acontecem com todas as versões. MPEG-1 os produz quase em qualquer lugar em que há uma superfície plana com um baixo nível de detalhe (como uma parede) e MPEG-2 os mostra nas mesmas áreas, mas menos freqüentemente (eles são particularmente visíveis a bitrates mais baixos, como qualquer um acostumado com satélite digital pode testemunhar). MPEG-4 tem significantemente menos de um problema com baixos níveis de detalhes, mas ainda produz blocos DCT, especialmente em áreas escuras (veja este assunto no Doom9 para mais sobre estes blocos e MPEG-4).

(Incidentemente, DCT representa "discrete cosine transform" (transformar co-seno discreto) e é uma das técnicas que o MPEG usa para fazer sua compressão. Elas diferem de macroblocks que é a maioria notável em áreas de alto movimento quando o bitrate é insuficiente para descrever o movimento com precisão e também de ruído de mosquito que é um artefato que tende a aparecer próximo das extremidades e áreas de alto contaste).

Como indicado acima, a causa destes blocos parece ser uma falta de detalhe em áreas da imagem que o encoder não vê e assim aplica muita compressão. No processo os detalhes que estavam lá foram suavizados e a área se transformou num bloco DCT.

O objetivo deste filtro é tentar fazer para essas áreas mais notadas para o encoder de forma a alocar mais bits e assim não precisar comprimir tanto. A sua astúcia perceberá que este filtro, basicamente, é projetado para aumentar o bitrate (e diminuir a compressibilidade) do clipe. Enquanto isto é considerado um pecado capital pela maioria, há pelo menos duas razões válidas para fazer assim.

Primeiro, enquanto a possível relação de compressão mais alta for claramente desejável, deve-se considerar o custo. Ninguém aceita um filme com uma resolução de 120x90, embora sabendo ter uma excelente relação de compressão. Um efeito semelhante poderia ser alcançado suavizando o clipe até parecer que sua tela do monitor está coberta com vaselina, mas novamente, ninguém aceitaria este tipo de imagem.

Poderia ser discutido que blocos DCT são igualmente inaceitáveis com uma codificação de boa qualidade. A opinião geral difere grandemente nisto, mas um número crescente, eu inclusive, estamos procurando um modo seguro para se livrar deles. Este filtro é a minha contribuição ao esforço.

Segundo, como a tecnologia de compressão evolui e melhora às vezes é necessário re-codificar velhos filmes em formatos novos, mais avançados. A remoção de artefatos dos filmes existentes é muito mais difícil do que parar de aparecer em primeiro lugar. Assim, removendo os blocos DCT do seu codificado fará mais fácil a re-compressão de seus filmes depois.

## Como ele trabalha

O filtro divide cada quadro em uma série de blocos (de dimensões configuráveis) e confere cada bloco em troca da quantia de detalhe que contém. Se o nível de detalhe está dentro da gama definida, o bloco é processado de acordo com o parâmetro de método (veja a seção de Uso abaixo).

## Uso

Há vários métodos que podem reduzir potencialmente ou podem eliminar blocos DCT: incluindo barulho, aguçando, e borrando. Estas aproximações diferentes são acessadas com o parâmetro method, combinado com vários parâmetros compartilhados por todos os métodos como também parâmetros específicos a cada um. Há um método adicional chamado "show" que realça cada bloco que será afetado pelo filtro.

A forma geral de uso é

> `Blockbuster` (clip, method="...", shared parameters, method-specific parameters)

O parâmetro method pode ser um "noise", "dither", "sharpen", "blur" ou "show". Parâmetros específico a cada método será listado na seção de Métodos abaixo. Os parâmetros comuns a todos os métodos são:

Parâmetro | Descrição | Padrão
--- | --- | ---
block_size | Determina o tamanho dos blocos nos quais cada quadro é divido antes de processar. O valor representa a largura e altura do bloco e não pode ser menor que 3. | 8
detail_min, detail_max | Determina a quantia de detalhe que deve estar presente num bloco a ser processado. Este valor é uma porcentagem e pode estar entre 1 e 100. Representa a porcentagem dos níveis de brilho único dentro do bloco. Por exemplo, se block_size é fixado em 8, cada bloco contém 64 píxeis. Se detail_min é 1 e detail_max é 50, um bloco só será processado se contiver entre 1 e 32 níveis de brilho único. Uma colocação de detail_min=1, detail_max=100 processará o quadro inteiro. | detail_min=1, detail_max=10
luma_offset, luma_threshold | Os píxeis luma na gama 0-luma_threshold serão compensados por luma_offset nos blocos processados. Por exemplo, se luma_threshold é 30 e luma_offset é -2, os píxeis escuros (com um luma entre 0 e 30 inclusive) terá 2 subtraídos deles, fazendo-os ainda ligeiramente mais escuro. (Lógica: foi descoberto que o parâmetro lumoff do plugin mpeg2dec de Marc FD parece reduzir o aparecimento de "blocos escuros" MPEG-4 - blocos DCT em áreas escuras do quadro - mais adiante. Estes parâmetros são projetados para fazer a mesma coisa, mas força a mudança de brilho só em áreas que parecem precisar disso). | luma_offset=0, luma_threshold=25

## Métodos

### method="noise"

Este método inclui ruído para o clipe, distribuído normalmente - também conhecido como Gaussian. Testes mostraram que o ruído Gaussian é bem mais satisfatório para os propósitos deste filtro que ruído distribuído uniformemente.

Com ruído distribuído uniformemente, cada valor possível é o que pode acontecer a qualquer outro. Quer dizer, se você gerar uma sucessão de números na gama 1-100, a qualquer ponto na sucessão é provável gerar 5 como 95.

"Normalmente distribuídos" significa a chance de cada valor acontecer não ser igual. Digamos que você gera números normalmente distribuídos com um mean de 0 e uma variação de 1 (para uma explicação destas condições as ligações veja no término do parágrafo). O gerador pode teoricamente emitir qualquer número que se ajuste num ponto flutuante de dupla precisão, mas levado como um todo os números calcularão a média para zero (isso é o que mean=0, significa). Aproximadamente com estes parâmetros 68% dos valores estarão entre -1 e 1, quase 95% entre -2 e 2 e cerca de 99% entre -3 e 3. A probabilidade de gerar números significativamente mais altos ou mais baixos realmente é muito pequena, com a probabilidade de se ter o menor adicional além de zero. Você precisaria gerar bilhões de números fortuitos Gaussian com mean 0, variação 1 antes de ver, por exemplo, o valor 9 ser gerado. Você pode ler mais sobre distribuição normal aqui e aqui.

O ruído Gaussian tende a se concentrar em volta do especificado mean e é assim mais "natural" que o ruído distribuído uniformemente. A maioria das coisas em natureza (inclusive precipitação primaveril, entrada calorífica e claro, ruído) agrupe ao redor um "valor normal", com progressivamente menos ocorrências freqüentes como você obtém daquela norma mais adiante.

Você pode ler mais sobre acrescentar ruído para eliminar blocos DCT neste artigo Ars Technical (editado por Wilbert: eu não posso mais achar o assunto pertinente).

> `Blockbuster` (clip, method="noise", common parameters, float "mean", float "variance", int "cache", int "seed")

Parâmetro | Descrição | Padrão
--- | --- | ---
mean, variance | O mean e a variação do ruído randômico gerado. | mean = 0, variance = 1
cache | Porque a geração de números Gaussian é muito lenta, para alcançar desempenho razoável Blockbuster cria um cache de números fortuitos na inicialização. Este parâmetro especifica o tamanho do cache em kilobytes. Enquanto você puder fixar este valor a um número positivo, é melhor mantê-lo bastante grande para manter corretamente o ruído fortuito. Enquanto o padrão parecer bastante grande, considere isto: Se você tiver um bloco de tamanho 8, então cada bloco tem uma área de 64 píxeis. Cada píxel exige 2 bytes para descrevê-lo, assim um bloco processado consumirá 128 bytes de dados fortuitos. Se são processados 10% dos blocos em uma imagem 640x480, requererá quase 62 Kb de números aleatórios. | 256
seed | Por padrão o gerador de número pseudo-fortuito usará o tempo atual do sistema como seu valor de semente. Com certeza, aplicações onde os resultados previsíveis são desejados, o parâmetro de semente pode ser usado para anular esse padrão, provendo o mesmo "ruído fortuito" cada vez que o filtro é rodado. A semente pode ser qualquer número de 0 a 2,147,483,647. Quando zero, o tempo atual do sistema é usado. | 0

### method="dither"

Este método é bem parecido ao "método de ruído", com a única diferença de que este método acrescentará o mesmo ruído a cada quadro do clipe, considerando que o "método de ruído" acrescentará ruído diferente a cada quadro. O efeito disto é duro descrever, mas fácil de ver, assim tente você mesmo com uma variação alta. A comparação mais perto que eu posso pensar é que este método produz um efeito semelhante ao assistir o filme por um copo salpicado.

A razão pela qual incluí este método é porque eu achei ao usar o method = "noise" que a natureza constantemente variável do ruído produziu movimento e ao contrário nas áreas estáticas dos quadros, particularmente ao usar um baixo bit de taxa. A minha esperança que usando o mesmo ruído para cada quadro prevenirá movimento artificial em áreas estáticas. Isto deve ser considerado experimental.

> `Blockbuster` (clip, method="dither", common parameters, float "mean", float "variance", int "seed")

Para uma descrição dos parâmetros deste método, veja o método de "ruído" acima. Note porém que o método "dither" não tem nenhum parâmetro de cache desde que sempre só gera bastante ruído para um quadro.

### method="sharpen"

Este método aplica um básico (e rápido) filtro de aguçamento a blocos processados. E deste modo "amplia" detalhe já presente no bloco em lugar de acrescentar ruído novo.

> `Blockbuster` (clip, method="sharpen", common parameters, int "strength")

Parâmetro | Descrição | Padrão
--- | --- | ---
strength | Especifica a força para aguçar, de 1-100. | 25

### method="blur"

Este método aplica um borrado 3x3 aos blocos processados. É atualmente experimental, desde que teoricamente reduzir a freqüência de blocos de baixa freqüência não reduzirá o aparecimento de blocos DCT. Vale uma prova, entretanto, :).

> `Blockbuster` (clip, method="blur", common parameters, int "strength")

Parâmetro | Descrição | Padrão
--- | --- | ---
strength | Especifica a força para borrar, de 1-100. | 25

### method="show"

Este método realça blocos que serão processados com os parâmetros comuns de blocos relacionados especificados (block_size, detail_min, e detail_max). É principalmente útil como uma ajuda visual fixando os percentuais de detalhes à gama desejada.

Este método não tem nenhum parâmetro adicional.

## TODO - a fazer

- Otimizações MMX/SSE (Eu tenho que aprender assembler x86 primeiro...).
- Método de máscara Unsharp.

## Autor

Ross Thomas <ross(at)grinfinity.com>

$Date: 2004/08/13 21:57:25 $`Portuguese translation by RoLon`