iOSはカメラの投影を元に戻します


87

宇宙のQRコードに関連するデバイスの位置を推定しようとしています。私はiOS11で導入されたARKitとVisionフレームワークを使用していますが、この質問への答えはおそらくそれらに依存していません。

Visionフレームワークを使用すると、カメラフレームのQRコードの境界となる長方形を取得できます。この長方形を、QRコードを標準位置から変換するために必要なデバイスの平行移動と回転に一致させたいと思います。

たとえば、フレームを観察すると、次のようになります。

*            *

    B
          C
  A
       D


*            *

一方、QRコードから1m離れていて、その中心にあり、QRコードの辺が10cmであると仮定すると、次のようになります。

*            *


    A0  B0

    D0  C0


*            *

これらの2つのフレーム間のデバイス変換はどのようになっていますか?観測されたQRコードがわずかに非平面であり、完全に1つではないものでアフィン変換を推定しようとしているため、正確な結果が得られない可能性があることを理解しています。

後者は、この問題について私が興味を持っていないARKitから推測された変換をすでに考慮してsceneView.pointOfView?.camera?.projectionTransformいるsceneView.pointOfView?.camera?.projectionTransform?.camera.projectionMatrixので、よりも役立つと思います。

どのように記入しますか

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

==== Edit2 ====

電話がQRコードと水平に平行なままである場合、回転が正常に機能することに気付きました(つまり、回転行列は[[a、0、b]、[0、1、0]、[c、0、d]]です。 )、実際のQRコードの向きに関係なく:

ここに画像の説明を入力してください

他の回転は機能しません。


ねえ、QRコードを介してデバイスの距離を取得しようとしていますか?もしそうなら、以下の私の答えを参照してください。
エフェロンダンツラー2017

編集:あなたの未解決の質問については、1。単に不要な値が挿入されているようです。おそらく、呼び出されたマッピング方法、または描画されている円を処理する他の何か(などdrawCircle(... rotation))2。仕様を読む時間がありませんでした3. 2と同じ
Ephellon Dantzler 2017

いくつかのコードを共有できますか?
Michal Zaborowski 2017

回答:


1

数学(三角法):

方程式

注:下の角度は(lQRコードの長さ)、左の角度はk、、上の角度はi(カメラ)です。

画像


確かに、しかし私は観測された角度iと元の距離しか知りませんl
Guig 2017

それは結構iです、反対を見つける方法はありますか?lそれが直角でない場合は、kまたはのいずれかを見つけるためにさらに多くの数学が必要thetaです。i + k + theta = 180
エフェロンダンツラー2017

1
三角法を機能させるには、2つの距離と1つの角度、または2つの角度と1つの距離のいずれかが必要です。1つの角度と1つの距離からすべてを取得する方法はありません
Guig 2017

QRコードが正方形であるため、垂直と水平の2つの角度を観察できますか?
ボブウェイクフィールド

1

問題はマトリックスにないのではないかと思います。頂点の配置にあります。2D画像を追跡するには、ABCD頂点を反時計回りに配置する必要があります(開始点は仮想原点に ある頂点です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は、ノードのピボットプロパティに対して、コンポーネントの逆の順序で回転を適用します。最初にrollZ軸を中心に)、次にyawY軸を中心に)、次にpitchX軸を中心に)です。したがって、回転順序はZYXです。

また、Nukepediaの行列演算に関する役立つ投稿があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.