Obtenha miniaturas nítidas e claras do MP4 com o FFmpeg / ImageMagick

6

Meu objetivo final é obter instantâneos significativos de vídeos de 30 min ou 1 hora. "Significativo" é um pouco ambicioso, por isso simplifiquei meus requisitos.

A imagem deve ser nítida - não embaçada.

Inicialmente, achei que isso significava obter um "quadro-chave". Como há muitos keyframes, decidi escolher o quadro-chave mais próximo do terceiro minuto do vídeo, que geralmente era "significativo" o suficiente para mim. Eu segui o conselho em: Comando FFmpeg para encontrar o quadro-chave mais próximo ao terceiro minuto

Mas o problema é que esses quadros-chave são frequentemente (nem sempre) borrados. Um exemplo é:

Eutentei,então, Miniaturas significativas para um vídeo usando o FFmpeg o que ajudou a obter instantâneos mais significativos, mas eu ainda frequentemente (nem sempre) obtive quadros desfocados como os acima.

Você notará que esse tipo de imagem é essencialmente uma sobreposição de duas cenas diferentes. Às vezes, no entanto, recebo imagens que funcionam para mim - assim:

A imagem acima não é muito significativa, mas é nítida.

Idealmente, gostaria que o FFmpeg não retornasse quadros desfocados. Como alternativa, gostaria de usar um script para detectar quadros desfocados e selecionar os menos desfocados de, digamos, 5 quadros. Alguém sabe como fazer isso?

    
por cnfcnf 14.02.2013 / 11:26

1 resposta

6

"significativo" é bastante subjetivo, mas "embaçado" é bastante objetivo e simples de detectar.

Eu tive um problema semelhante e depois de um pouco de pesquisa acabei com o seguinte algoritmo:

  • Determine o tamanho do arquivo de vídeo em segundos.
  • Gere 10 miniaturas png usando o ffmpeg e a detecção de mudança de cena com algo como:

    ffmpeg -ss {$skip} -i {$input} -vf "select=gt(scene\,0.3)" -r 1 -frames:v 1 {$output}
    

Em cada iteração $skip é aumentado em 10% na duração do vídeo em segundos. O parâmetro 0.3 pode não ser o mais adequado para você, mas você pode jogar com ele. Isso resolveu o problema com as cenas sobrepostas e / ou imagens completamente borradas.

  • Detecte as bordas dessas 10 miniaturas e reduza-as para melhor desempenho com o ImageMagick:

    convert {$input} -thumbnail {$w}x{$h} -colorspace Gray -edge 1 {$path_to_downscaled_image}
    

Estou usando -thumbnail para dimensionar a imagem. Então estou adicionando um filtro preto e branco. Por fim, faço a detecção de bordas com um raio de 1. Isso produz uma imagem em preto e branco apenas com as bordas marcadas como brancas. Isso significa que quanto mais branca a imagem tiver, mais arestas haverá nela. Você terá algo assim:

  • IdentifiqueasimagensempretoebrancoresultantescomoImageMagick:

    identify-format'{$format}'{$path_to_downscaled_image}

Oquevocêdeveestarinteressadoé%[mean]e%[desvio-padrão].Joguecomelesevejaoquemelhorcombinacomvocê.Bastaordenartodasasimagensresultantespor"% [média] +% [desvio-padrão]" por exemplo. Encontre a mesma imagem antes de começarmos a redimensioná-la e filtrá-la.

  • Por último, escolha o mais "ousado", encontre o original e, opcionalmente, converta novamente:

    convert {$input} -thumbnail {$w}x{$h} -adaptive-sharpen 1.25x0.75 {$final_output}
    

Descobri que -adaptive-sharpen realmente ajuda com o resultado final porque aguça as imagens apenas em torno dessas mesmas arestas. Eu tentei diferentes geometrias e descobri que 1.25x0.75 funciona melhor para mim quando estou diminuindo para um quarto da resolução original.

Eu fiz isso em PHP e demora cerca de 25 segundos para um filme de 12 minutos ser executado, o que é bom para mim.

Espero que isso tenha sido útil.

por 10.12.2013 / 16:56