2 डी बिंदु को 3 डी स्थान पर परिवर्तित करना


9

मेरे पास ज्ञात cameraMatrixऔर के साथ एक निश्चित कैमरा है distCoeffs। मेरे पास एक शतरंजबोर्ड भी है जो कि निश्चित है, transformऔर rotationवेक्टर का उपयोग करके भी गणना की जाती है solvePnP

मैं सोच रहा हूं कि एक ही विमान पर 2 डी बिंदु के 3 डी स्थान को कैसे प्राप्त करना संभव है, जो कि शतरंज की चौकी पर स्थित है, नीचे दिए गए चित्र की तरह:

यहां छवि विवरण दर्ज करें

एक बात सुनिश्चित है कि उस बिंदु का Z 0 है, लेकिन उस बिंदु का X और Y कैसे प्राप्त करें ।


अपने ट्रांसफ़ॉर्मेशन और रोटेशन वैक्टर के साथ, क्या आप 3D में सभी कोसबोर्ड कोनों की व्याख्या करने में सक्षम हैं?
मिका

यदि आप कहते हैं कि Z 0 होगा, तो क्या आपके लिए उस बिंदु के समतल-निर्देशांक प्राप्त करना ठीक है? जैसे "लाल दिशा में 10 सेमी और हरी दिशा में शून्य से 15 सेमी नीचे?
मिका

@ मिका यह काम नहीं करेगा, क्योंकि कैमरे के करीब के पिक्सल बड़े क्षेत्र का प्रतिनिधित्व करते हैं
EBAG

प्लेन का निर्देशन किसी पालतू जानवर की होमोग्राफी से करना आसान है। लेकिन अगर आपको अपने कैमरे में 3 डी स्थान केंद्रित 3 डी बिंदुओं की आवश्यकता है, तो आपको अपने रोटेशन और ट्रांसलेशन वैक्टर के अनुसार विमान को बदलना होगा।
मिका

क्या आप इस बिंदु निर्देशांक के अपने अपेक्षित परिणाम प्रदान कर सकते हैं?
अब्देलअज़ीज़ अब्देलतेफ़

जवाबों:


6

आप इसे 3 सरल चरणों के साथ हल कर सकते हैं:

चरण 1:

3 डी दिशा वेक्टर की गणना करें, कैमरा प्रक्षेपण मॉडल के inverting द्वारा दिए गए 2d छवि बिंदु के अनुरूप किरण के कैमरे के समन्वय फ्रेम में व्यक्त किया गया है:

std::vector<cv::Point2f> imgPt = {{u,v}}; // Input image point
std::vector<cv::Point2f> normPt;
cv::undistortPoints     (imgPt, normPt, cameraMatrix, distCoeffs);
cv::Matx31f ray_dir_cam(normPt[0].x, normPt[0].y, 1);
// 'ray_dir_cam' is the 3d direction of the ray in camera coordinate frame
// In camera coordinate frame, this ray originates from the camera center at (0,0,0)

चरण 2:

इस किरण के सदिश की 3 डी दिशा की गणना कैमरे और शतरंज के बीच के सापेक्ष पोज़ का उपयोग करते हुए, शतरंज की बिसात से जुड़े फ्रेम में करें।

// solvePnP typically gives you 'rvec_cam_chessboard' and 'tvec_cam_chessboard'
// Inverse this pose to get the pose mapping camera coordinates to chessboard coordinates
cv::Matx33f R_cam_chessboard;
cv::Rodrigues(rvec_cam_chessboard, R_cam_chessboard);
cv::Matx33f R_chessboard_cam = R_cam_chessboard.t();
cv::Matx31f t_cam_chessboard = tvec_cam_chessboard;
cv::Matx31f pos_cam_wrt_chessboard = -R_chessboard_cam*t_cam_chessboard;
// Map the ray direction vector from camera coordinates to chessboard coordinates
cv::Matx31f ray_dir_chessboard = R_chessboard_cam * ray_dir_cam;

चरण 3:

3 डी किरण और जेड = 0 के साथ बिसात विमान के बीच चौराहे की गणना करके वांछित 3 डी बिंदु खोजें:

// Expressed in the coordinate frame of the chessboard, the ray originates from the
// 3d position of the camera center, i.e. 'pos_cam_wrt_chessboard', and its 3d
// direction vector is 'ray_dir_chessboard'
// Any point on this ray can be expressed parametrically using its depth 'd':
// P(d) = pos_cam_wrt_chessboard + d * ray_dir_chessboard
// To find the intersection between the ray and the plane of the chessboard, we
// compute the depth 'd' for which the Z coordinate of P(d) is equal to zero
float d_intersection = -pos_cam_wrt_chessboard.val[2]/ray_dir_chessboard.val[2];
cv::Matx31f intersection_point = pos_cam_wrt_chessboard + d_intersection * ray_dir_chessboard;

आपका तरीका पूरी तरह से काम करता है, धन्यवाद :)
EBAG

1

चूंकि आपका मामला मैदानों तक सीमित है, इसलिए सरल तरीका यह है कि होमोग्राफी का उपयोग किया जाए।

सबसे पहले अपनी छवि को अनस्टॉर्ट करें। फिर होमोग्राफी मैट्रिक्स की गणना करने के लिए findHomography का उपयोग करें जो आपके पिक्सेल समन्वय (छवि) को वास्तविक समन्वय में बदल देता है (जैसे सेमी में यूक्लिडियन स्पेस)। इस एक के समान कुछ:

#include <opencv2/calib3d.hpp>
//...

//points on undistorted image (in pixel). more is better
vector<Point2f>  src_points = { Point2f(123,321), Point2f(456,654), Point2f(789,987), Point2f(123,321) };
//points on chessboard (e.g. in cm)
vector<Point2f>  dst_points = { Point2f(0, 0), Point2f(12.5, 0), Point2f(0, 16.5), Point2f(12.5, 16.5) }; 
Mat H = findHomography(src_points, dst_points, RANSAC);

//print euclidean coordinate of new point on undistorted image (in pixel)
cout << H * Mat(Point3d(125, 521, 0)) << endl;

मैंने वही किया जो आपने कहा था: वेक्टर <Point2f> कोनों, वेक्टर <Point2f> objectPoints2d; findChessboardCorners (img, patternSize, कोनों); calchessboardCorners (patternSize, squareSize, objectPoints2d); chessboardHomography = findHomography (कोनों, objectPoints2d, RANSAC);
EBAG

यह काम नहीं करता है, और यह समन्वय करता है कि यह सही नहीं है
EBAG

भले ही आप पिक्सेल के साथ होमोग्राफी मैट्रिक्स को गुणा करें जो कि शतरंजबोर्ड पर स्थित है [0,0,0] यह वापस आ जाएगा [-192, -129, 0.33]
EBAG

@EBAG क्या आप पहले छवि को कम नहीं करते हैं? check objectPoints2d सही हो। इवेंट प्रिंट करें और उन्हें मैन्युअल रूप से जांचें।
ma.mehralian
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.