OpenCV と Jupyter + Matplotlib 備忘録(FuncAnimation 編)

Memorandum about OpenCV, Jupyter and Matplotlib (FuncAnimation version).

OpenCV と Jupyter を使ってリアルタイムのビデオキャプチャ表示をしようとすると、いつもそのやり方が分からなくなって、半日近く試行錯誤することになるので、備忘録としてまとめておくことにしました。

そもそも Matplotlib は難しくて、何も参考にせずにスラスラとコードを書ける人は、あまりいないのではないでしょうか。多くの方が、Stack Overflow などを見ながらコードを書いているのではないか、と想像します。

まずは動くコード

最初に、動くコードを示してしまおうと思います。ちなみに、私は Jupyter や Matplotlib の権威でもなんでもなく、上に書いたように、Stack Overflow を見ながら苦心してなんとか動くコードを書けた、というくらいのレベルです。なお、今回使用したバージョンは以下の通りです。

  • macOS 10.15.7(Catalina)
  • Python 3.9.11
  • opencv-python==4.6.0.66
  • matplotlib==3.5.3
  • notebook==6.4.12(Jupyter Notebook)
%matplotlib notebook

import cv2
from matplotlib import animation
from matplotlib import pyplot as plt

CAMERA_ID = 0  # 必要に応じて変えてください


def capread_rgb():
    ret, frame = cap.read()
    if ret:
        ret_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
    else:
        ret_frame = None
    return ret, ret_frame


def init():
    return (im,)


def animate(dummy):
    ret, frame = capread_rgb()
    im.set_data(frame)
    return (im,)


cap = cv2.VideoCapture(CAMERA_ID)
if not cap.isOpened():
    print("Cannot open camera")
    exit()

fig, ax = plt.subplots()

ret, frame = capread_rgb()
im = plt.imshow(frame)

anim = animation.FuncAnimation(
    fig, animate, init_func=init, interval=1, blit=True
)
plt.show()

さて、コードの説明(備忘録)です。

%matplotlib notebook

Jupyter セッション(セル)中に動画を表示するためには必須です。%matplotlib inline ではうまく動きません。

CAMERA_ID = 0

後で出てくる cv2.VideoCapture() のための引数です。デフォルトのカメラは 0 ですが、適宜変更の必要があるかも知れません。

capread_rgb()

OpenCV で取り込まれる画像は BGR の配列になっているので、Matplotlib で表示できるよう、これを RGB に変換します。

init(), animate()

後で FuncAnimation() に渡すための関数です。blit=True で使うので、いずれも (im,) を返す必要があります。

plt.show()

Jupyter 内で動かすときは、この行は不要ですが、Python アプリケーションコードとして動かす場合に必要なので、混乱を避けるために、書いておいたほうが良さそうです。

参考文献

以下のブログや Q&A を参考にさせて頂きました。ありがとうございました。Thanks for the helpful blogs and discussions below.

今日はここまで。

お問い合わせはお気軽に!

お問い合わせを頂いた後、継続して営業活動をしたり、ニュースレター等をお送りしたりすることはございません。
御返答は 24時間以内(営業時間中)とさせて頂いております。もし返答が届かない場合、何らかの事情でメールが不達となっている可能性がございます。大変お手数ですが、別のメールアドレス等で督促頂けますと幸いです。