iOS15.4からLiDARの生データにアクセスできるようになりました。
それを使ってDepth情報を取る場合、画像データと共に取ることがケースとして多いと思うので、上記の
// Create an object to output video sample buffers.
videoDataOutput = AVCaptureVideoDataOutput()
captureSession.addOutput(videoDataOutput)
// Create an object to output depth data.
depthDataOutput = AVCaptureDepthDataOutput()
depthDataOutput.isFilteringEnabled = isFilteringEnabled
captureSession.addOutput(depthDataOutput)
// Create an object to synchronize the delivery of depth and video data.
outputVideoSync = AVCaptureDataOutputSynchronizer(dataOutputs: [depthDataOutput, videoDataOutput])
outputVideoSync.setDelegate(self, queue: videoQueue)
こんな感じでDelegateをセットしてあげて、
func dataOutputSynchronizer(_ synchronizer: AVCaptureDataOutputSynchronizer,
didOutput synchronizedDataCollection: AVCaptureSynchronizedDataCollection)
で取得したイメージとdepthにアクセ スできます。
そんな時に、取得したdepthに対して値を取ると非線形データになっている場合があると思います。(逆数の上に対数取ったみたいな形になっている)
そのような場合は、下記のようにtypeをdepth系のものに指定してあげる必要があります。
let depthMap = syncedDepthData.depthData.converting(toDepthDataType: kCVPixelFormatType_DepthFloat32).depthDataMap
こうすることで、データが線形のmeter単位のものとして取れるようになります。
まとめると、以下のようなDelegateで深度情報は取得できます。
func dataOutputSynchronizer(_ synchronizer: AVCaptureDataOutputSynchronizer,
didOutput synchronizedDataCollection: AVCaptureSynchronizedDataCollection) {
// Retrieve the synchronized depth and sample buffer container objects.
guard let syncedDepthData = synchronizedDataCollection.synchronizedData(for: depthDataOutput) as? AVCaptureSynchronizedDepthData,
let syncedVideoData = synchronizedDataCollection.synchronizedData(for: videoOutput) as? AVCaptureSynchronizedSampleBufferData else { return }
DispatchQueue.main.async {
let rotatedImage = drawImage.rotate(radians: .pi / 2) // 90度戻す
self.previewView.image = rotatedImage
let depthPixelBuffer = syncedDepthData.depthData.converting(toDepthDataType: kCVPixelFormatType_DepthFloat32).depthDataMap
// ピクセルバッファをロックしてアクセス
CVPixelBufferLockBaseAddress(depthPixelBuffer, .readOnly)
// 深度データにアクセス
let baseAddress = CVPixelBufferGetBaseAddress(depthPixelBuffer)!
let depthPointer = baseAddress.assumingMemoryBound(to: Float32.self)
let point = CGPoint(x: 100,y: 50)
let width = CVPixelBufferGetWidth(depthPixelBuffer)
let depthValue = depthPointer[Int(point.y * CGFloat(width) + point.x)]
// ピクセルバッファのロックを解除
CVPixelBufferUnlockBaseAddress(depthPixelBuffer, .readOnly)
print(depthValue)
}
}
めっちゃ備忘録でした。