В OpenCV нет стандартной функции для расчета необходимой матрицы с использованием двух разных камер. Но это очень легко реализовать самостоятельно.
Вы можете добавить функцию к five-point.cpp
и перекомпилировать OpenCV.
Я только что добавил перегруженную функцию cv::findEssentialMat
с дополнительным параметром для матрицы второй камеры.
cv::Mat cv::findEssentialMat(InputArray _points1, InputArray _points2, InputArray _cameraMatrix1, InputArray _cameraMatrix2, int method, double prob, double threshold, OutputArray _mask)
{
CV_INSTRUMENT_REGION();
Mat points1, points2, cameraMatrix1, cameraMatrix2;
_points1.getMat().convertTo(points1, CV_64F);
_points2.getMat().convertTo(points2, CV_64F);
_cameraMatrix1.getMat().convertTo(cameraMatrix1, CV_64F);
_cameraMatrix2.getMat().convertTo(cameraMatrix2, CV_64F);
int npoints = points1.checkVector(2);
CV_Assert(npoints >= 0 && points2.checkVector(2) == npoints &&
points1.type() == points2.type());
CV_Assert(cameraMatrix1.rows == 3 && cameraMatrix1.cols == 3 && cameraMatrix1.channels() == 1);
CV_Assert(cameraMatrix2.rows == 3 && cameraMatrix2.cols == 3 && cameraMatrix2.channels() == 1);
if (points1.channels() > 1)
{
points1 = points1.reshape(1, npoints);
points2 = points2.reshape(1, npoints);
}
double fx1 = cameraMatrix1.at<double>(0, 0);
double fy1 = cameraMatrix1.at<double>(1, 1);
double cx1 = cameraMatrix1.at<double>(0, 2);
double cy1 = cameraMatrix1.at<double>(1, 2);
double fx2 = cameraMatrix2.at<double>(0, 0);
double fy2 = cameraMatrix2.at<double>(1, 1);
double cx2 = cameraMatrix2.at<double>(0, 2);
double cy2 = cameraMatrix2.at<double>(1, 2);
points1.col(0) = (points1.col(0) - cx1) / fx1;
points2.col(0) = (points2.col(0) - cx2) / fx2;
points1.col(1) = (points1.col(1) - cy1) / fy1;
points2.col(1) = (points2.col(1) - cy2) / fy2;
// Reshape data to fit opencv ransac function
points1 = points1.reshape(2, npoints);
points2 = points2.reshape(2, npoints);
threshold /= (fx1 + fy1) / 2;
Mat E;
if (method == RANSAC)
createRANSACPointSetRegistrator(makePtr<EMEstimatorCallback>(), 5, threshold, prob)->run(points1, points2, E, _mask);
else
createLMeDSPointSetRegistrator(makePtr<EMEstimatorCallback>(), 5, prob)->run(points1, points2, E, _mask);
return E;
}
Затем вам нужно добавить объявление функции в calib3d.hpp
, перекомпилировать и переустановить версию OpenCV.
Дополнительный вопрос: Если я вычислил основную матрицу, могу ли я просто использовать ее в качестве параметра в методе computeCorrespondEpilines()
вместо основной матрицы, если предположить, что изображения уже выпрямлены?
Да, я думаю, это должно сработать.