How do I get depth data from the UIImagePicker

I am trying to get the depth data associated with an image in the PhotoLibrary. I can get the image, and the URL, but I can't seem to get the aux data associated with it. The call to

CGImageSourceCreateWithURL
returns a source, but the call to
CGImageSourceCopyAuxiliaryDataInfoAtIndex
returns
nil
for both
kCGImageAuxiliaryDataTypeDisparity
and
kCGImageAuxiliaryDataTypeDepth
. Is there something I am missing here?

Replies

Your question is much clearer in SO with the posted code !


func imagePickerController(_ picker: UIImagePickerController,    didFinishPickingMediaWithInfo info: [String : Any]) {
    let image = info[UIImagePickerControllerOriginalImage]
    let url = info[UIImagePickerControllerImageURL]
    print("url=",url)

    guard let source = CGImageSourceCreateWithURL(url as! CFURL, nil) else {
        return
    }
    guard let auxDataInfo = CGImageSourceCopyAuxiliaryDataInfoAtIndex(source, 0, kCGImageAuxiliaryDataTypeDisparity) as? [AnyHashable : Any] else {
        return
    }
}


What I do not understand is what you do lines 6 and 9 with the result of the calls ?

source and auxDataInfo are lost when you exit.

Unless you forgot to post some part of the code ?


Did you consider using :

func dictionaryRepresentation(forAuxiliaryDataType outAuxDataType: AutoreleasingUnsafeMutablePointer<NSString?>?) -> [AnyHashable : Any]?


Discussion


When using CGImageDestination functions to write depth data (along with image data) to a HEIF, JPEG, or DNG file, you can use this method to obtain a dictionary of primitive depth map information, then use the

CGImageDestinationAddAuxiliaryDataInfo(_:_:_:)
function to embed that data into the output file.


And read this tutorial for full details on how to get the result.

h ttps://www.raywenderlich.com/168312/image-depth-maps-tutorial-ios-getting-started

Sorry, I only posted part of the code. The issue is that it appears that the depth data is not available.

The second call to populate the auxDataInfo always returns nil. If it returns something other than nil, I operate on the data.


I fear that the aux data is not avalable from the image that is returned from the Picker.

Is this possible?

Claude31,

Thanks again for your response earlier.

I have a working depth analysis program that can see the depth on a JPG that is opened directly from the url in the simulator.

I have not been able to get the depth data from an image that is returned from the UIImagePicker.


Is there a special mediaType or something that needs to be set in the UIImagePicker to allow it to provide access to the depth data? Is the Depth data a different URL than the image? I have tried everything I can think of to get the data.


Thanks

Well, could you first show the complete code for func imagePickerController

And show what you get from print(url)


It is very difficult to help if you show only what you think is the problem, which may be elsewhere.

I sorry, I should have posted this earlier. I am using much of the sample code from Apple for the Image Picker. In the next to last funciton, I am attempting to access the depth data for the image that is being returned from the picker. The image that I am picking is a portrait image that has depth data when I email the file to my macbook and open it from the simulator. Please let me know if you see something that would help me. Thanks again for the help.


