Захват неподвижного изображения с высоким разрешением во время предварительного просмотра видео низкого разрешения в iOS

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

Но на практике это не работает. Когда я переключаю разрешение на высокое или низкое, в методе делегата, который обеспечивает видеокадры, я распечатывал значения экспозиции и усиления. Для первого кадра после изменения разрешения я вижу усиление, значения экспозиции становятся очень низкими. После нескольких кадров он постепенно возвращается к значению, которое я установил. Так что для тех первых нескольких кадров я получаю синие испорченные и более темные изображения. Почему экспозиция, значения усиления не устанавливаются сразу? Как решить эту проблему? Есть ли лучший способ добиться того, чего я хочу?

Моя процедура следующая. я использую

  1. Одна AVCaptureSession
  2. Один AVCaptureDevice
  3. Один AVCaptureInput
  4. Один AVCaptureVideoDataOutput
  5. Один AVCaptureStillImageOutput.

Предварительная установка сеанса изначально устанавливается в AVCaptureSessionPresetInputPriority, а разрешение устанавливается путем установки активного формата AVCaptureDevice. Разрешение изначально ширина: 2592 и высота: 1936. Ниже приведен код для настройки камеры.

- (void)setupCamera
{
    // Set up Capture Session.
    self.avCaptureSession = [[AVCaptureSession alloc] init];
    [self.avCaptureSession beginConfiguration];

    // InputPriority allows us to select a more precise format (below)
    [self.avCaptureSession setSessionPreset:AVCaptureSessionPresetInputPriority];

    // Create a video device and input from that Device.  Add the input to the capture session.
    self.videoDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

    // Configure Focus, Exposure, and White Balance
    NSError *error;
    if([self.videoDevice lockForConfiguration:&error])
    {
        int imageWidth = 2592;
        int imageHeight = 1936;

        // Select capture format
        [self selectCaptureFormat:@{ @"width": @(imageWidth),
                                     @"height": @(imageHeight)}];

        // Allow exposure to initially change
        if ([self.videoDevice isExposureModeSupported:AVCaptureExposureModeLocked])
            [self.videoDevice setExposureMode:AVCaptureExposureModeLocked];

        // Allow white balance to initially change
        if ([self.videoDevice isWhiteBalanceModeSupported:AVCaptureWhiteBalanceModeLocked])
            [self.videoDevice setWhiteBalanceMode:AVCaptureWhiteBalanceModeLocked];

        [self.videoDevice unlockForConfiguration];
    }

    //  Add the device to the session.
    AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:self.videoDevice error:&error];

    [self.avCaptureSession addInput:input];

    //  Create the output for the capture session.
    dataOutput = [[AVCaptureVideoDataOutput alloc] init];

    // We don't want to process late frames.
    [dataOutput setAlwaysDiscardsLateVideoFrames:YES];

    [dataOutput setVideoSettings:[NSDictionary
                                  dictionaryWithObject:[NSNumber numberWithInt:kCVPixelFormatType_32BGRA]
                                  forKey:(id)kCVPixelBufferPixelFormatTypeKey]];

    [dataOutput setSampleBufferDelegate:self queue:dispatch_get_main_queue()];

    [self.avCaptureSession addOutput:dataOutput];

    //Add still image outpu to the session.
    dataImageOutput = [[AVCaptureStillImageOutput alloc] init];
    if ([self.avCaptureSession canAddOutput:dataImageOutput]) {
        [dataImageOutput setOutputSettings:@{AVVideoCodecKey : AVVideoCodecJPEG}];
        [self.avCaptureSession addOutput:dataImageOutput];
    }

    [self.avCaptureSession commitConfiguration];
}

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

(void)setupColorCameraWithOption:(bool) enableCaptureStillImage
{
    NSError *error;

    [self.avCaptureSession beginConfiguration];

    if(enableCaptureStillImage)
    {
        if ([self.avCaptureSession canSetSessionPreset:AVCaptureSessionPresetPhoto])
        {
            [self.avCaptureSession setSessionPreset:AVCaptureSessionPresetPhoto]; 
        }
        else
        {
            [self.avCaptureSession setSessionPreset:AVCaptureSessionPresetHigh];
        }
    }

    if([self.videoDevice lockForConfiguration:&error])
    {
        if(!enableCaptureStillImage)
        {
            int imageWidth = 2592;
            int imageHeight = 1936;

            // Finds the formats on the device which matches this resolution and sets that format as active format.
            [self selectCaptureFormat:@{ @"width": @(imageWidth),
                                         @"height": @(imageHeight)}];
        }

        double _durationSeconds = CMTimeGetSeconds(duration);
        if(self.videoDevice.activeFormat.minISO < iso && self.videoDevice.activeFormat.maxISO > iso &&
           CMTimeGetSeconds(self.videoDevice.activeFormat.minExposureDuration) < _durationSeconds &&
            CMTimeGetSeconds(self.videoDevice.activeFormat.maxExposureDuration) > _durationSeconds)
        {
            if([self.videoDevice isExposureModeSupported:AVCaptureExposureModeCustom])
                [self.videoDevice setExposureModeCustomWithDuration:duration ISO:iso completionHandler:^(CMTime syncTime) {
                }];

            if([self.videoDevice isWhiteBalanceModeSupported:AVCaptureWhiteBalanceModeLocked])
                [self.videoDevice setWhiteBalanceModeLockedWithDeviceWhiteBalanceGains:deviceGain completionHandler:^(CMTime syncTime) {
                }];
        }

        [self.videoDevice unlockForConfiguration];
    }

    [self.avCaptureSession commitConfiguration];

}

Ниже приведен код для захвата неподвижного изображения.

- (void)captureImage
{
    [self setupColorCameraWithOption:true];
    [dataImageOutput captureStillImageAsynchronouslyFromConnection:[dataImageOutput connectionWithMediaType:AVMediaTypeVideo] completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {
        [self setupColorCameraWithOption:false];

    }];
}

0 ответов

Другие вопросы по тегам