https://a.storyblok.com/f/270183/121353/345b7324de/blog_human-detection_1200x600.png

OpenCVによるリアルタイム人間検出

最終更新日 April 15, 2020

所要時間:1 分

このブログでは、独自の "スマート "ビデオカメラの作り方を紹介します。Webカメラのフレームから画像を取得し、フレーム内に人間がいるかどうかを検出し、潜在的な脅威について通知するためにVonage Communication API経由でSMSを送信する方法を紹介します。

はじめに

このアイデアは、両親の家に泥棒が入った後に思いついた。実家は人里離れた場所にあり、防犯カメラもなく、警察は犯人を見つけることができなかった。その後、両親は家に防犯設備を設置することにした。当時大学生だった私は、自分のスキルを活かして両親のためにセキュリティシステムを構築することにした。

私はこれを完全に実用的なプロトタイプとして開発したので、遠慮なく私に連絡してほしい。 実用的なプロトタイプこれは私の家族によって利用されている!

ハードウェア要件

Raspberry Piが必要です。 ラズベリーパイ2), a ラズベリーパイカメラそして 「ダミー "セキュリティカメラ.

前提条件

このプロジェクトを組み立てるには、ハードウェアの他に以下のものが必要だ:

物体検出アルゴリズム

このチュートリアルでは、Haar分類器を使います。これは、Paul ViolaとMichael Jonesが2001年の論文 "Rapid Object Detection using a Boosted Cascade of Simple Features "で開発した効果的な物体検出手法です。

最初に、アルゴリズムは分類器を訓練するために、多くの陽性画像(我々の場合、様々な人物の画像)と陰性画像(フレーム上に人間を含まない画像)を必要とする。

そこから、分類器からある特徴をつかまなければならない。各特徴は、黒い三角形の下のピクセルの合計から白い四角形の下のピクセルの合計を引くことによって得られる単一の値である。

カスケード分類器とそのアルゴリズムについては、こちらをご覧ください。 OpenCV: カスケード分類器の記事.

実施

Raspberry Pi上で、新しいPythonファイルを作成し、以下のimport文を使って必要なライブラリをすべてインポートする:

import cv2
import nexmo
import time

これらのライブラリは、人を検出したり、検出した人についてユーザーに伝えたり、送信されたテキスト間の時間差を計算したりするために使用される。

その後、お手持ちのカメラでビデオ撮影を開始します:

video_captured = cv2.VideoCapture(0)

上記のパラメータに0を指定すると、使用可能な最初のビデオカメラを使用することになります。通常、使用可能なビデオカメラは1台だけですが、外部カメラが接続されている場合は、適切なパラメータをVideoCaptureに渡すことで、使用するストリームを指定できます。

それでは、Vonage API SMS クライアントを初期化してみましょう。そのためには、作成したVonage API AccountのダッシュボードにあるAPIキーとシークレットが必要です:

client_nexmo = nexmo.Client(key=’your_project_key’, secret=’your_secret_key’)

この後、すでに学習済みの分類器を読み込みます。このチュートリアルで使用する分類器は リンクをクリックし、プロジェクトで使用したい分類器を選択します。

我々は haarcascade_fullbody.xmlクラシファイアを使用します。

テスト目的で、また適切なスクリーンショットを掲載しやすくするために、私は haarcascade_frontalface_default.xmlクラシファイアを サンプル・レポしかし haarcascade_fullbody.xml分類器は防犯カメラのユースケースに最も適しています。

classifier = cv2.CascadeClassifier('haarcascade/haarcascade_fullbody.xml')

検出のほとんどは、以下のコードで行われる:

while (True):
    # read frame-by-frame
    ret, frame = video_captured.read()

    # set the frame to gray as we do not need color, save up the resources
    gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # pass the frame to the classifier
    persons_detected = classifier.detectMultiScale(gray_frame, 1.3, 5)

    # check if people were detected on the frame
