この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
1 はじめに
CX事業本部の平内(SIN)です。
機械学習によって動画を処理する場合、推論等による処理時間で、フレームレートが下がってしまう場合がありま。このような時、1つの指標になるのがFPSです。
要件に適応出来ているかどうかは、FPSはいくら出ているかで表現できます。
そして、よく見られるのが下のようなものです。画面の隅に、フレーム数とFPSが表示されています。
今回は、このような表示のためのクラスを作ってみました。コードの内容は、ネット上で広く利用されているものと同じです。
2 コード
FPS表示を担う部分を、DispFpsクラスとしました。
コンストラクタで、表示の諸元(色、フォント、サイズなど)を定義しています。
dispFps.py
from timeit import default_timer as timer
import cv2
class DispFps():
def __init__(self):
# 表示関連定義
self.__width = 80
self.__height = 20
self.__font_size = 0.4
self.__font_width = 1
self.__font_style = cv2.FONT_HERSHEY_COMPLEX
self.__font_color = (255, 255, 255)
self.__background_color = (0, 0, 0)
# フレーム数カウント用変数
self.__frame_count = 0
# FPS計算用変数
self.__accum_time = 0
self.__curr_fps = 0
self.__prev_time = timer()
self.__str = "FPS: "
def __calc(self):
# フレーム数更新
self.__frame_count += 1
# FPS更新
self.__curr_time = timer()
self.__exec_time = self.__curr_time - self.__prev_time
self.__prev_time = self.__curr_time
self.__accum_time = self.__accum_time + self.__exec_time
self.__curr_fps = self.__curr_fps + 1
if self.__accum_time > 1:
self.__accum_time = self.__accum_time - 1
self.__str = "FPS: " + str(self.__curr_fps)
self.__curr_fps = 0
def __disp(self, frame, str, x1, y1, x2, y2):
cv2.rectangle(frame, (x1, y1), (x2, y2), self.__background_color, -1)
cv2.putText(frame, str, (x1 + 5, y2 - 5), self.__font_style, self.__font_size, self.__font_color, self.__font_width)
def disp(self, frame):
# 表示内容計算
self.__calc()
# フレーム数(左上に表示する)
self.__disp(frame, str(self.__frame_count), 0, 0, x2 = self.__width, y2 = self.__height)
# FPS(右上に表示する)
screen_width = int(frame.shape[1])
self.__disp(frame, self.__str, screen_width - self.__width, 0, screen_width, self.__height)
上記のクラスを利用している例です。
動画処理するループに入る前に、DispFpsのインスタンスを生成し、ループの中で、disp()を呼ぶだけです。
なお、ループの中で呼ばれているtime.sleep(0.8)は、推論処理などを模擬したダミーのウエイト処理です。
index.py
import cv2
import time
from dispFps import DispFps
# Webカメラ
DEVICE_ID = 0
WIDTH = 800
HEIGHT = 600
FPS = 24
def main():
cap = cv2.VideoCapture (DEVICE_ID)
# フォーマット・解像度・FPSの設定
cap.set(cv2.CAP_PROP_FRAME_WIDTH, WIDTH)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, HEIGHT)
cap.set(cv2.CAP_PROP_FPS, FPS)
# フォーマット・解像度・FPSの取得
width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
fps = cap.get(cv2.CAP_PROP_FPS)
print("fps:{} width:{} height:{}".format(fps, width, height))
# [DispFps]インスタンス生成
dispFps = DispFps()
while True:
# カメラ画像取得
_, frame = cap.read()
if(frame is None):
continue
# 擬似的なウエイト
time.sleep(0.8)
# [DispFps]計算及び表示
dispFps.disp(frame)
# 画像表示
cv2.imshow('frame', frame)
# 'q'をタイプされたらループから抜ける
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# VideoCaptureオブジェクト破棄
cap.release()
cv2.destroyAllWindows()
if __name__ == '__main__':
main()
3 実行結果
time.sleep()に与えるウエイト値を変えてみた場合の、FPS表示は、下記のようになりました。
実装上、1FPS以上遅い場合は、1となってしまうことにご注意下さい。
ウエイト | FPS |
---|---|
0.01 | 24 |
0.05 | 12〜13 |
0.08 | 9〜10 |
0.1 | 6〜7 |
0.15 | 6 |
0.2 | 4 |
0.5 | 2 |
0.8 | 1 |
1.0 | 1 |
2.0 | 1 |
4 最後に
このクラスで軽易にFPS表示出来るようになれば、作業が捗るかも知れません・・・