Macro-mode in AVCaptureDevice(custom camera)

Hi,

I would like to use macro-mode for the custom camera using AVCaptureDevice in my project. This feature might help to automatically adjust and switch between lenses to get a close up clear image. It looks like this feature is not available and there are no open apis to achieve macro mode from Apple. Is there a way to get this functionality in the custom camera without losing the image quality. Please let me know if this is possible.

Thanks you, Adil Thamarasseri

Answered by DTS Engineer in 821296022

Hello @AdilT,

This feature might help to automatically adjust and switch between lenses to get a close up clear image. It looks like this feature is not available

This is a common misconception:

If you are using a virtual device that includes the ultra-wide camera (i.e. the builtInDualWideCamera or the builtInTripleCamera), then the default behavior is that the virtual device will automatically switch-over to the ultra-wide camera according to the activePrimaryConstituentDeviceSwitchingBehavior of the device.

In short, as long as you are using one of the virtual devices I mentioned above, the default behavior is the feature you are looking for.

-- Greg

Hello @AdilT,

This feature might help to automatically adjust and switch between lenses to get a close up clear image. It looks like this feature is not available

This is a common misconception:

If you are using a virtual device that includes the ultra-wide camera (i.e. the builtInDualWideCamera or the builtInTripleCamera), then the default behavior is that the virtual device will automatically switch-over to the ultra-wide camera according to the activePrimaryConstituentDeviceSwitchingBehavior of the device.

In short, as long as you are using one of the virtual devices I mentioned above, the default behavior is the feature you are looking for.

-- Greg

I too need this capability, for photographing product labels and OCR text recognition. The small size (and font) of the labels requires macro function. The Camera App on my iPhone 15 Pro (iOS 18.3) automatically enters Macro mode and creates very sharp Label images, which OCR accurately.

However, within my iOS Swift app with AVCapture there appears to be no way of enabling this behaviour: close focus is not possible and therefore Labels do not OCR properly.

Hello, it sounds like both of you are struggling with the automatic device switching behaviors.

If you can provide me with a focused sample project that demonstrates that the automatic switching is not occurring for you, I can examine your code to see why that might be happening!

-- Greg

I solved the problem by explicitly setting the device, as per the below function:

func getMacroDevice() -> AVCaptureDevice? {
        if let device = AVCaptureDevice.default(.builtInTripleCamera,
                                                for: .video, position: .back) {
            return device
        }
        if let device = AVCaptureDevice.default(.builtInDualCamera,
                                                       for: .video, position: .back) {
            return device
        } else {
            if let device = AVCaptureDevice.default(for: .video) {
                return device
            } else {
                return nil
            }
        }
    }

I use this function in the session.beginConfiguration() part of the camera functionality to set the device.

The order is important, because on my iPhone 15 Pro if the Dual Camera is the first choice then macro mode doesn't occur.

Also, on my M1 iPad Pro, builtInDouble and builtInTriple don't apply (the let fails): the iPad will close focus using the default camera device.

It seems to me that if the default behaviour is to automatically switch, then in my development environment and on my devices the supposed behaviour is not working.

Regards, Michaela

Hey Michaela,

Ok, I'm glad you found a solution!

It seems to me that if the default behaviour is to automatically switch, then in my development environment and on my devices the supposed behaviour is not working.

The default behavior I mentioned had an important condition: "If you are using a virtual device that includes the ultra-wide camera (i.e. the builtInDualWideCamera or the builtInTripleCamera)".

So, if your code was previously using the builtInDualCamera (which is different from the builtInDualWideCamera), then I would not expect it to focus on very close-up objects, because the builtInDualCamera does not include the ultra-wide camera.

-- Greg

Further to Greg's reply to my solution, I confirm that builtInDualCamera does not provide close-focus, whereas builtInDualWideCamera does. I've therefore revised my solution (to support different iPhone / iPad models) as per below:

func getMacroDevice() -> AVCaptureDevice? {
        if let device = AVCaptureDevice.default(.builtInTripleCamera,
                                                for: .video, position: .back) {
            return device
        }
        if let device = AVCaptureDevice.default(.builtInDualWideCamera,for: .video, position: .back) {
            return device
        }
        if let device = AVCaptureDevice.default(for: .video) {
            return device
        }
        return nil
    }

I'm still puzzled by the "default behaviour" not working and will explore further at https://developer.apple.com/documentation/avfoundation/avcapturedevice/activeprimaryconstituentdeviceswitchingbehavior

UPDATE: using device = AVCaptureDevice.default(for: .video) and then getting that device's .primaryConstituentDeviceSwitchingBehavior returns .unsupported for my iPhone 15 Pro under iOS 18.3. So, it seems that our code must specify a primary constituent device, as per my code above, otherwise the default device does not qualify for switching, if available. Perhaps this is what Greg was getting at with his original answer.

Also, the M1 iPad Pro has a .builtInDualWideCamera, which is probably its default.

Regards, Michaela

Close focussing requires the use of a virtual device that has some form of wide-angle lens, especially ultra-wide. However, for my application needs (small label with small fonts) this can mean that the camera is very close to the subject, thereby blocking illumination - resulting in poorer OCR results.

My solution to this is to use the device's Video Zoom Factor capability (if available), which is a digital zoom feature rather than optical (i.e. it's based on cropping the sensor output)

The below code sample is used in the Photo Preview UI, with reference to the class that manages the camera set up and delegates ("camera") and to the available device determined by that class instance.

Of course, zooming (cropping) too much can also cause OCR results to deteriorate: so it's a case of trial and error. There is a videoMaxZoomFactor read-only property for applicable device formats.

Slider(
    value:$zoomFactor,
          in: 1.0...4.0,
          step: 0.5
     ) {
           Text("Zoom")
        } minimumValueLabel: {
            Text("1x")
         } maximumValueLabel: {
              Text("4x")
         } onEditingChanged: { _ in
              do {
                 try camera.device?.lockForConfiguration()
                   camera.device?.ramp(toVideoZoomFactor: self.zoomFactor,withRate:1.0)
                camera.device?.unlockForConfiguration()
              } catch {
                  print("**** Unable to set camera zoom")
              }
   }

Regards, Michaela

Macro-mode in AVCaptureDevice(custom camera)
 
 
Q