Extraia o canal Y de cada quadro I do filme MPEG4 da maneira mais perdida possível


1

Estou trabalhando em um experimento de rastreamento de vídeo e fiquei preso a vídeos bastante compactados com o codec MPEG4 DivX 5x / 6x. Sou bastante novo em formatos de imagem, codecs e compactação, mas acho que descobri que estou preso a essa qualidade, a menos que viole a segunda lei da termodinâmica.

Agora, para rastrear meus insetos (sim, é isso que estou fazendo), estou interessado apenas nos quadros I (a taxa de quadros é alta o suficiente) e não estou interessado nos canais de cores U e V, pois eles só têm um valor para cada bloco e, portanto, não me dê a resolução que eu quero. É o canal Y que tem todas as informações que me interessam. Escrevi meu rastreador e ele não pode analisar o vídeo, por isso precisa de uma pasta com fotos.

Agora, minha pergunta é: como posso extrair todos os quadros I para imagens em escala de cinza (apenas canal Y) SEM QUALQUER OUTRA QUALIDADE DE QUALIDADE? Estou trabalhando no ubuntu 14.04 e preferencialmente usaria o ffmpeg ou o imageJ, pois eles já estão presentes no meu pipeline. Onde estou agora é:

Acho que descobri que cada segundo quadro é um quadro I, mas não tenho certeza disso. Eu usei:

ffprobe -show_frames movie.avi | grep -A2 "video" | grep "key_frame"

output: 
key_frame=1
key_frame=0
key_frame=1
key_frame=0
key_frame=1
key_frame=0
key_frame=1
key_frame=0
key_frame=1
key_frame=0

--
this goes on for exactly the number of frames, as this bit of code tells me: 
ffprobe -show_frames movie.avi | grep -A2 "video" | grep -c "key")
13369

Agora, pensei em descobrir como extrair todos os quadros que eu:

ffmpeg -i movie.avi -vf '[in]select=eq(pict_type\,I)[out]' /picture%d.jpg         

Mas parece me devolver todos os quadros.

ls *jpg | wc -l
133370

O que estou fazendo errado? Esta é a saída que o ffmpeg me fornece:

ffmpeg version N-77455-g4707497 Copyright (c) 2000-2015 the FFmpeg developers
built with gcc 4.8 (Ubuntu 4.8.4-2ubuntu1~14.04)
configuration: --extra-libs=-ldl --prefix=/opt/ffmpeg --mandir=/usr/share/man --enable-avresample --disable-debug --enable-nonfree --enable-gpl --enable-version3 --enable-libopencore-amrnb --enable-libopencore-amrwb --disable-decoder=amrnb --disable-decoder=amrwb --enable-libpulse --enable-libdcadec --enable-libfreetype --enable-libx264 --enable-libx265 --enable-libfdk-aac --enable-libvorbis --enable-libmp3lame --enable-libopus --enable-libvpx --enable-libspeex --enable-libass --enable-avisynth --enable-libsoxr --enable-libxvid --enable-libvo-aacenc --enable-libvidstab
libavutil      55. 11.100 / 55. 11.100
libavcodec     57. 20.100 / 57. 20.100
libavformat    57. 20.100 / 57. 20.100
libavdevice    57.  0.100 / 57.  0.100
libavfilter     6. 21.101 /  6. 21.101
libavresample   3.  0.  0 /  3.  0.  0
libswscale      4.  0.100 /  4.  0.100
libswresample   2.  0.101 /  2.  0.101
libpostproc    54.  0.100 / 54.  0.100 
Guessed Channel Layout for  Input Stream #0.1 : stereo
Input #0, avi, from 'movie.avi':
Duration: 00:08:54.76, start: 0.000000, bitrate: 3006 kb/s
Stream #0:0: Video: mpeg4 (Simple Profile) (DX50 / 0x30355844), yuv420p, 720x576 [SAR 16:15 DAR 4:3], 1462 kb/s, 25 fps, 25 tbr, 25 tbn, 25 tbc
Stream #0:1: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 48000 Hz, 2 channels, s16, 1536 kb/s
[swscaler @ 0x3c2e920] deprecated pixel format used, make sure you did set range correctly
Output #0, image2, to './picture%d.jpg':
Metadata:
encoder         : Lavf57.20.100
Stream #0:0: Video: mjpeg, yuvj420p(pc), 720x576 [SAR 16:15 DAR 4:3], q=2-31, 200 kb/s, 25 fps, 25 tbn, 25 tbc
Metadata:
  encoder         : Lavc57.20.100 mjpeg
