Я пытаюсь откалибровать камеру с объективом «рыбий глаз». Поэтому я использовал модуль объектива «рыбий глаз», но получаю странные результаты независимо от того, какие параметры искажения я исправляю. Я использую это входное изображение: https://i.imgur.com/apBuAwF.png
где красные кружки обозначают углы, которые я использую для калибровки камеры.
Это лучшее, что я мог получить, вывод: https://imgur.com/a/XeXk5
В настоящее время я не знаю наизусть, каковы размеры сенсора камеры, но на основе фокусного расстояния в пикселях, которое рассчитывается в моей азотной матрице, я делаю вывод, что размер моего сенсора составляет примерно 3,3 мм (при условии, что мое физическое фокусное расстояние составляет 1,8 мм. ), что мне кажется реалистичным. Тем не менее, неискаживая входное изображение, я получаю ерунду. Может ли кто-нибудь сказать мне, что я делаю неправильно?
матрицы и среднеквадратичные значения, полученные при калибровке:
K:[263.7291703200009, 0, 395.1618975493187;
0, 144.3800397321767, 188.9308218101271;
0, 0, 1]
D:[0, 0, 0, 0]
rms: 9.27628
мой код:
#include <opencv2/opencv.hpp>
#include "opencv2/core.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/ccalib/omnidir.hpp"
using namespace std;
using namespace cv;
vector<vector<Point2d> > points2D;
vector<vector<Point3d> > objectPoints;
Mat src;
//so that I don't have to select them manually every time
void initializePoints2D()
{
points2D[0].push_back(Point2d(234, 128));
points2D[0].push_back(Point2d(300, 124));
points2D[0].push_back(Point2d(381, 126));
points2D[0].push_back(Point2d(460, 127));
points2D[0].push_back(Point2d(529, 137));
points2D[0].push_back(Point2d(207, 147));
points2D[0].push_back(Point2d(280, 147));
points2D[0].push_back(Point2d(379, 146));
points2D[0].push_back(Point2d(478, 153));
points2D[0].push_back(Point2d(551, 165));
points2D[0].push_back(Point2d(175, 180));
points2D[0].push_back(Point2d(254, 182));
points2D[0].push_back(Point2d(377, 185));
points2D[0].push_back(Point2d(502, 191));
points2D[0].push_back(Point2d(586, 191));
points2D[0].push_back(Point2d(136, 223));
points2D[0].push_back(Point2d(216, 239));
points2D[0].push_back(Point2d(373, 253));
points2D[0].push_back(Point2d(534, 248));
points2D[0].push_back(Point2d(624, 239));
points2D[0].push_back(Point2d(97, 281));
points2D[0].push_back(Point2d(175, 322));
points2D[0].push_back(Point2d(370, 371));
points2D[0].push_back(Point2d(578, 339));
points2D[0].push_back(Point2d(662, 298));
for(int j=0; j<25;j++)
{
circle(src, points2D[0].at(j), 5, Scalar(0, 0, 255), 1, 8, 0);
}
imshow("src with circles", src);
waitKey(0);
}
int main(int argc, char** argv)
{
Mat srcSaved;
src = imread("images/frontCar.png");
resize(src, src, Size(), 0.5, 0.5);
src.copyTo(srcSaved);
vector<Point3d> objectPointsRow;
vector<Point2d> points2DRow;
objectPoints.push_back(objectPointsRow);
points2D.push_back(points2DRow);
for(int i=0; i<5;i++)
{
for(int j=0; j<5;j++)
{
objectPoints[0].push_back(Point3d(5*j,5*i,1));
}
}
initializePoints2D();
cv::Matx33d K;
cv::Vec4d D;
std::vector<cv::Vec3d> rvec;
std::vector<cv::Vec3d> tvec;
int flag = 0;
flag |= cv::fisheye::CALIB_RECOMPUTE_EXTRINSIC;
flag |= cv::fisheye::CALIB_CHECK_COND;
flag |= cv::fisheye::CALIB_FIX_SKEW;
flag |= cv::fisheye::CALIB_FIX_K1;
flag |= cv::fisheye::CALIB_FIX_K2;
flag |= cv::fisheye::CALIB_FIX_K3;
flag |= cv::fisheye::CALIB_FIX_K4;
double rms =cv::fisheye::calibrate(
objectPoints, points2D, src.size(),
K, D, rvec, tvec, flag, cv::TermCriteria(3, 20, 1e-6)
);
Mat output;
cerr<<"K:"<<K<<endl;
cerr<<"D:"<<D<<endl;
cv::fisheye::undistortImage(srcSaved, output, K, D);
cerr<<"rms: "<<rms<<endl;
imshow("output", output);
waitKey(0);
cerr<<"image .size: "<<srcSaved.size()<<endl;
}
Если у кого-то есть идея, не стесняйтесь поделиться кодом на Python или на C ++. Все, что плывет на вашей лодке.
РЕДАКТИРОВАТЬ:
Как вы могли заметить, для калибровки я использую не черно-белую шахматную доску, а углы плиток, составляющих мой ковер. В конце концов, я думаю, цель - получить угловые координаты, которые представляют образцы радиусов искажения. Ковер в некоторой степени такой же, как и шахматная доска, единственное отличие - опять же, я думаю, - это тот факт, что у вас меньше высокочастотных краев в тех, например, углах ковра, чем на черно-белой шахматной доске.
Я знаю, что количество изображений очень ограничено, то есть всего 1. Я ожидаю, что изображение будет до некоторой степени неискаженным, но я также ожидаю, что неискажение будет выполнено очень хорошо. Но в этом случае вывод изображения выглядит полной ерундой.
В итоге я использовал это изображение с шахматной доской: предоставлено https://imgur.com/a/WlLBR на этом веб-сайте: https://sites.google.com/site/scarabotix/ocamcalib-toolbox/ocamcalib-toolbox-download-page Но результаты по-прежнему очень плохие: диагональные линии, как на другом выходном изображении, которое я опубликовал.
Спасибо