"Нажмите, чтобы сфокусироваться", чтобы "автофокусироваться" при изменении содержимого в режиме камеры. Логика, как в приложении с камерой или UIImagePickerController для iOS?

Как мне переключиться с "нажмите, чтобы сфокусировать" на конкретном объекте POI обратно в состояние "автофокусировки" автоматически после потери фокуса при изменении содержимого в представлении? Если вы заметили поведение фокуса в приложении Camera Camera или UIImagePickerController, после того, как вы нажмете фокус на какую-то область и вы отпустите телефон, камера автоматически переключится на непрерывную автофокусировку в центре экрана.

Мне нужна дополнительная гибкость, чем то, что может предоставить UIImagePickerController, поэтому мне нужно использовать AVFoundation для имитации поведения UIImagePickerController...

Ответ 1

Сначала это звучит очень сложно: но это оказалось очень просто, Apple уже сделала 99% работы для нас. Все, что вам нужно сделать, это установить "subjectAreaChangeMonitoringEnabled" и зарегистрировать KVO в "AVCaptureDeviceSubjectAreaDidChangeNotification"! В документах iOS 6.1:

Значение этого свойства указывает, должен ли приемник контролировать область видеообъекта для изменений, таких как изменения освещения, существенное движение и т.д. Если мониторинг изменения предметной области включен, объект устройства захвата отправляет AVCaptureDeviceSubjectAreaDidChangeNotification всякий раз, когда он обнаруживает изменить предметную область, и в это время заинтересованный клиент может хотите перефокусироваться, настроить экспозицию, баланс белого и т.д.

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

Вы можете наблюдать за изменениями этого свойства с использованием значения ключа наблюдения.

(Еще лучше, вам не нужно обрабатывать много угловых случаев. Что делать, если устройство находится в середине "adjustingFocus" в POI, а контент изменился? Вы не хотите, чтобы устройство возвращалось к автофокусу в центре, и хотите, чтобы действие фокуса закончилось. Сообщение об изменении области было вызвано только после того, как фокус сделан.)

Пример фрагмента кода из моего проекта. (Структура соответствует официальному примеру AVFoundation AVCam, поэтому вы можете легко их установить и попробовать):

// CameraCaptureManager.m

@property (nonatomic, strong) AVCaptureDevice *backFacingCamera;

- (id) init{
    self = [super init];
    if (self){

        // TODO: more of your setup code for AVFoundation capture session
        for (AVCaptureDevice *device in [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]) {
            if (device.position == AVCaptureDevicePositionBack){
                self.backFacingCamera = device;
            }
        }

        NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];

        void (^subjectAreaDidChangeBlock)(NSNotification *) = ^(NSNotification *notification) {

            if (self.videoInput.device.focusMode == AVCaptureFocusModeLocked ){
                // All you need to do is set the continuous focus at the center. This is the same behavior as
                // in the stock Camera app
                [self continuousFocusAtPoint:CGPointMake(.5f, .5f)];
            }
        };

        self.subjectAreaDidChangeObserver = [notificationCenter addObserverForName:AVCaptureDeviceSubjectAreaDidChangeNotification
                                                                            object:nil
                                                                             queue:nil
                                                                        usingBlock:subjectAreaDidChangeBlock];

        [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
        [self addObserver:self forKeyPath:keyPathAdjustingFocus options:NSKeyValueObservingOptionNew context:NULL];
    }

    return self;
}

-(void) dealloc{
    // Remove the observer when done
    NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
    [notificationCenter removeObserver:self.deviceOrientationDidChangeObserver];
}

- (BOOL) setupSession{
    BOOL sucess = NO;

    if ([self.backFacingCamera lockForConfiguration:nil]){
        // Turn on subject area change monitoring
        self.backFacingCamera.subjectAreaChangeMonitoringEnabled = YES;
    }

    [self.backFacingCamera unlockForConfiguration];

    // TODO: Setup add input etc...

    return sucess;
}

Ответ 2

Я только что увидел комментарий от @Xiaochao Yang, и я хочу добавить объяснение кода CGPointMake(.5f, .5f). Согласно API Apple, CGPoint, который вы устанавливаете на камеру, находится в диапазоне от {0,0} до {1,1}, в то время как CGPointMake(.5f, .5f) означает центр камеры.

Это свойство представляет собой CGPoint, где {0,0} соответствует левому верхнему краю области изображения, а {1,1} соответствует нижнему праву в ландшафтном режиме с кнопкой "домой" справа - это применяется, даже если устройство находится в портретном режиме

Из Ссылка на класс AVCaptureDevice