OpenCVちょっと動かしたいなーと思って、macに気軽にインストールしてみたらはまったので、備忘録代わりにAVIファイルを表示させて保存するまでの記事です。
この記事で行うこと
- OS X Mavericksに、Homebrew使ってOpenCVを導入
- OpenCV2 + PythonでAVIファイルを読み込んで保存する
この記事でわからないこと
- Homebrewのインストール方法
インストール
Homebrewは最新にしておきましょう。
pythonの環境は、pyenv系のバージョン切り替えて使う環境の場合、Homebrew経由のopencvインストールと相性が悪いようで、コンパイルが通りませんでした。
pyenvは諦めて、Homebrewからpythonをインストールする形にしています。
デフォルトのHomebrewにはOpenCVが用意されていないので、コンピュータサイエンス向けのライブラリのインストールが必要です。
参考1:Homebrew でOpenCVをインストールする方法
それではインストールと行きたいところですが、OpenCVを入れる前に動画を扱うためのあれこれをインストールしておきます。これをしないと静止画はいいのですが、動画を処理しようとしてエラーで悩みます。
参考2:virtualenvwrapperによるOpenCV + Python環境の構築 (2)
参考3:Mac OS XでFFmpegのインストールとWebM動画の作り方
pythonが入っていないところから始めると以下のようになります。
numpyが入っていないと、OpenCVのインストールが失敗することがあるので先に入れています。
ffmpeg周りはやや過剰かもしれません。とりあえずOpenCVについては、後でエラーが出ると嫌なのでオプション全部載せにしています。
$ brew tap homebrew/science
$ brew install python
$ pip install numpy
$ brew install cmake automake celt faac fdk-aac git lame libass libtool libvorbis libvpx libvo-aacenc opencore-amr openjpeg opus sdl schroedinger shtool speex texi2html theora wget x264 xvid yasm
$ brew install ffmpeg --with-fdk-aac --with-libvo-aacenc --with-libvorbis --with-libvpx --with-openjpeg --with-theora --with-opencore-amr
$ brew install eigen
$ brew install jasper
$ brew install tbb
$ brew install qt
$ brew install opencv --with-eigen --with-jasper --with-libtiff --with-qt --with-tbb --with-ffmpeg
OpenCVのコンパイルにやたら時間がかかりますが(MacBookAir環境で10分ぐらい)、気長に待ちましょう。
動画(AVIファイル)を表示する
詳解OpenCVのサンプルで、AVIファイルを読んで画面にスライダー(トラックバー)付きで表示する例がありますので、これをPythonで実装します。
# coding: UTF-8
import numpy as np
import cv2
# 実装の参考 http://www.beechtreetech.com/opencv-exercises-in-python
# cv2を使うように変更
updatelock = False # トラックバー処理中のロックフラグ
windowname = 'frame' # Windowの名前
trackbarname = 'Position' # トラックバーの名前
# AVIファイルを読む
# aviは適当な長さのサンプルをインターネットから拾ってくる
# 参考:http://www.engr.colostate.edu/me/facil/dynamics/avis.htm
cap = cv2.VideoCapture('drop.avi')
# トラックバーを動かしたときに呼び出されるコールバック関数の定義
def onTrackbarSlide(pos):
updatelock = True
cap.set(cv2.cv.CV_CAP_PROP_POS_FRAMES, pos)
updatelock = False
# 名前付きWindowを定義する
cv2.namedWindow(windowname, cv2.WINDOW_NORMAL)
# AVIファイルのフレーム数を取得する
frames = int(cap.get(cv2.cv.CV_CAP_PROP_FRAME_COUNT))
# フレーム数が1以上ならトラックバーにセットする
if (frames > 0):
cv2.createTrackbar(trackbarname, windowname, 0, frames, onTrackbarSlide)
# AVIファイルを開いている間は繰り返し(最後のフレームまで読んだら終わる)
while(cap.isOpened()):
# トラックバー更新中は描画しない
if (updatelock):
continue
# 1フレーム読む
ret, frame = cap.read()
# 読めなかったら抜ける
if ret == False:
break
# 画面に表示
cv2.imshow(windowname,frame)
# 現在のフレーム番号を取得
curpos = int(cap.get(cv2.cv.CV_CAP_PROP_POS_FRAMES))
# トラックバーにセットする(コールバック関数が呼ばれる)
cv2.setTrackbarPos(trackbarname, windowname, curpos)
# qを押したら抜ける
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# AVIファイルを解放
cap.release()
# Windowを閉じる
cv2.destroyAllWindows()
OpenCVのインストールが正常であれば、実行時にエラーが出ずに、Windowが開いて動画が表示されます。
最後まで行くと自動的に終わります。トラックバーを操作するとその場面から続きが再生されます。
カメラの映像を動画(AVIファイル)で保存する
次は、Mac内蔵のカメラを使って、カメラ映像をそのまま動画保存するサンプルです。
# coding: UTF-8
import numpy as np
import cv2
# カメラからのキャプチャ指定
cap = cv2.VideoCapture(0)
# コーデックの指定
fourcc = cv2.cv.CV_FOURCC('m', 'p', '4', 'v')
# 保存ファイルとフレームレートとサイズの指定
out = cv2.VideoWriter('output.m4v',fourcc, 30, (640,480))
# カメラオープン中はずっと処理する
while(cap.isOpened()):
# キャプチャ画像を取り出す
ret, frame = cap.read()
# データがなければ抜ける
if ret==False:
break
# 画像をファイルに書き込む
out.write(frame)
# 画像を画面に出力する
cv2.imshow('frame',frame)
# "q"が押されたら抜ける
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# 後始末
cap.release()
out.release()
cv2.destroyAllWindows()
画面上に、カメラからの映像が出力されます。また、同時にファイルに書き込みも行われています。
出力ファイルは、m4v形式でmacから直接読めるので、再生されるかどうか試してみましょう。
動画にフィルタをかける
最後はOpenCVらしく、読み込んだ動画にフィルタをかけてみましょう。元のaviファイルを入力、処理結果後の画像を出力情報として、どちらも画面上に表示されるようにしています。
# coding: UTF-8
import numpy as np
import cv2
import cv2.cv as cv
updatelock = False # トラックバー処理中のロックフラグ
windowname_in = 'inframe' # Window(元画像)の名前
windowname_out = 'outframe' # Window(変換画像)の名前
trackbarname = 'Position' # トラックバーの名前
# AVIファイルを読む
cap = cv2.VideoCapture('drop.avi')
# トラックバーを動かしたときに呼び出されるコールバック関数の定義
def onTrackbarSlide(pos):
updatelock = True
cap.set(cv.CV_CAP_PROP_POS_FRAMES, pos)
updatelock = False
# Cannyエッジ検出
def doCanny(img):
# カラー画像をグレー画像に変換
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
return cv2.Canny(gray, 100, 200)
# 名前付きWindowを定義する
cv2.namedWindow(windowname_in, cv2.WINDOW_NORMAL)
cv2.namedWindow(windowname_out, cv2.CV_WINDOW_AUTOSIZE)
# AVIファイルのフレーム数を取得する
frames = int(cap.get(cv2.cv.CV_CAP_PROP_FRAME_COUNT))
# フレーム数が1以上ならトラックバーにセットする
if (frames > 0):
cv2.createTrackbar(trackbarname, windowname_in, 0, frames, onTrackbarSlide)
# AVIファイルを開いている間は繰り返し
while(cap.isOpened()):
# トラックバー更新中は描画しない
if (updatelock):
continue
# 1フレーム読む
ret, frame = cap.read()
# 読めなかったら抜ける
if ret == False:
break
# 画面に表示
cv2.imshow(windowname_in,frame)
cv2.imshow(windowname_out,doCanny(frame))
# 現在のフレーム番号を取得
curpos = int(cap.get(cv.CV_CAP_PROP_POS_FRAMES))
# トラックバーにセットする(コールバック関数が呼ばれる)
cv2.setTrackbarPos(trackbarname, windowname_in, curpos)
# qを押したら抜ける
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# AVIファイルを解放
cap.release()
# Windowを閉じる
cv2.destroyAllWindows()
動画のエッジを検出して、outframeのWindowに表示します。
まとめ
- OpenCV + Pythonは気軽に静止画、動画を表示、加工できるのでちょっと試すのに便利です。
- 動画の入出力の最初で詰まると面白さ半減なので、ちゃんと動く事を確認しましょう。
- インターネット上には、OpenCV1 + Pythonのサンプルと、OpenCV2 + Pythonのサンプルがごちゃごちゃ(前者が多い印象)なので、間違えないようにしましょう。