मैं अंतरिक्ष में एक क्यूआर कोड से संबंधित अपने डिवाइस की स्थिति का अनुमान लगाने की कोशिश कर रहा हूं। मैं ARKit और विज़न फ्रेमवर्क का उपयोग कर रहा हूँ, दोनों को iOS11 में पेश किया गया है, लेकिन इस प्रश्न का उत्तर शायद उन पर निर्भर नहीं करता है।
विज़न फ्रेमवर्क के साथ, मैं उस आयत को प्राप्त करने में सक्षम हूँ जो कैमरा फ्रेम में एक क्यूआर कोड को बांधता है। मैं एक मानक स्थिति से क्यूआर कोड को बदलने के लिए डिवाइस के अनुवाद और रोटेशन के लिए इस आयत से मेल खाना चाहता हूं।
उदाहरण के लिए यदि मैं फ्रेम का निरीक्षण करता हूं:
* *
B
C
A
D
* *
अगर मैं क्यूआर कोड से 1 मी दूर था, तो उस पर केंद्रित था, और मान लिया कि क्यूआर कोड में 10 सेमी का एक पक्ष होता है।
* *
A0 B0
D0 C0
* *
उन दो फ़्रेमों के बीच मेरा डिवाइस परिवर्तन क्या रहा है? मैं समझता हूं कि एक सटीक परिणाम संभव नहीं हो सकता है, क्योंकि हो सकता है कि मनाया गया क्यूआर कोड थोड़ा नॉन प्लानर हो और हम एक ऐसी चीज पर एक बदलाव का अनुमान लगाने की कोशिश कर रहे हैं जो पूरी तरह से एक नहीं है।
मुझे लगता 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
}
==== संपादित करें ====
चीजों की संख्या की कोशिश करने के बाद, मैंने ओपन सीसीवी प्रोजेक्शन और परिप्रेक्ष्य सॉल्वर का उपयोग करके कैमरा पोज अनुमान के लिए जाना समाप्त कर दिया, solvePnP
इससे मुझे एक रोटेशन और अनुवाद मिलता है जो कि क्यूआर कोड रेफ़रेंशियल में कैमरा पोज़ का प्रतिनिधित्व करना चाहिए। हालाँकि, उन मूल्यों का उपयोग करते समय और उलटे परिवर्तन के लिए वस्तुओं को रखने के लिए, जहां क्यूआर कोड कैमरा स्थान में होना चाहिए, मुझे गलत तरीके से स्थानांतरित किए गए मान मिलते हैं, और मैं काम करने के लिए रोटेशन प्राप्त करने में सक्षम नहीं हूं:
// 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
}
यहाँ उत्पादन है:
जहां ए, बी, सी, डी क्यूआर कोड कोनों होते हैं, जिस क्रम में उन्हें कार्यक्रम में भेजा जाता है।
पूर्वानुमानित उत्पत्ति तब होती है जब फ़ोन घूमता है, लेकिन यह कहाँ से स्थानांतरित किया जाना चाहिए। हैरानी की बात है, अगर मैं टिप्पणियों के मूल्यों को स्थानांतरित करता हूं, तो मैं इसे ठीक करने में सक्षम हूं:
// (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)
जब मैं सीधे क्यूआर कोड को देखता हूं, तो अभिविन्यास ठीक है, लेकिन फिर यह कुछ इस तरह से बदल जाता है कि फोन रोटेशन से संबंधित प्रतीत होता है:
मेरे पास बकाया प्रश्न हैं:
- मैं रोटेशन को कैसे हल करूं?
- स्थिति शिफ्ट मान कहां से आते हैं?
- क्या सरल रिश्ता रोटेशन, अनुवाद, QRCornerCoordinatesInQRRef, टिप्पणियों, इंट्रिक्टिक्स को सत्यापित करता है? क्या यह 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 ====
मैंने देखा है कि जब फोन क्यूआर कोड (यानी रोटेशन मैट्रिक्स [[ए, 0, बी]], [0, 1, 0], [सी, 0, डी] के समानांतर होता है तो रोटेशन ठीक काम करता है। ), कोई फर्क नहीं पड़ता कि वास्तविक क्यूआर कोड अभिविन्यास क्या है:
अन्य रोटेशन काम नहीं करते।