iOSの顔検出を画像で表示する

要は、顔検出部分に画像を配置するだけなんですが、ちょっと引っかかったのでメモ。

参考:顔認識とCore Imageフィルタのコラボ

この手のサンプルはたくさんあるけど、大体がCIFilter使ってるパターンが多いので、その部分をUIImageで描画すればいいんじゃないかってメドをつけたんだけど、なかなかうまく行かなかった。大まかにいうと下記の点。

1.UIImageで描画する際に、y方向の座標が逆になる。

通常、左上が(0,0)になると思ってたんだけど、y方向は画像の左下が(0,0)になっているようで、その点を描画時に補正。

2.カメラ/カメラロールの画像の向き

iPhoneで撮影されたデータは、UIImage.imageOrientationに向きを持っている。

参考:まみったー iPhone の向きと UIImageOrientation メモ

で、この向きが縦位置の時にうまくいかなかったので、色々調べたら、一度、UIImageで書き直してしまえば問題ないらしい。

これはちょっと勘違いがありましたので、詳しくはこちらを。

参考:iPhoneカメラで撮影した画像のUIImageからCGImageを取り出すと90度傾く問題の解決法

これで基本的には問題ないようです。

一応、該当部分のソースはこんな感じです。

- (IBAction)checkFace2:(UIBarButtonItem *)sender {
    //UIImage.imageOrientationの値によって動作が異なるので、元画像を再描画しておく。
    UIImage *orgImage =[UIImage imageWithCGImage:_originalImage.CGImage];
    
    UIGraphicsBeginImageContext(orgImage.size);
    [orgImage drawInRect:CGRectMake(0, 0, orgImage.size.width, orgImage.size.height)];
    orgImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    
    CIImage *coreImage = [CIImage imageWithCGImage:orgImage.CGImage];
    
    //オプション辞書作成(顔検出の精度/高精度)
    NSDictionary *options = [NSDictionary
                             dictionaryWithObject:CIDetectorAccuracyHigh
                             forKey:CIDetectorAccuracy];
    
    //CIDetectorを生成(画像解析/現在は顔検出のみ指定可能)
    CIDetector *faceDetector = [CIDetector
                                detectorOfType:CIDetectorTypeFace
                                context:_imageContext
                                options:options];
    
    //顔検出(位置情報を配列で返す)
    NSArray *faces = [faceDetector featuresInImage:coreImage
                                           options:nil];
    //顔部分に画像を載せる
    for(CIFaceFeature *face in faces){
        NSLog(@"---check");
        coreImage = [CIFilter filterWithName:@"CISourceOverCompositing"
                               keysAndValues:kCIInputImageKey, [self makeIconForFace:face],
                     kCIInputBackgroundImageKey, coreImage, nil].outputImage;
    }
       
    CGImageRef cgImage = [_imageContext createCGImage:coreImage fromRect:[coreImage extent]];
    
    //image化するときの向きは、オリジナルに合わせないと横になる。何で?
    _myImageView.image = [UIImage imageWithCGImage:cgImage scale:1.0f orientation:_myImageView.image.imageOrientation];
    CGImageRelease(cgImage);

}
//顔にアイコンを描画
- (CIImage*)makeIconForFace:(CIFaceFeature*)face{
    
    // アイコンのUIImageを作成
    UIImage *iconImage = [UIImage imageNamed:@"icon_250_reasonably_small.jpg"];
    
    
    // 顔のサイズ情報を取得
    CGRect faceRect = [face bounds];
    
    int w = _originalImage.size.width;
    int h = _originalImage.size.height;
    int cx = faceRect.origin.x;
    int cy = faceRect.origin.y;
    int icon_w = faceRect.size.width;
    int icon_h = faceRect.size.height;
    
    //アイコンを顔サイズで描画(yは左下原点になるようなので補正)
    UIGraphicsBeginImageContext(CGSizeMake(w, h));
    [iconImage drawInRect:CGRectMake(cx, h - (cy + icon_h), icon_w, icon_h)];
    UIImage *iconImage_after = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    CIImage *image = [CIImage imageWithCGImage:iconImage_after.CGImage];
    
    return image;
}

テスト結果はこんな感じ。

iPhone実機でのテスト結果。
iPhone実機でのテスト結果。

テスト環境:iPhone5+Xcode 5.1.1

 

「iOSの顔検出を画像で表示する」への1件のフィードバック

コメントは停止中です。