Захват неподвижного изображения с высоким разрешением во время предварительного просмотра видео низкого разрешения в iOS
Я пытаюсь сделать снимок с максимальным разрешением во время предварительного просмотра видео через заднюю камеру. Я должен был изменить разрешение при съемке изображения и изменить разрешение обратно на разрешение видео. Я хочу, чтобы значения баланса белого и значения экспозиции оставались одинаковыми для всего процесса. Поэтому я начинаю с блокировки экспозиции и баланса белого. Каждый раз перед изменением разрешения я сохраняю экспозицию, значения баланса белого. Когда я начинаю настраивать сеанс и блокирую устройство, я меняю разрешение и устанавливаю эти значения экспозиции, значения баланса белого. Это в теории должно работать просто отлично.
Но на практике это не работает. Когда я переключаю разрешение на высокое или низкое, в методе делегата, который обеспечивает видеокадры, я распечатывал значения экспозиции и усиления. Для первого кадра после изменения разрешения я вижу усиление, значения экспозиции становятся очень низкими. После нескольких кадров он постепенно возвращается к значению, которое я установил. Так что для тех первых нескольких кадров я получаю синие испорченные и более темные изображения. Почему экспозиция, значения усиления не устанавливаются сразу? Как решить эту проблему? Есть ли лучший способ добиться того, чего я хочу?
Моя процедура следующая. я использую
- Одна AVCaptureSession
- Один AVCaptureDevice
- Один AVCaptureInput
- Один AVCaptureVideoDataOutput
- Один 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];
}];
}