本サイトは広告・プロモーションが含まれています
Python

【Python】OpenCVを使って動画に映る人の上に別の画像を貼る【フリーランス案件】

この記事はこんな人におすすめ

・PythonのライブラリOpenCVの参考になるコードをさがしている
・Pythonのフリーランスの仕事がどんなものがあるのか知りたい方
・実際フリーランスの依頼された仕事が、どれくらいの時間がかかるのか知りたい方
・ど

どうもこんには。
最近は雑用仕事から工事手配に仕事が変わりつつあるコンです。
プログラミングの時間どんどん減ってきているなぁ。。。

今日は、フリーランス案件を紹介しているサイトから
Pythonを使った仕事の案件を見つけだし
最近プログラミングできてないので、トライしてみたいと思います。

コン
コン
プログラミングを使った仕事をしたいんじゃい!!

見つけてきた案件はこちら

【案件】
OpenCVを使用し、動画内の人を認知し,別画像を組み込むプログラム作成(Python)
【報酬】
1万円

正直openCVは正直あんまりやってないですけど
とりあえずやってみます!

作業

動画の選定

OpenCVのGitHubにこの動画がありましたので
今回はこの動画に写っている人を検出していきます。

手法の選定

今回はOpenCV のカスケード分類器 CascadeClassifier を使用して、人の体を検出する方法を使用しました。

実は初めて知った手法なので、全然詳しくありません(笑)。


調べてみると
大量の画像からある物体の特徴を学習し、この特徴をまとめたデータのことを「カスケード分類器」呼ぶらしいです。

この分類器の人の体全体を検出してくれるバージョンを使えば
動画から人を検出してくれるらしい!!

ということで採用(笑)

このような検出手法には
手法によって独特な検出パラメータのチューニングだったりが精度に関わる部分があるのですが。。。
今回は省略省略!!

Pythonコードを書く

上のサンプル動画に写っている人を検出し、体の位置に画像をつけるコードを書いていきます。
ついでに、何人検出しているかも表示してみます。

import numpy as np
import cv2
import time

# 体全体のカスケードファイル(パスはカスケード分類器のxmlファイルを指定)
fullbody_detector = cv2.CascadeClassifier("/Users/hts/Documents/python_work/work1/haarcascade_fullbody.xml")
# サンプル動画
cap = cv2.VideoCapture('sample.avi')
# 人の上に表示する画像
mark = cv2.imread('mark.png')
height, width = mark.shape[:2]

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

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

# 画像保存用


# 最初のフレームの処理
end_flag, frame = cap.read()
# グレースケール変換
gray_prev = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
#動画サイズ取得
width_org = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height_org = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
#フレームレート取得
fps = cap.get(cv2.CAP_PROP_FPS)

#フォーマット指定
fmt = cv2.VideoWriter_fourcc('m', 'p', '4', 'v')
#注)グレースケールの画像を出力する場合は第5引数に0を与える
writer = cv2.VideoWriter('output.mp4', fmt, fps, (width_org, height_org))
writer_2 = cv2.VideoWriter('origin.mp4', fmt, fps, (width_org, height_org))
# 元の配列と同じ形にして0を代入
mask = np.zeros_like(frame)

while(end_flag):
    # グレースケールに変換
    writer_2.write(frame)
    gray_next = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    start = time.time()  
    # 全身の人を検出 
    # minSize:物体が取り得る最小サイズ。これよりも小さい物体は無視される
    # minNeighbors:物体候補となる矩形は,最低でもこの数だけの近傍矩形を含む
    body = fullbody_detector.detectMultiScale(gray_next,scaleFactor=1.1, minNeighbors=3, minSize=(40, 40))
    end = time.time()  
    # 検出時間を表示  
    print("{} : {:4.1f}ms".format("detectTime", (end - start) * 1000))

   
    
    # 人検出した数表示のため変数初期化
    human_cnt = 0
    # 人検出した部分を長方形で囲う
   
    
    for (x, y, w, h) in body:
        cv2.rectangle(frame, (x, y),(x+w, y+h),(0,255,0),2)
        frame[y+30:y+30+height, x:x+height]=mark
        # 人検出した数を加算
        human_cnt += 1
        

    # 人検出した数を表示
    cv2.putText(frame, "Human Cnt:{}".format(int(human_cnt)),(10,550), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,255,0), 1, cv2.LINE_AA)
    # ウィンドウに表示
    cv2.imshow('plant_programer', frame)
    writer.write(frame)
    

   # ESCキー
    k = cv2.waitKey(1)
    if k == 27:
        break

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

# 終了処理
writer.release()
cv2.destroyAllWindows()
cap.release()

ネットでコードを見つけそのまま使いました

完成した動画

上のコードを走らせた結果が以下になります。

かかった時間

1. 動画の選定:1時間
2. 手法の選定:1時間
3. コード書く:2時間

くらいの時間をかけて作成しました。
コードに時間がかかったのは、numpyの座標とopenCVの座標の違いに
久しぶりで戸惑ってしまいました。

案件が1万円だから、時給2500円くらい??
でも実際仕事で受け持つと、もうちょっと下調べを行い、2倍は時間をかけるので
8時間くらいはかけると思うので。。。

1日1万円のアルバイトくらい(笑)
試験監督アルバイトかな??( ; ; )

振り返り

動画を見ていただいた人には、ツッコミを入れてもらったかもしれないのですが。。。

変な画像を動画につけてしまい、申し訳ございません!!!

小学生のノリが30前にもなって抜け切らずにおります_| ̄|○

ペン太郎
ペン太郎
本当にヤバい人

動画の内容の話をすると
とりあえずカスケード分類器で適当なパラメーター使用しました。

そうすると下の写真のように人を検出。


街頭の影に隠れている人以外は検出できている!!

と思いきや

う〜ん。。。
右の男性の精度があんまりかな。。。

街灯の近くにいる人たちも検出できていないな。。。。

動画も全体的に、あまり良い精度ではなかった気がします。

もっといい精度だせとクライアント側から要求があれば
もちろんパラメータ調整も行うかもしれませんが

SSDであったり、OpenCVとは別のAIの手法を提案するかもしれません。



COMMENT

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

CAPTCHA