/
Copyright (C) 2017 Apple Inc. All Rights Reserved.
See LICENSE.txt for this sample’s licensing information
Abstract:
Main view controller for this application.
*/
import UIKit
import AVFoundation
import MobileCoreServices
import Photos
var activeImage: UIImage = UIImage()
class APLViewController: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
  @IBOutlet var imageView: UIImageView?
  @IBOutlet var cameraButton: UIBarButtonItem?
  @IBOutlet var overlayView: UIView?

  /
  @IBOutlet var takePictureButton: UIBarButtonItem?
  @IBOutlet var startStopButton: UIBarButtonItem?
  @IBOutlet var delayedPhotoButton: UIBarButtonItem?
  @IBOutlet var doneButton: UIBarButtonItem?
  var imagePickerController = UIImagePickerController()

  var cameraTimer = Timer()
  var capturedImages = [UIImage]()

  /

  override func viewDidLoad() {
  super.viewDidLoad()
  imagePickerController.modalPresentationStyle = .currentContext
  imagePickerController.delegate = self
        /
       
  /
  if !UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.camera) {
  toolbarItems = self.toolbarItems?.filter { $0 != cameraButton }
  }
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        /
    }
    /
   
  fileprivate func finishAndUpdate() {
  dismiss(animated: true, completion: { [weak self] in
  guard let `self` = self else {
  return
  }

  if `self`.capturedImages.count > 0 {
  if self.capturedImages.count == 1 {
  /
  `self`.imageView?.image = `self`.capturedImages[0]
                    activeImage = self.capturedImages[0]
  } else {
  /
  `self`.imageView?.animationImages = `self`.capturedImages
  `self`.imageView?.animationDuration = 5    /
  `self`.imageView?.animationRepeatCount = 0   /
  `self`.imageView?.startAnimating()
                    activeImage = self.capturedImages[0]
  }

  /
  `self`.capturedImages.removeAll()
                self.performSegue(withIdentifier: "SegueFromPicker", sender:self)
  }
  })
  }

  /

  @IBAction func showImagePickerForCamera(_ sender: UIBarButtonItem) {
  let authStatus = AVCaptureDevice.authorizationStatus(for: AVMediaType.video)

  if authStatus == AVAuthorizationStatus.denied {
  /
  /
  let alert = UIAlertController(title: "Unable to access the Camera",
    message: "To enable access, go to Settings > Privacy > Camera and turn on Camera access for this app.",
    preferredStyle: UIAlertControllerStyle.alert)

  let okAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
  alert.addAction(okAction)

  let settingsAction = UIAlertAction(title: "Settings", style: .default, handler: { _ in
  /
  guard let settingsUrl = URL(string: UIApplicationOpenSettingsURLString) else { return }
  if UIApplication.shared.canOpenURL(settingsUrl) {
  UIApplication.shared.open(settingsUrl, completionHandler: { (success) in
  /
  })
  }
  })
  alert.addAction(settingsAction)

  present(alert, animated: true, completion: nil)
  }
  else if (authStatus == AVAuthorizationStatus.notDetermined) {
  /
  /
  /
  /
  /
  /
  AVCaptureDevice.requestAccess(for: AVMediaType.video, completionHandler: { (granted) in
  if granted {
  DispatchQueue.main.async {
  self.showImagePicker(sourceType: UIImagePickerControllerSourceType.camera, button: sender)
  }
  }
  })
  } else {
  /
  showImagePicker(sourceType: UIImagePickerControllerSourceType.camera, button: sender)
  }
  }
  @IBAction func showImagePickerForPhotoPicker(_ sender: UIBarButtonItem) {
  showImagePicker(sourceType: UIImagePickerControllerSourceType.photoLibrary, button: sender)
  }

  fileprivate func showImagePicker(sourceType: UIImagePickerControllerSourceType, button: UIBarButtonItem) {
  /
  if (imageView?.isAnimating)! {
  imageView?.stopAnimating()
  }
  if capturedImages.count > 0 {
  capturedImages.removeAll()
  }

  imagePickerController.sourceType = sourceType
  imagePickerController.modalPresentationStyle =
  (sourceType == UIImagePickerControllerSourceType.camera) ?
  UIModalPresentationStyle.fullScreen : UIModalPresentationStyle.popover

  let presentationController = imagePickerController.popoverPresentationController
  presentationController?.barButtonItem = button /
  presentationController?.permittedArrowDirections = UIPopoverArrowDirection.any

  if sourceType == UIImagePickerControllerSourceType.camera {
  /
  imagePickerController.showsCameraControls = false

  /
  overlayView?.frame = (imagePickerController.cameraOverlayView?.frame)!
  imagePickerController.cameraOverlayView = overlayView
  }

  present(imagePickerController, animated: true, completion: {
  /
  })
  }

  /

  @IBAction func done(_ sender: UIBarButtonItem) {
  if cameraTimer.isValid {
  cameraTimer.invalidate()
  }
  finishAndUpdate()
  }

  @IBAction func takePhoto(_ sender: UIBarButtonItem) {
  imagePickerController.takePicture()
  }

  @IBAction func delayedTakePhoto(_ sender: UIBarButtonItem) {
  /
  doneButton?.isEnabled = false
  takePictureButton?.isEnabled = false
  delayedPhotoButton?.isEnabled = false
  startStopButton?.isEnabled = false

  let fireDate = Date(timeIntervalSinceNow: 5)
  cameraTimer = Timer.init(fire: fireDate, interval: 1.0, repeats: false, block: { timer in
  self.imagePickerController.takePicture()

  self.doneButton?.isEnabled = true
  self.takePictureButton?.isEnabled = true
  self.delayedPhotoButton?.isEnabled = true
  self.startStopButton?.isEnabled = true
  })
  RunLoop.main.add(cameraTimer, forMode: RunLoopMode.defaultRunLoopMode)
  }

  @IBAction func startTakingPicturesAtIntervals(_ sender: UIBarButtonItem) {
  /
  Start the timer to take a photo every 1.5 seconds.

  CAUTION: for the purpose of this sample, we will continue to take pictures indefinitely.
  Be aware we will run out of memory quickly.  You must decide the proper threshold number of
  photos allowed to take from the camera. One solution to avoid memory constraints is to save each
  taken photo to disk rather than keeping all of them in memory. In low memory situations sometimes
  our "didReceiveMemoryWarning" method will be called in which case we can recover some memory
  and keep the app running.
  */

  /
  startStopButton?.title = NSLocalizedString("Stop", comment: "Title for overlay view controller start/stop button")
  startStopButton?.action = #selector(stopTakingPicturesAtIntervals)

  /
  doneButton?.isEnabled = false
  delayedPhotoButton?.isEnabled = false
  takePictureButton?.isEnabled = false
  /
  cameraTimer = Timer.scheduledTimer(withTimeInterval: 1.5, repeats: true) { timer in
  self.imagePickerController.takePicture()
  }
  }

  @IBAction func stopTakingPicturesAtIntervals(_ sender: UIBarButtonItem) {
  /
  cameraTimer.invalidate()
  finishAndUpdate()

  /
  self.doneButton?.isEnabled = true
  self.takePictureButton?.isEnabled = true
  self.delayedPhotoButton?.isEnabled = true

  /
  startStopButton?.title = NSLocalizedString("Start", comment: "Title for overlay view controller start/stop button")
  startStopButton?.action = #selector(startTakingPicturesAtIntervals)
  }

  /

  func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
  let image = info[UIImagePickerControllerOriginalImage]
        let url = info[UIImagePickerControllerImageURL]
  print("url=",url)
        print("Info=", info)
        let imgData = NSData(contentsOf: (url as! URL))
        /
        if let imageSource = CGImageSourceCreateWithData(imgData! as CFData, nil) {
            let imageProperties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, nil)! as NSDictionary
            print ("ImageProps=", imageProperties)
            let auxDataInfo = CGImageSourceCopyAuxiliaryDataInfoAtIndex(imageSource, 0, kCGImageAuxiliaryDataTypeDisparity) as? [AnyHashable : Any]
                print ("auxDataInfo=", auxDataInfo)
        }
        let depthRdr = DepthReader()
        var pixelBuffer = depthRdr.depthDataMap(url: url as! URL)
   
        capturedImages.append(image as! UIImage)

  if !cameraTimer.isValid {
  /
  finishAndUpdate()
  }
  }

  func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
  dismiss(animated: true, completion: {
  /
  })
  }
}


