質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
YOLO

YOLOとは、画像検出および認識用ニューラルネットワークです。CベースのDarknetというフレームワークを用いて、画像や動画からオブジェクトを検出。リアルタイムでそれが何になるのかを認識し、分類することができます。

Q&A

解決済

1回答

5215閲覧

yolo3で動画検出する際に出てくるFPSとは

gurou

総合スコア8

YOLO

YOLOとは、画像検出および認識用ニューラルネットワークです。CベースのDarknetというフレームワークを用いて、画像や動画からオブジェクトを検出。リアルタイムでそれが何になるのかを認識し、分類することができます。

0グッド

1クリップ

投稿2020/08/19 08:46

編集2020/08/24 02:54

yolo3で動画検出を行っていると
左上にFPS11という文字が出てきます。

なんとなくフレームレートの事をさしているということはわかりましたが
11とは良いのでしょうか。悪いのでしょうか。

現在は以下のコードで動画検出を行っています

python#

1""" 2Class definition of YOLO_v3 style detection model on image and video 3""" 4 5import colorsys 6import os 7from timeit import default_timer as timer 8 9import numpy as np 10from keras import backend as K 11from keras.models import load_model 12from keras.layers import Input 13from PIL import Image, ImageFont, ImageDraw 14 15from yolo3.model import yolo_eval, yolo_body, tiny_yolo_body 16from yolo3.utils import letterbox_image 17import os 18from keras.utils import multi_gpu_model 19 20class YOLO(object): 21 _defaults = { 22 "model_path": 'C:/Users/0000526465/keras-yolo3/logs/000/trained_weights_final.h5', 23 "anchors_path": 'model_data/yolo_anchors.txt', 24 "classes_path": 'model_data/my_classes.txt', 25 "score" : 0.3, 26 "iou" : 0.45, 27 "model_image_size" : (320,320), 28 "gpu_num" : 1, 29 } 30 31 @classmethod 32 def get_defaults(cls, n): 33 if n in cls._defaults: 34 return cls._defaults[n] 35 else: 36 return "Unrecognized attribute name '" + n + "'" 37 38 def __init__(self, **kwargs): 39 self.__dict__.update(self._defaults) # set up default values 40 self.__dict__.update(kwargs) # and update with user overrides 41 self.class_names = self._get_class() 42 self.anchors = self._get_anchors() 43 self.sess = K.get_session() 44 self.boxes, self.scores, self.classes = self.generate() 45 46 def _get_class(self): 47 classes_path = os.path.expanduser(self.classes_path) 48 with open(classes_path) as f: 49 class_names = f.readlines() 50 class_names = [c.strip() for c in class_names] 51 return class_names 52 53 def _get_anchors(self): 54 anchors_path = os.path.expanduser(self.anchors_path) 55 with open(anchors_path) as f: 56 anchors = f.readline() 57 anchors = [float(x) for x in anchors.split(',')] 58 return np.array(anchors).reshape(-1, 2) 59 60 def generate(self): 61 model_path = os.path.expanduser(self.model_path) 62 assert model_path.endswith('.h5'), 'Keras model or weights must be a .h5 file.' 63 64 # Load model, or construct model and load weights. 65 num_anchors = len(self.anchors) 66 num_classes = len(self.class_names) 67 is_tiny_version = num_anchors==6 # default setting 68 try: 69 self.yolo_model = load_model(model_path, compile=False) 70 except: 71 self.yolo_model = tiny_yolo_body(Input(shape=(None,None,3)), num_anchors//2, num_classes) \ 72 if is_tiny_version else yolo_body(Input(shape=(None,None,3)), num_anchors//3, num_classes) 73 self.yolo_model.load_weights(self.model_path) # make sure model, anchors and classes match 74 else: 75 assert self.yolo_model.layers[-1].output_shape[-1] == \ 76 num_anchors/len(self.yolo_model.output) * (num_classes + 5), \ 77 'Mismatch between model and given anchor and class sizes' 78 79 print('{} model, anchors, and classes loaded.'.format(model_path)) 80 81 # Generate colors for drawing bounding boxes. 82 hsv_tuples = [(x / len(self.class_names), 1., 1.) 83 for x in range(len(self.class_names))] 84 self.colors = list(map(lambda x: colorsys.hsv_to_rgb(*x), hsv_tuples)) 85 self.colors = list( 86 map(lambda x: (int(x[0] * 255), int(x[1] * 255), int(x[2] * 255)), 87 self.colors)) 88 np.random.seed(10101) # Fixed seed for consistent colors across runs. 89 np.random.shuffle(self.colors) # Shuffle colors to decorrelate adjacent classes. 90 np.random.seed(None) # Reset seed to default. 91 92 # Generate output tensor targets for filtered bounding boxes. 93 self.input_image_shape = K.placeholder(shape=(2, )) 94 if self.gpu_num>=2: 95 self.yolo_model = multi_gpu_model(self.yolo_model, gpus=self.gpu_num) 96 boxes, scores, classes = yolo_eval(self.yolo_model.output, self.anchors, 97 len(self.class_names), self.input_image_shape, 98 score_threshold=self.score, iou_threshold=self.iou) 99 return boxes, scores, classes 100 101 def detect_image(self, image): 102 start = timer() 103 104 if self.model_image_size != (None, None): 105 assert self.model_image_size[0]%32 == 0, 'Multiples of 32 required' 106 assert self.model_image_size[1]%32 == 0, 'Multiples of 32 required' 107 boxed_image = letterbox_image(image, tuple(reversed(self.model_image_size))) 108 else: 109 new_image_size = (image.width - (image.width % 32), 110 image.height - (image.height % 32)) 111 boxed_image = letterbox_image(image, new_image_size) 112 image_data = np.array(boxed_image, dtype='float32') 113 114 print(image_data.shape) 115 image_data /= 255. 116 image_data = np.expand_dims(image_data, 0) # Add batch dimension. 117 118 out_boxes, out_scores, out_classes = self.sess.run( 119 [self.boxes, self.scores, self.classes], 120 feed_dict={ 121 self.yolo_model.input: image_data, 122 self.input_image_shape: [image.size[1], image.size[0]], 123 K.learning_phase(): 0 124 }) 125 126 print('Found {} boxes for {}'.format(len(out_boxes), 'img')) 127 128 font = ImageFont.truetype(font='font/FiraMono-Medium.otf', 129 size=np.floor(3e-2 * image.size[1] + 0.5).astype('int32')) 130 thickness = (image.size[0] + image.size[1]) // 300 131 132 for i, c in reversed(list(enumerate(out_classes))): 133 predicted_class = self.class_names[c] 134 box = out_boxes[i] 135 score = out_scores[i] 136 137 label = '{} {:.2f}'.format(predicted_class, score) 138 draw = ImageDraw.Draw(image) 139 label_size = draw.textsize(label, font) 140 141 top, left, bottom, right = box 142 top = max(0, np.floor(top + 0.5).astype('int32')) 143 left = max(0, np.floor(left + 0.5).astype('int32')) 144 bottom = min(image.size[1], np.floor(bottom + 0.5).astype('int32')) 145 right = min(image.size[0], np.floor(right + 0.5).astype('int32')) 146 print(label, (left, top), (right, bottom)) 147 148 if top - label_size[1] >= 0: 149 text_origin = np.array([left, top - label_size[1]]) 150 else: 151 text_origin = np.array([left, top + 1]) 152 153 # My kingdom for a good redistributable image drawing library. 154 for i in range(thickness): 155 draw.rectangle( 156 [left + i, top + i, right - i, bottom - i], 157 outline=self.colors[c]) 158 draw.rectangle( 159 [tuple(text_origin), tuple(text_origin + label_size)], 160 fill=self.colors[c]) 161 draw.text(text_origin, label, fill=(0, 0, 0), font=font) 162 del draw 163 164 end = timer() 165 print(end - start) 166 return image 167 168 def close_session(self): 169 self.sess.close() 170 171def detect_video(yolo, video_path, output_path=""): 172 import cv2 173 vid = cv2.VideoCapture(video_path) 174 if not vid.isOpened(): 175 raise IOError("Couldn't open webcam or video") 176 video_FourCC = int(vid.get(cv2.CAP_PROP_FOURCC)) 177 video_fps = vid.get(cv2.CAP_PROP_FPS) 178 video_size = (int(vid.get(cv2.CAP_PROP_FRAME_WIDTH)), 179 int(vid.get(cv2.CAP_PROP_FRAME_HEIGHT))) 180 isOutput = True if output_path != "" else False 181 if isOutput: 182 print("!!! TYPE:", type(output_path), type(video_FourCC), type(video_fps), type(video_size)) 183 out = cv2.VideoWriter(output_path, video_FourCC, video_fps, video_size) 184 accum_time = 0 185 curr_fps = 0 186 fps = "FPS: ??" 187 prev_time = timer() 188 while True: 189 return_value, frame = vid.read() 190 image = Image.fromarray(frame) 191 image = yolo.detect_image(image) 192 result = np.asarray(image) 193 curr_time = timer() 194 exec_time = curr_time - prev_time 195 prev_time = curr_time 196 accum_time = accum_time + exec_time 197 curr_fps = curr_fps + 1 198 if accum_time > 1: 199 accum_time = accum_time - 1 200 fps = "FPS: " + str(curr_fps) 201 curr_fps = 0 202 cv2.putText(result, text=fps, org=(3, 15), fontFace=cv2.FONT_HERSHEY_SIMPLEX, 203 fontScale=0.50, color=(255, 0, 0), thickness=2) 204 cv2.namedWindow("result", cv2.WINDOW_NORMAL) 205 cv2.imshow("result", result) 206 if isOutput: 207 out.write(result) 208 if cv2.waitKey(1) & 0xFF == ord('q'): 209 break 210 yolo.close_session() 211 212 213

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

