2B noktayı 3B konuma dönüştürme


9

Ben bilinen sabit bir kamera var cameraMatrixve distCoeffs. Ben de sabit bir satranç tahtası var, transformve rotationvektör de kullanılarak hesaplanır solvePnP.

Aşağıdaki resim gibi, satranç tahtasının bulunduğu düzlemde bir 2D noktasının 3D konumunu nasıl elde edebileceğinizi merak ediyorum:

resim açıklamasını buraya girin

Kesin olan bir şey , o noktanın Z'nin 0 olması, ancak o noktanın X ve Y'nin nasıl elde edileceğidir .


dönüşüm ve rotasyon vektörlerinizle tüm satranç tahtası köşelerini 3D olarak açıklayabilir misiniz?
Micka

Z'nin 0 olacağını söylüyorsanız, sadece o noktanın düzlem koordinatlarını almanız uygun mudur? Gibi "kırmızı yönde 10 cm gidiyor ve yeşil yönde eksi 15 cm gidiyor?
Micka

@Micka bu işe yaramayacak, çünkü kameraya daha yakın olan pikseller daha büyük alanı temsil ediyor
EBAG

petspektif bir homografi ile düzlem koordinatlarını elde etmek kolaydır. Ancak kameranızın merkezindeki 3B boşluğundaki 3B noktalara ihtiyacınız varsa, düzlemi daha sonra dönüş ve çeviri vektörlerinize göre dönüştürmeniz gerekir.
Micka

Bu nokta koordinatlarından beklenen sonucu verebilir misiniz?
AbdelAziz AbdelLatef

Yanıtlar:


6

Bunu 3 basit adımla çözebilirsiniz:

Aşama 1:

Kamera projeksiyon modelini tersine çevirerek verilen 2d görüntü noktasına karşılık gelen ışının kameranın koordinat çerçevesinde ifade edilen 3B yön vektörünü hesaplayın:

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)

Adım 2:

Kamera ve satranç tahtası arasındaki göreceli pozu kullanarak, satranç tahtasına bağlı koordinat çerçevesinde bu ışının vektörünün 3B yönünü hesaplayın:

// 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;

Aşama 3:

Z = 0 ile 3d ışın ve satranç tahtası düzlemi arasındaki kavşağı hesaplayarak istenen 3B noktasını bulun:

// 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;

Yönteminiz mükemmel çalışıyor, teşekkürler :)
EBAG

1

Vakanız ovalarla sınırlı olduğundan, basit yol Homografi kullanmaktır.

Önce görüntünüzü bozun . Sonra findHomography'yi kullanın Piksel gerçek (Öklid alan örneğin cm) koordine etmek (resim) koordinat dönüşümü eşyazımı matrisi hesaplamak için kullanılır. Buna benzer bir şey:

#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;

Ne dediğini yaptım: vektör <Point2f> köşeleri, vektör <Point2f> objectPoints2d; findChessboardCorners (img, patternSize, köşeler); calcChessboardCorners (patternSize, squareSize, objectPoints2d); satranç tahtasıHomografi = findHomografi (köşeler, objectPoints2d, RANSAC);
EBAG

çalışmıyor ve döndürdüğü koordinat doğru değil
EBAG

Hatta çarpma satranç tahtasının üzerinde bulunan piksel ile eşyazımı matrisi eğer [0,0,0] o [-192, -129, 0.33] dönecektir
EBAG

@EBAG önce resmi depolar mısınız? objectPoints2d'yi kontrol edin. Olay yazdırın ve manuel olarak kontrol edin.
ma.mehralian
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.