The output from the run looks like this:

2018-05-09 21:05:35.004622-0400 3DUtils[969:272322] [DYMTLInitPlatform] platform initialization successful

2018-05-09 21:05:36.300527-0400 3DUtils[969:272117] [MC] System group container for systemgroup.com.apple.configurationprofiles path is /private/var/containers/Shared/SystemGroup/systemgroup.com.apple.configurationprofiles

2018-05-09 21:05:36.304227-0400 3DUtils[969:272117] [MC] Reading from public effective user settings.

url= Optional(file:///private/var/mobile/Containers/Data/Application/08EA98E6-0341-4CA9-8C43-4ADF680C46C9/tmp/8E5D016C-8924-4576-B9E0-D2D53AA959B2.jpeg)

Info= ["UIImagePickerControllerImageURL": file:///private/var/mobile/Containers/Data/Application/08EA98E6-0341-4CA9-8C43-4ADF680C46C9/tmp/8E5D016C-8924-4576-B9E0-D2D53AA959B2.jpeg

ImageProps= {

ColorModel = RGB;

DPIHeight = 72;

DPIWidth = 72;

Depth = 8;

PixelHeight = 2048;

PixelWidth = 1538;

ProfileName = "Display P3";

"{ExifAux}" = {

Regions = {

HeightAppliedTo = 3088;

RegionList = (

{

AngleInfoRoll = 355;

AngleInfoYaw = 0;

ConfidenceLevel = 1000;

FaceID = 4;

Height = "0.3050000071525574";

Timestamp = 2147483647;

Type = Face;

Width = "0.4110000133514404";

X = "0.3985000252723694";

Y = "0.5034999847412109";

},

{

Height = "0.3050000071525574";

Type = Focus;

Width = "0.4110000133514404";

X = "0.3985000252723694";

Y = "0.5034999847412109";

}

);

WidthAppliedTo = 2320;

};

};

"{Exif}" = {

ApertureValue = "2.275007206687806";

BrightnessValue = "0.1036512370311253";

ComponentsConfiguration = (

1,

2,

3,

0

);

CustomRendered = 8;

DateTimeDigitized = "2018:05:05 17:35:25";

DateTimeOriginal = "2018:05:05 17:35:25";

ExifVersion = (

2,

2,

1

);

ExposureBiasValue = 0;

ExposureMode = 0;

ExposureProgram = 2;

ExposureTime = "0.06666666666666667";

FNumber = "2.2";

Flash = 24;

FlashPixVersion = (

1,

0

);

FocalLenIn35mmFilm = 32;

FocalLength = "2.87";

ISOSpeedRatings = (

320

);

LensMake = Apple;

LensModel = "iPhone X front TrueDepth camera 2.87mm f/2.2";

LensSpecification = (

"2.87",

"2.87",

"2.2",

"2.2"

);

MeteringMode = 5;

PixelXDimension = 1538;

PixelYDimension = 2048;

SceneCaptureType = 0;

SceneType = 1;

SensingMethod = 2;

ShutterSpeedValue = "3.90712145655681";

SubsecTimeDigitized = 924;

SubsecTimeOriginal = 924;

WhiteBalance = 0;

};

"{JFIF}" = {

DensityUnit = 0;

JFIFVersion = (

1,

0,

1

);

XDensity = 72;

YDensity = 72;

};

"{MakerApple}" = {

1 = 9;

14 = 0;

2 = <bc00c300 82006200 5d00c103 54032f00 24002800 33004b00 68006100 6e007100 d000d000 ac00a300 9000af03 84032f00 24002800 35004f00 6d007300 6a006500 da00ce00 a9006c00 c0005d01 be015f00 25002b00 3a005500 67008000 69006800 ce00c500 a7007500 8f005303 e7030b01 24002900 3d006300 5b006900 5c006700 e400db00 b6007800 42007503 fc03dc00 29003400 40006c00 5e005e00 62005900 f400e500 bb007700 4e004703 69020101 26003000 45006900 55005e00 69004000 e600d500 94005600 4000af00 b400f100 60003c00 4b006500 65005d00 61004700 bc00a100 3c009900 d600d800 ab001701 0b01eb00 b2008100 6f007000 56004f00 9c005f00 3d00e200 24013201 87000a01 2001e100 eb00bd00 78005d00 4c004900 8a004100 4700ef00 6f018201 a900fe00 dd000901 0801ed00 80002a00 1e001500 d2003c00 3f00d800 8701a201 32011801 0001eb00 4c01ec00 94001e00 0d001100 da002800 3900ec00 77018401 c400f300 cb00ce00 cd00c300 6a002a00 3f002900 dd002c00 2900ce00 3a014201 7c00f500 1101d300 eb007c00 60005b00 4a003f00 e1006300 2600bb00 01010101 9500f300 f900b400 54004400 45004100 3e004200 e600bc00 43006700 99007d00 9a00cf00 80002800 29004700 4b003100 4c005200 e900f300 e800d300 8c008900 9800a500 23002100 2c003f00 42003800 54004800>;

20 = 4;

23 = 2048;

25 = 104;

29 = "0.01916484";

3 = {

epoch = 0;

flags = 1;

timescale = 1000000000;

value = 685386048740708;

};

31 = 1;

4 = 1;

5 = 209;

6 = 208;

7 = 1;

8 = (

"-0.06963165",

"-0.9845309",

"-0.06825648"

);

};

"{TIFF}" = {

DateTime = "2018:05:05 17:35:25";

Make = Apple;

Model = "iPhone X";

ResolutionUnit = 2;

Software = "11.3";

XResolution = 72;

YResolution = 72;

};

}

auxDataInfo= nil

In your print you get :


ImageProps= {

ColorModel = RGB;

DPIHeight = 72;

DPIWidth = 72;

Depth = 8;


Isn't it the depth you look for ?


In that case, it should be (I'm not sure of the key) accessible as :

imageProperties["Depth"] as? Int


Thanks to tell if that works