FFmpeg eq filter complex: Contraste

4

Eu estou jogando com o filtro eq no FFmpeg:

link

Usando um comando como:

ffmpeg -y -loop 1 -i input.jpg -filter_complex "[0:v]eq=1:0:1:1:1:1:1:1[outv]" -map [outv] -c:v libx264 -t 3 -pix_fmt yuv420p out.mp4 # does nothing

A documentação sugere que o primeiro componente do filtro é o contraste:

Set the contrast expression. The value must be a float value in range -2.0 to 2.0. The default value is "0".

No entanto, descobri que, para não haver mudanças no contraste, o valor deve ser "1". Este não deveria ser o padrão?

Enfim, estou confuso se esse primeiro valor é mesmo contraste. Não se comporta como eu esperaria contraste. Estou comparando-o a, e. css -webkit-filter: contrast(x) . Em CSS, contrast(0) torna toda a imagem cinza. No entanto, no FFmpeg, a imagem parece ser parte amarela e parte cinza (presumivelmente dependente da minha imagem:

CSS contrast(-1) é inválido. No entanto, no FFmpeg, o contraste -1 é quase um contraste invertido. Eu entendo as duas coisas foram implementadas completamente separadamente, mas eu teria esperado uma relação aproximada. Eu estou entendendo mal o valor do contraste dos filtros eq?

    
por Jon G 15.06.2015 / 15:30

2 respostas

6

Você precisa especificar as opções no filtro por nome, para que as configurações originais do filtro precisem ser alteradas para ...

-filter_complex "[0:v]eq=contrast=1:brightness=0:saturation=1:gamma=1:
gamma_r=1:gamma_g=1:gamma_b=1:gamma_weight=1[outv]"

... se você quiser definir todos esses parâmetros. Caso contrário, o filtro vai ignorar suas configurações e aplicar os valores padrão, ou pode interpretar erroneamente o valor de uma opção pretendida para outra (não não deve , mas coisas estranhas aconteceram com os filtros do FFmpeg).

No que se refere aos valores selecionados e aos resultados finais, o código slhck apontado mostra que os conjuntos de valor um por opção são executados por meio de uma série de cálculos internos; em seguida, os resultados são usados para avaliar e fazer ajustes no nível do pixel . Parece que o cálculo "base" para contrast é ...

(param->contrast * 256 * 16)

... então o valor padrão de 0 resultaria em 0, um valor especificado de 1 resultaria em 4096, um valor de -0.00275 resultaria em -11.264, etc, e esses valores base são usado em outros cálculos abaixo da linha. Em outras palavras, seria melhor considerar o tratamento desses parâmetros como único, então passe algum tempo brincando com eles para ver como eles funcionam. Para ter uma ideia verdadeira dos efeitos, você pode ajustar e pesquisar a saída das configurações de eq usando o FFplay, por exemplo:

ffplay -i input.jpg -vf "eq=contrast=1.5:brightness=-0.05:saturation=0.75"

No que diz respeito ao seu script original, como você estava usando apenas uma entrada (seu jpeg), um filtro (eq) e todas as opções, exceto contrast , estavam carregando valores padrão, você pode reduzir o script para o seguinte para obter o seu MP4 de 3 segundos, desde que eq=contrast=1 produza resultados desejáveis:

ffmpeg -y -loop 1 -i input.jpg -vf "eq=contrast=1" -c:v libx264 \
-pix_fmt yuv420p -t 3 out.mp4

divulgação completa: pós-edição de 2016/06/19 para maior esclarecimento e informações estendidas

    
por 19.06.2015 / 09:52
3

Para responder à sua pergunta original sobre o contraste no FFmpeg em relação ao CSS, o código O fragmento abaixo parece sugerir que contrast no FFmpeg se aplica apenas a luminância / luma (brilho), enquanto saturation só se aplica a crominância / croma (cores).

static void set_contrast(EQContext *eq)
{
    eq->contrast = av_clipf(av_expr_eval(eq->contrast_pexpr, eq->var_values, eq), -1000.0, 1000.0);
    eq->param[0].contrast = eq->contrast;
    eq->param[0].lut_clean = 0;
    check_values(&eq->param[0], eq);
}

// ...

static void set_saturation(EQContext *eq)
{
    int i;

    eq->saturation = av_clipf(av_expr_eval(eq->saturation_pexpr, eq->var_values, eq), 0.0, 3.0);

    for (i = 1; i < 3; i++) {
        eq->param[i].contrast = eq->saturation;
        eq->param[i].lut_clean = 0;
        check_values(&eq->param[i], eq);
    }
}

Observe como em set_contrast , somente param[0] (denotando o primeiro componente de cor, que em YUV é Y, o luma) é alterado, enquanto em set_saturation apenas param[1] e param[2] (denotando amarelo e magenta, o croma) são alterados. Isso deve levar em conta o fato de que você está vendo amarelo e magenta, dois componentes de cores chroma , quando você diminui o contraste para 0 no FFmpeg. Quando você ajusta a saturação para 0 também, estou vendo uma imagem cinza clara semelhante à produzida pelo CSS.

A relação entre contrast e saturate do CSS versus contrast e saturation do FFmpeg pode ser estabelecida como:

filter: contrast(c) saturate(s);

is equivalent to

eq=contrast=c:saturation=c*s

Capturas de tela obrigatórias mostrando c = 0,6 e s = 1,3:

    
por 06.10.2016 / 08:33