Tôi đang cố gắng ước tính vị trí thiết bị của mình liên quan đến mã QR trong không gian. Tôi đang sử dụng ARKit và khung Vision, cả hai đều được giới thiệu trong iOS11, nhưng câu trả lời cho câu hỏi này có lẽ không phụ thuộc vào chúng.
Với khung Vision, tôi có thể lấy hình chữ nhật giới hạn mã QR trong khung máy ảnh. Tôi muốn khớp hình chữ nhật này với bản dịch và xoay thiết bị cần thiết để chuyển đổi mã QR từ vị trí chuẩn.
Ví dụ, nếu tôi quan sát khung hình:
* *
B
C
A
D
* *
trong khi nếu tôi cách mã QR 1m, căn giữa vào nó và giả sử mã QR có cạnh là 10cm, tôi sẽ thấy:
* *
A0 B0
D0 C0
* *
chuyển đổi thiết bị của tôi giữa hai khung hình đó là gì? Tôi hiểu rằng có thể không có kết quả chính xác, vì có thể mã QR quan sát được hơi không phẳng và chúng tôi đang cố gắng ước tính một chuyển đổi affine trên một thứ không phải là một hoàn hảo.
Tôi đoán sceneView.pointOfView?.camera?.projectionTransform
là hữu ích hơn sceneView.pointOfView?.camera?.projectionTransform?.camera.projectionMatrix
vì sau này đã tính đến chuyển đổi được suy ra từ ARKit mà tôi không quan tâm đến vấn đề này.
Tôi sẽ điền như thế nào
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
}
==== Chỉnh sửa ====
Sau khi thử một số thứ, tôi đã kết thúc ước tính tư thế máy ảnh bằng cách sử dụng công cụ giải phối cảnh và phép chiếu openCV, solvePnP
Điều này mang lại cho tôi cách xoay và bản dịch sẽ đại diện cho tư thế máy ảnh trong tham chiếu mã QR. Tuy nhiên, khi sử dụng các giá trị đó và đặt các đối tượng tương ứng với phép biến đổi nghịch đảo, nơi mã QR phải ở trong không gian máy ảnh, tôi nhận được các giá trị được dịch chuyển không chính xác và tôi không thể xoay vòng hoạt động:
// 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
}
Đây là đầu ra:
trong đó A, B, C, D là các góc mã QR theo thứ tự chúng được chuyển đến chương trình.
Điểm gốc dự đoán vẫn giữ nguyên vị trí khi điện thoại xoay, nhưng nó sẽ bị dịch chuyển so với vị trí cần thiết. Đáng ngạc nhiên, nếu tôi thay đổi các giá trị quan sát, tôi có thể sửa điều này:
// (imageSize.height * (1 - $0.y), imageSize.width * $0.x)
// replaced by:
(imageSize.height * (1.35 - $0.y), imageSize.width * ($0.x - 0.2))
và bây giờ nguồn gốc được dự đoán vẫn giữ nguyên vị trí. Tuy nhiên tôi không hiểu giá trị dịch chuyển đến từ đâu.
Cuối cùng, tôi đã cố gắng cố định hướng tương đối với tham chiếu mã 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)
Định hướng tốt khi tôi nhìn thẳng vào mã QR, nhưng sau đó nó thay đổi theo một thứ gì đó có vẻ liên quan đến xoay điện thoại:
Câu hỏi nổi bật mà tôi có là:
- Làm cách nào để giải quyết vấn đề xoay vòng?
- giá trị dịch chuyển vị trí đến từ đâu?
- Những mối quan hệ đơn giản nào mà xoay, dịch, QRCornerCoferencesInQRRef, quan sát, nội hàm xác minh? Có phải là O ~ K ^ -1 * (R_3x2 | T) Q không? Bởi vì nếu vậy thì điều đó giảm đi một vài bậc.
Nếu điều đó hữu ích, đây là một vài giá trị số:
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 ====
Tôi nhận thấy rằng xoay hoạt động tốt khi điện thoại nằm ngang song song với mã QR (tức là ma trận xoay là [[a, 0, b], [0, 1, 0], [c, 0, d]] ), bất kể hướng mã QR thực tế là gì:
Vòng quay khác không hoạt động.