【问题标题】:AVCaptureDevice adjustingExposure is False but captured image is darkAVCaptureDeviceadjustingExposure 为 False 但捕获的图像很暗
【发布时间】:2015-01-31 08:46:03
【问题描述】:

我正在编写的 Mac OS X 应用程序正在使用 macbook 内置的 facetime 相机拍摄照片。

在 MacBookAir3,2、MacBookPro8,2 和 MacBookPro10,2 上它运行良好,但在新的 macbook 上它会拍摄“暗”照片。我知道这是因为自动曝光,但我很难让它工作。 AVCaptureDevice adjustingExposure 设置为 NO 但拍摄的照片仍然完全黑暗。

代码:setupCamera 在应用启动期间被调用一次

-(void) setupCamera
{
    session = [[AVCaptureSession alloc] init];
    session.sessionPreset = AVCaptureSessionPresetPhoto;

    sessionInitialized = YES;

    device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

    [device lockForConfiguration:NULL];
    if ([device isExposureModeSupported:AVCaptureExposureModeContinuousAutoExposure])
        [device setExposureMode:AVCaptureExposureModeContinuousAutoExposure];

    if ([device isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus])
        [device setFocusMode:AVCaptureFocusModeContinuousAutoFocus];

    if ([device isWhiteBalanceModeSupported:AVCaptureWhiteBalanceModeContinuousAutoWhiteBalance])
        [device setWhiteBalanceMode:AVCaptureWhiteBalanceModeContinuousAutoWhiteBalance];

    [device unlockForConfiguration];


    NSError *error = nil;
    AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];
    if(error != nil) {
        // ...
    }

    if([session canAddInput:input]) {
        [session addInput:input];
    } else {
        // ...
    }

    output = [[AVCaptureStillImageOutput alloc] init];
    NSDictionary *outputSettings = @{ AVVideoCodecKey : AVVideoCodecJPEG };
    [output setOutputSettings:outputSettings];

    if([session canAddOutput:output]) {
        [session addOutput:output];
    } else {
        // ...
    }
}

...然后每次点击 UI 中的 snap 按钮都会调用 shootPhoto 函数:

-(void) shootPhoto
{
    [session startRunning];

    if([device lockForConfiguration:NULL]) {
        if ([device isExposureModeSupported:AVCaptureExposureModeContinuousAutoExposure])
            [device setExposureMode:AVCaptureExposureModeContinuousAutoExposure];

        if ([device isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus])
            [device setFocusMode:AVCaptureFocusModeContinuousAutoFocus];

        if ([device isWhiteBalanceModeSupported:AVCaptureWhiteBalanceModeContinuousAutoWhiteBalance])
            [device setWhiteBalanceMode:AVCaptureWhiteBalanceModeContinuousAutoWhiteBalance];

        [device unlockForConfiguration];
    }

    if(device.adjustingFocus == NO && device.adjustingExposure == NO && device.adjustingWhiteBalance == NO) {
        [self actuallyCapture];
    } else {
        [device addObserver:self forKeyPath:@"adjustingExposure" options:NSKeyValueObservingOptionNew context:MyAdjustingExposureObservationContext];
        [device addObserver:self forKeyPath:@"adjustingFocus" options:NSKeyValueObservingOptionNew context:MyAdjustingFocusObservationContext];
        [device addObserver:self forKeyPath:@"adjustingWhiteBalance" options:NSKeyValueObservingOptionNew context:MyAdjustingWhiteBalanceObservationContext];
    }
}

-(void) actuallyCapture
{
    if ([session isRunning] == NO)
        return;

    connection = [output connectionWithMediaType:AVMediaTypeVideo];
    [output captureStillImageAsynchronouslyFromConnection:connection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {
        // save file etc ...
    }];
}

这个想法是检查相机设备是否正在调整焦点、曝光或白平衡。如果不立即致电actuallyCapture。如果它正在调整 - 添加观察者并从 observeValueForKeyPath 调用 actuallyCapture

问题是 addObserver 调用永远不会被调用,因为设备返回所有 adjustingX==NO - 但是,捕获的照片仍然是暗的。

可能是什么原因?我在等待白平衡和曝光调整正确吗?

对我来说很难调试,因为我只拥有那些运行良好的设备。

【问题讨论】:

    标签: macos avcapturesession avcapturedevice adjustment facetime


    【解决方案1】:

    我自己设法解决了这个问题。我是这样做的:

    adjustingExposureadjustingFocusadjustingWhiteBalance设置观察者:

    [self.device addObserver:self forKeyPath:@"adjustingExposure" options:NSKeyValueObservingOptionNew context:MyAdjustingExposureObservationContext];
    [self.device addObserver:self forKeyPath:@"adjustingFocus" options:NSKeyValueObservingOptionNew context:MyAdjustingFocusObservationContext];
    [self.device addObserver:self forKeyPath:@"adjustingWhiteBalance" options:NSKeyValueObservingOptionNew context:MyAdjustingWhiteBalanceObservationContext];
    

    要捕获照片,请初始化 AVCaptureSession,但设置 1 秒延迟计时器并在触发后实际捕获:

    -(void) shootPhoto
    {
        dispatch_async(self.sessionQueue, ^{
            if([self setupCamera]) {
                self.sessionInitialized = YES;
                [self.session startRunning];
    
                self.isWaitingToCaptureImage = YES;
                dispatch_async(dispatch_get_main_queue(), ^{
                    self.captureDelayTimer = [NSTimer scheduledTimerWithTimeInterval:1.0
                                                                              target:self
                                                                            selector:@selector(actuallyCapture)
                                                                            userInfo:nil
                                                                             repeats:NO];
                });
            }
        });
    }
    

    observeValueForKeyPath:ofObject:change:context 中检查是否所有三个调整都已完成,如果已完成 - 取消上面设置的计时器并拍摄照片:

    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
    {
        if(!self.sessionInitialized || !self.isWaitingToCaptureImage) {
            [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
            return;
        }
    
        if (context != MyAdjustingExposureObservationContext && context != MyAdjustingFocusObservationContext && context != MyAdjustingWhiteBalanceObservationContext) {
            [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
            return;
        } else {
            if (self.device.adjustingExposure || self.device.adjustingFocus || self.device.adjustingWhiteBalance) {
                NSLog(@"not ready to capture yet");
                return;
            } else {
                NSLog(@"ready to capture");
                if (self.captureDelayTimer && self.captureDelayTimer.isValid) {
                    [self.captureDelayTimer invalidate];
                    self.captureDelayTimer = nil;
                }
                [self actuallyCaptureDispatch];
            }
        }
    }
    

    【讨论】:

    • 什么是 MyAdjustingWhiteBalanceObservationContext?
    猜你喜欢
    • 1970-01-01
    • 2021-10-09
    • 1970-01-01
    • 2013-10-01
    • 2017-07-26
    • 1970-01-01
    • 2016-08-30
    • 2020-08-24
    • 1970-01-01
    相关资源
    最近更新 更多