天井に魚眼カメラがあり、床のいくつかの点を特定したいと考えています。カメラのすぐ下に参照システム (実世界) の原点を配置しました。すべてのオブジェクトの位置をセンチメートル単位で知りたいと考えています。この図は次のことを示しています。
まず、カメラのキャリブレーションを実行し、RMS が 1.11 の次の結果を取得しました。
キャリブレーションの結果、内部パラメーター (カメラ マトリックス) を取得したので、cv::solvePnP を使用して回転ベクトルと並進ベクトルを取得しました。これを適用するために、歪みのない画像内のいくつかのポイント (ピクセル単位) をマークし、参照システムに従って実世界でそれらを測定しました。
たとえば、原点は 1024x768 画像の中心にあるため、次のようになります。
- ポイント 0: ImagePoint(512, 384) [ピクセル] --> ObjectPoint(0,0) [センチメートル]
次のコードはこれを示しています。
std::vector<cv::Point2f> imagePointsPix;
std::vector<cv::Point3f> objectPointsCm;
imagePointsPix.push_back(cv::Point2f(512.,384.));
imagePointsPix.push_back(cv::Point2f(404.,512.));
imagePointsPix.push_back(cv::Point2f(666.,211.));
imagePointsPix.push_back(cv::Point2f(519.,66.));
objectPointsCm.push_back(cv::Point3f(0., 0., 0.));
objectPointsCm.push_back(cv::Point3f(-80.,-132.,0.));
objectPointsCm.push_back(cv::Point3f(120.,188.,0.));
objectPointsCm.push_back(cv::Point3f(-40.,268.,0.));
cv::Mat rvec(1,3,cv::DataType<double>::type);
cv::Mat tvec(1,3,cv::DataType<double>::type);
cv::Mat rotationMatrix(3,3,cv::DataType<double>::type);
cv::solvePnP(objectPointsCm, imagePointsPix, cameraMatrix, distCoeffs, rvec, tvec, 0, SOLVEPNP_ITERATIVE);
cv::Rodrigues(rvec,rotationMatrix);
これで、カメラ行列、回転行列、および移動ベクトルが得られたので、これを参照として使用することで、位置がピクセル単位であれば任意の点を計算できます。これはコードです:
cv::Mat uvPoint = cv::Mat::ones(3,1,cv::DataType<double>::type); //u,v,1
uvPoint.at<double>(0,0) = 512.; //img point for which we want its real coordinates
uvPoint.at<double>(1,0) = 384.;
cv::Mat tempMat, tempMat2;
double s;
tempMat = rotationMatrix.inv() * cameraMatrix.inv() * uvPoint;
tempMat2 = rotationMatrix.inv() * tvec;
s = 0 + tempMat2.at<double>(2,0); //before 0 it was 285, which represents the height Zconst
s /= tempMat.at<double>(2,0);
std::cout << "P = " << rotationMatrix.inv() * (s * cameraMatrix.inv() * uvPoint - tvec) << std::endl;
パラメータを取得するために使用したのと同じポイントで、次の結果が得られます。
- ポイント 0 --> (0.213, 3.391) ((0,0) のはずです) ERROR : 3.69 cm
- ポイント 1 --> (-68.28, -112.82) ((-80, -132) のはずです) ERROR : 17.49 cm
- ポイント 2 --> (84.48, 137.61) ((120, 188) のはずです) ERROR : 49.62 cm
残りのポイントもエラーが大きすぎることを示しています...さらに多くのポイントを使用しましたが、結果は改善されません。どこで間違えたのかわからない、誰か助けてくれる?
前もって感謝します。