新着情報

3. 動画ファイルの人物検出とその追跡プログラム(TrackingHumanBody.py)

動画に登場する人の検出とその人数をカウントする動画(output5-1)です。

output5-1をクリックしてください。

ブラウザーがFirefoxや Microsoft Edgeの場合は直接動画を見ることができます。

Safariやgoogle chromeの場合は動画プラグインを厳密化しており、ブラウザーから直接動画を見られず、ファイル保存となります。

この場合、保存後に.aviファイルを開くことのできる動画アプリでご覧下さい。

 

 

Fig.1 ビデオは映像に登場する人物を検知し赤枠で囲み、動きを緑線で追跡します。映像上で検知した人物を赤枠で囲み、その人数のカウント値とこれまでの最大カウント値をリアルタイムで記載する。

 

OpenCVライブラリを使用して、テスト動画ファイル(768×576.avi)を読み込み、動画に登場する人物を検出して、緑色の線で追跡する。動画中の検出人物を赤色の枠線で囲み、また、検出された人物の現在の人数のカウント値と最大値を表示する動画(output3.mp4)を作成するpythonプログラム(trackingofbody.py)を備忘録メモとして記載する。。

1)の参考文献を主に参考にして、ビデオの1フレーム書き込み時における時間遅れ(30ミリ秒)を付加する為、

# ESCキー

k = cv2.waitKey(30)

if k == 27:

break

の if 構文をプログラムに入れている。

今後の問題として、この人物追跡プログラムの必要部分を関数化し、GUIボタンと紐付けをする予定である。tkinterライブラリーでフレームWidgetか又はCanvas Widget内に対象映像と処理映像を表示させたいと思っている。

動画の書き込みに関して、1フレーム読み取りと時間差をつけるタイミングに問題があると動画書き込みに失敗する。この問題を調べて、備忘録メモを書いて置きたいと思う。

 

参考文献:

1) OpenCVで人検出と行動を追跡をしてみた

https://qrunch.net/@Atom/entries/5lm14eJkJxBG7OIC

2) OpenCV-Python Tutorials 1

◎カメラから動画を撮影する

◎ファイルから動画を読み込む

◎ 動画を保存する

http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_gui/py_video_display /py_video_display.html

3) [C++] OpenCVを用いて動画の書き込みを行う[画像処理]

 

以下にPythonプログラム trackingofbody.py を示す。
</pre>

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sat Dec  7 21:34:10 2019

@author: PBK-****
"""

import numpy as np
import cv2  

# 体全体のカスケードファイル
#body_cascade_path = './haarcascades/haarcascade_frontalface_default.xml'
fullbody_detector = cv2.CascadeClassifier("./haarcascades/haarcascade_fullbody.xml")
# サンプル画像
cap = cv2.VideoCapture('768x576.avi')

width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = cap.get(cv2.CAP_PROP_FPS)

print(fps, width,height)
fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v')
#fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('output3.mp4',fourcc, fps, (width,height))

# Shi-Tomasiのコーナー検出パラメータ
feature_params = dict( maxCorners = 20,
                       qualityLevel = 0.2,
                       minDistance = 15,
                       blockSize = 10 )  

# Lucas-Kanade法のパラメータ
lk_params = dict( winSize  = (10,10),
                  maxLevel = 2,
                  criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.3))  

# ランダムに色を100個生成(値0~255の範囲で100行3列のランダムなndarrayを生成)
color = np.random.randint(0, 255, (100, 3))  

# 最初のフレームの処理
end_flag, frame = cap.read()
# グレースケール変換
gray_prev = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# 追跡に向いた特徴
feature_prev = cv2.goodFeaturesToTrack(gray_prev, mask = None, **feature_params)
# 元の配列と同じ形にして0を代入
mask = np.zeros_like(frame)
maxbody = 0
while(end_flag):
    # グレースケールに変換
    gray_next = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)  

    # 全身の人を検出
    # minSize:物体が取り得る最小サイズ。これよりも小さい物体は無視される
    # minNeighbors:物体候補となる矩形は,最低でもこの数だけの近傍矩形を含む  

    body = fullbody_detector.detectMultiScale(gray_next,scaleFactor=1.15, minNeighbors=3, minSize=(3, 8))  

#    print(len(body))

    if len(body) > maxbody:
        maxbody = len(body)

    # オプティカルフロー検出
    # オプティカルフローとは物体やカメラの移動によって生じる隣接フレーム間の物体の動きの見え方のパターン
    feature_next, status, err = cv2.calcOpticalFlowPyrLK(gray_prev, gray_next, feature_prev, None, **lk_params)
    # オプティカルフローを検出した特徴点を選別(0:検出せず、1:検出した)
    good_prev = feature_prev[status == 1]
    good_next = feature_next[status == 1]  

    # オプティカルフローを描画
    for i, (next_point, prev_point) in enumerate(zip(good_next, good_prev)):
        prev_x, prev_y = prev_point.ravel()
        next_x, next_y = next_point.ravel()
#        mask = cv2.line(mask, (next_x, next_y), (prev_x, prev_y), color[i].tolist(), 2)
#        frame = cv2.circle(frame, (next_x, next_y), 5, color[i].tolist(), -1)
        mask = cv2.line(mask, (next_x, next_y), (prev_x, prev_y), (0,255,0), 2)
        frame = cv2.circle(frame, (next_x, next_y), 2, (0,255,0), -1)
    img = cv2.add(frame, mask)  

    # 人検出した数表示のため変数初期化
    body_num = 0
    # 現時点における人検出した部分を長方形で囲う
    for (x, y, w, h) in body:
        cv2.rectangle(img, (x, y),(x+w, y+h),(0,0,255),3)
        # 人検出した数を加算
        body_num += 1  

    # 現時点における人検出した数とこれまで検出した最大人数の表示  

    cv2.putText(img, "Body Cnt:{}".format(int(body_num)),(10,550), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0,255,0), 1, cv2.LINE_AA)
    cv2.putText(img, "Max Body Cnt:{}".format(int(maxbody)),(150,550), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0,255,0), 1, cv2.LINE_AA)
#    cv2.putText(img, "Body Cnt:{}".format(int(body_num)),(10,550), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,255,0), 1, cv2.LINE_AA)
#    cv2.putText(img, "Max Body Cnt:{}".format(int(maxbody)),(150,550), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,255,0), 1, cv2.LINE_AA)
#    cv2.putText(img, "Body Cnt:{}".format(int(body_num)),(10,550), cv2.FONT_HERSHEY_PLAIN, 0.5, (0,255,0), 1, cv2.LINE_AA)
#    cv2.putText(img, "Max Body Cnt:{}".format(int(maxbody)),(150,550), cv2.FONT_HERSHEY_PLAIN, 0.5, (0,255,0), 1, cv2.LINE_AA)
    # ウィンドウに表示
    cv2.imshow('humanbody_detection', img)
    out.write(img)
   # ESCキー
    k = cv2.waitKey(30)
    if k == 27:
        break  

    # 次のフレーム、ポイントの準備
    gray_prev = gray_next.copy()
    feature_prev = good_next.reshape(-1, 1, 2)
    end_flag, frame = cap.read()  

# 終了処理
cv2.destroyAllWindows()
cap.release()  
<pre class="crayon-selected">

コメント投稿フォーム

メールアドレスが公開されることはありません。 が付いている欄は必須項目です