4

で描画するために、CGPointから返された結果を変換する方法を理解しようとしています。以前は、物事を簡単にするために画像を0回転に正規化していましたが、横向きモードで保持されたデバイスで撮影された画像では問題が発生します。CIFaceFeatureCALayer

私はこれにしばらく取り組んできましたが成功せず、タスクの理解が間違っているのか、アプローチが間違っているのか、あるいはその両方なのかわかりません。これが私が正しいと思うことです:

カメラからの元の画像

CIDetector featuresInImage:options:メソッドのドキュメントによると

A dictionary that specifies the orientation of the image. The detection is 
adjusted to account for the image orientation but the coordinates in the 
returned feature objects are based on those of the image.

UIImageViewに表示される画像

以下のコードでは、UIImageViewをオーバーレイするCAShapeレイヤーを介してCGPointを描画するために、CGPointを回転させようとしています。

私が行っていること(...または私が行っていると思う...)は、左目のCGPointをビューの中心に移動し、90度回転してから、ポイントを元の位置に戻すことです。これは正しくありませんが、どこが間違っているのかわかりません。それは私のアプローチが間違っているのですか、それとも私がそれを実装している方法ですか?

#define DEGREES_TO_RADIANS(angle) ((angle) / 180.0 * M_PI)

--leftEyePositionはCGPointです

CGAffineTransform  transRot = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(90));

float x = self.center.x;
float y = self.center.y;
CGAffineTransform tCenter = CGAffineTransformMakeTranslation(-x, -y);
CGAffineTransform tOffset = CGAffineTransformMakeTranslation(x, y);

leftEyePosition = CGPointApplyAffineTransform(leftEyePosition, tCenter);
leftEyePosition = CGPointApplyAffineTransform(leftEyePosition, transRot);
leftEyePosition = CGPointApplyAffineTransform(leftEyePosition, tOffset);

この投稿から:https : //stackoverflow.com/a/14491293/840992、imageOrientationに基づいて回転を行う必要があります

オリエンテーション

Apple / UIImage.imageOrientation Jpeg / File kCGImagePropertyOrientation

UIImageOrientationUp    = 0  =  Landscape left  = 1
UIImageOrientationDown  = 1  =  Landscape right = 3
UIImageOrientationLeft  = 2  =  Portrait  down  = 8
UIImageOrientationRight = 3  =  Portrait  up    = 6

メッセージは2013年2月1日午後4時9分にskinnyTODによって編集されました

4

2 に答える 2

6

私はまったく同じ問題を理解する必要があります。Apple のサンプル「SquareCam」はビデオ出力で直接動作しますが、UIImage からの結果が必要です。そこで、いくつかの変換メソッドを使用して CIFaceFeature クラスを拡張し、UIImage とその UIImageView (または UIView の CALayer) に関して正しいポイントの位置と境界を取得しました。完全な実装は、 https ://gist.github.com/laoyang/5747004 に投稿されています。直接使用できます。

以下は、CIFaceFeature からのポイントの最も基本的な変換です。返された CGPoint は、画像の方向に基づいて変換されます。

- (CGPoint) pointForImage:(UIImage*) image fromPoint:(CGPoint) originalPoint {

    CGFloat imageWidth = image.size.width;
    CGFloat imageHeight = image.size.height;

    CGPoint convertedPoint;

    switch (image.imageOrientation) {
        case UIImageOrientationUp:
            convertedPoint.x = originalPoint.x;
            convertedPoint.y = imageHeight - originalPoint.y;
            break;
        case UIImageOrientationDown:
            convertedPoint.x = imageWidth - originalPoint.x;
            convertedPoint.y = originalPoint.y;
            break;
        case UIImageOrientationLeft:
            convertedPoint.x = imageWidth - originalPoint.y;
            convertedPoint.y = imageHeight - originalPoint.x;
            break;
        case UIImageOrientationRight:
            convertedPoint.x = originalPoint.y;
            convertedPoint.y = originalPoint.x;
            break;
        case UIImageOrientationUpMirrored:
            convertedPoint.x = imageWidth - originalPoint.x;
            convertedPoint.y = imageHeight - originalPoint.y;
            break;
        case UIImageOrientationDownMirrored:
            convertedPoint.x = originalPoint.x;
            convertedPoint.y = originalPoint.y;
            break;
        case UIImageOrientationLeftMirrored:
            convertedPoint.x = imageWidth - originalPoint.y;
            convertedPoint.y = originalPoint.x;
            break;
        case UIImageOrientationRightMirrored:
            convertedPoint.x = originalPoint.y;
            convertedPoint.y = imageHeight - originalPoint.x;
            break;
        default:
            break;
    }
    return convertedPoint;
}

