Core Imageの顔認識をOS Xで - その2 [OpenCV関係]
昨日Core Imageフレームワークの顔認識の基本的な使い方をまとめた。今日はiMacやMacBook ProにビルトインされたFaceTimeカメラを読み込むためにAV Foundationフレームワークを使いやり方をまとめる。以前やったQTKit Captureに良く似ている。
QTKit CaptureのあたまのQTの文字をAVにするだけで、だいたい動く。
AVSessionが前代のデータの流れを制御して、AVCaptureDeviceInputが入力でAVCaptureDeviceがデバイスそのもの、AVCaptureVideoDataOutputが外にデータを持ち出すためのクラスで、実際のハード(たとえばFaceTimeカメラ)に対応するAVCaptureDeviceを作ってAVCaptureDeviceInputにつないで、そのAVCaptureDeviceInputをAVSessionに入力として渡す。AVCaptureVideoDataOutputもAVSessionに出力として渡してAVSessionにstartRunningメッセージを投げると、AVCaptureVideoDataOutputからデータがdelegateに渡される、というしくみ。
画像の場合、AVMediaTypeVideoかAVMediaTypeMuxedを選ぶことになる。FaceTimeカメラはAVMediaTypeVideoに分類されている(AVMediaTypeMuxedは昔は1394経由のDVストリームぐらいだったけど、DisplayPortやHDMIなんかを受けたときもこれになるのかな。今のMacはターゲットディスプレイモード以外では受け取れないのかな)。
使える入力デバイスは
入力デバイスが決まればそれで
ところで、セッションが特定の入力デバイスや出力オブジェクトを拒否する場合があるらしい。これはセッションに
入力画像のデータはCMSampleBufferRefに入っている。ちなみにQTKit CaptureではCVImageBufferRefだった。どうちがうかというとほとんど違わない。CMSampleBufferRefはCore Mediaのオブジェクトで、CVImageBufferRefはCore Videoになっている。QTKit Captureは画像が中心だったけどAV Foundationではテキストなんかも受けられるようにしたのでCore Videoによく似たCore Mediaを作ってそれを使うようにしたんだろう、おそらく。
3 FaceTimeカメラをAV Foundationで読む
ついでにAV FoundationでFaceTimeカメラの画像を読み込む方法をまとめておく。AV FoundationフレームワークはむかしやったQTKit Captureとまったく同じ思想で作られている。なんでわざわざ別にしたかと言うとQTKit Captureは名前の通りQuickTimeがベースになっていて、iOSではQuickTimeが存在しないからである。QTKit CaptureのあたまのQTの文字をAVにするだけで、だいたい動く。
AVSessionが前代のデータの流れを制御して、AVCaptureDeviceInputが入力でAVCaptureDeviceがデバイスそのもの、AVCaptureVideoDataOutputが外にデータを持ち出すためのクラスで、実際のハード(たとえばFaceTimeカメラ)に対応するAVCaptureDeviceを作ってAVCaptureDeviceInputにつないで、そのAVCaptureDeviceInputをAVSessionに入力として渡す。AVCaptureVideoDataOutputもAVSessionに出力として渡してAVSessionにstartRunningメッセージを投げると、AVCaptureVideoDataOutputからデータがdelegateに渡される、というしくみ。
3.1 入力デバイス用オブジェクト
入力に使えるハードウェアデバイスはメディアタイプごとに分類されている。メディアタイプは- AVMediaTypeVideo
- AVMediaTypeAudio
- AVMediaTypeText
- AVMediaTypeClosedCaption
- AVMediaTypeSubtitle
- AVMediaTypeTimecode
- AVMediaTypeTimedMetadata
- AVMediaTypeMuxed
画像の場合、AVMediaTypeVideoかAVMediaTypeMuxedを選ぶことになる。FaceTimeカメラはAVMediaTypeVideoに分類されている(AVMediaTypeMuxedは昔は1394経由のDVストリームぐらいだったけど、DisplayPortやHDMIなんかを受けたときもこれになるのかな。今のMacはターゲットディスプレイモード以外では受け取れないのかな)。
使える入力デバイスは
NSArray *devices = [AVCaptureDevice devices]; for (id device in devices) NSLog(@"%@", [device localizedName]);で、そのとき実際に繋がっているすべてのデバイスのdescriptionを表示できる。わかりやすいものとそうでないものがあって、ハードに依存する。実際のアプリではこのdescriptionをNSMenuItemに表示させてユーザに選択させる、という手はずになるだろう。もうすこし限定する形でdevicesWithMediaType:メソッドや、決めうちするdefaultDeviceWithMediaType:メソッドもある。
入力デバイスが決まればそれで
AVCaptureDeviceInput *deviceInput; deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];AVCaptureDeviceInputのインスタンスを作る。
3.2 出力用オブジェクト
同じように出力用にAVCaptureVideoDataOutput* dataOutput = [[AVCaptureVideoDataOutput alloc] init]; [dataOutput setSampleBufferDelegate:self queue:dispatch_get_main_queue()];とする。これはAVCaptureVideoDataOutputのインスタンスを作って、データを受け取るdelegate(上の場合はself)を指定する。QT Kit Captureと違ってGCDのどのディスパッチキューを使うか指定することができる。これでdelegateが呼ばれるスレッドを変更することができる。
3.3 AVCaptuireSessionとの接続
これであとはsession = [[AVCaptureSession alloc] init]; [session addInput:deviceInput]; [session addOutput:dataOutput];としてセッションのインスタンスを作って
[session startRunning];とやればいい。
ところで、セッションが特定の入力デバイスや出力オブジェクトを拒否する場合があるらしい。これはセッションに
if ([session canAddInput:deviceInput]) [session addInput:deviceInput]; if ([session canAddOutput:dataOutput]) [session addOutput:dataOutput];というふうに問い合わせてから接続しろ、とReferenceには書いてある。どういう場合に拒否されるのかはよくわからない。
3.4 データの受け取り
データを受け取るにはdelegateに- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection;というメソッドを実装すればいい。このメソッドはAVCaptureVideoDataOutputSampleBufferDelegateプロトコルで定義されていて、delegateはこのプロトコルをconformするのがいい。
入力画像のデータはCMSampleBufferRefに入っている。ちなみにQTKit CaptureではCVImageBufferRefだった。どうちがうかというとほとんど違わない。CMSampleBufferRefはCore Mediaのオブジェクトで、CVImageBufferRefはCore Videoになっている。QTKit Captureは画像が中心だったけどAV Foundationではテキストなんかも受けられるようにしたのでCore Videoによく似たCore Mediaを作ってそれを使うようにしたんだろう、おそらく。
2013-07-29 05:37
nice!(0)
コメント(0)
トラックバック(0)
コメント 0