OpenCVを使ったPythonでの動画処理について、ここではwebカメラで撮影しているストリーム動画の画面に図形を描写してみます。
この画面への図形描写は、画像からのオブジェクト検出であるとか、機械学習などの顔認証などを行う時に、顔の部分などを四角で囲んで表示するような処理に繋がります。
すでに画像ファイルに関しての描画処理は行っていますので以下を参考にしてください。
では、動画ストリームに図形を描画していきましょう。
動画に図形を固定位置に描画する
まず、動画に四角形を特定の位置に描画するコードを書いていきます。最後に全体のコードをまとめて再掲します。
基本的なところはカメラの接続のコードがベースになります。
import cv2
cap = cv2.VideoCapture(0)
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
OpenCVライブラリーをインポートして、VideoCapture()で0を指定してwebカメラと接続します。ここは動画ファイルのパスを指定して、保存してある動画を利用しても構いません。get()でビデオの映像の幅と高さを自動的に取得して、intでキャストして整数にしています。このあたりはこれまでの処理と同じです。
x = width//2
y = height//2
w = width//4
h = height//4
ここでは描く図形の座標と幅を画面のサイズを基準に与えています。x,yは四角の左上の座標で、w,hはそこを基準にした幅と高さです。座標を整数で与える為に小数点以下切り捨ての割り算を行っています。
while True:
ret, frame = cap.read()
cv2.rectangle(frame, (x, y), (x+w, y+h), color=(0,0,255),thickness= 4)
cv2.imshow('frame', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
while文を使って、カメラのキャプチャーを実行しますが、全体的なコードは別のところでこれまで行ってきた処理と一緒です。read()で読み込み、imshow()で表示、if文の部分で[q]キーを押して処理を中断します。
違いは、rectangle()を用いて四角形を描く部分です。動画のframeを渡し、四角形の左上の座標と右下の座標を与え、色を赤色に指定、線の太さを4としています。
cap.release()
cv2.destroyAllWindows()
カメラを解放し、ウインドウを破棄しています。
全体のコードを再掲するとこうなります。
import cv2
cap = cv2.VideoCapture(0)
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
x = width//2
y = height//2
w = width//4
h = height//4
while True:
ret, frame = cap.read()
cv2.rectangle(frame, (x, y), (x+w, y+h), color=(0,0,255),thickness= 4)
cv2.imshow('frame', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
これをPythonファイルに保存してターミナルから実行すると次のようなイメージで映像が表示されるはずです。
webカメラで自撮りしている場合は、上記のようなイメージで表示され、赤色の四角い枠が固定された位置に描かれます。
動画に図形をマウスでインタラクティブに描画する
上では動画の設定した位置に四角形を描画しましたが、ここではマウスで動画をクリックした位置に任意の大きさの四角形を描画する操作をしてみます。
上のコードでは最初に描画する図形の座標を変数として設定しましたが、ここではマウスのクリックで図形を描画するコールバック関数を設定していこうと思います。
マウスのクリックでの図形描画は以下でもsetMouseCallback()を使って行いましたので参照してください。
では、ライブラリーをインポートするところから順にコードを書いていきましょう。最後に全体のコードをまとめて再掲します。
import cv2
def draw_rectangle(event,x,y,flags,param):
global pt1,pt2,topLeft_clicked,botRight_clicked
if event == cv2.EVENT_LBUTTONDOWN:
if topLeft_clicked == True and botRight_clicked == True:
topLeft_clicked = False
botRight_clicked = False
pt1 = (0,0)
pt2 = (0,0)
if topLeft_clicked == False:
pt1 = (x,y)
topLeft_clicked = True
elif botRight_clicked == False:
pt2 = (x,y)
botRight_clicked = True
draw_rectangle()という関数を定義します。変数にマウスの操作を示すevent、マウスの座標を示すx、y、他に必要となるフラグやパラメーターをflags、paramsを与えています。
global変数として、pt1、pt2で座標、topLeft_clicked、botRight_clickedはそれに対応した図形の左上の位置と右下の位置でのクリック操作の判定を与えます。
if event == cv2.EVENT_LBUTTONDOWN: でマウスの左ボタンかクリックされた時の動作を続けて決めていきます。
if topLeft_clicked == True and botRight_clicked == True: で図形の左上と右下がクリックで決定された場合は、マウスの操作を初期値に戻しています。
if topLeft_clicked == False: でまだ図形の右上が決定されて無い場合は、マウスの位置の座標が定められて、クリックすることでその位置で描画することになります。
elif botRight_clicked == False: でまだ図形の左下が決定されて無い場合は、マウスの位置の座標が定められて、クリックすることでその位置で描画することになります。
pt1 = (0,0)
pt2 = (0,0)
topLeft_clicked = False
botRight_clicked = False
global変数のそれぞれをここで初期化しています。
cap = cv2.VideoCapture(0)
cv2.namedWindow('Drawing rectangle')
cv2.setMouseCallback('Drawing rectangle', draw_rectangle)
VideoCapture()に0を指定してカメラを接続しています。nameWindow()でウインドウの名前をつけています。setMouseCallback()でマウスイベントの処理をセットします。ここで先ほど定義したdraw_rectangleを指定しています。
while True:
ret, frame = cap.read()
if topLeft_clicked:
cv2.circle(frame, center=pt1, radius=5, color=(0,0,255), thickness=-1)
if topLeft_clicked and botRight_clicked:
cv2.rectangle(frame, pt1, pt2, (0, 0, 255), 2)
cv2.imshow('Drawing rectangle', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
while文でカメラを動作させています。このコードはほとんどこれまでと同じです。違うところはread()で読み込むところとimshow()で表示するところ間に、マウスの操作のコードを入れています。
if topLeft_clicked:で描画する四角形の左上の位置がクリックされた時に、circle()を使ってクリック位置に丸印をつけています。動画を読み込み、中心の位置と半径を指定し、色を赤にして塗りつぶす操作をしています。
if topLeft_clicked and botRight_clicked:で四角形の左上と右上の位置がクリックされた時に、rectangle()を使って四角形を描画しています。動画を読み込み、左上、右下の座標、色、線の太さを指定しています。
cap.release()
cv2.destroyAllWindows()
いつものように、このコードで終了さています。
全体のコードは以下のようになります。
import cv2
def draw_rectangle(event,x,y,flags,param):
global pt1,pt2,topLeft_clicked,botRight_clicked
if event == cv2.EVENT_LBUTTONDOWN:
if topLeft_clicked == True and botRight_clicked == True:
topLeft_clicked = False
botRight_clicked = False
pt1 = (0,0)
pt2 = (0,0)
if topLeft_clicked == False:
pt1 = (x,y)
topLeft_clicked = True
elif botRight_clicked == False:
pt2 = (x,y)
botRight_clicked = True
pt1 = (0,0)
pt2 = (0,0)
topLeft_clicked = False
botRight_clicked = False
cap = cv2.VideoCapture(0)
cv2.namedWindow('Drawing rectangle')
cv2.setMouseCallback('Drawing rectangle', draw_rectangle)
while True:
ret, frame = cap.read()
if topLeft_clicked:
cv2.circle(frame, center=pt1, radius=5, color=(0,0,255), thickness=-1)
if topLeft_clicked and botRight_clicked:
cv2.rectangle(frame, pt1, pt2, (0, 0, 255), 2)
cv2.imshow('Drawing rectangle', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
このコードをPythonファイルに保存し、ターミナルで実行すると、カメラで写した映像が表示されます。その表示の上の任意の位置を左クリックすると赤い丸印が描画され、もう1つ別の箇所をクリックするとこの2点を対角線にした四角形が動画の上に描画されることになります。
最後に
OpenCVを使ったPythonでの動画処理について、ここではwebカメラで撮影しているストリーム動画の画面に図形を描写してみました。
ここでは、動画の固定した位置への図形の描写と、任意の位置への図形の描写を行ってみました。
画面への図形描写は、画像からのオブジェクト検出や、機械学習などの顔認証などを行う時に顔の部分などを四角で囲んで表示するような処理に繋がりますので、その時の為に押さえて起きましょう。