LoginSignup
0
0

More than 5 years have passed since last update.

Opencv: meanshift&CamShiftで遊んでみた♬その2;VGG16で物体識別

Last updated at Posted at 2018-05-29

当然の発展として、物体識別であらかじめ識別してタグ付けした。

おまけに、fpsを画面に表示するようにしました。
ちなみに、7-8fps(1060)、29-30fps(1080)でした。

コードは以下に置いた

OpenCV / meanshift_recognizedByVGG16.py

やったこと

機能として以下3つ追加した。
1.追跡する物体を決定したとき、物体識別をVGG16で実施
2.fpsを計測して画像の左上に表示
3.動画を保存する

1.追跡する物体を決定したとき、物体識別をVGG16で実施

コードは以下のとおりで、先日のFlaskと同じくVGG16を利用したyomikomi()関数を使った。今回は引数として取得した画像を渡す。

def yomikomi(img):
    batch_size = 2
    num_classes = 1000
    img_rows, img_cols=img.shape[0],img.shape[1]
    input_tensor = Input((img_rows, img_cols, 3))

    # 学習済みのVGG16をロード
    # 構造とともに学習済みの重みも読み込まれる
    model = VGG16(weights='imagenet', include_top=True, input_tensor=input_tensor)
    model.summary()

    # 引数で指定した画像ファイルを読み込む
    # サイズはVGG16のデフォルトである224x224にリサイズされる
    # 読み込んだPIL形式の画像をarrayに変換
    x = image.img_to_array(img)
    x = np.expand_dims(x, axis=0)
    #preds = model.predict(preprocess_input(x))
    preds = model.predict(x)
    results = decode_predictions(preds, top=1)[0]
    return str(results[0][1])

呼び出し側は以下のとおり、

def main():     
    cap = cv2.VideoCapture(0)
    # 追跡する枠の座標とサイズ
    x = 100
    y = 100
    w = 224
    h = 224
    track_window = (x, y, w, h)
    # フレームの取得
    ret,frame = cap.read()
    cv2.waitKey(2) 
    # 追跡する枠を決定
    while True:
        ret,frame = cap.read()
        img_dst = cv2.rectangle(frame, (x,y), (x+w, y+h), 255, 2)
        cv2.imshow("SHOW MEANSHIFT IMAGE",img_dst)
        roi = frame[y:y+h, x:x+w]
        if cv2.waitKey(20)>0:
            txt=yomikomi(roi)
            break

追跡する物体が確定して、画像を取得したところでその画像を引数にしてyomikomi(img)に渡して物体識別をしてもらいます。その結果は、上記のように識別物体の名称str(results[0][1])として受け取ります。
こうして追跡している間中、名称を表示するようにしました。

2.fpsを計測して画像の左上に表示

fpsの計測は以下のとおりです。

   curr_time = timer()
   exec_time = curr_time - prev_time
   prev_time = curr_time
   accum_time = accum_time + exec_time
   curr_fps = curr_fps + 1
   if accum_time > 1:
        accum_time = accum_time - 1
        fps = "FPS: " + str(curr_fps)
         curr_fps = 0

   cv2.putText(img_dst, fps, (30,50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,0,0), 1)

最後の行で表示しています。表示文字の大きさは1としましたが、案外大きく表示されます。そして、物体識別したタグも同様に以下のように記載しました。

img_dst = cv2.rectangle(frame, (x,y), (x+w, y+h), 255, 2)

cv2.putText(img_dst, txt, (x+3,y+10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,0,0), 1)

上で物体を四角で囲み、二行目でその左上に表示するようにしています。ここでは文字サイズ0.5としました。

3.動画を保存する

これも以前やっていますが、img_dstを直接保存しようとしてもうまくいきません。
ということで当該部分を抜き出すと、以下のとおりでうまくいきます。

OUT_FILE_NAME = "meanshift_result.mp4"
FRAME_RATE=8
out = cv2.VideoWriter(OUT_FILE_NAME, \
              cv_fourcc('M', 'P', '4', 'V'), \
              FRAME_RATE, \
              (w, h), \
              True)
img_dst = cv2.resize(img_dst, (int(h), w))
out.write(img_dst)    

ここで下から二番目の変換が重要なようです。これがないとうまく保存できません。
※元画像が大きすぎて保存できていない⇒(224,224)サイズに縮小でうまくいく
あとはおまじないの関数が必要です。

def cv_fourcc(c1, c2, c3, c4):
        return (ord(c1) & 255) + ((ord(c2) & 255) << 8) + \
            ((ord(c3) & 255) << 16) + ((ord(c4) & 255) << 24)

まとめ

・opencv.meanshiftに物体識別を行って、物体検出しつつ物体追跡をできるようにした
・fpsは7-8fps程度あり、追加により劣化はしていない。
・動画保存の機能を追加した

・説明は省いたが、前回のものに比較すると、最初の物体選択の画面を追跡画面と共通になるように変更した。これにより、Webでも追跡が開始できるようにできる
・複数物体もやれそうだが、次回以降にする

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0