11とは良いのでしょうか。悪いのでしょうか。

fps = frame per second
1秒間に11回の検出ができるということです。

11とは良いのでしょうか。悪いのでしょうか。

物体検出で何をやりたいのかという用途次第です。
その頻度の検出でも使いたい用途で問題ないのであれば、それでいいのではないでしょうか。
動画は30FPSで流したい場合は「3フレームに1回だけ検出して、残り2フレームは前回検出した結果を使い回す」とか工夫すれば、動画自体は30FPSで流せます。


ちなみに、Youtube の動画は一般的に30FPSです。

追記

python

1def detect_video(yolo, video_path, output_path=""): 2 import cv2 3 4 vid = cv2.VideoCapture(video_path) 5 if not vid.isOpened(): 6 raise IOError("Couldn't open webcam or video") 7 video_FourCC = int(vid.get(cv2.CAP_PROP_FOURCC)) 8 video_fps = vid.get(cv2.CAP_PROP_FPS) 9 video_size = ( 10 int(vid.get(cv2.CAP_PROP_FRAME_WIDTH)), 11 int(vid.get(cv2.CAP_PROP_FRAME_HEIGHT)), 12 ) 13 isOutput = True if output_path != "" else False 14 if isOutput: 15 print( 16 "!!! TYPE:", 17 type(output_path), 18 type(video_FourCC), 19 type(video_fps), 20 type(video_size), 21 ) 22 out = cv2.VideoWriter(output_path, video_FourCC, video_fps, video_size) 23 accum_time = 0 24 curr_fps = 0 25 fps = "FPS: ??" 26 prev_time = timer() 27 i = 0 28 while True: 29 return_value, frame = vid.read() 30 image = Image.fromarray(frame) 31 32 if i % 3 == 0: 33 image = yolo.detect_image(image) 34 result = np.asarray(image) 35 curr_time = timer() 36 exec_time = curr_time - prev_time 37 prev_time = curr_time 38 accum_time = accum_time + exec_time 39 curr_fps = curr_fps + 1 40 if accum_time > 1: 41 accum_time = accum_time - 1 42 fps = "FPS: " + str(curr_fps) 43 curr_fps = 0 44 cv2.putText( 45 result, 46 text=fps, 47 org=(3, 15), 48 fontFace=cv2.FONT_HERSHEY_SIMPLEX, 49 fontScale=0.50, 50 color=(255, 0, 0), 51 thickness=2, 52 ) 53 cv2.namedWindow("result", cv2.WINDOW_NORMAL) 54 cv2.imshow("result", result) 55 if isOutput: 56 out.write(result) 57 if cv2.waitKey(1) & 0xFF == ord("q"): 58 break 59 i += 1 60 yolo.close_session()

