Elsaの技術日記(徒然なるままに)

主に自分で作ったアプリとかの報告・日記を記載

MENU

OpenCVで作成した文字や四角形を移動させてみる

OpenCVで動画を再生させたり、動画のフレーム数を変えたり、フレームレート切り替えたり、、、
動画を切った貼ったやっていると、
あれ??今フレームレート想定通りになっているかな??遅くない??早くない??
と不安になることがあります。

動画を見比べて判断すればよいのですが、
ただの動画だと分かりにくい。。

ということで、自作でサンプル動画を作成してみることにしました。
ただ連番画像を動画にするだけだと画像作成面倒ですし、やりなれた方法ですので、
今回は、OpenCVのライブラリとして提供されている、
rectangleとTextを用いて、自作で動画を作成してみることにしました。



■作成した動画

今回自作できた動画はこちら。

ただ0~9までの数字を動かしているだけです。
フレームレートは10fpsで録画したものです。

■環境

今回は、Pythonを用いました。
Pythonのバージョンですが、
Python 3.7.4
です。

■rectangle、putText関数の仕様

冒頭でも述べた通り、OpenCVのライブラリを用いて
長方形や文字を入れ込んでいきます。

OpenCVでは長方形や文字を入れるための関数として、
rectangle、putText関数があります。

まずrectangleですが、枠線や塗りつぶした矩形、長方形を描画できます。
こちらのように定義されており、
rectangle(Mat& img, Point pt1, Point pt2, const Scalar& color, int thickness=1, int lineType=8, int shift=0)
引数は、
 img – 画像.
 pt1 – 矩形の1つの頂点.
 pt2 – pt1 の反対側にある矩形の頂点.
 color – 矩形の色,あるいは輝度値(グレースケール画像).
 thickness – 矩形の枠線の太さ. CV_FILLED などの負の値の場合,塗りつぶされた矩形が描かれます.
 lineType – 枠線の種類. line() を参照してください.
 shift – 点の座標において,小数点以下の桁を表すビット数.
となります。
※参考:描画関数 — opencv 2.2 documentation


次にputTextですが、文字列を画像上に描画することが出来、
こちらのように定義されております。
putText(Mat& img, const string& text, Point org, int fontFace, double fontScale, Scalar color, int thickness=1, int lineType=8, bool bottomLeftOrigin=false)
引数ですが、
 img – 画像.
 text – 描かれる文字列.
 org – 文字列の左下角の,画像中の座標.
 fontFace – フォントの種類.以下のうちの1つ. FONT_HERSHEY_SIMPLEX , FONT_HERSHEY_PLAIN , FONT_HERSHEY_DUPLEX , FONT_HERSHEY_COMPLEX , FONT_HERSHEY_TRIPLEX ,    FONT_HERSHEY_COMPLEX_SMALL , FONT_HERSHEY_SCRIPT_SIMPLEX , FONT_HERSHEY_SCRIPT_COMPLEX .また,各フォントIDを, FONT_HERSHEY_ITALIC と組み合わせて,斜体文字にすることもできます.
 fontScale – フォントのスケールファクタ.これがフォント特有の基本サイズに掛け合わされます.
 color – 文字列の色.
 thickness – フォントの描画に利用される線の太さ.
 lineType – 線の種類.詳細は line を参照してください.
 bottomLeftOrigin – true の場合は画像データの原点が左下,そうでない場合は左上になります.
となります。
※参考:描画関数 — opencv 2.2 documentation

■rectangleとputTextを用いて動画を作成してみる

先ほど記載しました通り、rectangleやputTextでは座標を指定して描画しますので、
動いているように見せるためには座標をフレーム毎に変更させればOKです。

今回作成したコードはこちら。

import cv2
import numpy as np

BASEPOS_WIDTH = 100
BASEPOS_HEIGHT = 100
HOLISONTALNUM = 4
VERTICALNUM = 4
LOOP_COUNT = 12

VIDEO_SIZE = (HOLISONTALNUM * BASEPOS_WIDTH,VERTICALNUM * BASEPOS_HEIGHT)
FONT = cv2.FONT_HERSHEY_SIMPLEX

outputFile = 'ImgVideo.mp4'
fourcc = cv2.VideoWriter_fourcc('m','p','4', 'v')
frameRate = 10.0

def MakeSampleVideo():
    video  = cv2.VideoWriter(outputFile, fourcc, frameRate, (VIDEO_SIZE))

    imgNum = 0
    count = 0

    while True: 
        white_img = np.zeros((VERTICALNUM * BASEPOS_HEIGHT, HOLISONTALNUM * BASEPOS_WIDTH,3), dtype='uint8')
        white_img.fill(255)
        for v in range(VERTICALNUM):
            for h in range(HOLISONTALNUM):    
                left =  BASEPOS_WIDTH * h
                right = BASEPOS_WIDTH * (h+1)
                top = BASEPOS_HEIGHT * v
                bottom = BASEPOS_HEIGHT * (v+1)

                white_img = cv2.rectangle(white_img,(left,top),(right,bottom),(0,0,0),2)
                cv2.putText(white_img,str(imgNum),(left+25,bottom-25),FONT,2,(0,0,0),3)

                #動画を見るだけならこちらを利用
                # cv2.imshow('sample', white_img)
                # if cv2.waitKey(100) & 0xff == ord('q'):
                #     break

                #動画を保存するとき
                video.write(white_img)

                if imgNum > (VERTICALNUM * HOLISONTALNUM - 2):
                    imgNum = 0

                else:
                    imgNum+=1

        if count > LOOP_COUNT:
            break
        else:
            count += 1

    video.release()

MakeSampleVideo()

まずベースとなる画像ですが、

white_img = np.zeros((VERTICALNUM * BASEPOS_HEIGHT, HOLISONTALNUM * BASEPOS_WIDTH,3), dtype='uint8')
white_img.fill(255)

で作成した真っ白な画像になります。
画像サイズは、400px × 400pxです。

今回rectangle、putTextの描画位置を動かしている処理はこちら。

left =  BASEPOS_WIDTH * h
right = BASEPOS_WIDTH * (h+1)
top = BASEPOS_HEIGHT * v
bottom = BASEPOS_HEIGHT * (v+1)

white_img = cv2.rectangle(white_img,(left,top),(right,bottom),(0,0,0),2)
cv2.putText(white_img,str(imgNum),(left+25,bottom-25),FONT,2,(0,0,0),3)

BASEPOS_WIDTH、BASEPOS_HEIGHTはそれぞれ100pxで、
v、hは0~3が入ります。
上記パラメータを用いて、
left、right、top、bottomという、座標位置を算出。
これにより、
rectangleでは100px × 100pxの四角形を左上から右下へ順番に表示させることが出来ます。
putTextも同様に、左下の座標をleft,bottomで指定しております。

後は、一周だけだと寂しいので今回は10週数字が動くようにしました。

if count > LOOP_COUNT:
    break
else:
    count += 1

ここはもう少し工夫すれば簡潔に書くことが出来るかも。

■最後に

今回はrectangleやputTextを用いて、OpenCVが用意するライブラリで描画した四角形や文字で動かし、
動画を作成してみました。

作ってみたけど、30fpsや60fpsにすると流石に早すぎて目が追えない。。
まぁ、低速であれば使い道はあるかな??
結局無駄なものを作ってしまったかも。。