CIDetector の使い方

とりあえず使うだけなら CIDetector オブジェクトを作って画像を渡せば結果が返ってくる。簡単!


まず、CIDetector オブジェクトの作成は以下のクラスメソッドで

+ (CIDetector *)detectorOfType:(NSString *)type context:(CIContext *)context options:(NSDictionary *)options

最初の detectorType では何を認識するのか指定する。けど、今現在は顔認識(CIDetectorTypeFace)しかできません。
次にオプションの設定。これも今現在は精度(CIDetectorAccuracy)しか設定できない。しかも指定できるのは CIDetectorAccuracyLow と CIDetectorAccuracyHigh の二つだけ!
コードにするとこんな感じ。

NSDictionary *detectorOptions = [[NSDictionary alloc] initWithObjectsAndKeys:CIDetectorAccuracyLow, CIDetectorAccuracy, nil];
CIDetector *faceDetector = [CIDetector detectorOfType:CIDetectorTypeFace context:nil options:detectorOptions];


次に使用方法。これも以下のメソッドで一発!

-(NSArray *)featuresInImage:(CIImage *)image options:(NSDictionary *)options

これで返り値の NSArray に見つけた顔の分だけ CIFeature(CIFaceFeature) オブジェクトが返ってきます。


引数ですが、最初の CIImage は顔認識をしたい画像。
次に options の NSDictionary は CIImage の画像(データ)の向き(CIDetectorImageOrientation)を指定します。
この画像(データ)の向きと値の関係は以下の通り。

enum {
    PHOTOS_EXIF_0ROW_TOP_0COL_LEFT	    = 1, //   1  =  0th row is at the top, and 0th column is on the left (THE DEFAULT).
    PHOTOS_EXIF_0ROW_TOP_0COL_RIGHT	    = 2, //   2  =  0th row is at the top, and 0th column is on the right.  
    PHOTOS_EXIF_0ROW_BOTTOM_0COL_RIGHT      = 3, //   3  =  0th row is at the bottom, and 0th column is on the right.  
    PHOTOS_EXIF_0ROW_BOTTOM_0COL_LEFT       = 4, //   4  =  0th row is at the bottom, and 0th column is on the left.  
    PHOTOS_EXIF_0ROW_LEFT_0COL_TOP          = 5, //   5  =  0th row is on the left, and 0th column is the top.  
    PHOTOS_EXIF_0ROW_RIGHT_0COL_TOP         = 6, //   6  =  0th row is on the right, and 0th column is the top.  
    PHOTOS_EXIF_0ROW_RIGHT_0COL_BOTTOM      = 7, //   7  =  0th row is on the right, and 0th column is the bottom.  
    PHOTOS_EXIF_0ROW_LEFT_0COL_BOTTOM       = 8  //   8  =  0th row is on the left, and 0th column is the bottom.  
};

これは Apple のサンプルに入っていたコードで、これを使って iPhone のカメラでキャプチャした画像に顔認識かけるにはこんな感じで指定ができます。

UIDeviceOrientation curDeviceOrientation = [[UIDevice currentDevice] orientation];
switch (curDeviceOrientation) {
    case UIDeviceOrientationPortraitUpsideDown:  // Device oriented vertically, home button on the top
        exifOrientation = PHOTOS_EXIF_0ROW_LEFT_0COL_BOTTOM;
        break;
    case UIDeviceOrientationLandscapeLeft:       // Device oriented horizontally, home button on the right
        exifOrientation = PHOTOS_EXIF_0ROW_TOP_0COL_LEFT;
        break;
    case UIDeviceOrientationLandscapeRight:      // Device oriented horizontally, home button on the left
        exifOrientation = PHOTOS_EXIF_0ROW_BOTTOM_0COL_RIGHT;
        break;
    case UIDeviceOrientationPortrait:            // Device oriented vertically, home button on the bottom
    default:
        exifOrientation = PHOTOS_EXIF_0ROW_RIGHT_0COL_TOP;
        break;
}
imageOptions = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:exifOrientation] forKey:CIDetectorImageOrientation];
NSArray *features = [faceDetector featuresInImage:ciImage options:imageOptions];

これで iPhone が縦でも横でもちゃんとキャプチャした画像を顔認識できます。


最後に、返り値の配列に入っている CIFeature は以下のプロパティを持っています。

  • type
  • bounds

type は何が認識されたかを示しますが、今は顔認識のみの対応なので CIFeatureTypeFace しか返ってこないはずです。
bounds はその認識されたものの CGRect です。顔認識の場合は顔として認識された範囲になります。
そして、顔認識の場合の CIFaceFeature オブジェクトは以下のプロパティを持っています。

  • type
  • bounds
  • hasLeftEyePosition
  • hasMouthPosition\
  • hasRightEyePosition
  • leftEyePosition
  • mouthPosition
  • rightEyePosition

それぞれのプロパティは読んだままの意味です。
has〜で各プロパティの値の有無を確認、その後それぞれの箇所の位置を CGPoint でゲットするようにします。
この時ゲットした座標は、渡した CIImage の座標系と同じものになります。


以上で、CIDetector の超簡単な使い方のメモは終了。
自分としては、面倒なのはどちらかと言うと CIDetector の使い方よりも、その前後の座標系の変換じゃないのかな?と感じる。
それ位 CIDetecotr を”使う”のは簡単。