OpenCVはカメラを使って動画を撮影するための非常に簡単なインタフェースを用意している.初めの一歩として、カメラ(私はノートPCに備え付けのウェブカメラを使っている)で撮影した動画を白黒(グレースケール)の動画に変換して表示させてみよう.
動画を撮影するにはまず VideoCapture(device)
関数を用いてVideoCapture
型のオブジェクトを生成する.関数の引数device
は撮影に用いるカメラのデバイス番号を指定する(動画の撮影にはならないが、デバイス番号の代わりに動画ファイルのファイル名を指定してもよい).デバイス番号はコンピュータに接続されているカメラを識別するための番号で、普通はカメラが1台だけしか接続されていないので,0か -1をデバイス番号として指定する(カメラが複数台ある場合は,1やそれ以上の番号を指定して区別する). VideoCapture
型のオブジェクトを生成してしまえば,1フレームごとに撮影することが可能.ただし,撮影終了後にrelease()
関数を用いてビデオ撮影デバイスを解放することを忘れないようにしよう.
注意: デバイス番号を0として撮影できない場合は、デバイス番号を-1としてみよう。
実行例: 以下のプログラムはq
をキー入力すれば終了する。(注: 画像の場合と同様に、Jupyter notebookとしては停止させられないことがある)
import numpy as np
import cv2
cap = cv2.VideoCapture(0)
while(True):
# Capture frame-by-frame
ret, frame = cap.read()
# Our operations on the frame come here
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# Display the resulting frame
cv2.imshow('frame',gray)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()
# Notebookの場合はこれが必要
for _ in range(5):
cv2.waitKey(1)
メソッドcap.read()
は (True
/False
)の2値の値を返す.フレームの読み込みが正しく行われれば True
を返す(カメラ撮影ではなく動画ファイルを表示する場合、この関数がFalse
を返せばファイルの最後に到達したかことがわかる).
オブジェクト cap
に初期化(適切な値がセット)されていないことがある.そのような場合はエラーを返す.そこであらかじめ cap.isOpened()
関数を使ってTrue
が返ってくるのを確かめることで、値の初期化の確認ができる.なおTrueでなければ(カメラ(動画ファイル)を一旦解放した状態なら)cap.open()
関数によって再びカメラを使って動画を録画(動画ファイルを表示)することができる.
この動画の属性は cap.get(propId)
関数を使って調べられる. propId
は0から18までの整数値で,それぞれ数値に対し動画の属性情報(ただし、その動画が指定された属性情報を持っていれば)が対応している.属性情報の詳細についてはここ: `cv::VideoCapture::get()` を参照のこと.幾つかの属性情報は cap.set(propId, value)
関数を使って変更できる.ここで value
は新しく設定する値である.
例えば, cap.get(3)
と cap.get(4)
を実行すれば,フレームの横幅(width)と縦幅(height)の値が得られる.(著者が使用しているカメラであれば)デフォルトで640x480となるが,320x240に変更するのであれば, ret = cap.set(3,320)
と ret = cap.set(4,240)
を実行する.
Note
もしもエラーが生じるようであれば,カメラを扱えるソフトウェア(Linuxであればcheese
)を使って,カメラが正常に動作することを確認する.
ファイルから動画を表示する方法は,カメラから動画を撮影する方法と基本的に同じである.カメラのデバイス番号の代わりに動画ファイルのファイル名を指定するだけでよい.なおフレームを表示している間は cv2.waitKey() に適切な時間を設定すること.設定する時間が極端に短いと動画が高速に再生され,逆に長く設定すると極端なスロー再生になる.通常は25ミリ秒と指定すればよい.
実行例: 以下のプログラムはqをキー入力すれば終了する:
import numpy as np
import cv2
fname="test.avi"
cap = cv2.VideoCapture(fname)
cv2.namedWindow(fname)
if (cap.isOpened()):
while True:
ret, frame = cap.read()
if ret:
cv2.imshow(fname,frame)
if cv2.waitKey(25) & 0xFF == ord('q'):
break
else:
break
cap.release()
cv2.destroyAllWindows()
# Notebookの場合はこれが必要
for _ in range(5):
cv2.waitKey(1)
Note 動かない時には、適切なバージョンのffmpeg か gstreamerがインストールされていることを確認せよ.ffmpeg/gstreamerのインストールに間違いがあると VideoCapture が期待通りに動作しない.なおcodecにも注意すること。 (私の環境では MJPG なら動くが他のはダメであった)
mp4ファイルに挑戦してみる。
import numpy as np
import cv2
fname="cockatoo.mp4"
cap = cv2.VideoCapture(fname) # mp4 file
cv2.namedWindow(fname)
if (cap.isOpened()):
while True:
ret, frame = cap.read()
if ret:
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
cv2.imshow('frame')
if cv2.waitKey(25) & 0xFF == ord('q'):
break
else:
break
else:
print("Cannot open the file!")
cap.release()
cv2.destroyAllWindows()
# Notebookの場合はこれが必要
for _ in range(5):
cv2.waitKey(1)
このようにファイルは存在しても『開けない』。そこでskvideoを試す
注: pip install sk-video
が必要になろう
import numpy as np
import cv2
import skvideo.io
fname="test.mp4" # MOV形式のファイルも再生できる
# cap = cv2.VideoCapture('cockatoo.mp4') # mp4 file
cap = skvideo.io.FFmpegReader(fname)
cv2.namedWindow(fname)
for frame in cap.nextFrame():
frame=cv2.cvtColor(frame,cv2.COLOR_RGB2BGR) # MOVファイルなどで必要
cv2.imshow(fname,frame)
if cv2.waitKey(25) & 0xFF == ord('q'):
break
cap.close()
cv2.destroyAllWindows()
# Notebookの場合はこれが必要
for _ in range(5):
cv2.waitKey(1)
連続した番号をもつ静止画ファイルを「パラパラ漫画」の要領で表示させると動画にみえる。また次に学ぶ「動画を保存する」を使うと動画のファイルができあがる:( videos.zipをダウンロードし、展開すること)
import numpy as np
import cv2
cap = cv2.VideoCapture('videos/slow%03d.jpg')
while(cap.isOpened()):
ret, frame = cap.read()
if ret:
cv2.imshow('frame',frame)
# rec.write(frame)
else:
break
if cv2.waitKey(25) & 0xFF == ord('q'):
break
cv2.destroyAllWindows()
# Notebookの場合はこれが必要
for _ in range(5):
cv2.waitKey(1)
cap.release()
ここまでで動画を撮影し,1フレームごとに処理ができるようになった。そこで動画をファイルに保存してみよう.画像として保存するなら cv2.imwrite()
関数を使えばよいが,動画ファイルとして保存するにはひと工夫必要である.
ここでは、動画ファイルとして保存するために VideoWriter(filename, fourcc, fps, frameSize, isColor)
関数を用いてVideoWriter
型のオブジェクトを生成する.VideoWriter
関数の第1引数filename
は保存する動画ファイル名(例: output.avi
)を指定する.第2引数fourcc
は FourCC
コード(詳細は次の段落で説明)を,第3引数fps
は動画の再生速度、第4引数frameSize
は解像度を設定する.最後の引数isColor
は isColor
フラグを指定します.このフラグが True
であればカラーの動画,そうでなければ白黒(グレースケール)の動画として保存される.
FourCC
は動画のコーデックを指定するための4バイトのコードで、使用可能なコードのリストは fourcc.org で確認できる.OS依存なので気を付けて選ぶこと.以下のコードは著者のマシンでは正しく動作した.
例えばMJPG(モーションJPEG)コーデックを使う場合、FourCC コードは cv2.VideoWriter_fourcc('M','J','P','G')
もしくは cv2.VideoWriter_fourcc(*'MJPG')
のように指定する.
実行例: 次のコードはカメラから撮影した映像を上下反転させて保存する.(qのキー入力で終了する)
import numpy as np
import cv2
cap = cv2.VideoCapture(0)
# Define the codec and create VideoWriter object
fourcc = cv2.VideoWriter_fourcc(*'MJPG')
out = cv2.VideoWriter('output.avi',fourcc, 20.0, (640,480))
while(cap.isOpened()):
ret, frame = cap.read()
if ret:
frame = cv2.flip(frame,0)
# write the flipped frame
out.write(frame)
cv2.imshow('frame',frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
else:
break
# Release everything if job is finished
cap.release()
out.release()
cv2.destroyAllWindows()
# Notebookの場合はこれが必要
for _ in range(5):
cv2.waitKey(1)
Note ビデオが保存されていない時には、FourCCコードをいろいろ試してみよ。私のあるマシン(Linux, Anaconda Python 3.5.2)ではXVIDでは保存されず、MJPGなら保存できた。
追記: ビデオ読み込みと同様、skvideoを使うと、mp4形式の書き込みも可能なようである。詳しくは skvideo-io参照のこと
import skvideo.io
import numpy as np
outputdata = np.random.random(size=(25, 480, 680, 3)) * 255
outputdata = outputdata.astype(np.uint8)
skvideo.io.vwrite("outputvideo.mp4", outputdata)
import skvideo.io
import numpy as np
outputdata = np.random.random(size=(25, 480, 680, 3)) * 255
outputdata = outputdata.astype(np.uint8)
writer = skvideo.io.FFmpegWriter("outputvideo2.mp4")
for i in range(25):
writer.writeFrame(outputdata[i, :, :, :])
writer.close()