ARKit – 如何在二维码上放置 3D 对象? [英] ARKit – How to put 3D Object on QRCode?
问题描述
我实际上是在尝试使用 ARKit 在 QRCode 上放置 3D 对象为此,我使用 AVCaptureDevice 来检测二维码并建立二维码区域,该区域为我提供 CGRect.然后,我在 CGRect 的每个点上进行 hitTest 以获得平均 3D 坐标,如下所示:
I'm actually trying to put a 3D Object on QRCode with ARKit For that I use a AVCaptureDevice to detect a QRCode and establish the area of the QRCode that gives me a CGRect. Then, I make a hitTest on every point of the CGRect to get the average 3D coordinates like so :
positionGiven = SCNVector3(0, 0, 0)
for column in Int(qrZone.origin.x)...2*Int(qrZone.origin.x + qrZone.width) {
for row in Int(qrZone.origin.y)...2*Int(qrZone.origin.y + qrZone.height) {
for result in sceneView.hitTest(CGPoint(x: CGFloat(column)/2,y:CGFloat(row)/2), types: [.existingPlaneUsingExtent,.featurePoint]) {
positionGiven.x+=result.worldTransform.columns.3.x
positionGiven.y+=result.worldTransform.columns.3.y
positionGiven.z+=result.worldTransform.columns.3.z
cpts += 1
}
}
}
positionGiven.x=positionGiven.x/cpts
positionGiven.y=positionGiven.y/cpts
positionGiven.z=positionGiven.z/cpts
但是 hitTest 没有检测到任何结果并冻结相机,而当我通过触摸屏幕进行 hitTest 时它可以工作.你知道为什么它不起作用吗?你有其他想法可以帮助我实现我想做的事情吗?
But the hitTest doesn't detect any result and freeze the camera while when I make a hitTest with a touch on screen it works. Do you have any idea why it's not working ? Do you have an other idea that can help me to achieve what I want to do ?
我已经考虑过使用 CoreMotion 进行 3D 转换,它可以让我倾斜设备,但这似乎非常乏味.我也听说ARWorldAlignmentCamera可以锁定场景坐标以匹配相机的方向,但我不知道如何使用它!
I already thought about 3D translation with CoreMotion that can give me the tilt of the device but that seems really tedious. I also heard about ARWorldAlignmentCamera that can locked the scene coordinate to match the orientation of the camera but I don't know how to use it !
编辑:每次触摸屏幕时我都会尝试移动我的 3D 对象,并且 hitTest 为正值,而且非常准确!我真的不明白为什么在像素区域上进行 hitTest 不起作用...
Edit : I try to move my 3D Object every time I touch the screen and the hitTest is positive, and it's pretty accurate ! I really don't understand why hitTest on an area of pixels doesn't work...
Edit 2 :这是在屏幕上进行 2-5 次触摸的 hitTest 的代码:
Edit 2 : Here is the code of the hitTest who works with 2-5 touches on the screen:
@objc func touch(sender : UITapGestureRecognizer) {
for result in sceneView.hitTest(CGPoint(x: sender.location(in: view).x,y: sender.location(in: view).y), types: [.existingPlaneUsingExtent,.featurePoint]) {
//Pop up message for testing
alert("\(sender.location(in: view))", message: "\(result.worldTransform.columns.3)")
//Moving the 3D Object to the new coordinates
let objectList = sceneView.scene.rootNode.childNodes
for object : SCNNode in objectList {
object.removeFromParentNode()
}
addObject(SCNVector3(result.worldTransform.columns.3.x,result.worldTransform.columns.3.y,result.worldTransform.columns.3.z))
}
}
编辑 3 :我设法部分解决了我的问题.
Edit 3 : I manage to resolve my problem partially.
我取相机的变换矩阵 (session.currentFrame.camera.transform),以便对象位于相机前面.然后我使用 CGRect 的位置在 (x,y) 上应用平移.但是我无法翻译 z 轴,因为我没有足够的信息.我可能需要像 hitTest 那样估计 z 坐标..
I take the transform matrix of the camera (session.currentFrame.camera.transform) so that the object is in front of the camera. Then I apply a translation on (x,y) with the position of the CGRect. However i can't translate the z-axis because i don't have enough informations. And I will probably need a estimation of z coordinate like the hitTest do..
提前致谢!:)
推荐答案
您可以使用 Apple 的 Vision API 检测二维码并放置一个锚点.
You could use Apple's Vision API to detect the QR code and place an anchor.
要开始检测二维码,请使用:
To start detecting QR codes, use:
var qrRequests = [VNRequest]()
var detectedDataAnchor: ARAnchor?
var processing = false
func startQrCodeDetection() {
// Create a Barcode Detection Request
let request = VNDetectBarcodesRequest(completionHandler: self.requestHandler)
// Set it to recognize QR code only
request.symbologies = [.QR]
self.qrRequests = [request]
}
在ARSession
的didUpdate Frame
public func session(_ session: ARSession, didUpdate frame: ARFrame) {
DispatchQueue.global(qos: .userInitiated).async {
do {
if self.processing {
return
}
self.processing = true
// Create a request handler using the captured image from the ARFrame
let imageRequestHandler = VNImageRequestHandler(cvPixelBuffer: frame.capturedImage,
options: [:])
// Process the request
try imageRequestHandler.perform(self.qrRequests)
} catch {
}
}
}
处理 Vision QR 请求并触发命中测试
Handle the Vision QR request and trigger the hit test
func requestHandler(request: VNRequest, error: Error?) {
// Get the first result out of the results, if there are any
if let results = request.results, let result = results.first as? VNBarcodeObservation {
guard let payload = result.payloadStringValue else {return}
// Get the bounding box for the bar code and find the center
var rect = result.boundingBox
// Flip coordinates
rect = rect.applying(CGAffineTransform(scaleX: 1, y: -1))
rect = rect.applying(CGAffineTransform(translationX: 0, y: 1))
// Get center
let center = CGPoint(x: rect.midX, y: rect.midY)
DispatchQueue.main.async {
self.hitTestQrCode(center: center)
self.processing = false
}
} else {
self.processing = false
}
}
func hitTestQrCode(center: CGPoint) {
if let hitTestResults = self.latestFrame?.hitTest(center, types: [.featurePoint] ),
let hitTestResult = hitTestResults.first {
if let detectedDataAnchor = self.detectedDataAnchor,
let node = self.sceneView.node(for: detectedDataAnchor) {
let previousQrPosition = node.position
node.transform = SCNMatrix4(hitTestResult.worldTransform)
} else {
// Create an anchor. The node will be created in delegate methods
self.detectedDataAnchor = ARAnchor(transform: hitTestResult.worldTransform)
self.sceneView.session.add(anchor: self.detectedDataAnchor!)
}
}
}
然后在添加锚点时处理添加节点.
Then handle adding the node when the anchor is added.
func renderer(_ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode? {
// If this is our anchor, create a node
if self.detectedDataAnchor?.identifier == anchor.identifier {
let sphere = SCNSphere(radius: 1.0)
sphere.firstMaterial?.diffuse.contents = UIColor.redColor()
let sphereNode = SCNNode(geometry: sphere)
sphereNode.transform = SCNMatrix4(anchor.transform)
return sphereNode
}
return nil
}
这篇关于ARKit – 如何在二维码上放置 3D 对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!