iOS - AVCaptureDevice - 自动对焦和相机捕捉曝光

iOS - AVCaptureDevice - Autofocus & Exposure with camera capture

我一直在使用 AVCaptureDevice 实现自定义相机,这需要自动对焦和曝光才能很好地工作。我正在使用以下代码进行相机初始化

- (void) initializeCamera {

    AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];

    if(status == AVAuthorizationStatusAuthorized) { // authorized
        [self.captureVideoPreviewLayer removeFromSuperlayer];
        self.captureSession = [[AVCaptureSession alloc] init];
        self.captureSession.sessionPreset = AVCaptureSessionPresetPhoto;
        [self removeDeviceObserverForFocus];
        self.captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
        [self addDeviceObserverForFocus];

        NSError *error = nil;

        [self.captureDevice lockForConfiguration:nil]; //you must lock before setting torch mode
        [self.captureDevice setSubjectAreaChangeMonitoringEnabled:YES];
        [self.captureDevice unlockForConfiguration];


        //Capture layer
        self.captureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.captureSession];
        self.captureVideoPreviewLayer.bounds = CGRectMake(0, 0, CGRectGetWidth([UIScreen mainScreen].bounds), CGRectGetHeight([UIScreen mainScreen].bounds));
        self.captureVideoPreviewLayer.position = CGPointMake(CGRectGetMidX(self.captureVideoPreviewLayer.bounds), CGRectGetMidY(self.captureVideoPreviewLayer.bounds));
        [self.captureVideoPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
        self.captureVideoPreviewLayer.connection.enabled = YES;
        [self.viewCamera.layer insertSublayer:self.captureVideoPreviewLayer atIndex:0];


        //Capture input

        self.captureInput = [AVCaptureDeviceInput deviceInputWithDevice:self.captureDevice error:&error];
        if (!self.captureInput) {
            [self capturePhoto];
        }
        else {
            if ([self.captureSession canAddInput:self.captureInput]) {
                [self.captureSession addInput:self.captureInput];
            }
        }

        self.captureOutput = [[AVCaptureStillImageOutput alloc] init];
        [self.captureOutput setOutputSettings:@{AVVideoCodecKey : AVVideoCodecJPEG}];
        [self.captureSession addOutput:self.captureOutput];

        //THIS LINE 
        [self.captureSession setSessionPreset:AVCaptureSessionPresetPhoto];

        // setup metadata capture
        AVCaptureMetadataOutput *metadataOutput = [[AVCaptureMetadataOutput alloc] init];
        CGRect visibleMetadataOutputRect = [self.captureVideoPreviewLayer metadataOutputRectOfInterestForRect:self.vwCamera.bounds];
        metadataOutput.rectOfInterest = visibleMetadataOutputRect;
        [self.captureSession addOutput:metadataOutput];

        dispatch_async(dispatch_get_main_queue(), ^{

            [self.captureSession startRunning];
        });

    }
    else if(status == AVAuthorizationStatusNotDetermined){ // not determined

        //Try for getting permission
        [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
            [self performSelectorOnMainThread:@selector(initializeCamera) withObject:nil waitUntilDone:NO];
        }];
    }

}

- (void)removeDeviceObserverForFocus {
    @try {
        while ([self.captureDevice observationInfo] != nil) {
            [self.captureDevice removeObserver:self forKeyPath:@"adjustingFocus"];
        }
    }
    @catch (NSException *exception) {
        NSLog(@"Exception");
    }
    @finally {
    }
}

- (void)addDeviceObserverForFocus {
    [self.captureDevice addObserver:self forKeyPath:@"adjustingFocus" options:NSKeyValueObservingOptionNew context:nil];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    if( [keyPath isEqualToString:@"adjustingFocus"] ){
        BOOL adjustingFocus = [ [change objectForKey:NSKeyValueChangeNewKey] isEqualToNumber:[NSNumber numberWithInt:1] ];
        if (adjustingFocus) {
            [self showFocusSquareAtPoint:self.viewCamera.center];
        }
    }
}

为了通过相机的移动来监控焦点,我正在执行以下操作..

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(avCaptureDeviceSubjectAreaDidChangeNotification:) name:AVCaptureDeviceSubjectAreaDidChangeNotification object:nil];

#pragma mark - AVCaptureDeviceSubjectAreaDidChangeNotification

-(void)avCaptureDeviceSubjectAreaDidChangeNotification:(NSNotification *)notification{
    CGPoint devicePoint = CGPointMake( 0.5, 0.5 );

    [self focusWithMode:AVCaptureFocusModeContinuousAutoFocus exposeWithMode:AVCaptureExposureModeContinuousAutoExposure atDevicePoint:devicePoint monitorSubjectAreaChange:NO];
    [self showFocusSquareAtPoint:self.vwCamera.center];

}

- (void)focusWithMode:(AVCaptureFocusMode)focusMode exposeWithMode:(AVCaptureExposureMode)exposureMode atDevicePoint:(CGPoint)point monitorSubjectAreaChange:(BOOL)monitorSubjectAreaChange
{
    dispatch_async( dispatch_get_main_queue(), ^{
        AVCaptureDevice *device = self.captureDevice;
        NSError *error = nil;
        if ( [device lockForConfiguration:&error] ) {
            // Setting (focus/exposure)PointOfInterest alone does not initiate a (focus/exposure) operation.
            // Call -set(Focus/Exposure)Mode: to apply the new point of interest.
            if ( device.isFocusPointOfInterestSupported && [device isFocusModeSupported:focusMode] ) {
                device.focusPointOfInterest = point;
                device.focusMode = focusMode;
            }

            if ( device.isExposurePointOfInterestSupported && [device isExposureModeSupported:exposureMode] ) {
                device.exposurePointOfInterest = point;
                device.exposureMode = exposureMode;
            }

            device.subjectAreaChangeMonitoringEnabled = monitorSubjectAreaChange;
            [device unlockForConfiguration];
        }
        else {
            NSLog( @"Could not lock device for configuration: %@", error );
        }
    } );
}

当我使用这个 [self.captureSession setSessionPreset:AVCaptureSessionPresetPhoto];

时一切正常

如果我将相机预设更改为其他设置,例如 AVCaptureSessionPresetHigh 自动对焦和曝光无法正常工作..

谁遇到过这种情况?

感谢您的帮助。

您是要拍照还是录制视频?因为高预设是针对视频的,曝光和聚焦的工作方式不同(我相信)。这是文档中有关不同预设的信息 - AVCaptureSessionPresets