Side data:
  unknown side data type 10 (24 bytes) 
Stream mapping:
Stream #0:0 -> #0:0 (mpeg4 (native) -> mjpeg (native))
Press [q] to stop, [?] for help

frame=13370 fps=506 q=24.8 Lsize=N/A time=00:08:54.80 bitrate=N/A dup=6685 drop=0 speed=20.2x    
video:157591kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown

Então, algumas perguntas:

  • O que estou fazendo errado? Por que isso me devolve todos os quadros?
  • O jpeg causará mais perdas? Ou é a mesma compactação usada no intra-frame no mpeg4? Talvez eu devesse usar tiff?
  • Como extraio apenas o canal y?
  • É normal que eu receba um quadro I a cada segundo quadro? Eu tenho lido um pouco sobre a codificação MPEG4 e parece que não quadros inteiros, mas blocos são usados ​​como referência? Estou então extraindo todos os quadros que contêm esses blocos? Existe um nível superior com quadros de referência inteiros "reais"?
  • Eu acho que não há como recuperar mais qualidade?

Muito, muito obrigado pela sua ajuda!

Muitas felicidades,

Rik Verdonck

Respostas:


4

O ffmpeg usa implicitamente a taxa de quadros da fonte, a menos que explicitamente especificado de outra forma. Se o número de quadros fornecidos pelo decodificador / filtro for diferente dessa taxa, os quadros serão duplicados ou eliminados para alcançá-lo. Isso pode ser remediado gerando novos registros de data e hora para cada quadro selecionado ou especificando uma taxa de quadros que corresponda à frequência de quadros I por 1 segundo de vídeo. Mais seguro para fazer o primeiro.

Você pode usar TIFF ou PNG ou BMP em vez de JPEG para evitar mais compactação. Não tenho certeza se os esquemas de previsão são os mesmos para os codecs JPEG e MPEG.

Um quadro I em qualquer outro quadro é incomum para um codec MPEG-4, mas você disse que estes estavam mal codificados. Alguém definiu um GOP, ou seja, intervalo de quadro-chave de 2 ou um limiar de alteração de cena muito baixo, provavelmente o primeiro.

Em resumo, use

ffmpeg -i movie.avi -vf "select=eq(pict_type\,I),setpts=N/25/TB" -pix_fmt gray /picture%d.png 

Editado

Para extração direta de componente Y, use

ffmpeg -i movie.avi -vf "select=eq(pict_type\,I),setpts=N/25/TB,extractplanes=y" -pix_fmt gray /picture%d.png   

Parece bom. Você sabe se -pix_fmt graycorresponde diretamente ao componente Y da entrada?
slhck

Eu pensei que sim, mas parece que há algum filtro aplicado - a expansão do alcance, parece. Comando de elevação direta adicionado.
Gyan

Olá Mulvya, obrigado por sua ajuda. Parece funcionar, mas recebo alguma saída no meu terminal que me preocupa um pouco. É assim: Past duration 0.999992 too large Last message repeated 30 times Past duration 0.999992 too largeN/A time=00:00:11.36 bitrate=N/A speed=22.7x Last message repeated 33 times Past duration 0.999992 too largeN/A time=00:00:23.48 bitrate=N/A speed=23.5x Repetido cerca de 20 vezes.
cabra anti-coelho

Ignore isto. Não faz diferença na saída.
Gyan
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.