Python

【初心者向け】機械学習を使って動画に映っているものを判定する方法を徹底解説!

【初心者向け】機械学習を使って動画に映っているものを判定する方法を徹底解説!

こんにちは、さすを(@sasuwo0409)です。

いきなりですが、

今話題のPythonで機械学習をしてみたい!

身近なもので機械学習をしてみたい!

動画やビデオを使ったプログラムを書いてみたい!

と思ってはいませんか?

今回の記事は、Pythonの機械学習を使って、動画・ビデオに映っているものを判定する方法を解説していきます。

サンプルコードも載せているので、実際に試してみることも可能です。

それでは本文をどうぞ。

困っている人
困っている人

機械学習で動画やビデオ内のものを判定をしてみたいけど、やり方がわからなくて困ってる。

手順をサンプルコードを含めて教えて欲しいな。

さすを
さすを

この悩みを解決します!

この記事を読むとわかること:

Pythonの機械学習で動画・ビデオ内に映っているものを判定する方法

筆者の情報:

  • 現役システムエンジニア 兼 ブロガー
  • 過去に6,000万のPython案件を受注
  • 最近ハマっていることは機械学習

※0円のサンプルテキストという近道
独学よりプログラミングスクールの方が効果は出やすいですが、値段が高く、なかなか手を出しづらいですよね。techgymでは無料のサンプルテキストをもらえるので、これを使ってPythonの基礎を学ぶのもありだと思います。

>>techgymの無料サンプルテキストはこちらから

スポンサーリンク

【機械学習】動画に映っているものを判定する方法

【機械学習】動画に映っているものを判定する方法

今回は以下の動画に映っているシベリアンハスキーを判定していきます。

図1:入力動画
図1:入力動画

>>詳しい動画はこちら

なお、プログラム完成までの手順は以下の通りです。

  1. 開発環境の確認
  2. ライブラリのインストール
  3. プログラムの作成
さすを
さすを

それでは、始めていきましょう!

プログラム作成時の開発環境

  • OS : Windows10
  • Pythonのバージョン:3.9.0
  • OpenCVのバージョン:4.5.2
  • TensorFlowのバージョン:2.7.0
  • Kerasのバージョン:2.7.0
  • Googletransのバージョン:3.0.0
  • 使用エディタ:Visual Studio Code

上記のバージョンでないとプログラムが動かないというわけではないので、適宜読み替えていただければと思います。

また、この記事ではVisual Studio Code上でプログラムを動かしていますが、プログラムが書けるエディタであれば問題ありません。

既にインストールされている方はそちらを使っていただければと思います。

エディタがないと、プログラムを書くことがほとんどできないので、まだインストールされていない方はこの機会にインストールしてしまいましょう。

>>ソースコードエディタ(VSCode)のインストール方法[Windows版]
>>ソースコードエディタ(VSCode)のインストール方法[Mac版]

ライブラリのインストール

これから紹介するプログラムでは以下の4つのライブラリを使用しています。

  • OpenCV
  • TensorFlow
  • Keras
  • Googletrans

ライブラリのインストールが済んでいない方は「【これだけ知っておけばOKです】 現役エンジニアもよく使う便利なPythonライブラリ24選」からインストールしてください。

さすを
さすを

この記事に取り上げられているライブラリは、どれも使い勝手がいいので、まだインストールしていないものがあれば、ついでにインストールしておくのがおすすめです!

実際に作成したスクリプト文

必要なライブラリのインストールができたら、実際にプログラムを書いていきます。

#必要なライブラリのインポート
from keras.applications.resnet import ResNet50
from keras.preprocessing import image
from keras.applications.resnet import preprocess_input, decode_predictions
import numpy as np
from googletrans import Translator
import cv2

#resnet-50を呼ぶ関数
def resnet(model,translator,img):
    x = cv2.resize(img, dsize=(224,224))
    x = image.img_to_array(x)
    x = np.expand_dims(x, axis=0)
    x = preprocess_input(x)

    preds = model.predict(x)
    res = decode_predictions(preds, top=1)[0][0]
    return res[1],res[2]

model = ResNet50(weights='imagenet')
translator = Translator()

