これまでは画像を扱っていたが、今回からは動画を扱っていく。
おお、ワンランクアップですね!
とは言っても、動画は画像の連続であるから、基本的なことは変わらない。
変わらないんですか?動きがあるのとないので違う気がしますが。
先ほども言ったが、動画は画像の連続だ。画像をコマ送りで表示すると、動きがあるように見える。それが動画だ。
あ、なるほど。なんかわかった気がします。
この部分の話は長くなる。
さっさとOpenCVで動画を扱う方法を紹介しよう。
動画の読み込み
OpenCVでは動画ファイル(.mp4など)だけではなく、WebカメラやUSBカメラから映像を取得し処理することができる。
カメラってことは、リアルタイム映像も処理できるってことですか?
その通り。世の中では、監視カメラのリアルタイム映像を解析して、犯罪の予知や工場の安全管理など、様々なことに画像解析が使われている。
動画ファイルを読み込む
まずは動画ファイル(mp4)を読み込む。
リアルタイムじゃないやつですね。
動画の読み込みにはcv2.VideoCapture()を使う。動画ファイルの場合、引数に対象ファイルのパスを指定する。
import cv2
path = 'input/Aquarium.mp4'
cap = cv2.VideoCapture(path)
これで、変数capに動画情報が読み込まれる。
中身はどうなるんです?
それは後からだ。
もったいぶるなぁ。
USBカメラから動画を読み込む
続いてUSBカメラの映像を読み込む。
ここでは、USBでPCに接続したカメラも、PCに内蔵されたカメラも対象となる。
これはリアルタイム映像ですね!
この場合、引数を0~の数値で指定する。
import cv2
cap = cv2.VideoCapture(0)
へ、これだけですか!?
これだけだ。複数のカメラが接続されていて、お目当ての映像がヒットしない場合、0, 1, 2, …と数字を置き換えて試すといい。
???
この数字はデバイスIDというもので、PCが認識したデバイスに対し0から順にIDを振ったものだ。だからデフォルトは0になる。
さらに厄介なことに、WindowsではこのデバイスIDを確認する手段がない。
だから、0から順に試すしかないんですね。
左様。一応Linuxの場合は確認方法はあるみたいだがな。
ネットワークカメラから動画を読み込む。
最後はネットワークカメラから動画を読み込む。
ここでのネットワークカメラとは、デバイスと直接接続されておらず、ネットワークを介して繋がっているカメラを指す。
わっ、それっぽくなってきましたね。
ネットワークカメラの映像はRTSPプロトコルで取得するケースが多いと思われるので、その方法で読み込み方を紹介する。
RTSP?
Real Time Streaming Protocolの頭文字を取ってRTSPという。
その名の通り、リアルタイムの映像配信に特化したプロトコルだ。
import cv2
#URLは例です
cap = cv2.VideoCapture("rtsp://user:password@192.168.10.1:47614/ipcam_h264.sdp")
user、password、IPアドレスおよびポート番号は、使用するカメラに合わせて変えるのだ。
user、passwordはカメラにアクセスするためのユーザとパスワードってことですね。
動画を表示する
今度は読み込んだ動画をプログラムの中で表示する。
冒頭でも言ったが、動画は画像の連続だ。画像解析では、動画であっても1コマずつの画像として処理していくことが基本となる。
例えば、フレームレートが30FPSの動画の場合、動画1秒間の処理はフレーム処理を30回繰り返して行われる。
結局、処理の単位は画像なんですね。
早速、サンプルコードを見てみよう。
import cv2
path = r'input/Aquarium.mp4'
cap = cv2.VideoCapture(path)
i=1
while True :
print("Frame: "+ str(i))
#フレーム情報取得
ret, img = cap.read()
#動画が終われば処理終了
if ret == False:
break
#動画表示
cv2.imshow('Video', img)
i +=1
cap.release()
cv2.destroyAllWindows()
動画を読み込んだ後、フレームごとの処理はwhile構文の中で行われている。
while True: って、処理が無限に続くあれですよね。
その通り。先ほど、動画情報は変数capに格納したな。
cap = cv2.VideoCapture(path)でしたね。
while構文の中でcap.read()をとしている部分で、フレームごとの画像情報をcapから取り出している。
そして、動画が終わると変数retにFalseがセットされ、while処理が終わる仕組みだ。
if ret == False: の部分ですね。
while構文の中をもう少し見てみよう。cv2.imshow()で映像を表示している。
あれ、画像の時と同じですね、、!
左様。何度も言うが、動画は画像の連続だ。だから、動画を分解すると画像になる。つまり、画像を処理するときと同じになる。
なんか、思ったよりシンプルな感じがします。
但し、このときcap.release()とcv2.destroyAllWindows()はwhile構文の外側に書くことを忘れないように。
whileの中だと、1フレーム目ですべて消えちゃうからですね。
ところで、cap.release()って何です?
これもおまじないだ。
またおまじない!教えてください!!
やけに熱が入っているな。
cap.release()は、明示的にカメラリソースの開放を宣言している。つまり、もう使いません、と。
これを宣言しないと、例えば他のアプリケーションからカメラにアクセスできなくなる可能性もある。
だから、おまじないとして必ず書くように。
動画を出力する
次は動画をファイルとして出力する。動画の出力にはcv2.VideoWriter()を使う。
import cv2
path = r'./input/Aquarium.mp4'
cap = cv2.VideoCapture(path)
#動画サイズ取得
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
#フレームレート取得
fps = cap.get(cv2.CAP_PROP_FPS)
#フォーマット指定
fmt = cv2.VideoWriter_fourcc('m', 'p', '4', 'v')
#注)グレースケールの映像を出力する場合は第5引数に0を与える
writer = cv2.VideoWriter('./result/output.mp4', fmt, fps, (width, height),0)
i=1
while True :
print("Frame: "+ str(i))
#フレーム情報取得
ret, img = cap.read()
#動画が終われば処理終了
if ret == False:
break
#グレースケールに変換
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#動画表示
cv2.imshow('Video', img_gray)
#動画書き込み
writer.write(img_gray)
i +=1
cap.release()
#これを忘れるとプログラムが出力ファイルを開きっぱなしになる
writer.release()
cv2.destroyAllWindows()
VideoWriter_fourcc()
動画の出力は画像の出力より若干手間がかかる。
まず、VideoWriter_fourcc()で動画のフォーマットを指定する必要がある。
fourccって何ですか?
fourccは、データフォーマットを一意に識別するための4文字の識別子を指す。
four-character codeの略語だ
なるほど。例えばどんなのがあります?
fourccの総数はかなりの数があるが、よく使われるデータフォーマットをいくつか紹介しよう。
コーデック | FourCC | 説明 |
---|---|---|
H.264 | h264 | 高画質・高圧縮率で広く利用されているコーデック。Blu-ray Discや地上デジタル放送などでも採用されている。 |
H.265/HEVC | h265 | H.264の後継規格。4K/8K映像の配信などで利用されている。 |
MPEG-4 | mp4v | DVDなどで利用されているコーデック。比較的古い規格だが、互換性が高い。 |
VP9 | vp90 | Googleが開発したオープンソースのコーデック。YouTubeなどで採用されている。 |
AV1 | av01 | 次世代オープンソースコーデックとして高画質・高圧縮率が期待される。 |
MJPEG | mjpg | 静止画を連続して表示する方式で、動画の圧縮率は低いが、高速な処理が可能。監視カメラやWebカメラなどで利用されている。 |
DivX | divx | MPEG-4をベースに開発されたコーデック。DVDripなどで利用されていた。 |
Xvid | xvid | MPEG-4に準拠したコーデック。オープンソースであることが特徴 |
WMV | wmv1 | Microsoftが開発したコーデック。Windows Media Playerなどで利用されている。 |
Theora | theo | オープンソースのコーデック。Ogg形式の動画ファイルなどで利用されている。 |
cv2.VideoWriter_fourcc(‘m’, ‘p’, ‘4’, ‘v’)ではfourccを1文字ずつ引数に渡すことになっているから、間違えないように。
はいさー!
cv2.VideoWriter()
ここから動画書き出し処理の本体だ。
cv2.VideoWriter()には引数として、出力ファイルのパス、フォーマット(fmt)、フレームレート(fps)、フレームサイズ(width, height)を指定する。
最後の引数0は、グレースケール映像を出力する場合に指定する。
#注)グレースケールの映像を出力する場合は第5引数に0を与える
writer = cv2.VideoWriter('./result/output.mp4', fmt, fps, (width, height),0)
フォーマットはVideoWriter_fourcc()で指定したフォーマットですね。
この時点では、まだ出力動画のひな型を作ったに過ぎない。ここから、変数writerに対して動画を1フレームずつ書き込んでいく。
※While構文中
#動画書き込み
writer.write(img_gray)
While構文中でフレームごとに処理していくわけですね。
そうだ。最後はwriter.release()として、動画出力が完了する。
今回までで、画像や動画の基本的な入出力は説明した。
次回からは画像の加工や処理を取り上げていく。
ありがとうございました~~♪