Extrahieren Sie den Y-Kanal jedes I-Frames so verlustfrei wie möglich aus dem MPEG4-Film

681
Goat-Anti-Rabbit

Ich arbeite an einem Video-Tracking-Experiment und stecke mit Videos fest, die mit dem MPEG4 DivX 5x / 6x-Codec ziemlich stark komprimiert sind. Ich bin relativ neu mit Bildformaten, Codecs und Komprimierung, aber ich glaube, ich habe herausgefunden, dass ich bei dieser Qualität bleibe, es sei denn, ich verstoße gegen den zweiten Hauptsatz der Thermodynamik.

Nun, um meine Insekten zu verfolgen (yeap, das ist was ich mache), interessiere ich mich nur für I-Frames (Framerate ist hoch genug) und ich interessiere mich nicht für die Farbkanäle U und V, da sie nur solche haben Einen Wert für jeden Block und daher nicht die Auflösung, die ich möchte. Es ist der Y-Kanal, der alle Informationen enthält, an denen ich interessiert bin. Ich habe meinen Tracker selbst geschrieben, er kann kein Video analysieren und benötigt daher einen Ordner mit Standbildern.

Nun ist meine Frage: Wie kann ich alle I-Frames zu Graustufenbildern (nur Y-Kanal) extrahieren, OHNE weiteren Qualitätsverlust? Ich arbeite in Ubuntu 14.04 und benutze bevorzugt ffmpeg oder imageJ, da sie bereits in meiner Pipeline vorhanden sind. Wo ich jetzt bin:

Ich glaube, ich habe herausgefunden, dass jeder zweite Frame ein Ich-Frame ist, aber ich bin mir nicht sicher. Ich benutzte:

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 

Nun dachte ich, ich habe herausgefunden, wie ich jeden Frame extrahieren kann:

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

Aber es scheint mir alle Frames zurückzugeben.

ls *jpg | wc -l 133370 

Was mache ich falsch? Dies ist die Ausgabe, die mir ffmpeg gibt:

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 

Also ein paar Fragen:

  • Was mache ich falsch? Warum gibt es mir alle Frames zurück?
  • Wird jpeg weiteren Verlust verursachen? Oder ist es die gleiche Komprimierung wie bei MPEG4 innerhalb von Frames? Soll ich vielleicht stattdessen tiff verwenden?
  • Wie extrahiere ich nur den Y-Kanal?
  • Ist es normal, dass ich jeden zweiten Frame ein I-Frame bekomme? Ich habe ein wenig in die MPEG4-Codierung eingelesen und es scheint, dass nicht ganze Frames, sondern Blöcke als Referenz verwendet werden. Muss ich dann alle Frames extrahieren, die solche Blöcke enthalten? Gibt es eine höhere Ebene mit "echten" Referenzrahmen?
  • Ich denke, es gibt keine Möglichkeit, mehr Qualität zu erreichen.

Vielen, vielen Dank für Ihre Hilfe!

Schöne Grüße,

Rik Verdonck

1

1 Antwort auf die Frage

4
Gyan

ffmpeg verwendet implizit die Framerate der Quelle, sofern nicht ausdrücklich etwas anderes angegeben ist. Wenn sich die Anzahl der vom Decoder / Filter gelieferten Frames von dieser Rate unterscheidet, werden die Frames dupliziert oder verworfen, um sie zu erreichen. Dies kann behoben werden, indem für jeden ausgewählten Frame neue Zeitstempel generiert werden oder indem eine Framerate angegeben wird, die der Frequenz von I-Frames pro 1 Sekunde Video entspricht. Sicherer, das Erste zu tun.

Sie können anstelle von JPEG TIFF oder PNG oder BMP verwenden, um weitere Komprimierung zu vermeiden. Unsicher, ob die Vorhersageschemas für JPEG- und MPEG-Codecs gleich sind.

Ein I-Frame bei jedem zweiten Frame ist für einen MPEG-4-Codec ungewöhnlich, aber Sie sagten, diese waren schlecht codiert. Jemand hat entweder ein GOP gesetzt, dh ein Keyframe-Intervall von 2, oder einen sehr niedrigen Szenenänderungsschwellenwert, wahrscheinlich der frühere.

Zusammenfassend verwenden

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

Bearbeitet

Verwenden Sie für die direkte Y-Komponentenextraktion

ffmpeg -i movie.avi -vf "select=eq(pict_type\,I),setpts=N/25/TB,extractplanes=y" -pix_fmt gray /picture%d.png 
Sieht gut aus. Wissen Sie jedoch, ob `-pix_fmt grey` direkt der Y-Komponente der Eingabe entspricht? slhck vor 8 Jahren 0
Ich dachte schon, aber es scheint, als ob ein Filter angewendet wird - die Bereichserweiterung sieht aus wie. Direkter Hubbefehl hinzugefügt. Gyan vor 8 Jahren 0
Hallo Mulvya, danke für deine Hilfe. Es scheint zu funktionieren, aber ich bekomme etwas Output in meinem Terminal, das mich etwas beunruhigt. Es sieht so aus: `Vergangene Dauer 0,999992 zu groß Letzte Nachricht wiederholt 30 Mal Letzte Dauer 0,999992 zu großN / A Zeit = 00: 00: 11.36 Bitrate = N / A Geschwindigkeit = 22.7x Letzte Nachricht wiederholt 33 Mal Letzte Zeit 0,999992 zu großN / Eine Zeit = 00: 00: 23.48 Bitrate = N / A Geschwindigkeit = 23.5x Wiederholt etwa 20 mal. Goat-Anti-Rabbit vor 8 Jahren 0
Ignoriere es. Macht keinen Unterschied in der Ausgabe. Gyan vor 8 Jahren 0