2014-02-26 3 views
7

ПОСЛЕ постукивать, чтобы сделать снимок, я хочу заблокировать экспозицию и выключить факел, как только экспозиция перестает корректироваться. Таким образом, я добавил наблюдатель обращаться adjustingExposure:AVFoundation - Как контролировать экспозицию

- (IBAction)configureImageCapture:(id)sender 
{ 
    [self.session beginConfiguration]; 

    [self.cameraController device:self.inputDevice exposureMode:AVCaptureExposureModeAutoExpose]; 
    [self.cameraController device:self.inputDevice torchMode:AVCaptureTorchModeOn torchLevel:0.8f]; 

    [self.session commitConfiguration]; 

    [(AVCaptureDevice *)self.inputDevice addObserver:self forKeyPath:@"adjustingExposure" options:NSKeyValueObservingOptionNew context:MyAdjustingExposureObservationContext];   
} 

Вот метод observeValueForKeyPath:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 
{ 
    if (context == MyAdjustingExposureObservationContext) { 
     if([keyPath isEqualToString:@"adjustingExposure"]) 
     { 
      BOOL adjustingExposure = [ [change objectForKey:NSKeyValueChangeNewKey] isEqualToNumber:[NSNumber numberWithInt:1] ]; 

      if (!adjustingExposure) 
      { 
       [(AVCaptureDevice *)self.cameraController.inputDevice removeObserver:self forKeyPath:@"adjustingExposure"]; 

       if ([self.inputDevice isExposureModeSupported:AVCaptureExposureModeLocked]) { 
        dispatch_async(dispatch_get_main_queue(), 
            ^{ 
             NSError *error = nil; 
             if ([self.inputDevice lockForConfiguration:&error]) { 
              // 5) lock the exposure 
              [self.cameraController device:self.inputDevice exposureMode:AVCaptureExposureModeLocked]; 

              // 6) turn off the Torch 
              [self.cameraController device:self.inputDevice torchMode:AVCaptureTorchModeOn torchLevel:0.0001f]; 

              [self.inputDevice unlockForConfiguration]; 
             } 
            }); 
       }      
      } 
     } 
    } else { 
     [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; 
    } 
} 

@ user3115647 отправил эту information, что это именно то, что я пытаюсь сделать.

Но сделайте снимок ДО факел выключен.

Вот мой captureStillImageAsynchronouslyFromConnection: self.captureConnection completeHandler. Этот блок возникает после съемки изображения. Предполагается, что наблюдениеValueForKeyPath происходит, когда камера регулирует экспозицию до того, как изображение будет снято. Но мой факел не идет низко, прежде чем изображение будет снято. Либо это проблема синхронизации, либо я неправильно настраиваю конфигурацию камеры.

- (void)captureImage 
{ 
    // configureImageCapture has already been done 
    [self.stillImageOutput captureStillImageAsynchronouslyFromConnection:self.captureConnection completionHandler: ^(CMSampleBufferRef imageSampleBuffer, NSError *error) 
    { 
     if (imageSampleBuffer != NULL) 
     { 
      // Log the image properties 
      CFDictionaryRef attachmentsRef = CMGetAttachment(imageSampleBuffer, kCGImagePropertyExifDictionary, NULL); 
      NSDictionary *properties = (__bridge NSDictionary *)(attachmentsRef); 
      NSLog(@"Image Properties => %@", (properties.count) ? properties : @"none"); 
+0

ОК. Я знаю, что этот вопрос касается как фокуса, так и экспозиции, но сначала я соглашусь на то, чтобы выставлять себя под воздействием экспозиции. Я нашел ответ на то, что я пытаюсь сделать с экспозицией здесь: http://stackoverflow.com/questions/12635446/accessing-ios-6-new-apis-for-camera-exposure-and-shutter-speed/20660981 # 20660981 – Patricia

+0

У меня возникли проблемы с тем, чтобы KVO выполнял так, как ожидалось. Изображение снимается до выключения факела. – Patricia

+0

Я обновил код до того, что у меня есть. Ищете какую-то помощь здесь. Заранее спасибо. – Patricia

ответ

1

У меня есть что-то подобное, если использовать вспышку вместо факела. У меня есть наблюдатель для @"videoDevice.flashActive". Сначала я попытался использовать exposureModeLocked, но для меня это тоже не сработало.

  1. Сфотографируйте со вспышкой на
  2. Затем мгновенно превратить вспышку и сделать еще один снимок, прежде чем экспозиция имеет время, чтобы приспособиться

код ниже, вероятно, не просто работать самостоятельно, но он упрощен от того, что я сделал.

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void*)context 
{ 
    if (context == AdjustingExposureContext) 
    { 
     self.isAdjustingExposure = [change[NSKeyValueChangeNewKey] boolValue]; 
    } 
    else if (context == FlashModeChangedContext) 
    { 
     self.isFlashActive = [change[NSKeyValueChangeNewKey] boolValue]; 
     if (!self.flashActive) 
     { 
      [self captureImage]; // QUICKLY! capture 2nd image without 
     }       // flash before exposure adjusts 
    } 
    if (!self.isAdjustingExposure && self.flashActive) 
    { 
     [self removeObserver:self forKeyPath:@"videoDevice.adjustingExposure" context:AdjustingExposureContext]; 
     [self captureImage]; // capture 1st image with the flash on 
    } 
} 

Теперь в функции обратного вызова для captureStillImageAsynchronouslyFromConnection:,

if (self.isFlashActive) 
    [self.videoDeviceInput.device setFlashMode:NO]; 

Однако, если вам нужно взять больше, чем одну фотографию без вспышки при пониженной экспозиции, эта стратегия может не работать.

+0

Я не попадаю в условие if (context == FlashModeChangedContext).Будет ли камера обрабатывать это, просто добавив наблюдателя, как и другие (т. Е. [(AVCaptureDevice *) self.inputDevice addObserver: self forKeyPath: @ "adjustingFlash": NSKeyValueObservingOptionNew context: MyAdjustingFlashObserationContext];) ????? – Patricia

+0

Да, точно, но keyPath - это 'flashMode', см. [Здесь] (https://developer.apple.com/library/mac/documentation/AVFoundation/Reference/AVCaptureDevice_Class/Reference/Reference.html#//apple_ref/ occ/instp/AVCaptureDevice/flashMode) – EthanP

+0

Я, наконец, понимаю ваше последнее утверждение: если вам нужно взять более одной фотографии без вспышки при пониженной экспозиции, эта стратегия может не сработать. Количество снимков, которые будут экспоненциально увеличиваться с каждым нажатием. – Patricia

1

Это почти наверняка вопрос времени. Позвоните captureStillImageAsynchronouslyFromConnection:completionHandler: внутри вашего блока if. Тогда захват будет всегда выполняться после того, как экспозиция заблокирована.

if ([self.inputDevice isExposureModeSupported:AVCaptureExposureModeLocked]) { 
    dispatch_async(dispatch_get_main_queue(), 
     ^{ 
      NSError *error = nil; 
      if ([self.inputDevice lockForConfiguration:&error]) { 
       //code to lock exposure here 
       //take photo here 
      } 
     }); 
} 
+0

К тому времени, как я попал в наблюдатель, я уже вызвал метод captureStillImageAsynchronouslyFromConnection: completeHandler. Я не знаю, как делать то, что вы предлагаете, и я не могу (на всю жизнь) найти пример кода, который использует обработчик завершения, прежде чем вызывать метод captureStillImageAsynchronouslyFromConnection: completeHandler. – Patricia

Смежные вопросы