上記の変換に基づくカテゴリ メソッドは次のとおりです。

// Get converted features with respect to the imageOrientation property
- (CGPoint) leftEyePositionForImage:(UIImage *)image;
- (CGPoint) rightEyePositionForImage:(UIImage *)image;
- (CGPoint) mouthPositionForImage:(UIImage *)image;
- (CGRect) boundsForImage:(UIImage *)image;

// Get normalized features (0-1) with respect to the imageOrientation property
- (CGPoint) normalizedLeftEyePositionForImage:(UIImage *)image;
- (CGPoint) normalizedRightEyePositionForImage:(UIImage *)image;
- (CGPoint) normalizedMouthPositionForImage:(UIImage *)image;
- (CGRect) normalizedBoundsForImage:(UIImage *)image;

// Get feature location inside of a given UIView size with respect to the imageOrientation property
- (CGPoint) leftEyePositionForImage:(UIImage *)image inView:(CGSize)viewSize;
- (CGPoint) rightEyePositionForImage:(UIImage *)image inView:(CGSize)viewSize;
- (CGPoint) mouthPositionForImage:(UIImage *)image inView:(CGSize)viewSize;
- (CGRect) boundsForImage:(UIImage *)image inView:(CGSize)viewSize;

(もう1つ注意する必要があるのは、UIImageの向きから顔の特徴を抽出するときに正しいEXIFの向きを指定することです。かなり混乱しています...これが私がしたことです:

int exifOrientation;
switch (self.image.imageOrientation) {
    case UIImageOrientationUp:
        exifOrientation = 1;
        break;
    case UIImageOrientationDown:
        exifOrientation = 3;
        break;
    case UIImageOrientationLeft:
        exifOrientation = 8;
        break;
    case UIImageOrientationRight:
        exifOrientation = 6;
        break;
    case UIImageOrientationUpMirrored:
        exifOrientation = 2;
        break;
    case UIImageOrientationDownMirrored:
        exifOrientation = 4;
        break;
    case UIImageOrientationLeftMirrored:
        exifOrientation = 5;
        break;
    case UIImageOrientationRightMirrored:
        exifOrientation = 7;
        break;
    default:
        break;
}

NSDictionary *detectorOptions = @{ CIDetectorAccuracy : CIDetectorAccuracyHigh };
CIDetector *faceDetector = [CIDetector detectorOfType:CIDetectorTypeFace context:nil options:detectorOptions];

NSArray *features = [faceDetector featuresInImage:[CIImage imageWithCGImage:self.image.CGImage]
                                          options:@{CIDetectorImageOrientation:[NSNumber numberWithInt:exifOrientation]}];

)

于 2013-06-10T07:28:45.900 に答える
0

画像の水平中心軸について、見つかった顔の座標を反転するために必要なものだと思います

この変換を試すことができますか:

CGAffineTransform transform = CGAffineTransformIdentity;
transform = CGAffineTransformTranslate(transform, 0.0f, image.size.height);
transform = CGAffineTransformScale(transform, 1.0f, -1.0f);
[path applyTransform:transform];

この変換は、顔を見つける前に image.imageOrientation を 0 に設定した場合にのみ機能します。

于 2013-02-01T20:54:59.923 に答える