Image Depth Maps Tutorial for iOS: Getting Started | raywenderlich.com

Learn how you can use the incredibly powerful image manipulation frameworks on iOS to use image depth maps with only a few lines of code.


This is a companion discussion topic for the original entry at https://www.raywenderlich.com/8246240-image-depth-maps-tutorial-for-ios-getting-started
1 Like

Love this tutorial and the code.
I have one question though. I’d like to save the image with the manipulated depth data back to the camera roll. But not as the finished processed image. I’d like it to show up in the photos app as an image with portrait mode. Where you can change the focal length etc
In short: is this possible? Load an image with depth data. Manipulate depth data. Save it back as an image with depth information.
CgdestinationAddAuxData etc but I wasn’t able to do it. Would be cool if the tutorial covered this topic too! Thanks for your great work!

It’s really a good tutorial and explanation.
I have 1 question here:
Is it possible to get distance of every pixel on the image from the Camera?

Hi Owen, very nice tutorial. One suggestion for the normalize function would be to use the Accelerate framework vector based functions. It’s much faster than stepping pixel by pixel. And also something people should learn about.
I replaced your normalize() with the following two functions.
best regards
Will L-B

import Accelerate

extension CVPixelBuffer {
func vectorNormalize( targetVector: UnsafeMutableBufferPointer) β†’ [Float] {
// range = max - min
// normalized to 0…1 is (pixel - minPixel) / range

  // see Documentation "Using vDSP for Vector-based Arithmetic" in vDSP under system "Accelerate" documentation

  // see also the Accelerate documentation section 'Vector extrema calculation'
  // Maximium static func maximum<U>(U) -> Float
  //      Returns the maximum element of a single-precision vector.

  //static func minimum<U>(U) -> Float
  //      Returns the minimum element of a single-precision vector.


  let maxValue = vDSP.maximum(targetVector)
  let minValue = vDSP.minimum(targetVector)

  let range = maxValue - minValue
  let negMinValue = -minValue

  let subtractVector = vDSP.add(negMinValue, targetVector)
      // adding negative value is subtracting
  let result = vDSP.divide(subtractVector, range)

  return result

}

func normalize() β†’ CVPixelBuffer {
// grayscale buffer float32 ie Float
// return normalized CVPixelBuffer

  CVPixelBufferLockBaseAddress(self,
                               CVPixelBufferLockFlags(rawValue: 0))
  let width = CVPixelBufferGetWidthOfPlane(self, 0)
  let height = CVPixelBufferGetHeightOfPlane(self, 0)
  let count = width * height

  let bufferBaseAddress = CVPixelBufferGetBaseAddressOfPlane(self, 0)
      // UnsafeMutableRawPointer

  let pixelBufferBase  = unsafeBitCast(bufferBaseAddress, to: UnsafeMutablePointer<Float>.self)

  let depthCopy  =   UnsafeMutablePointer<Float>.allocate(capacity: count)
  depthCopy.initialize(from: pixelBufferBase, count: count)
  let depthCopyBuffer = UnsafeMutableBufferPointer<Float>(start: depthCopy, count: count)

  let normalizedDisparity = vectorNormalize(targetVector: depthCopyBuffer)

  pixelBufferBase.initialize(from: normalizedDisparity, count: count)
      // copy back the normalized map into the CVPixelBuffer

  depthCopy.deallocate()

// depthCopyBuffer.deallocate()

  CVPixelBufferUnlockBaseAddress(self, CVPixelBufferLockFlags(rawValue: 0))

  return self

}
}

Thanks for the suggestions above!