web-dev-qa-db-ja.com

OpenCV unConstraintPointsとtriangulatePointは奇妙な結果をもたらします(ステレオ)

空間内のいくつかのポイントの3D座標を取得しようとしていますが、undistortPoints()triangulatePoints()の両方から奇妙な結果が得られます。

両方のカメラの解像度が異なるため、別々にキャリブレーションし、RMS _0,34_と_0,43_のエラーを取得し、stereoCalibrate()を使用して詳細を取得しました行列、_0,708_のRMS)を取得し、stereoRectify()を使用して残りの行列を取得しました。これを使用して、収集した座標の作業を開始しましたが、奇妙な結果が得られます。

たとえば、入力は_(935, 262)_であり、undistortPoints()出力はあるポイントでは_(1228.709125, 342.79841)_であり、別のポイントではそれぞれ_(934, 176)_と_(1227.9016, 292.4686)_です。これらのポイントは両方とも、歪みが最小であるフレームの中央に非常に近いため、これは奇妙です。 300ピクセル移動するとは思っていませんでした。

traingulatePoints()に渡されると、結果はさらに奇妙になります。実際の3点間の距離を(定規を使用して)測定し、各画像のピクセル間の距離を計算しました。今回はポイントがかなり平坦な平面上にあったため、| AB |/| BC |のように、これら2つの長さ(ピクセルと実数)が一致しました。どちらの場合も約4/9でした。ただし、triangulatePoints()は、| AB |/| BC |を使用して結果を表示します。 3/2または4/2であること。

これは私のコードです:

_double pointsBok[2] = { bokList[j].toFloat()+xBok/2, bokList[j+1].toFloat()+yBok/2 };
cv::Mat imgPointsBokProper = cv::Mat(1,1, CV_64FC2, pointsBok);

double pointsTyl[2] = { tylList[j].toFloat()+xTyl/2, tylList[j+1].toFloat()+yTyl/2 };
//cv::Mat imgPointsTyl = cv::Mat(2,1, CV_64FC1, pointsTyl);
cv::Mat imgPointsTylProper = cv::Mat(1,1, CV_64FC2, pointsTyl);

cv::undistortPoints(imgPointsBokProper, imgPointsBokProper, 
      intrinsicOne, distCoeffsOne, R1, P1);
cv::undistortPoints(imgPointsTylProper, imgPointsTylProper, 
      intrinsicTwo, distCoeffsTwo, R2, P2);

cv::triangulatePoints(P1, P2, imgWutBok, imgWutTyl, point4D);

double wResult = point4D.at<double>(3,0);
double realX = point4D.at<double>(0,0)/wResult;
double realY = point4D.at<double>(1,0)/wResult;
double realZ = point4D.at<double>(2,0)/wResult;
_

ポイント間の角度はちょっと良いですが、通常はそうではありません:

_`7,16816    168,389 4,44275` vs `5,85232    170,422 3,72561` (degrees)
`8,44743    166,835 4,71715` vs `12,4064    158,132 9,46158`
`9,34182    165,388 5,26994` vs `19,0785    150,883 10,0389`
_

フレーム全体でundistort()を使用しようとしましたが、同じように奇妙な結果が得られました。 BポイントとCポイントの間の距離は常にほとんど変わらないはずですが、それでもこれが私が得たものです。

_7502,42     
4876,46 
3230,13 
2740,67 
2239,95 
_

フレームごと。

ピクセル距離(下)と実際の距離(上)-非常に似ているはずです: |BC| distance

角度:

ABC angle

また、undistortPoints()undistort()の両方で同じ結果が得られるべきではありませんか(ここに別のビデオセットがあります)。
enter image description here

64
Petersaber

関数cv :: unConstraintは、歪みの除去と再投影を一度に実行します。次の操作リストを実行します。

  1. カメラの投影を元に戻します(カメラ行列の逆数による乗算)
  2. 歪みモデルを適用して歪みを元に戻す
  3. 提供された回転行列R1/R2で回転します
  4. 提供された射影行列P1/P2を使用して、プロジェクトが画像を指します

行列R1、P1、またはを渡す場合。 cv :: stereoCalibrate()のR2、P2、入力ポイントは歪みがなく、修正されます。整流とは、対応する点が同じy座標を持つように画像が変換されることを意味します。対応するポイントの配置を変更せずに、両方の画像に任意の平行移動またはスケーリングを適用できるため、画像修正のための独自のソリューションはありません。そうは言っても、cv :: stemeoCalibrate()は、投影の中心をかなりシフトする可能性があります(たとえば、300ピクセル)。純粋な歪みをなくしたい場合は、(R1の代わりに)単位行列と(P1の代わりに)元のカメラの行列Kを渡すことができます。これにより、元のピクセル座標と同様のピクセル座標が得られるはずです。

1
Tobias