try:
        human_count = persons_detected.shape[0]
else:
        human_count = 0
    
    # extract boxes so we can visualize things better
    # for actual deployment with hardware, not needed
    for (x, y, w, h) in persons_detected:
        cv2.rectangle(frame, (x,y), (x+w, y+h), (255, 0, 0), 2)    
    cv2.imshow('Video footage', frame)

    if (cv2.waitKey(1) & 0xFF == ord('q')):
        break

キャプチャしたビデオストリームから各フレームを読み込む。リソースを節約するためにグレーに変換するのも良いアイデアだ。それが終わると、そのフレームを分類器に渡して、人物が検出されたかどうかを確認する。その場合、検出された人物を囲む矩形がフレーム上に描かれる。

私の顔が検出された例をご覧ください:

Example below of my face being detectedExample below of my face being detected

など、別の分類器をロードする場合は、次のようにします。 upperbody.xmlまたは fullbody.xmlのような別の分類器を読み込めば、同じコードで検出ができるようになる。

フルボディ分類器は、フレームに体全体が写っている場合にのみ、フレームに写っている人物を認識することに注意してください。顔や上半身だけでは認識できません。上半身クラシファイアも同様で、顔がフレームに入っているだけでは検出は成功しません。

これは、OpenCVが提供する分類器の制限から来るものです。独自の分類器を訓練することはいつでも可能です。それには余分な時間とリソースがかかりますが、その方面についてもっと学びたいのであれば、このプロジェクトを構築する良い方法です。

では、Vonage SMS API機能をアプリケーションに追加して、ビデオフレーム上で見知らぬ人が検出された場合にユーザーに通知できるようにしてみましょう。

:ユーザーが1つの検出イベントに対して多くのSMSメッセージを受け取らないように、(特にテスト中は)これに遅延を加えることが重要です。

この例では time.sleep(number of seconds)しかし、もっと洗練された独自のメソッドがあれば、自由に開発してください。

コードのtry/elseブロックの後に以下のコードを追加する:

if (human_count > 0):
        client_nexmo.send_message({
            'from': ‘your_outbound_phone_number’,
                'to': ‘your_inbound_phone_number’,
                'text': 'There has been ' + str(human_count) + ' human(s) detected!',
        })

SMSは、フレーム上に少なくとも1人の人間が検出された場合にのみ送信される。メッセージを送りすぎないようにするため、スレッドを約5秒間スリープさせ、その後フレーム内の人を探す。

これだけです!たった50行のコードで、Vonage SMS APIを使い、あなたの家の敷地を覗き見している人を検知し、その時に便利な通知を受け取ることができます。

この投稿のソースコードは、以下にあります。 GitHubのリンク.このプロジェクトで使われているHaar Cascade分類器も含まれているので、すぐに使い始めることができます。

改善の可能性

もちろん、このプロジェクトをより洗練された効率的なものにするためには、もっとできることがある。

まず time.sleep()の方法では、フレーム解析の間に少なくとも5秒のギャップがあることになり、これは理想的な状況ではないので、改善できるはずです。また、カメラからのビデオフレーム画像を特定の検出エリアだけにトリミングし、検出効率を向上させるのも良いアイデアでしょう。

参考文献

https://docs.opencv.org/master/db/d28/tutorial_cascade_classifier.html https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_gui/py_video_display/py_video_display.html https://github.com/opencv/opencv/tree/master/data/haarcascades

シェア:

https://a.storyblok.com/f/270183/364x364/50552ba95c/misha-behei.png
Misha Beheiカスタマー・ソリューション・エンジニア

ミーシャは カスタマー・ソリューション・エンジニアVonage のカスタマー・ソリューション・エンジニアで、Video API の開発に専念している。サンフランシスコの喧騒からウィスコンシン州ミルウォーキーの魅力へ移り、現在は中西部の隠れた魅力を発見することに余暇を費やしている。