try:    
    #動画の読み込み
    cap = cv2.VideoCapture('読み込みたい動画のファイルパス')

    #カメラで読み込みたい場合はこちら
    # cap = cv2.VideoCapture(0)

    before = None

    if cap.isOpened() == False:
        raise Exception

    while (cap.isOpened()):
    #pcのカメラで読み込みたい場合はこちら
    # while True:

        ret, frame = cap.read()

        if ret == True:
        
            cv2.imshow('Raw Frame', frame)

            frame_moto = frame.copy()

            #白黒処理
            gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
            if before is None:
                before = gray.copy().astype('float')
                continue

            #加重平均
            cv2.accumulateWeighted(gray, before, 0.5)
            mdframe = cv2.absdiff(gray, cv2.convertScaleAbs(before))

            #面積
            thresh = cv2.threshold(mdframe, 3, 255, cv2.THRESH_BINARY)[1]

            #輪郭データ変換
            contours, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

            if len(contours)>0:
                max_area = 0
                target = contours[0]
                for cnt in contours:

                    #輪郭の面積
                    area = cv2.contourArea(cnt)
                    if max_area < area and area < 40000 and area > 4000:
                        max_area = area;
                        target = cnt

                #矩形表を示す
                if max_area <= 4000:
                    areaframe = frame
                    cv2.putText(areaframe, 'not detected', (0,50), cv2.FONT_HERSHEY_PLAIN, 3, (0, 255, 0), 3, cv2.LINE_AA)
            
                else:
                    x,y,w,h = cv2.boundingRect(target)
                    img = frame_moto[y:y+h,x:x+w]

                    #縦横が0でない
                    if img.shape[0] != 0 and img.shape[1] != 0:
                        res = resnet(model, translator, img)

                        #判定結果が7割を超えた場合出力
                        if res[1] >= 0.7:
                            print(res)
                            areaframe = cv2.rectangle(frame, (x,y), (x+w, y+h), (0,255,0), 2)
                            cv2.putText(areaframe, res[0], (0,50), cv2.FONT_HERSHEY_PLAIN, 3, (0,255,0), 3, cv2.LINE_AA)
                            cv2.imshow('MotionDetected Area Frame', areaframe)
                        
                        else:
                            cv2.imshow('MotionDetected Area Frame', frame)

            #Enterキーで処理終了
            k = cv2.waitKey(1)
            if k == 13:
                break

        else:
            break

except Exception as e:
    print("エラーが発生しました。")
    print(e)

finally:
    #ウィンドウをすべて閉じる
    cap.release()
    cv2.destroyAllWindows()

実行結果はこちらです。

GPUを使っていないので、動画はやや粗くなってしまいましたが、無事に判定することができました。

さすを
さすを

コピペで作ることができるので、ぜひ試してみてくださいね!

なお、動画やビデオではなく、画像を分類したい方は「【コピペOKです】機械学習で画像分類する方法【Pythonで気軽に体験できます】」の記事で詳しく解説しているので参考にしてみてください。

機械学習の判定データは集めなくてOK

今回のプログラムでは「Resnet-50」という深さが50層の畳み込みニューラルネットワークを使用しています。

畳み込みニューラルネットワーク(たたみこみニューラルネットワーク、: Convolutional neural network、略称: CNNまたはConvNet)は層間を共通重みの局所結合で繋いだニューラルネットワークの総称・クラスである。機械学習、特に画像や動画認識に広く使われる。

wikipedia

Resnet-50は、120万枚以上の画像を学習しているものなので、それを読み込むことで、自分の手で判定データを作らずに機械学習済みのデータをつかうことができます。

さすを
さすを

22行目「model = ResNet50(weights=”imagenet”)」でトレーニング済みモデルを利用することを宣言しています!

また、機械学習の判定に使えそうなAPIをもっと知りたい方は『Amazon、Google、IBM、Microsoftが公開する、AIを使うための「API」「ライブラリ」「実行環境」一覧」』の記事がおすすめです。

判定精度はばらつきがある

今回のプログラムでは、学習してある画像イメージの中で70%以上合致すると判定したものを出力するようにしてあります。

('Arctic_fox', 0.72308445)
('Siberian_husky', 0.8023355)
('dugong', 0.7145132)
('American_egret', 0.86516947)
('Great_Pyrenees', 0.7862776)
('Siberian_husky', 0.7332032)
('Arctic_fox', 0.78965193)
('Siberian_husky', 0.75948596)
('Siberian_husky', 0.8483436)
('Eskimo_dog', 0.71327275)
('Eskimo_dog', 0.72835493)
('Siberian_husky', 0.8615434)
('Siberian_husky', 0.8156751)
('Siberian_husky', 0.7889818)
('Siberian_husky', 0.8095434)
('Siberian_husky', 0.7186799)
('Siberian_husky', 0.7766576)
('Siberian_husky', 0.75811297)
('lakeside', 0.85151744)

実際に映っているのはシベリアンハスキーですが、時々「ホッキョクギツネ」「ダイサギ」「ジュゴン」「グレート・ピレニーズ」「アメリカン・エスキモー・ドッグ」「湖畔」と判定されてしまいました。

もちろん、動画によって判定精度は変わりますが、この条件で正しく判定できたのは、58%程度でした。

もし、判定精度を上げたいのであれば、使用する学習モデルを変更するか、GitHubから似たようなプログラムをコピーして活用することをおすすめします。

最後に:難しいことは頭のいい人に任せよう

Pythonの機械学習を使って、動画・ビデオに映っているものを判定する方法を解説してきました。

機械学習というと難しいイメージがあるかもしれませんが、すでにある学習データを使えば、案外シンプルに作れるということが分かったのではないでしょうか。

というわけで、これからも機械学習を使って、たのしみながら自分の作業を減らせるような便利なものを開発していきたいと思います。

この記事がすこしでもあなたの役に立っていたら嬉しいです!

それでは!

参考にした動画:Pythonで動体検知をして遊んでみた

あなたにおすすめの記事:

>>【絶対に挫折しない】 Python書籍のおすすめ9選【現役エンジニアが推薦します】


コメント

タイトルとURLをコピーしました