見出し画像

【AI×カメラ】父親か息子か、リアルタイムでAIが判別するシステムを作ってみた!



【AI×カメラ】父親か息子か、リアルタイムでAIが判別するシステムを作ってみた!


今日は、AI技術を使ってカメラに映った人物が「父親」か「息子」かをリアルタイムで判別するシステムを作ってみました。AIや顔認識に興味がある方はもちろん、初心者の方にも分かりやすく解説していくので、読んでみてください!


今回作ったもの

今回の目標は、USBカメラでリアルタイムに映像を取得し、その映像に映っている人物が「父親」か「息子」かをAIが判別するシステムを作ることです。

簡単な流れはこんな感じです👇

  1. Visual Studio Code で開発環境を整える。

  2. USBカメラ でリアルタイムに映像を取得。

  3. AIがその映像を解析し、「父親」か「息子」かを判別。

これをAIにやらせると、なんだか未来感がありますよね!


作り方

1. 開発環境のセットアップ

まずは、Visual Studio Codeを使ってPythonの環境を整えました。USBカメラの映像を取り込むために `opencv-python` を使い、AIモデルを動かすために `tensorflow` をインストール。

# bash
pip install tensorflow opencv-python

2. 学習済みモデルを使う

次に、学習済みのAIモデル(H5形式)を読み込みました。
学習済みのAIモデルの作り方はこちらの記事を参考にしてください。


このモデルは、すでに「父親」と「息子」の顔をたくさん学習しているので、カメラに映った顔を見分けることができます。

3. カメラでリアルタイムに映像を取得

そして、USBカメラを使ってリアルタイムの映像を取得! カメラで顔をキャッチすると、AIが即座に「父親」か「息子」かを判定してくれます。

# 必要なライブラリをインポートします
import cv2  # OpenCVライブラリ: 画像処理やコンピュータビジョンのためのライブラリ
import tensorflow as tf  # TensorFlowライブラリ: 機械学習モデルの構築と実行に使用
import numpy as np  # NumPyライブラリ: 数値計算や配列操作に使用

# 学習済みの機械学習モデルを指定したパスから読み込みます
# 'father_child_classifier.h5' は事前に訓練されたモデルのファイル名です
model = tf.keras.models.load_model('C:/temp/father_child_classifier.h5')

# USBカメラを初期化します
# 通常、接続されている最初のカメラはインデックス0です
cap = cv2.VideoCapture(0)

# カメラが正常に開かれたかどうかを確認します
if not cap.isOpened():
    print("カメラを開けません")  # エラーメッセージを表示
    exit()  # プログラムを終了

# Haar Cascadeの顔検出器を読み込みます
# OpenCVには事前に訓練された顔検出用の分類器が含まれています
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')

