从ARCamera设置VNImageOptionCameraIntrinsics

时间:2018-09-02 20:20:03

标签: ios objective-c arkit coreml

我正在构建一个将ARKit与CoreML相结合的应用程序。我使用以下几行将帧传递到VNImageRequestHandler

// the frame of the current Scene
CVPixelBufferRef pixelBuffer = _cameraPreview.session.currentFrame.capturedImage;

NSMutableDictionary<VNImageOption, id> *requestOptions = [NSMutableDictionary dictionary];
VNImageRequestHandler *handler = [[VNImageRequestHandler alloc] initWithCVPixelBuffer:pixelBuffer options:requestOptions];

请注意requestOptions。它应该包含VNImageOptionCameraIntrinsics字段,该字段将相机内部函数传递给CoreML。

在使用ARKit之前,我曾使用CMSampleBufferRef从相机中获取图像。可以使用以下方法检索和设置内部变量:

CFTypeRef cameraIntrinsicData = CMGetAttachment(sampleBuffer, kCMSampleBufferAttachmentKey_CameraIntrinsicMatrix, nil);
requestOptions[VNImageOptionCameraIntrinsics] = (__bridge id)(cameraIntrinsicData);

但是,我现在正在使用ARFrame,但是由于pixelBuffer被旋转,我仍然想设置正确的内在函数。

查看文档:

https://developer.apple.com/documentation/vision/vnimageoption?language=objc

https://developer.apple.com/documentation/arkit/arcamera/2875730-intrinsics?language=objc

我们可以看到ARCamera也提供了内在函数,但是,如何在requestOptions中正确设置此值?

到目前为止,应该是这样的:

ARCamera *camera = _cameraPreview.session.currentFrame.camera;
NSMutableDictionary<VNImageOption, id> *requestOptions = [NSMutableDictionary dictionary];
// How to put camera.intrinsics here?
requestOptions[VNImageOptionCameraIntrinsics] = camera.intrinsics;

1 个答案:

答案 0 :(得分:1)

如评论中的Giovanni所述,将UIDeviceOrientation转换为CGImagePropertyOrientation可以避免使用VNImageOptionCameraIntrinsics

Utils.m

+(CGImagePropertyOrientation) getOrientation {
    CGImagePropertyOrientation orientation;
    UIDeviceOrientation deviceOrientation = [[UIDevice currentDevice] orientation];
    switch (deviceOrientation) {
        case UIDeviceOrientationPortrait:
            orientation = kCGImagePropertyOrientationRight;
            break;
        case UIDeviceOrientationPortraitUpsideDown:
            orientation = kCGImagePropertyOrientationLeft;
            break;
        case UIDeviceOrientationLandscapeLeft:
            orientation = kCGImagePropertyOrientationUp;
            break;
        case UIDeviceOrientationLandscapeRight:
            orientation = kCGImagePropertyOrientationDown;
            break;
        default:
            orientation = kCGImagePropertyOrientationRight;
            break;
    }
    return orientation;
}

ViewController.mm

- (void)captureOutput {
    ARFrame *frame = self.cameraPreview.session.currentFrame;
    CVPixelBufferRef pixelBuffer = frame.capturedImage;

    CGImagePropertyOrientation deviceOrientation = [Utils getOrientation];
    NSMutableDictionary<VNImageOption, id> *requestOptions = [NSMutableDictionary dictionary];

    VNImageRequestHandler *handler = [[VNImageRequestHandler alloc] initWithCVPixelBuffer:pixelBuffer orientation:deviceOrientation options:requestOptions];

    [handler performRequests:@[[self request]] error:nil];
}