我試圖估計我的設備位置與空間中的QR碼相關。我使用ARKit和Vision框架,都是在iOS11中引入的,但這個問題的答案可能不依賴於它們。iOS恢復相機投影
使用Vision框架,我可以獲取在相機框架中綁定QR碼的矩形。我想將這個矩形匹配到從標準位置轉換QR碼所需的設備轉換和旋轉。
例如,如果我觀察幀:
* *
B
C
A
D
* *
而如果我是米從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,觀察,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碼方向如何:
其他旋轉不起作用。
嘿,你想通過QR碼獲取設備距離嗎?如果是這樣,請參閱下面的答案。 –
編輯:爲你的未解決的問題, 1.這聽起來像只是一個不必要的值插入。可能在調用的映射方法中,或其他處理正在繪製的圓的其他任何東西(如'drawCircle(... rotation)') 2.沒有時間閱讀規格 3.與2相同 –
您會能夠分享一些代碼? – mientus