# 無限ループを開始します。これにより、リアルタイムでカメラからの映像を処理できます
while True:
    # カメラからフレーム(画像)を取得します
    ret, frame = cap.read()
    if not ret:
        print("フレームを取得できませんでした")  # フレーム取得失敗時のエラーメッセージ
        break  # ループを抜けてプログラムを終了

    # フレームをグレースケールに変換します
    # 顔検出の際にカラー情報が不要なため、処理を軽くするためにグレースケールにします
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # 顔検出器を使用してフレーム内の顔を検出します
    # detectMultiScaleは検出された顔の矩形(位置と大きさ)を返します
    faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5)

    # 検出された各顔に対して以下の処理を行います
    for (x, y, w, h) in faces:
        # 検出された顔の周りに青色の矩形を描画します
        # (x, y)は矩形の左上の座標、wとhは幅と高さ
        # (255, 0, 0)はBGR形式での色指定(青色)
        # 2は線の太さ
        cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 0), 2)

        # 顔の領域(Region of Interest: ROI)を切り出します
        face_roi = frame[y:y + h, x:x + w]

        # モデルに入力するために顔画像を前処理します

        # 顔画像をモデルの入力サイズにリサイズします(ここでは150x150ピクセル)
        face_roi_resized = cv2.resize(face_roi, (150, 150))

        # 画像データを正規化します
        # ピクセル値を0から1の範囲にスケーリングします
        # これはモデルの学習時と同じ前処理を行うためです
        face_roi_normalized = face_roi_resized / 255.0

        # モデルの入力形状に合わせて次元を拡張します
        # モデルはバッチ処理を想定しているため、1つの画像でも4次元配列にする必要があります
        # 形状が (1, 150, 150, 3) になります
        face_input = np.expand_dims(face_roi_normalized, axis=0)

        # 学習済みモデルを使用して顔画像の分類を行います
        prediction = model.predict(face_input)

        # 予測結果を解釈します
        # ここでは2クラス分類を想定しており、出力が0〜1の値です
        # 閾値0.5を基準にクラスを決定します
        if prediction[0][0] > 0.5:
            label = "Yasu"  # 予測結果が0.5より大きい場合のラベル
        else:
            label = "KOTA"  # それ以外の場合のラベル

        # フレームにラベル(名前)を表示します
        # テキストの位置は顔の矩形の左上より少し上に設定
        # フォント、サイズ、色、太さを指定
        cv2.putText(frame, label, (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX,
                    0.9, (36, 255, 12), 2)

    # 処理後のフレームをウィンドウに表示します
    cv2.imshow('Father and Son Detection', frame)

    # キー入力を待ちます
    # 1ミリ秒待機し、'q'キーが押されたらループを終了します
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# ループを抜けた後、カメラを解放します
cap.release()

# 全てのOpenCVウィンドウを閉じます
cv2.destroyAllWindows()


# 1. **ライブラリのインポート**
#    - `cv2`: OpenCVは画像やビデオの処理、コンピュータビジョンのタスクに広く使用されるライブラリです。
#    - `tensorflow`: TensorFlowは機械学習や深層学習モデルの構築、訓練、実行に使用されます。
#    - `numpy`: NumPyは数値計算を効率的に行うためのライブラリで、特に配列操作に強力です。


# 2. **モデルの読み込み**
#    - `tf.keras.models.load_model`を使用して、事前に訓練されたモデルファイル(ここでは`father_child_classifier.h5`)をロードします。
#    - このモデルは、顔画像を「Yasu」または「KOTA」に分類するために使用されます。



# 3. **カメラの初期化と確認**
#    - `cv2.VideoCapture(0)`でカメラを初期化します。`0`は通常、最初に接続されたカメラを指します。
#    - `cap.isOpened()`でカメラが正常に開かれたか確認します。開けない場合はエラーメッセージを表示してプログラムを終了します。



# 4. **顔検出器の読み込み**
#    - `cv2.CascadeClassifier`を使用して、Haar Cascade分類器を読み込みます。これは顔検出に使用される事前訓練されたモデルです。
#    - `haarcascade_frontalface_default.xml`は正面顔を検出するための分類器ファイルです。

# 5. **メインループ**
#    - カメラから連続的にフレーム(画像)を取得します。
#    - 各フレームをグレースケールに変換します。これは顔検出の処理を効率化するためです。
#    - グレースケール画像を用いて顔検出を行います。`detectMultiScale`関数は検出された顔の位置とサイズを返します。
#    - 検出された各顔に対して以下の処理を行います:
#        - 顔の周りに矩形を描画します。これにより、検出された顔が視覚的に確認できます。
#        - 顔領域を切り出し、モデルに入力するためにリサイズと正規化を行います。
#        - モデルに顔画像を入力し、予測を行います。出力が0.5より大きければ「Yasu」、それ以外なら「KOTA」とラベル付けします。
#        - フレームにラベルを表示します。
#    - 処理後のフレームをウィンドウに表示します。
#    - キー入力を待ち、'q'キーが押された場合はループを終了します。


# 6. **クリーンアップ**
#    - ループを抜けた後、カメラを解放し、全てのOpenCVウィンドウを閉じます。これにより、リソースが適切に解放されます。

このコードで、リアルタイムのカメラ映像を表示できます。AIがこの映像を見て判別を始めます!


実際に動かしてみた結果

システムを動かしてみたら、父親や息子の顔をカメラに映したときに、正確に「父親」か「息子」と判定してくれました! これは、AIが自分で判断してくれている感じがして、めちゃくちゃ未来を感じました。



課題と今後の展望

課題 1: 「娘」が映ったら?

今回のモデルは「父親」と「息子」だけで学習されています。そのため、もし「娘」がカメラに映った場合でも、AIは「父親」か「息子」として判別してしまいます。この点は改善が必要ですね。

課題 2: 環境の影響

カメラでの映像取得は、照明や背景に影響を受けやすいです。暗い場所や逆光だと、AIがうまく顔を認識できないことがあります。次は、どんな環境でも正確に認識できるモデルを作りたいです!


これからの挑戦

このシステムは基本的な「父親」と「息子」の判別には成功しましたが、「娘」や「母親」といった新しいクラスを追加して、さらに複雑なシステムを作っていきたいです。照明の変化にも対応できるように、環境への対応力も強化していきます。


まとめ

今回は、父親と息子をリアルタイムで判別するAIシステムを作りました。初心者の方でもこうしたAI技術を試すことができるので、興味がある方はぜひ挑戦してみてください!


この記事が気に入ったらサポートをしてみませんか?