投稿2020/08/19 09:03

編集2020/08/24 07:07
tiitoi

総合スコア21956

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

gurou

2020/08/19 22:57

分かりやすい解説ありがとうございます。 リアルタイム検出にできればしたいです。 仮にGPUのスペックを上げればもう少し検出速度は上がるものなのでしょうか。 また、3フレームに1回の検出に変更するためには、どのようにyolo.pyを変更すればよいのでしょうか。 初心者のもので、何かご教授いただけると幸いです。よろしくお願いいたします。
tiitoi

2020/08/20 02:27

> 仮にGPUのスペックを上げればもう少し検出速度は上がるものなのでしょうか。 性能のいい GPU を用意できれば、それだけ速度は上がります。 GPU の性能が一番速度に効いてくる部分です。 > 3フレームに1回の検出に変更するためには、どのようにyolo.pyを変更すればよいのでしょうか。 すみませんが、YOLOv3 というのはモデルの名称でして、実装はいろいろあるので、具体的な手順はここでは示せません。 例えば、以下は疑似コードですが、 i = 0 while True: __カメラから映像取得 __if i % 3 == 0: ____検出処理 __取得した映像表示 __i += 1 とすれば3回に1回だけ検出ということができますね。 お使いのコードを読んで、3回に1回だけ検出する判定条件を追加すればいいと思います。
gurou

2020/08/20 06:13

現在使用しているコードを載せました。 PCに保存した動画を検出しているのですが どこにコードを入れたらよいかがわかりません。 ご教授お願い致します。
tiitoi

2020/08/20 07:11 編集

編集するなら detect_video() の中ではないでしょうか? そこに先のコメントに書いたようなループがあると思うので、そこにロジックを追加してください
gurou

2020/08/24 02:55

何度もすみません。 yolo.pyを載せました。 最後の部分を編集すればよいというのはなんとなくわかるのですが どこをどうすればよいでしょうか。 python学習中で、まだコード全文を理解するのが難しいです。 よろしくお願いいたします。
tiitoi

2020/08/24 07:07

追記しましたが、 if i % 3 == 0: image = yolo.detect_image(image) で3回に1回だけ検出するというようにすればいいと思います。
gurou

2020/08/24 08:02

3回に1回FPSが20までしか上がらず、まだカクカクしたため 6回に1回まで上げたところ、スムーズに検出することができました。ありがとうございます
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問