I'm using the camera video feed for some image processing and would like to optimise for fastest shutter speed. I know you can manually set exposure duration and ISO using
setExposureModeCustomWithDuration:ISO:completionHandler:
but this requires one to set both the values by hand. Is there a method or clever trick to allow you to set the exposure duraction manually but have the ISO handle itself to try to correctly expose the image?
However, with auto ISO you can apply exposure compensation with manual exposure. This would alter the selection of the ISO setting to achieve the target exposure based on compensation, and in conjunction with the lens aperture and shutter speed settings you have selected.
Should You Use Auto ISO? Absolutely, you should! As you have probably gathered, Auto ISO is a great feature that's useful in situations where the light is changing rapidly or you don't have time to adjust your settings in fast-paced situations.
Automatic ISO is widely used by both professional and beginner photographers alike. Rather than having to manually adjust your ISO for every photo, your camera does the work.
Open the Photos app and find the photo. Swipe up on it to reveal Effects. Swipe left until you see the Long Exposure effect. Tap on it to create your long exposure photo.
I'm not sure if this solution is the best one, since I was struggling with this as you were. What I've done is to listen to changes in the exposure offset and, from them, adjust the ISO until you reach an acceptable exposure level. Most of this code has been taken from the Apple sample code
So, First of all, you listen for changes on the ExposureTargetOffset. Add in your class declaration:
static void *ExposureTargetOffsetContext = &ExposureTargetOffsetContext;
Then, once you have done your device setup properly:
[self addObserver:self forKeyPath:@"captureDevice.exposureTargetOffset" options:NSKeyValueObservingOptionNew context:ExposureTargetOffsetContext];
(Instead of captureDevice, use your property for the device) Then implement in your class the callback for 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];
}
}
}
}
With this code, the Shutter speed will remain constant and the ISO will be adjusted to leave the image not too under or overexposed.
Don't forget to remove the observer whenever is needed. Hope this suits you.
Cheers!
Code sample provided by @khose on 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()
}
}
}
Usage:device?.addObserver(self, forKeyPath: "exposureTargetOffset", options: NSKeyValueObservingOptions.new, context: &exposureTargetOffsetContext)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With