MPEG4 ムービーから各 I フレームの Y チャンネルを可能な限りロスレスで抽出します。

MPEG4 ムービーから各 I フレームの Y チャンネルを可能な限りロスレスで抽出します。

私はビデオ トラッキング実験に取り組んでおり、MPEG4 DivX 5x/6x コーデックで圧縮されたビデオで行き詰まっています。私は画像形式、コーデック、圧縮についてはあまり詳しくありませんが、熱力学の第二法則に違反しない限り、この品質で行き詰まることがわかったと思います。

さて、昆虫を追跡するには (そう、それが私のやっていることです)、I フレームだけが必要です (フレーム レートは十分に高い)。カラー チャネル U と V には興味がありません。ブロックごとに 1 つの値しかないため、必要な解像度が得られないからです。私が興味を持っているすべての情報があるのは Y チャネルです。トラッカーは自分で作成しましたが、ビデオを解析できないため、静止画のフォルダーが必要です。

ここでの質問は、品質をこれ以上損なうことなく、すべての I フレームをグレースケール (Y チャンネルのみ) 画像に抽出するにはどうすればよいかということです。私は Ubuntu 14.04 で作業しており、ffmpeg または imageJ を優先的に使用したいと思います。これらは既にパイプラインに存在しているためです。現在の状況は次のとおりです。

2 フレームごとに I フレームであることを理解したと思いますが、確信はありません。私は以下を使用しました:

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

さて、私はすべての I フレームを抽出する方法を見つけたと思いました:

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

しかし、すべてのフレームが返されるようです。

ls *jpg | wc -l
133370

何が間違っているのでしょうか? ffmpeg の出力は次のようになります:

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

そこで、いくつか質問があります。

  • 何が間違っているのでしょうか? すべてのフレームが返されるのはなぜですか?
  • jpeg ではさらに損失が発生しますか? それとも、mpeg4 のフレーム内で使用されるのと同じ圧縮ですか? 代わりに tiff を使用する必要があるでしょうか?
  • Y チャネルのみを抽出するにはどうすればよいでしょうか?
  • 2 フレームごとに I フレームを取得するのは正常ですか? MPEG4 エンコードを少し読んでみたところ、フレーム全体ではなくブロックが参照として使用されているようです。そのようなブロックを含むすべてのフレームを抽出しているのですか? 「実際の」参照フレーム全体を含む上位レベルはありますか?
  • これ以上の品質回復方法はないのでしょうか?

ご協力に本当に感謝しています!

幸運をお祈りしています、

リック・フェルドンク

答え1

ffmpeg は、明示的に指定されない限り、ソースのフレーム レートを暗黙的に使用します。デコーダー/フィルターによって提供されるフレーム数がそのレートと異なる場合、そのレートを達成するためにフレームが複製またはドロップされます。これは、選択したフレームごとに新しいタイムスタンプを生成するか、ビデオの 1 秒あたりの I フレームの頻度と一致するフレーム レートを指定することによって解決できます。前者を実行する方が安全です。

さらなる圧縮を避けるために、JPEG の代わりに TIFF、PNG、または BMP を使用できます。JPEG コーデックと MPEG コーデックの予測スキームが同じかどうかは不明です。

1 フレームおきの I フレームは MPEG-4 コーデックでは珍しいですが、これらはエンコードが不適切だとおっしゃいました。誰かが GOP、つまりキーフレーム間隔を 2 に設定しているか、シーン変更しきい値を非常に低く設定しています。おそらく前者でしょう。

要約すると、

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

編集済み

Y成分を直接抽出するには、

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

関連情報