우주에서 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 코드 방향에 관계없이 :
다른 회전은 작동하지 않습니다.