我试图估算与太空中QR码相关的设备位置。我在iOS11中使用了ARKit和Vision框架,但这个问题的答案可能并不依赖于它们。
使用Vision框架,我能够获得在相机框架中限制QR码的矩形。我希望将此矩形与从标准位置转换QR码所需的设备平移和旋转相匹配。
例如,如果我观察到框架:
* *
B
C
A
D
* *
如果我距离QR码1米远,以它为中心,假设QR码的边长为10cm,我会看到:
* *
A0 B0
D0 C0
* *
这两个帧之间的设备转换是什么?我知道确切的结果可能是不可能的,因为可能观察到的QR码略微是非平面的,我们正试图估计一个不完美的东西的仿射变换。
我认为sceneView.pointOfView?.camera?.projectionTransform
比sceneView.pointOfView?.camera?.projectionTransform?.camera.projectionMatrix
更有帮助,因为后者已经考虑了从ARKit推断的转换,我对这个问题不感兴趣。
我将如何填写
func get transform(
qrCodeRectangle: VNBarcodeObservation,
cameraTransform: SCNMatrix4) {
// qrCodeRectangle.topLeft etc is the position in [0, 1] * [0, 1] of A0
// expected real world position of the QR code in a referential coordinate system
let a0 = SCNVector3(x: -0.05, y: 0.05, z: 1)
let b0 = SCNVector3(x: 0.05, y: 0.05, z: 1)
let c0 = SCNVector3(x: 0.05, y: -0.05, z: 1)
let d0 = SCNVector3(x: -0.05, y: -0.05, z: 1)
let A0, B0, C0, D0 = ?? // CGPoints representing position in
// camera frame for camera in 0, 0, 0 facing Z+
// then get transform from 0, 0, 0 to current position/rotation that sees
// a0, b0, c0, d0 through the camera as qrCodeRectangle
}
====编辑====
在尝试了很多事情后,我最终使用openCV投影和透视解算器进行相机姿态估计,solvePnP
这给了我一个旋转和平移,它应该代表QR码参考中的相机姿势。但是,当使用这些值并放置与逆变换相对应的对象时,QR码应该在相机空间中,我得到不准确的移位值,并且我无法使旋转起作用:
// some flavor of pseudo code below
func renderer(_ sender: SCNSceneRenderer, updateAtTime time: TimeInterval) {
guard let currentFrame = sceneView.session.currentFrame, let pov = sceneView.pointOfView else { return }
let intrisics = currentFrame.camera.intrinsics
let QRCornerCoordinatesInQRRef = [(-0.05, -0.05, 0), (0.05, -0.05, 0), (-0.05, 0.05, 0), (0.05, 0.05, 0)]
// uses VNDetectBarcodesRequest to find a QR code and returns a bounding rectangle
guard let qr = findQRCode(in: currentFrame) else { return }
let imageSize = CGSize(
width: CVPixelBufferGetWidth(currentFrame.capturedImage),
height: CVPixelBufferGetHeight(currentFrame.capturedImage)
)
let observations = [
qr.bottomLeft,
qr.bottomRight,
qr.topLeft,
qr.topRight,
].map({ (imageSize.height * (1 - $0.y), imageSize.width * $0.x) })
// image and SceneKit coordinated are not the same
// replacing this by:
// (imageSize.height * (1.35 - $0.y), imageSize.width * ($0.x - 0.2))
// weirdly fixes an issue, see below
let rotation, translation = openCV.solvePnP(QRCornerCoordinatesInQRRef, observations, intrisics)
// calls openCV solvePnP and get the results
let positionInCameraRef = -rotation.inverted * translation
let node = SCNNode(geometry: someGeometry)
pov.addChildNode(node)
node.position = translation
node.orientation = rotation.asQuaternion
}
这是输出:
其中A,B,C,D是按顺序传递给程序的QR码角。
当手机旋转时,预测的原点保持不变,但它会从应有的位置移开。令人惊讶的是,如果我移动观察值,我能够纠正这个:
// (imageSize.height * (1 - $0.y), imageSize.width * $0.x)
// replaced by:
(imageSize.height * (1.35 - $0.y), imageSize.width * ($0.x - 0.2))
现在预测的起源保持稳健。但是,我不明白班次值的来源。
最后,我尝试相对于QR码参考修正了方向:
var n = SCNNode(geometry: redGeometry)
node.addChildNode(n)
n.position = SCNVector3(0.1, 0, 0)
n = SCNNode(geometry: blueGeometry)
node.addChildNode(n)
n.position = SCNVector3(0, 0.1, 0)
n = SCNNode(geometry: greenGeometry)
node.addChildNode(n)
n.position = SCNVector3(0, 0, 0.1)
当我直接查看二维码时,方向很好,但随后会转移一些似乎与手机轮换有关的内容:
我遇到的突出问题是:
如果有帮助,这里有一些数值:
Intrisics matrix
Mat 3x3
1090.318, 0.000, 618.661
0.000, 1090.318, 359.616
0.000, 0.000, 1.000
imageSize
1280.0, 720.0
screenSize
414.0, 736.0
==== Edit2 ====
我注意到当手机水平平行于QR码时旋转工作正常(即旋转矩阵是[[a,0,b],[0,1,0],[c, 0,d]]),无论实际的QR码方向是什么:
其他轮换不起作用。
答案 0 :(得分:1)
注意:底部为l
(QR码长度),左角为k
,顶角为i
(相机)
答案 1 :(得分:1)
我认为问题不在矩阵中。它位于顶点位置。要跟踪2D图像,您需要逆时针放置ABCD顶点(起点是位于虚构原点 x:0, y:0
中的A顶点)。我认为VNRectangleObservation类的Apple文档(图像分析请求检测到的投影矩形区域的信息)含糊不清。您按照官方文档中的顺序放置了顶点:
var bottomLeft: CGPoint
var bottomRight: CGPoint
var topLeft: CGPoint
var topRight: CGPoint
但是它们需要像笛卡尔坐标系中的正旋转方向(约Z
轴)一样放置:
ARKit中的世界坐标空间(以及SceneKit和Vision中)始终跟随right-handed convention
(正Y
轴向上指向,正Z
轴指向观察者并且正X
轴指向观众的右侧),但是根据您的会话配置进行定向。相机适用于本地坐标空间。
任何轴的旋转方向为正(逆时针)和负(顺时针)。对于在ARKit和Vision中进行跟踪,它至关重要。
旋转顺序也很有意义。 ARKit和SceneKit以相反的顺序相对于节点的pivot属性应用旋转:首先roll
(约Z
轴),然后yaw
(约{{1} }},然后Y
(约pitch
轴)。因此,轮换顺序为X
。
此外,还有关于Nukepedia的Matrix Operations的有用帖子。