87 votes

iOS revenir projection caméra

Je vais essayer d'estimer mon appareil position par rapport à un QR code dans l'espace. Je suis en utilisant ARKit et la Vision du cadre, à la fois introduit dans iOS11, mais la réponse à cette question ne dépend pas d'eux.

Avec la Vision du cadre, je suis en mesure d'obtenir le rectangle qui délimite un QR code dans le cadre de l'appareil. J'aimerais correspondre à ce rectangle pour le dispositif de translation et de rotation nécessaire pour transformer le QR code à partir d'une position de référence.

Par exemple, si j'observe l'image:

*            *

    B
          C
  A
       D


*            *

alors que si j'étais à 1m de distance à partir du QR code, centré sur elle, et en supposant que le QR code a un côté de 10cm j'aimerais voir:

*            *


    A0  B0

    D0  C0


*            *

ce qui a été mon appareil de transformation entre ces deux images? Je comprends qu'un résultat exact pourrait ne pas être possible, parce que peut-être observés QR code est un peu hors du plan et nous essayons d'estimer une transformation affine sur quelque chose qui n'est pas parfaitement.

Je suppose que l' sceneView.pointOfView?.camera?.projectionTransform est plus utile que l' sceneView.pointOfView?.camera?.projectionTransform?.camera.projectionMatrix depuis le plus tard tient déjà compte de transformer déduit à partir de la ARKit que je ne suis pas intéressé à ce problème.

Comment pourrais-je le remplir

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 
}

====Edit====

Après avoir essayé plusieurs choses, j'ai fini par aller pour la caméra pose d'estimation à l'aide d'openCV projection et le point de vue du solveur, solvePnP Cela me donne de rotation et de translation, qui devrait représenter la caméra pose dans le QR code référentielle. Cependant lors de l'utilisation de ces valeurs et de placer des objets correspondant à la transformation inverse, où le QR code doit être dans la caméra de l'espace, je reçois inexactes valeurs décalées, et je ne suis pas en mesure d'obtenir la rotation de travailler:

// 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
}

Voici le résultat:

enter image description here

où A, B, C, D sont le QR code de coins dans l'ordre qu'ils sont passés au programme.

La prédiction de l'origine reste en place lorsque le téléphone tourne, mais il est déplacé de l'endroit où il devrait être. Étonnamment, si je déplace les observations des valeurs, je suis en mesure de corriger ce:

  // (imageSize.height * (1 - $0.y), imageSize.width * $0.x)
  // replaced by:
  (imageSize.height * (1.35 - $0.y), imageSize.width * ($0.x - 0.2))

enter image description here

et maintenant, la prédiction de l'origine reste solidement en place. Cependant, je ne comprends pas d'où le changement des valeurs viennent.

Enfin, j'ai essayé d'obtenir une orientation fixe relativement au code QR référentielle:

    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)

L'orientation est très bien, quand je regarde le code QR tout droit, mais alors il se déplace par quelque chose qui semble être liées au téléphone mobile en rotation:enter image description here

Les questions en suspens que j'ai sont:

  • Comment puis-je résoudre la rotation?
  • où la position de décalage de valeurs proviennent de?
  • Quelle relation simple n'rotation, translation, QRCornerCoordinatesInQRRef, des observations, des intrisics vérifier? Est-il O ~ K^-1 * (R_3x2 | T) Q ? Parce que si c'est pour finir par un peu d'ordre de grandeur.

Si c'est utile, voici quelques valeurs numériques:

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 ====

J'ai remarqué que la rotation fonctionne bien lorsque le téléphone reste à l'horizontale parallèle à la QR code (c'est à dire la matrice de rotation est [[a, 0, b], [0, 1, 0], [c, 0, d]]), sans que le QR code de l'orientation est:

enter image description here

De rotation ne fonctionne pas.

2voto

Gigantic Points 4447

Je suppose que le problème n'est pas dans la matrice. C'est dans les sommets de placement. Pour le suivi des images en 2D, vous devez placer ABCD sommets des aiguilles d'une montre (le point de départ est Un sommet situé dans l'imaginaire origine x:0, y:0). Je pense que la Documentation d'Apple sur VNRectangleObservation classe (plus d'informations sur projetée des régions rectangulaires détectée par une analyse d'image demande) est vague. Vous avez placé vos vertices dans le même ordre que celui qui est dans la documentation officielle:

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

Mais ils doivent être placés de la même manière que le sens de rotation positif (environ Z axe) se produit dans le système de coordonnées Cartésiennes:

enter image description here

Monde de Coordonnées de l'Espace dans ARKit (ainsi que dans SceneKit et de la Vision) suit toujours un right-handed convention (positifs Y axe pointe vers le haut, le positif Z axe pointe vers le spectateur et le positif X axe pointe vers le spectateur a le droit), mais est orientée en fonction de votre session de configuration. La caméra fonctionne en Local Espace de Coordonnées.

Le sens de Rotation sur un axe quelconque est positif (sens anti-Horaire) et négatif (sens Horaire). Pour le suivi en ARKit et la Vision, il est d'une importance critique.

enter image description here

L'ordre de rotation est également logique. ARKit, ainsi que SceneKit, s'applique rotation par rapport au nœud de propriété pivot dans l'ordre inverse de l'volets: premièrement roll (environ Z axe), alors yaw (environ Y axe), alors pitch (environ X de l'axe). Donc, l'ordre de rotation est - ZYX.

Aussi, il est utile de post sur les Opérations matricielles sur Nukepedia.

1voto

<h1>Math (Trig.) :<p><img src="https://latex.codecogs.com/png.latex?%5Cbg_white%20%5Clarge%20d%20%3D%20%5Cfrac%7Bl%5Ctimes%20sin%5C%3B%5Ctheta%5Ctimes%20sin%5C%3Bk%7D%7Bsin%5C%3Bi%7D" alt="Equation"></p><p>Notes : le fond est <code></code> (la longueur du code QR), l’angle gauche est <code></code> , et l’angle au sommet est <code></code> (la caméra)</p><p><img src="https://i.stack.imgur.com/sMU1g.jpg" alt="Picture"></p></h1>

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X