opencv with ffmpegで無劣化動画を作成

とりあえずCVS version限定(かは知らないけど、あと多分古すぎないffmpeg限定)。
研究なんかだと実験動画は無劣化(無圧縮か可逆圧縮)な物じゃないと困る。が、OpenCVでそれを作るのは意外と面倒?
適当にOpenCVで検索すると出てくるfourccの"DIV "は、(少なくともlinuxでは)今は使えないみたい。何故かは知らん。で、可逆圧縮で検索すると良く出てくるffvhuffは、yuv420pで保存されるので普通に劣化する。yuv444pとかyuvj444pでも試して見たけどイヤンと言われたので、たぶん対応してない。つか今まで怪しいとは思いつつ普通に使ってた。
で、今日適当に探したその解決策。

その1.FFV1

さり気なく普通にある別の可逆圧縮フォーマット。これが普通に使える。なんでかって言うとOpenCVのコードに

  // set a few optimal pixel formats for lossless codecs of interest..
     int codec_pix_fmt;
     switch (codec_id) {
     case CODEC_ID_JPEGLS:
         // BGR24 or GRAY8 depending on is_color...
         codec_pix_fmt = writer->input_pix_fmt;
         break;
     case CODEC_ID_FFV1:
         // no choice... other supported formats are YUV only
         codec_pix_fmt = PIX_FMT_RGBA32;
         break;

とかって書いてあるから。うーんアドホックな香り。ん、このコードだとJPEGLSも使えるのかも。
これの欠点は、結構重いこと。

その2.無圧縮(RAWVIDEO)

で、軽さを極める無圧縮をーって思うと、何故かRAWVIDEOなのに劣化してる。と思うとさっきのコードのすぐ下に

     case CODEC_ID_RAWVIDEO:
     default:
         // good for lossy formats, MPEG, etc.
         codec_pix_fmt = PIX_FMT_YUV420P;
         break;

なるコードが。"set a few optimal pixel formats for lossless codecs"で"good for lossy formats, MPEG, etc."なyuv420pとか設定する神経が分からん。これをBGR24に変更すると、怪しい動画が出来るようになる。具体的には

  • mplayerとgmplayerで結果が違う(mplayerだと上下逆さま、横もかも)
  • OpenCVで読み込もうとするとSIGFPEを吐く。ホントに浮動小数演算でエラーを吐く。
  • OpenCVで読み込んだ画像は無劣化で、向きとかも正常:)

まあSIGFPEはtrap仕掛けない限り表に出てこないけど。