要は、顔検出部分に画像を配置するだけなんですが、ちょっと引っかかったのでメモ。
参考:顔認識と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;
}
テスト結果はこんな感じ。
テスト環境:iPhone5+Xcode 5.1.1