トップページ -> コンピュータ実習 -> Octave を用いた画像処理,信号処理 -> AVI 形式のビデオファイルを扱う例
[サイトマップへ], [サイト内検索へ],

AVI 形式のビデオファイルを扱う例

サイト構成 連絡先,業績など コンピュータ実習 データの扱い コンピュータ設定 教材(公開) サポートページ

AVI 形式のビデオファイルを扱う例を説明


前準備

必見 Web ページ: http://www.csse.uwa.edu.au/~pk/Research/MatlabFns/

必見 Web ページ: http://www.eecs.berkeley.edu/Research/Projects/CS/vision/bsds/

※ プロンプトを変えたいときは,次のように操作する.

PS1('> ')

※ Octave のインストールによっては,Octave の起動時に毎回次の操作を行う必要があるかもしれない

pkg load image

実行方法と実行結果の例

  1. Octave の起動

    Linux の場合

    Windows の場合

    デスクトップのアイコン等を使って Octave を起動

  2. ビデオファイルの読み込み(1フレーム分)とフレームの確認表示

    ファイル名とフレーム番号を指定している./usr/OpenCV-2.0.0/samples/c/tree.avi は OpenCV に付属のサンプルデータ

    pkg load video
    img = aviread("/usr/local/share/OpenCV/samples/c/tree.avi", 100);
    imshow(img);
    

    ■ Octave 3.6.3, Ubuntu バージョン 12.04 での実行結果例

aviread() 関数で,必ずしもすべての種類 avi ファイルが読めるとは限りません. ffmpeg 内のコーデックと avi ビデオファイルの相性に起因すると思われるバグの例を示しておきます (このときは, Linux なら winff のようなツールを使ってエンコードしなおす)

1004 の挙動がおかしい

■ フレーム番号 1003

■ フレーム番号 1004

■ フレーム番号 1005


Octave で avi 形式ビデオファイルを扱う例

avi 形式ビデオファイルに関する情報取得

aviinfo() 関数を使って,1秒あたりのフレーム数,縦,横などを取得できます.

pkg load video
avi = aviinfo("/usr/local/share/OpenCV/samples/c/tree.avi");
avi

■ Octave 3.6.3, Ubuntu バージョン 12.04 での実行結果例

簡単なフレーム間差分表示

pkg load video;
img = aviread("/tmp/V0701001winff.avi", 1000);
img2 = aviread("/tmp/V0701001winff.avi", 1002);
# Octave 3.2.3 よりも古いバージョンの Octave では「imshow( (img2 - img) * 128 + 128 );」でうまく行く場合がある
imshow( ( (img2 - img) + 1 ) / 2 );

■ Octave 3.3.53, Ubuntu バージョン 10.10 での実行例

(参考)ビデオファイルの差分画像の表示例

カメラが固定している場合,背景がきれいに除去できることが確認できた.

avi 形式ビデオファイルの各フレームに関する繰り返し処理

ガウシアンフィルタを使って,avi 形式ビデオファイルの各フレームを「ぼかし」た後,32 色に減色することを繰り返す例. kbhit() 関数を使っているので,何かのキーを押すと次のフレームに移る.

pkg load video;
s = 2; 
f = fspecial("gaussian", s * 5, s); 
for i = [100:110]
  rgb = aviread("/usr/OpenCV-2.0.0/samples/c/tree.avi", i);
  rgb2 = imfilter(double(rgb), f, "same"); 
  imwrite(rgb2, "/tmp/hoge.ppm");
  system( "ppmquant 32 /tmp/hoge.ppm > /tmp/hoge2.ppm" ); 
  rgb3 = imread( "/tmp/hoge2.ppm" );
  imshow( rgb3 ); 
  kbhit(); 
end

※ imwrite() 関数の実行において「セマフォ・・・」のようなエラーがでることが有ります. このときは,プログラムの先頭で,関係の無い画像ファイルでいいので,imread(), imwrite() を実行しておく(つまり aviread() 関数の前に)とエラーを回避できる場合があります.

a = imread("fruits.jpg");
imwrite(a, "/tmp/fruits.jpg");

avi 形式ビデオファイルの生成の例

上の例では,画像を 1枚1枚表示していましたが,新しい avi ビデオファイルを作ってみることにします.

pkg load video;
s = 2; 
f = fspecial("gaussian", s * 5, s); 
F = avifile("tree2.avi");
for i = [1:445]
  rgb = aviread("/usr/OpenCV-2.0.0/samples/c/tree.avi", i);
  rgb2 = imfilter(double(rgb), f, "same"); 
  imwrite(rgb2, "/tmp/hoge.ppm");
  system( "ppmquant 32 /tmp/hoge.ppm > /tmp/hoge2.ppm" ); 
  rgb3 = imread( "/tmp/hoge2.ppm" );
  addframe(F, double(rgb3) / 255);
end

ビデオファイルのフレーム(複数)を順に読み込み,png 形式で保存

while 文を使用.第 fromframe フレームから読み込み,toframe に達するか,フレームが無くなるまで処理を続ける.

AVI ファイルの全フレームについて同じ処理を繰り返すときのプログラム見本としても使えると思います.

※ 画像ファイルの確認には,ImageMagick の display コマンドが便利です.

function png2avi(filename, basename, fromframe, toframe, fps, bitrate)
# png ファイルの連番画像ファイルを読み込んで,avi ファイルとして書き出す
f = avifile(filename, "fps", fps, "bitrate", bitrate );
i = fromframe;
while(true)
    # 変数 pngname は文字列データ
    pngname = sprintf("%s_%6.6d.png", basename, i); 
    rgb = imread( pngname );
    # 0 から 1 の範囲
    rgb2 = double(rgb) / 255;
    addframe(f, rgb2);
    i = i + 1;
    if ( i > toframe )
      break;
    endif
endwhile
endfunction

function avi2png(filename, basename, fromframe, toframe)
# avi ファイル(ファイル名は filename)を読み込んで,avi ファイルの中のフレームを png ファイルの連番画像ファイル(ファイル名は basename に「_」と数値をつなげたもの)として書き出す.
# png ファイルとして書き出すフレームの範囲は fromframe, toframe で指定する
i = fromframe;
while(true)
  try
    img = aviread(filename, i);
    # OCtave 3.2 系列の場合
    imwrite( img, sprintf("%s_%6.6d.png", basename, i) );
    # OCtave 3.0 系列の場合
#    imwrite( sprintf("\"%s_%6.6d.png\"", basename, i), img(:,:,1), img(:,:,2), img(:,:,3) );
    fdisp(stderr, i);
    i = i + 1;
    if ( i > toframe )
      break;
    endif
  catch
    # もし toframe の値が,ビデオファイルの実際のフレーム数より大きいと実行時エラーが出るので catch して break する
    break;
  end_try_catch
endwhile
endfunction

# avi ファイルを png 連番画像ファイルへ
# avi2png( "/home/kaneko/V0701001winff.avi", "/home/kaneko/20090701001_avi01", 2000, 2200 );
# png 連番画像ファイルを avi ファイルへ
# png2avi( "/home/kaneko/hoge.avi", "/home/kaneko/20090701001_avi01", 2000, 2200, 30, 800000);
avi2png( "/home/kaneko/V0701001winff.avi", "/home/kaneko/20090701001_avi01", 1, 10000 );