我が家では、3Dプリンタで作った治具をドアの錠前に貼り付けて、モータでオートロック/暗証番号解錠しています。
ドア外にカメラを貼り付けて、顔認証で解錠してぇな~~と思っていまして、先日に購入したMATLABで顔認証ソフトを作ろうとしています。
認証機能の前に、まずは顔の検出から。
MATLABでカメラ映像内の人の顔を検出するチュートリアルです。
本記事のスクリプトを実行する上で、Computer Vision Toolboxというオプションを追加で購入しています。
カメラ映像内の顔検出(単発)
スクリプト実行時にカメラ入力から1フレーム取得し、映像フレーム上に人の顔があれば、顔を検出した位置に黄色い枠を描画します。
参考ページ
- MATLABの公式マニュアル
- 動画ファイルを入力して、映像上の顔を検出した位置に枠を追加するサンプル
- https://jp.mathworks.com/help/releases/R2017b/vision/examples/face-detection-and-tracking-using-the-klt-algorithm.html
- 静岡理工科大学 水野先生のサンプル
- 上記のMATLAB公式サンプルをカメラ入力に変更
- https://mizunolab.sist.ac.jp/2019/07/matlab-deep-learning.html
スクリプト全体
ライブスクリプト全体を下記に示します。
webcamlist
%webcameraオブジェクト取得
cam = webcam(1)
%接続したcamera映像表示
preview(cam)
videoFrame = snapshot(cam); %スクリプト実行時点のスクショを1枚取得
imshow(videoFrame)
%顔検出器コンストラクト
%CascadeObjectDetectorには、顔の正面を検出できる事前学習済みの分類器を内臓
% (https://jp.mathworks.com/help/vision/ug/train-a-cascade-object-detector.html)
faceDetector = vision.CascadeObjectDetector(); %デフォルトで初期化→顔正面の検出器
%faceDetectorのアルゴリズムをVideoFrameに対して実行し、顔領域ボックスを取得
% ※bbox型:ボックスの(x座標,y座標,幅,高さ)を格納
boundingBox = step(faceDetector, videoFrame)
%結果確認
%もとのスクショに、顔位置のbboxデータを頂点とした長方形を描画
videoFrame_withBox = insertShape(videoFrame, 'Rectangle', boundingBox);
%作成した画像を表示
imshow(videoFrame_withBox)
実行結果
スクリプトを実行すると、カメラ入力から1フレーム取得して処理を行い、顔を検出した位置に黄色枠が追加されます。背景にモノが写り込んでても正しく顔を検出してますね。ちなみに、検出できるのは、あくまで正面よりで顔が傾いていない時のみのようです。正面を向いていても、顔が斜めに傾いていたら標準では検出できませんでした。
スクリプト解説
実行するコードを順番に解説していきます。
カメラ一覧表示
webcamlist
webcamlistコマンドを実行すると、利用可能なカメラデバイスの一覧を表示してくれます。1行目は皆さまお馴染みのlogicool C270を指しています。2行目は、スマホをwebカメラ化するためにインストールしたツールを指しています。iVCamはC270が届くまでのツナギで使っていました。
後述のスクリプトでカメラを選択できるように、利用可能なカメラの一覧を最初に確認するようにしましょう。
カメラ接続+動作確認
%webcameraオブジェクト取得
cam = webcam(1)
%接続したcamera映像表示
preview(cam)
webcamlistで使いたいカメラデバイスのインデックスを確認しました。ここでは、1行目に認識されているC270を使うことにします。
webcam関数の引数として
を与えると、webcamlistで1行目に認識していたC270に関連づいたカメラオブジェクトを取得できます。1
(※MATLAB言語では、配列・行列のインデックスは0ではなく1始まりな点に注意!)
preview関数に取得したカメラオブジェクトを与えると、カメラからの入力映像を確認できます。preview関数を実行しているのは、あくまでデバイスの動作確認のためです。ですので、正常動作していることを確認できたら、preview関数の行はコメントアウトしておくとよいでしょう。
人の顔の検出
videoFrame = snapshot(cam); %スクリプト実行時点のスクショを1枚取得
imshow(videoFrame)
%顔検出器コンストラクト
%CascadeObjectDetectorには、顔の正面を検出できる事前学習済みの分類器を内臓
% (https://jp.mathworks.com/help/vision/ug/train-a-cascade-object-detector.html)
faceDetector = vision.CascadeObjectDetector(); %デフォルトで初期化→顔正面の検出器
%faceDetectorのアルゴリズムをVideoFrameに対して実行し、顔領域ボックスを取得
% ※bbox型:ボックスの(x座標,y座標,幅,高さ)を格納
boundingBox = step(faceDetector, videoFrame)
%結果確認
%もとのスクショに、顔位置のbboxデータを頂点とした長方形を描画
videoFrame_withBox = insertShape(videoFrame, 'Rectangle', boundingBox);
%作成した画像を表示
imshow(videoFrame_withBox)
snapshot関数にカメラオブジェクトを与えることで、スクリプト実行時のカメラ映像の1フレームを取得できます。フレームデータはimshow関数に与えることで表示できます。ここでは比較用にオリジナルを表示しておきましょう。
MATLABでは、人の顔を検出できる分類器がデフォルトで用意されていて、vision.CascadeObjectDetector()をデフォルト(引数無し)で実行することで、人の顔の検出器を取得できます。
そして、step関数に検出器と画像を入力します。step関数とは、第1引数に受け取るSystem Object型のオブジェクト(ここでは顔検出器)のアルゴリズムを、第2引数に受けるデータ(ここでは映像フレーム)に対して実行させる関数です。今回では、顔が画像中にあれば、顔位置をbbox型のデータで返してくれます。
※bbox型:ボックスの(x座標,y座標,幅,高さ)を格納
なお、System Objectのアルゴリズムを実行する上では、下記のどれでもよいそうで。「検出器のアルゴリズム実行する」という意味合いだと、個人的には2番目のオブジェクト指向言語風の書き方が好きですが、世の中的には1番目の記法が主流なんですかね。
boundingBox = step(faceDetector, videoFrame);
boundingBox = faceDetector.step(videoFrame);
boundingBox = faceDetector(videoFrame)
確認のために、もとの画像の上に、検出した顔領域を描画します。insertShape関数でもとの映像フレーム上に顔領域の四角形を描画し、imshow関数で表示させます。すると、実行結果の画像のように元の映像フレームの上に顔領域のボックスを描画してくれます。
おまけ
メガネ・グラサンをかけててもいけました。
ちなみにこの写真のマスクは、今回の記事用にAmazonでYoutuberマスクを買って肌色でスプレーしました。
まとめ
公式の顔検出サンプルを一部改造して、カメラ入力映像中の顔位置を検出するサンプルを作成しました。
顔認証で使う際は、カメラ映像から入力顔画像を切り取る時に使えますね。あとは、顔を撮影した動画から教師データを作成したりする時などにも。
記事中のサンプルで、動作確認用のコードを除いた正味の処理は実質5行です。このテの画像処理は初体験だったのですが、すぐに動いてめっちゃ便利ですね。
コメント