Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS camera: manual exposure duration but auto ISO?

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?

like image 566
Joe Avatar asked Apr 23 '15 09:04

Joe


People also ask

Can you use exposure compensation in manual mode with Auto ISO?

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 I leave my camera on auto ISO?

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.

Do professional photographers use auto ISO?

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.

How do you get 30 second exposure on iPhone?

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.


2 Answers

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!

like image 137
khose Avatar answered Nov 06 '22 23:11

khose


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)

like image 24
Volodymyr Kulyk Avatar answered Nov 06 '22 23:11

Volodymyr Kulyk