结合 CoreML 对象检测和 ARKit 2D 图像检测
Combining CoreML Object Detection and ARKit 2D Image Detection
该应用程序检测特定的 2D 图像(使用 ARKit)并有一个检测一些家具的 mlmodel,mlmodel 是对象检测类型,它经过训练并且可以工作。根据检测到的内容,我需要将一些 3D 对象添加到场景或其他对象。
我使用 ARWorldTrackingConfiguration 创建了一个 AR 会话,我可以检测到 2D 图像,并且在方法 renderer(_:didAdd:for:) 中我添加了 3D 对象并且它完美地工作:
override func viewDidAppear(_ animated: Bool) {
super.viewWillAppear(animated)
guard let referenceImages = ARReferenceImage.referenceImages(inGroupNamed: "AR Resources", bundle: nil) else {
fatalError("Missing expected asset catalog resources.")
}
let configuration = ARWorldTrackingConfiguration()
configuration.worldAlignment = .gravityAndHeading
configuration.detectionImages = referenceImages
configuration.maximumNumberOfTrackedImages = 1
configuration.isAutoFocusEnabled = false
sceneView.session.run(configuration, options: [.resetTracking, .removeExistingAnchors])
}
此外,我设置了 mlmodel:
override func viewDidLoad() {
super.viewDidLoad()
sceneView.delegate = self
sceneView.session.delegate = self
setupML()
}
internal func setupML() {
guard let modelPath = Bundle.main.url(forResource: "furnituresDetector", withExtension: "mlmodelc") else {
fatalError("Missing model")
}
do {
let coreMLModel = try VNCoreMLModel(for: MLModel(contentsOf: modelPath))
let request = VNCoreMLRequest(model: coreMLModel) { [weak self] (request, error) in
DispatchQueue.main.async {
if let results = request.results {
print(results.count)
}
}
}
self.requests = [request]
} catch {
print("Core ML Model error")
}
}
目前我只想打印结果数以查看 ml 模型是否检测到某些东西。
直到这里一切正常,我 运行 应用程序和相机显示流畅。我没有启动新的相机会话,而是重用了我在
中找到的由 ARSCNView 启动的会话
所以我的解决方案是使用 session(_:didUpdate:) 向 coreml 模型发出请求,并持续知道模型是否检测到相机中出现的东西。
func session(_ session: ARSession, didUpdate frame: ARFrame) {
DispatchQueue(label: "CoreML_request").async {
guard let pixelBuffer = session.currentFrame?.capturedImage else {
return
}
let exifOrientation = self.exifOrientationFromDeviceOrientation()
let imageRequestHandler = VNImageRequestHandler(cvPixelBuffer: pixelBuffer, orientation: exifOrientation, options: [:])
do {
try imageRequestHandler.perform(self.requests)
} catch {
print(error)
}
}
}
如果我 运行 该应用程序可以正常工作,但问题是相机看起来很慢,如果我删除 session(_:didUpdate:) 中的代码,相机看起来又正常了。所以问题就在这里,我想发生的事情是它不是发出这个请求的合适地方,因为当检测到相机中的新帧时,这个方法一直被调用。
但我不知道在哪里提出请求或做什么。你有什么想法吗?
如果我找到了一些解决方案,我会更新它。
谢谢!
我找到了解决办法。问题是相机的可用缓冲区有限,我排队的缓冲区太多,而另一个视觉任务仍然 运行。
这就是相机慢的原因。因此,解决方案是在执行另一个请求之前释放缓冲区。
internal var currentBuffer: CVPixelBuffer?
func session(_ session: ARSession, didUpdate frame: ARFrame) {
guard currentBuffer == nil, case .normal = frame.camera.trackingState else {
return
}
self.currentBuffer = frame.capturedImage
DispatchQueue(label: "CoreML_request").async {
guard let pixelBuffer = session.currentFrame?.capturedImage else {
return
}
let exifOrientation = self.exifOrientationFromDeviceOrientation()
let imageRequestHandler = VNImageRequestHandler(cvPixelBuffer: pixelBuffer, orientation: exifOrientation, options: [:])
do {
// Release the pixel buffer when done, allowing the next buffer to be processed.
defer { self.currentBuffer = nil }
try imageRequestHandler.perform(self.requests)
} catch {
print(error)
}
}
}
在这里你可以查看文档:
https://developer.apple.com/documentation/arkit/recognizing_and_labeling_arbitrary_objects
该应用程序检测特定的 2D 图像(使用 ARKit)并有一个检测一些家具的 mlmodel,mlmodel 是对象检测类型,它经过训练并且可以工作。根据检测到的内容,我需要将一些 3D 对象添加到场景或其他对象。
我使用 ARWorldTrackingConfiguration 创建了一个 AR 会话,我可以检测到 2D 图像,并且在方法 renderer(_:didAdd:for:) 中我添加了 3D 对象并且它完美地工作:
override func viewDidAppear(_ animated: Bool) {
super.viewWillAppear(animated)
guard let referenceImages = ARReferenceImage.referenceImages(inGroupNamed: "AR Resources", bundle: nil) else {
fatalError("Missing expected asset catalog resources.")
}
let configuration = ARWorldTrackingConfiguration()
configuration.worldAlignment = .gravityAndHeading
configuration.detectionImages = referenceImages
configuration.maximumNumberOfTrackedImages = 1
configuration.isAutoFocusEnabled = false
sceneView.session.run(configuration, options: [.resetTracking, .removeExistingAnchors])
}
此外,我设置了 mlmodel:
override func viewDidLoad() {
super.viewDidLoad()
sceneView.delegate = self
sceneView.session.delegate = self
setupML()
}
internal func setupML() {
guard let modelPath = Bundle.main.url(forResource: "furnituresDetector", withExtension: "mlmodelc") else {
fatalError("Missing model")
}
do {
let coreMLModel = try VNCoreMLModel(for: MLModel(contentsOf: modelPath))
let request = VNCoreMLRequest(model: coreMLModel) { [weak self] (request, error) in
DispatchQueue.main.async {
if let results = request.results {
print(results.count)
}
}
}
self.requests = [request]
} catch {
print("Core ML Model error")
}
}
目前我只想打印结果数以查看 ml 模型是否检测到某些东西。
直到这里一切正常,我 运行 应用程序和相机显示流畅。我没有启动新的相机会话,而是重用了我在
所以我的解决方案是使用 session(_:didUpdate:) 向 coreml 模型发出请求,并持续知道模型是否检测到相机中出现的东西。
func session(_ session: ARSession, didUpdate frame: ARFrame) {
DispatchQueue(label: "CoreML_request").async {
guard let pixelBuffer = session.currentFrame?.capturedImage else {
return
}
let exifOrientation = self.exifOrientationFromDeviceOrientation()
let imageRequestHandler = VNImageRequestHandler(cvPixelBuffer: pixelBuffer, orientation: exifOrientation, options: [:])
do {
try imageRequestHandler.perform(self.requests)
} catch {
print(error)
}
}
}
如果我 运行 该应用程序可以正常工作,但问题是相机看起来很慢,如果我删除 session(_:didUpdate:) 中的代码,相机看起来又正常了。所以问题就在这里,我想发生的事情是它不是发出这个请求的合适地方,因为当检测到相机中的新帧时,这个方法一直被调用。 但我不知道在哪里提出请求或做什么。你有什么想法吗?
如果我找到了一些解决方案,我会更新它。 谢谢!
我找到了解决办法。问题是相机的可用缓冲区有限,我排队的缓冲区太多,而另一个视觉任务仍然 运行。
这就是相机慢的原因。因此,解决方案是在执行另一个请求之前释放缓冲区。
internal var currentBuffer: CVPixelBuffer?
func session(_ session: ARSession, didUpdate frame: ARFrame) {
guard currentBuffer == nil, case .normal = frame.camera.trackingState else {
return
}
self.currentBuffer = frame.capturedImage
DispatchQueue(label: "CoreML_request").async {
guard let pixelBuffer = session.currentFrame?.capturedImage else {
return
}
let exifOrientation = self.exifOrientationFromDeviceOrientation()
let imageRequestHandler = VNImageRequestHandler(cvPixelBuffer: pixelBuffer, orientation: exifOrientation, options: [:])
do {
// Release the pixel buffer when done, allowing the next buffer to be processed.
defer { self.currentBuffer = nil }
try imageRequestHandler.perform(self.requests)
} catch {
print(error)
}
}
}
在这里你可以查看文档:
https://developer.apple.com/documentation/arkit/recognizing_and_labeling_arbitrary_objects