EDITは、フロントカメラの画像に役立つこのコードを見つけましたhttp://blog.logichigh.com/2008/06/05/uiimage-fix/
他の人が同様の問題を抱えていて、私を助けてくれることを願っています. まだ解決策を見つけていません。(少し長く見えるかもしれませんが、ヘルパー コードの束にすぎません)
カメラから取得した画像 (前面と背面) とギャラリーからの画像に iOS 顔検出器を使用しています (UIImagePicker
カメラによる画像キャプチャとギャラリーからの画像選択の両方に avfoundation を使用していません)。 squarecam のデモのように写真を撮る)
私は検出のための座標を本当に台無しにしているので(もしあれば)、顔の境界を取得するための短いデバッグメソッドと、それらの上に正方形を描くユーティリティを書きました。検出器がどの方向を向いているかを確認したかったのです。仕事をしていました:
#define RECTBOX(R) [NSValue valueWithCGRect:R]
- (NSArray *)detectFaces:(UIImage *)inputimage
{
_detector = \[CIDetector detectorOfType:CIDetectorTypeFace context:nil options:\[NSDictionary dictionaryWithObject:CIDetectorAccuracyLow forKey:CIDetectorAccuracy\]\];
NSNumber *orientation = \[NSNumber numberWithInt:\[inputimage imageOrientation\]\]; // i also saw code where they add +1 to the orientation
NSDictionary *imageOptions = \[NSDictionary dictionaryWithObject:orientation forKey:CIDetectorImageOrientation\];
CIImage* ciimage = \[CIImage imageWithCGImage:inputimage.CGImage options:imageOptions\];
// try like this first
// NSArray* features = \[self.detector featuresInImage:ciimage options:imageOptions\];
// if not working go on to this (trying all orientations)
NSArray* features;
int exif;
// ios face detector. trying all of the orientations
for (exif = 1; exif <= 8 ; exif++)
{
NSNumber *orientation = \[NSNumber numberWithInt:exif\];
NSDictionary *imageOptions = \[NSDictionary dictionaryWithObject:orientation forKey:CIDetectorImageOrientation\];
NSTimeInterval start = \[NSDate timeIntervalSinceReferenceDate\];
features = \[self.detector featuresInImage:ciimage options:imageOptions\];
if (features.count > 0)
{
NSString *str = \[NSString stringWithFormat:@"found faces using exif %d",exif\];
\[faceDetection log:str\];
break;
}
NSTimeInterval duration = \[NSDate timeIntervalSinceReferenceDate\] - start;
NSLog(@"faceDetection: facedetection total runtime is %f s",duration);
}
if (features.count > 0)
{
[faceDetection log:@"-I- Found faces with ios face detector"];
for(CIFaceFeature *feature in features)
{
CGRect rect = feature.bounds;
CGRect r = CGRectMake(rect.origin.x,inputimage.size.height - rect.origin.y - rect.size.height,rect.size.width,rect.size.height);
[returnArray addObject:RECTBOX(r)];
}
return returnArray;
} else {
// no faces from iOS face detector. try OpenCV detector
}
[1]
たくさんの異なる写真を試した後、顔検出器の向きがカメラ画像のプロパティと一致していないことに気付きました。uiimage の向きが 3 (imageOrienation のクエリ) である正面向きのカメラからたくさんの写真を撮りましたが、顔検出器はその設定の顔を見つけられませんでした。すべての exif の可能性を調べたところ、顔検出器は最終的に顔を検出していましたが、向きはすべて一緒でした。
![1]: http://i.stack.imgur.com/D7bkZ.jpg
どうすればこれを解決できますか? 私のコードに間違いはありますか?
私が抱えていた別の問題 (ただし、顔検出器と密接に関連している) は、顔検出器が顔を拾うときに、「間違った」向き (主に正面向きのカメラで発生します) の場合、UIImage
最初に使用されたものは uiiimageview に正しく表示されますが、正方形のオーバーレイを描画します (アプリでopencv を使用しているUIImage
ため、opencv でオーバーレイを描画するために cvmat に変換することにしました) 画像全体が 90 度回転します (UIImage
最初に表示された i ではなく、cvmat 画像のみ)
ここで考えられる理由は、顔検出器が、UIimage から opencv mat への変換が使用しているバッファ (コンテキスト?) をいじっているということです。これらのバッファを分離するにはどうすればよいですか?
uiimage を cvmat に変換するコードは (UIImage
誰かが作成した「有名な」カテゴリから):
-(cv::Mat)CVMat
{
CGColorSpaceRef colorSpace = CGImageGetColorSpace(self.CGImage);
CGFloat cols = self.size.width;
CGFloat rows = self.size.height;
cv::Mat cvMat(rows, cols, CV_8UC4); // 8 bits per component, 4 channels
CGContextRef contextRef = CGBitmapContextCreate(cvMat.data, // Pointer to backing data
cols, // Width of bitmap
rows, // Height of bitmap
8, // Bits per component
cvMat.step[0], // Bytes per row
colorSpace, // Colorspace
kCGImageAlphaNoneSkipLast |
kCGBitmapByteOrderDefault); // Bitmap info flags
CGContextDrawImage(contextRef, CGRectMake(0, 0, cols, rows), self.CGImage);
CGContextRelease(contextRef);
return cvMat;
}
- (id)initWithCVMat:(const cv::Mat&)cvMat
{
NSData *data = [NSData dataWithBytes:cvMat.data length:cvMat.elemSize() * cvMat.total()];
CGColorSpaceRef colorSpace;
if (cvMat.elemSize() == 1)
{
colorSpace = CGColorSpaceCreateDeviceGray();
}
else
{
colorSpace = CGColorSpaceCreateDeviceRGB();
}
CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef)data);
CGImageRef imageRef = CGImageCreate(cvMat.cols, // Width
cvMat.rows, // Height
8, // Bits per component
8 * cvMat.elemSize(), // Bits per pixel
cvMat.step[0], // Bytes per row
colorSpace, // Colorspace
kCGImageAlphaNone | kCGBitmapByteOrderDefault, // Bitmap info flags
provider, // CGDataProviderRef
NULL, // Decode
false, // Should interpolate
kCGRenderingIntentDefault); // Intent
self = [self initWithCGImage:imageRef];
CGImageRelease(imageRef);
CGDataProviderRelease(provider);
CGColorSpaceRelease(colorSpace);
return self;
}
-(cv::Mat)CVRgbMat
{
cv::Mat tmpimage = self.CVMat;
cv::Mat image;
cvtColor(tmpimage, image, cv::COLOR_BGRA2BGR);
return image;
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)img editingInfo:(NSDictionary *)editInfo {
self.prevImage = img;
// self.previewView.image = img;
NSArray *arr = [[faceDetection sharedFaceDetector] detectFaces:img];
for (id r in arr)
{
CGRect rect = RECTUNBOX(r);
//self.previewView.image = img;
self.previewView.image = [utils drawSquareOnImage:img square:rect];
}
[self.imgPicker dismissModalViewControllerAnimated:YES];
return;
}