SSブログ

Core Imageの顔認識をOS Xで - その1 [OpenCV関係]

1  はじめに

こないだからいじっているポリゴンレンダラつながりでCore Imageフレームワークに10.7から実装された顔認識についてまとめてみる。

僕の認識では顔認識と言えばOpenCVだったんだけど、顔認識のニーズは高くて独自実装がスマホやデジカメだけでなくテレビなどにも搭載されるようになっているらしい。アルゴリズムは基本的にはOpenCVと同じように、特徴をツリー(カスケード)に列挙してにして全てにマッチしたものを顔とみなす、という方法になっていると思われるが、ツリーの構成の仕方や学習データの違いで認識精度や実行効率に差が出てくるはずである。もちろんOpenCV以外はソースにあたれないので想像でしかないけど。

OS XのCore Imageフレームワークに顔認識の機能が10.7から追加された。もちろん本来iOSで使るようにというのが動機で、OS Xはオマケでついでに実装された、と言う感じになっている。しかし非力なiOSで実用に堪えるようならOS Xでは楽勝だろう、と思って試しに動かしてみることにした。最終的にOpenCVと比較する。

前もって言っておくが、僕が書くのはOS XとMac装備のFaceTimeカメラでの使い方に関してであって、iOSは知らない。iOSなら他の人がいっぱい書いてるだろうと思うのでそっちを見て欲しい。

ところでまず訂正がある。以前、CGImageはピクセルの色の並びのデフォルトがBGRで、NSBitmapImageRepはRGBだと書いたが、これは僕の勘違いだった。どちらもRGB並びだった。CIImageもデフォルトではRGBなのでこの範囲では全部一緒。申し訳ない。まず訂正しておく。この色の並びの問題は、あとで影響してくる。

2  CIDetector

Core Imageフレームワークの顔認識はCIDertectorというクラスで実現されている。呼び出すのは簡単で、インスタンスを作ったあと、CIImageの画像を渡して解析させるだけ。非常に簡単だけど、調整できるパラメータはOpenCVに比べると極端に少ない。

2.1  インスタンス生成

CIDetectorのインスタンスを作るには
    CIDetector          detector;
    CIContext           *ciContext;
    NSDictionary        *dic;
    //	ciContextとdicの初期化
    detector = [[CIDetector detectorOfType:CIDetectorTypeFace
                                   context:ciContext
                                   options:dic] retain];
と言う感じ。引数は3つあって
  1. 認識対象
  2. CIContextのインスタンス
  3. オプション
である。
認識対象はいまのところCIDetectorTypeFaceだけしか定義されていない。いずれはCIDetectorで顔認識以外のことをさせるぞという意思の現れと解釈してくれ、ということだろう。たとえばthumb upやthumb downのジェスチャの認識なんかはiOSでは有用かもしれない。

ふたつめの引数は描画コンテクストである。解析対象のCIImageと同じコンテクストを渡せ、とReferenceには書いてある(nilでもいいかどうかは書いてないが、nilを渡してもとりあえず動く)。コンテクストを渡すとパフォーマンスがあがる、となっている。このCIDetectorのインスタンスを作るタイミングによるけど、CIImageを作るまえにコンテクストが決定できれば渡すことができるだろう。

ReferenceにはCIDetectorは大量のリソースを作って保持したままにするので、なるべく使い回せ、と書いてある。実装ではこのインスタンスを作るタイミングが難しくなる。

最後の引数はオプションで、今のところ
  • CIDetectorAccuracy(10.7以降)
  • CIDetectorTracking(10.8以降)
  • CIDetectorMinFeatureSize(10.8以降)
の3つのキーが定義されている。ひとつめのCIDetectorAccuracyは認識精度の指定で今のところ
  • CIDetectorAccuracyLow
  • CIDetectorAccuracyHigh
のふたつの値をとりえる。なんというアバウトな指定。まあ簡単でいい。

CIDetectorTrackingは静止画に対してではなく、動画で連続して同じ顔を追跡したいなら、YES(の値を保持したNSNumberインスタンス)を与える。Referenceにもヘッダにもあまり詳しい記述はないけど、複数の顔があったときに、それぞれに別のID(整数)が振られてそれが何フレーム分同じ顔と認識したか、と言う情報が得られるらしい。

CIDetectorMinFeatureSizeは文字通り最小のサイズを指定する。元画像の大きさの比(0〜1)で指定する。

こういうオプションの違いによる効果はあとで実際に動作させて整理する。

2.2  認識実行

認識実行はCIDetectorのインスタンスに
    CIImage             *image;
    NSArray *features = [detector featuresInImage:image];
というふうに顔が含まれた画像をCIImageにして渡す。その結果がCIFeatureのインスタンスの配列で返ってくる。CIFeatureはたんなるコンテナクラスで、
  • bounds
  • type
というふたつのインスタンス変数(プロパティ)を持っているだけである。typeはどういう認識をした結果なのかということを表して、boundsは認識結果を含む矩形をCGRectで持っている。typeにはCIFeatureTypeFaceという固定文字列だけが定義されている。顔認識の結果である、ということを示している。

このふたつだけではちょっとさみしいけど、実はCIFeatureのサブクラスでCFFaceFeatureというのがあって、顔認識の結果はこのインスタンスが返ってくる。

こいつは
  • letEyePosition
  • rightEyePosition
  • mouthPosition
  • trackingID
  • trackingFrameCount
のプロパティを持っている。それぞれ名前の通りで、実際に意味のある結果が得られているかどうかは、たとえばhasLeftEyePsoitionというプロパティがあってそれがYESだったらleftEyePositionに意味がある、ということになっている。××PositionのプロパティはCGPointで、trackingIDとtrackingFrameCountはint(NSIntegerではなく! まったくもって一貫性がないなあ)で保持している。

これらのプロパティについてはあとで実際の動作をまとめる。

この他にCIDetectorはfeaturesInImage:options:というメソッドも持っているが、画像がどっち向きなのか(縦なのか横なのかなど)を指定できるオプションを持っているだけである。iOSや、デジカメ画像を解析するときには意味があるけど、OS XでFaceTimeカメラを使う限りは関係ない。
nice!(0)  コメント(0)  トラックバック(0) 

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

献立07/27献立07/28 ブログトップ

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。