iOS恢复相机投影


87

我正在尝试估计与QR码在太空中相关的设备位置。我正在使用均在iOS11中引入的ARKit和Vision框架,但该问题的答案可能并不取决于它们。

使用Vision框架,我可以获得在相机框架中界定QR码的矩形。我想将此矩形与从标准位置转换QR码所需的设备平移和旋转进行匹配。

例如,如果我观察框架:

*            *

    B
          C
  A
       D


*            *

而如果我距QR码1m,以QR码为中心,假设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)

当我直视QR码时,方向很好,但是随后发生了一些与手机旋转有关的偏移:在此处输入图片说明

我有未解决的问题:

  • 我该如何解决轮换问题?
  • 位置偏移值从何而来?
  • 旋转,平移,QRCornerCoordinatesInQRRef,观测值,本征能验证什么简单关系?是O〜K ^ -1 *(R_3x2 | T)Q吗?因为如果是这样的话,那将减少几个数量级。

如果有帮助,请使用以下几个数值:

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

====编辑2 ====

我注意到,当手机水平平行于QR码时,旋转效果很好(即旋转矩阵为[[a,0,b],[0,1,0],[c,0,d]] ),无论实际的QR码方向是什么:

在此处输入图片说明

其他旋转无效。


嘿,您是否正在尝试通过QR码获取设备距离?如果是这样,请在下面查看我的答案。
Ephellon Dantzler

编辑:对于您的悬而未决的问题,1.听起来好像只是插入了一个不必要的值。可能是在称为的映射方法中,或者是其他与绘制的圆有关的事物(例如drawCircle(... rotation))。2.没时间阅读规范。3.与2相同
Ephellon Dantzler

您可以共享一些代码吗?
Michal Zaborowski

Answers:


1

数学(触发):

方程

注意:底部为l(QR码长度),左侧为k,顶部为i(相机)

图片


当然,但是我只知道观察到的角度i和原始距离l
Guig

很好,有没有办法找到相反的东西i?如果不是一个合适的角度,l那么要找到一个k或一个就涉及更多的数学运算thetai + k + theta = 180
Ephellon Dantzler

1
为了使三角函数起作用,我需要两个距离和一个角度,或者两个角度和一个距离。无法从一个角度和一个距离获得所有信息
Guig

QR码为正方形是否有帮助,以便您可以观察到垂直和水平两个角度?
鲍勃·韦克菲尔德

1

我想问题不在矩阵中。在顶点位置。为了跟踪2D图像,您需要逆时针放置ABCD顶点(起始点是位于假想原点的 A顶点x:0, y:0)。我认为有关VNRectangleObservation类(有关由图像分析请求检测到的投影矩形区域的信息)的Apple文档含糊不清。您按照与官方文档中相同的顺序放置了顶点:

var bottomLeft: CGPoint
var bottomRight: CGPoint
var topLeft: CGPoint
var topRight: CGPoint

但是,它们的放置方式必须与Z直角坐标系中出现正旋转方向(绕轴)相同:

在此处输入图片说明

ARKit(以及SceneKit和Vision中)的世界坐标空间始终遵循a right-handed convention(正Y轴指向上方,正Z轴指向查看者,正X轴指向查看者的右边),但基于会话的配置进行定向。相机在局部坐标空间中工作。

绕任何轴的旋转方向为正(逆时针)和负(逆时针)。对于在ARKit和Vision中进行跟踪,这一点至关重要。

在此处输入图片说明

旋转顺序也很有意义。ARKit和SceneKit均按照与组件相反的顺序相对于节点的ivot属性应用旋转:首先roll(绕Z轴),然后yaw(绕Y轴),然后pitch(绕X轴)。因此,轮换顺序为ZYX

此外,还有关于Nukepedia上的矩阵运算的有用文章。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.