I am building an application which combines ARKit with CoreML. I am passing frames to the VNImageRequestHandler
using the following lines:
// 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];
Note the requestOptions
. It should contain the VNImageOptionCameraIntrinsics
field which passes the camera intrinsics to CoreML.
Before using ARKit I was using a CMSampleBufferRef
to get images from the camera. The instrinsics could be retrieved and set using the following:
CFTypeRef cameraIntrinsicData = CMGetAttachment(sampleBuffer, kCMSampleBufferAttachmentKey_CameraIntrinsicMatrix, nil);
requestOptions[VNImageOptionCameraIntrinsics] = (__bridge id)(cameraIntrinsicData);
However, I am using an ARFrame
now, but I still want to set the correct intrinsics since the pixelBuffer
is rotated.
Looking at the docs:
https://developer.apple.com/documentation/vision/vnimageoption?language=objc
https://developer.apple.com/documentation/arkit/arcamera/2875730-intrinsics?language=objc
We can see that ARCamera
provides intrinsics as well, however, how do I set this value in the requestOptions
properly?
So far it should be something like this:
ARCamera *camera = _cameraPreview.session.currentFrame.camera;
NSMutableDictionary<VNImageOption, id> *requestOptions = [NSMutableDictionary dictionary];
// How to put camera.intrinsics here?
requestOptions[VNImageOptionCameraIntrinsics] = camera.intrinsics;
As Giovanni mentioned in the comments, converting UIDeviceOrientation
to CGImagePropertyOrientation
avoids the need to use VNImageOptionCameraIntrinsics
:
+(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;
}
- (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];
}