2017-06-16 119 views
63

我試圖估計我的設備位置與空間中的QR碼相關。我使用ARKit和Vision框架,都是在iOS11中引入的,但這個問題的答案可能不依賴於它們。iOS恢復相機投影

使用Vision框架,我可以獲取在相機框架中綁定QR碼的矩形。我想將這個矩形匹配到從標準位置轉換QR碼所需的設備轉換和旋轉。

例如,如果我觀察幀:

*   * 

    B 
      C 
    A 
     D 


*   * 

而如果我是米從QR碼,集中於它,並且假定QR碼遠離具有10cm的側我會看到:

*   * 


    A0 B0 

    D0 C0 


*   * 

這兩個幀之間的設備轉換是什麼?我知道一個確切的結果可能是不可能的,因爲可能觀察到的QR碼是非平面的,我們正在試圖估計一個並非完美的東西的仿射變換。

我猜sceneView.pointOfView?.camera?.projectionTransformsceneView.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 
} 

這裏是輸出:

enter image description here

其中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)) 

enter image description here

,現在預測起源於地方留成強勁。不過,我不明白移位值的來源。

最後,我試圖得到相對固定的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碼直視,但隨後通過的東西,似乎轉移可能與手機旋轉:enter image description here

懸而未決的問題我已經是:

  • 如何解決旋轉?
  • 位置偏移值從哪裏來?
  • 什麼簡單的關係做旋轉,翻譯,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 

==== ==== EDIT2

我已經注意到,旋轉工作正常時,手機都會保持與QR碼水平平行(即旋轉矩陣爲[[a,0,b],[0,1,0],[c,0,d]]),無論實際的QR碼方向如何:

enter image description here

其他旋轉不起作用。

+0

嘿,你想通過QR碼獲取設備距離嗎?如果是這樣,請參閱下面的答案。 –

+0

編輯:爲你的未解決的問題, 1.這聽起來像只是一個不必要的值插入。可能在調用的映射方法中,或其他處理正在繪製的圓的其他任何東西(如'drawCircle(... rotation)') 2.沒有時間閱讀規格 3.與2相同 –

+0

您會能夠分享一些代碼? – mientus

回答

0

數學(觸發):

Equation

注:底部是l(QR碼長度),左角度是k,並且頂部的角度是i(照相機)

Picture

+0

肯定,但我只知道觀測角度'我'和原始距離'l' – Guig

+0

這很好,有沒有辦法找到'我'的相反?如果它不是'l'的正確角度,那麼找到'k'或'theta'就會有更多的數學問題; 'i + k + theta = 180'。 –

+1

爲了讓三角函數工作,我需要兩個距離和一個角度,或者兩個角度和一個距離。沒有辦法從一個角度和一個距離獲取所有內容 – Guig