iOS相机:手动曝光持续时间但自动ISO?

我正在使用相机video输入进行一些图像处理,并希望优化最快的快门速度。 我知道您可以手动设置曝光持续时间和ISO使用

setExposureModeCustomWithDuration:ISO:completionHandler: 

但这要求人们手动设置两个值。 是否有方法或巧妙的技巧允许您手动设置曝光率,但有ISO句柄本身试图正确曝光图像?

我不确定这个解决方案是否是最好的解决方案,因为我正在努力解决这个问题。 我所做的是聆听曝光偏移的变化,并从中调整ISO直到达到可接受的曝光水平。 大部分代码都来自Apple示例代码

因此,首先,您要监听ExposureTargetOffset上的更改。 在您的class级声明中添加:

static void *ExposureTargetOffsetContext = &ExposureTargetOffsetContext;

然后,一旦您正确完成了设备设置:

[self addObserver:self forKeyPath:@"captureDevice.exposureTargetOffset" options:NSKeyValueObservingOptionNew context:ExposureTargetOffsetContext];

(而不是captureDevice,将您的属性用于设备)然后在您的类中实现KVO的回调:

 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{ if (context == ExposureTargetOffsetContext){ float newExposureTargetOffset = [change[NSKeyValueChangeNewKey] floatValue]; NSLog(@"Offset is : %f",newExposureTargetOffset); if(!self.device) return; CGFloat currentISO = self.device.ISO; CGFloat biasISO = 0; //Assume 0,3 as our limit to correct the ISO if(newExposureTargetOffset > 0.3f) //decrease ISO biasISO = -50; else if(newExposureTargetOffset < -0.3f) //increase ISO biasISO = 50; if(biasISO){ //Normalize ISO level for the current device CGFloat newISO = currentISO+biasISO; newISO = newISO > self.device.activeFormat.maxISO? self.device.activeFormat.maxISO : newISO; newISO = newISO < self.device.activeFormat.minISO? self.device.activeFormat.minISO : newISO; NSError *error = nil; if ([self.device lockForConfiguration:&error]) { [self.device setExposureModeCustomWithDuration:AVCaptureExposureDurationCurrent ISO:newISO completionHandler:^(CMTime syncTime) {}]; [self.device unlockForConfiguration]; } } } } 

使用此代码,快门速度将保持不变,并且将调整ISO以使图像不会过度曝光或过度曝光。

不要忘记在需要时移除观察者。 希望这适合你。

干杯!

代码示例由@khose在swift上提供:

private var device: AVCaptureDevice?
private var exposureTargetOffsetContext = 0

 override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { if device == nil { return } if keyPath == "exposureTargetOffset" { let newExposureTargetOffset = change?[NSKeyValueChangeKey.newKey] as! Float print("Offset is : \(newExposureTargetOffset)") let currentISO = device?.iso var biasISO = 0 //Assume 0,01 as our limit to correct the ISO if newExposureTargetOffset > 0.01 { //decrease ISO biasISO = -50 } else if newExposureTargetOffset < -0.01 { //increase ISO biasISO = 50 } if biasISO != Int(0) { //Normalize ISO level for the current device var newISO = currentISO! + Float(biasISO) newISO = newISO > (device?.activeFormat.maxISO)! ? (device?.activeFormat.maxISO)! : newISO newISO = newISO < (device?.activeFormat.minISO)! ? (device?.activeFormat.minISO)! : newISO try? device?.lockForConfiguration() device?.setExposureModeCustom(duration: AVCaptureDevice.currentExposureDuration, iso: newISO, completionHandler: nil) device?.unlockForConfiguration() } } } 

用法:
device?.addObserver(self, forKeyPath: "exposureTargetOffset", options: NSKeyValueObservingOptions.new, context: &exposureTargetOffsetContext)