J'essaie de calibrer une caméra avec un objectif fisheye. J'ai donc utilisé le module objectif fisheye, mais continue à obtenir des résultats étranges, peu importe les paramètres de distorsion que je fixe. Ceci est l'image d'entrée que j'utilise: https://i.imgur.com/apBuAwF.pngComment calibrer correctement mon appareil photo avec un objectif grand angle en utilisant openCV?
où les cercles rouges indiquent les coins que j'utilise pour calibrer mon appareil photo.
C'est le meilleur que je pouvais obtenir, sortie: https://imgur.com/a/XeXk5
Je ne en sais pas par cœur ce que les dimensions du capteur de la caméra sont, mais en fonction de la distance focale en pixels qui est calculée dans ma matrice nitrinsic , Je déduis que ma taille de capteur est d'environ 3,3 mm (en supposant que ma distance focale physique est de 1,8 mm), ce qui me semble réaliste. Pourtant, quand je ne déforme pas mon image d'entrée, j'ai un non-sens. Quelqu'un pourrait-il me dire ce que je fais peut-être incorrectement?
les matrices et efficace étant sortie par l'étalonnage:
K:[263.7291703200009, 0, 395.1618975493187;
0, 144.3800397321767, 188.9308218101271;
0, 0, 1]
D:[0, 0, 0, 0]
rms: 9.27628
mon code:
#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;
}
Si quelqu'un a une idée, vous pouvez soit partager un peu de code en Python soit en C++. C'est comme tu veux.
EDIT:
Comme vous pouvez avoir un avis que je n'utilise un damier noir et blanc pour l'étalonnage, mais les coins de tuiles constituant mon tapis. À la fin de la journée, l'objectif - je pense - est d'obtenir des coordonnées de coin qui représentent des échantillons des rayons de distorsion. Le tapis est dans une certaine mesure identique au damier, la seule différence - encore une fois je pense - est le fait que vous avez moins de bords à haute fréquence à ceux par exemple des coins sur le tapis que sur un damier noir et blanc.
Je sais que le nombre de photos est très limité, c'est-à-dire seulement 1. Je m'attends à ce que l'image ne soit pas déformée dans une certaine mesure, mais je m'attends aussi à ce que le décalage soit très bien fait. Mais dans ce cas, la sortie de l'image ressemble à un non-sens total.
Je fini par utiliser cette image avec un jeu d'échecs: https://imgur.com/a/WlLBR fournis par ce site: https://sites.google.com/site/scarabotix/ocamcalib-toolbox/ocamcalib-toolbox-download-page Mais les résultats sont encore très pauvres: des lignes diagonales comme l'autre image de sortie I posté.
Merci
C'est comme ça que c'est calibré. – karlphillip
@karlphillip Je n'ai actuellement aucun accès physique à la caméra. Aussi basé sur ce que j'ai trouvé en ligne. Il n'est pas obligatoire d'utiliser un échiquier. – privetDruzia
Oui, je voulais dire que c'était la façon la plus simple de le faire. Bonne chance alors! – karlphillip