Reputation: 6394
I am implementing tap to focus and am confused by how to use the different AVCaptureFocusModes
. Doing this:
[device setFocusPointOfInterest:focusPoint];
[device setFocusMode:AVCaptureFocusModeAutoFocus];
results in a successful focus, but since I'm locking the focal distance, moving the camera will lose focus forever. Instead, if I do this:
[device setFocusPointOfInterest:focusPoint];
[device setFocusMode:AVCaptureFocusModeContinousAutoFocus];
The autofocus engine seems to dismiss my point of interest and simply focus on what seems best. The camera app successfully focuses on your point of interest while also keeping continuous autofocus when you move the camera, how is this done?
This is my complete code as of now:
- (void)setFocusPointOfInterest:(CGPoint)point
{
Class captureDeviceClass = NSClassFromString(@"AVCaptureDevice");
if (captureDeviceClass != nil) {
AVCaptureDevice *device = [captureDeviceClass defaultDeviceWithMediaType:AVMediaTypeVideo];
if([device isFocusPointOfInterestSupported] &&
[device isFocusModeSupported:AVCaptureFocusModeAutoFocus]) {
CGRect screenRect = [[UIScreen mainScreen] bounds];
double screenWidth = screenRect.size.width;
double screenHeight = screenRect.size.height;
double focus_x = point.x/screenWidth;
double focus_y = point.y/screenHeight;
CGPoint focusPoint = CGPointMake(focus_x,focus_y);
if([device lockForConfiguration:nil]) {
[device setFocusPointOfInterest:focusPoint];
[device setFocusMode:AVCaptureFocusModeAutoFocus];
[device setExposurePointOfInterest:focusPoint];
if ([device isExposureModeSupported:AVCaptureExposureModeAutoExpose]){
[device setExposureMode:AVCaptureExposureModeAutoExpose];
}
[device unlockForConfiguration];
}
}
}
}
Upvotes: 3
Views: 2293
Reputation: 3488
Allow tap to focus with focus mode AVCaptureFocusModeAutoFocus
, and once the camera done focusing on the point you set, try setting the focus mode back to AVCaptureFocusModeContinuousAutoFocus
. This is bit tricky as focusing will take some time. In camera app you will see a small effect on preview when ever it focus.
The key point is, you can figure it out and the focus changes with a key value observing, and once you know that focus is done with auto focus, you can reset it to continuous auto focus.
When you start the camera session add a key value observer to AVCaptureDevice
[device addObserver:self forKeyPath:@"adjustingFocus" options:NSKeyValueObservingOptionNew context:nil];
when key value changes to new value you will know device is focusing or not. When it is not change focus to continuous auto focus.
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if( [keyPath isEqualToString:@"adjustingFocus"] ){
BOOL adjustingFocus = [ [change objectForKey:NSKeyValueChangeNewKey] isEqualToNumber:[NSNumber numberWithInt:1]];
if (!adjustingFocus) {
// Reset the focus mode to AVCaptureFocusModeContinuousAutoFocus here
}
}
}
now it will work exactly like camera app. i got this answer from very old SO answer but couldn't find it to refer here.
Upvotes: 4
Reputation: 2586
The system itself can detect significant changes in the image. All you have to do is to say that isSubjectAreaChangeMonitoringEnabled
is true
and then register for the AVCaptureDeviceSubjectAreaDidChangeNotification
like this:
captureDevice.isSubjectAreaChangeMonitoringEnabled = true
NotificationCenter.default.addObserver(self,
selector: #selector(subjectAreaDidChange),
name: NSNotification.Name.AVCaptureDeviceSubjectAreaDidChange,
object: nil)
Once your method gets called - simply switch to .continuousAutoFocus
like so:
do {
try captureDevice.lockForConfiguration()
} catch let error as NSError {
print("error: \(error.localizedDescription)")
return
}
captureDevice.focusMode = .continuousAutoFocus
captureDevice.unlockForConfiguration()
Upvotes: 6