opencv - 距離計測 - 姿勢推定 商用




イメージポイントからのx、y座標(3D)の計算 (2)

私は3D座標系でオブジェクトを見つけるタスクがあります。 私はほぼ正確なXとYの座標を取得する必要があるので、私は、この画像のオレンジ色のボールのように、移動するオブジェクトの上部に配置される既知のZ座標を持つ1つのカラーマーカーを追跡することに決めました。

まず、カメラのキャリブレーションを行い、固有のパラメータを取得した後、次のコードのようにcv :: solvePnPを使用して回転ベクトルと平行移動ベクトルを取得しました。

std::vector<cv::Point2f> imagePoints;
std::vector<cv::Point3f> objectPoints;
//img points are green dots in the picture
imagePoints.push_back(cv::Point2f(271.,109.));
imagePoints.push_back(cv::Point2f(65.,208.));
imagePoints.push_back(cv::Point2f(334.,459.));
imagePoints.push_back(cv::Point2f(600.,225.));

//object points are measured in millimeters because calibration is done in mm also
objectPoints.push_back(cv::Point3f(0., 0., 0.));
objectPoints.push_back(cv::Point3f(-511.,2181.,0.));
objectPoints.push_back(cv::Point3f(-3574.,2354.,0.));
objectPoints.push_back(cv::Point3f(-3400.,0.,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(objectPoints, imagePoints, cameraMatrix, distCoeffs, rvec, tvec);
cv::Rodrigues(rvec,rotationMatrix);

すべての行列を取った後、この式は画像ポイントをwolrd座標に変換するのに役立ちます:

ここで、MはcameraMatrix、R - rotationMatrix、t - tvec、sは未知数です。 Zconstは、オレンジボールの高さを表し、この例では285mmである。 だから、まずは前の方程式を解いて「s」を求め、イメージポイントを選んでX座標とY座標を見つけることができます:

これを解くと、Zconstが分かっているので、行列の最後の行を使って変数 "s"を見つけることができます。

cv::Mat uvPoint = cv::Mat::ones(3,1,cv::DataType<double>::type); //u,v,1
uvPoint.at<double>(0,0) = 363.; //got this point using mouse callback
uvPoint.at<double>(1,0) = 222.;
cv::Mat tempMat, tempMat2;
double s;
tempMat = rotationMatrix.inv() * cameraMatrix.inv() * uvPoint;
tempMat2 = rotationMatrix.inv() * tvec;
s = 285 + tempMat2.at<double>(2,0); //285 represents the height Zconst
s /= tempMat.at<double>(2,0);
std::cout << "P = " << rotationMatrix.inv() * (s * cameraMatrix.inv() * uvPoint - tvec) << std::endl;

この後、私は結果を得た:P = [-2629.5,1272.6,285]

Preal = [-2629.6,1269.5,285]という測定値と比較すると、

エラーは非常に小さく非常に小さいですが、このボックスをこの部屋の端に移動すると、エラーは20〜40mmになる可能性があります。 誰でも助けてくれますか?何か提案はありますか?


あなたの設定を考えると、エッジの20〜40mmの誤差は平均です。 あなたはすべてをうまくやったようです。

カメラ/システム構成を変更することなく、よりうまくいくことは難しいでしょう。 カメラのキャリブレーションをやり直して、より良い結果が得られることを期待できますが、これは改善されません(実際には実際のインスタントパラメータを消去しないでください)

count0で述べたように、精度がさらに必要な場合は、複数回測定する必要があります。


歪んだ画像や歪んでいない画像から緑のドット(imagePoints)が得られますか? 関数solvePnPは既にimagePointsを歪ませていないからです(あなたが歪み係数を渡さないか、それらをヌルとして渡さない限り)。 歪んでいない画像からそれらを取得している場合は、これらのimagePointを2度歪ませている可能性があります。その結果、コーナーでエラーが増えます。

https://github.com/Itseez/opencv/blob/master/modules/calib3d/src/solvepnp.cpp





pose-estimation