[ios] iOS 되돌리기 카메라 투영

우주에서 QR 코드와 관련된 내 장치 위치를 추정하려고합니다. 저는 ARKit과 Vision 프레임 워크를 사용하고 있는데, 둘 다 iOS11에 도입되었지만이 질문에 대한 대답은 아마도 그들에 의존하지 않을 것입니다.

Vision 프레임 워크를 사용하면 카메라 프레임에서 QR 코드를 묶는 직사각형을 얻을 수 있습니다. 이 사각형을 표준 위치에서 QR 코드를 변환하는 데 필요한 장치 변환 및 회전과 일치시키고 싶습니다.

예를 들어 프레임을 관찰하면 :

*            *

    B
          C
  A
       D


*            *

QR 코드에서 1m 떨어져 있고 그 중앙에 있고 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, 관찰, intrisics는 어떤 간단한 관계를 확인합니까? 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 코드 방향에 관계없이 :

여기에 이미지 설명 입력

다른 회전은 작동하지 않습니다.



답변

수학 (트리거) :

방정식

참고 : 하단은 l(QR 코드 길이), 왼쪽 각도는 k, 상단 각도는 i(카메라)입니다.

그림


답변

문제가 매트릭스에 없다고 생각합니다. 정점 배치에 있습니다. 2D 이미지를 추적하려면 ABCD 정점을 시계 반대 방향으로 배치해야합니다 (시작점은 가상 원점 에있는 정점 x:0, y:0). VNRectangleObservation 클래스 에 대한 Apple 문서 (이미지 분석 요청에 의해 감지 된 투영 된 직사각형 영역에 대한 정보)가 모호하다고 생각합니다. 공식 문서와 동일한 순서로 정점을 배치했습니다.

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

그러나 그들은 Z직교 좌표계에서 양의 회전 방향 ( 축 에 대한 )이 발생 하는 것과 같은 방식으로 배치되어야 합니다.

여기에 이미지 설명 입력

ARKit (SceneKit 및 Vision뿐만 아니라)의 World Coordinate Space는 항상 a right-handed convention(양의 Y축은 위쪽을 가리키고 양의 Z축은 뷰어를 향하고 양의 X축은 뷰어의 오른쪽 을 가리킴 )을 따르지만 세션의 구성에 따라 방향이 지정됩니다. . 카메라는 로컬 좌표 공간에서 작동합니다.

모든 축에 대한 회전 방향은 양수 (시계 반대 방향) 및 음수 (시계 방향)입니다. ARKit 및 Vision에서 추적하려면 매우 중요합니다.

여기에 이미지 설명 입력

회전 순서도 의미가 있습니다. ARKit과 SceneKit은 구성 요소의 역순으로 노드의 피벗 속성을 기준으로 회전을 적용합니다.roll ( Z축 에 대해 ), 다음으로 yaw( Y축 에 대해 ), 다음에 pitch( X축 에 대해 ). 따라서 회전 순서는 ZYX입니다.

또한 Nukepedia 에 Matrix Operations 에 대한 유용한 게시물이 있습니다.


답변