Calibrer le seul appareil photo à l'aide d'OpenCV 2.3.1 et C++
Je suis en train de calibrer une webcam à l'aide d'OpenCV 2.3.1 et Visual Studio 2010 (c++ application console). Je suis l'aide de cette classe:
class CameraCalibrator{
private:
std::vector<std::vector<cv::Point3f>> objectPoints;
std::vector<std::vector<cv::Point2f>> imagePoints;
//Square Lenght
float squareLenght;
//output Matrices
cv::Mat cameraMatrix; //intrinsic
cv::Mat distCoeffs;
//flag to specify how calibration is done
int flag;
//used in image undistortion
cv::Mat map1,map2;
bool mustInitUndistort;
public:
CameraCalibrator(): flag(0), squareLenght(36.0), mustInitUndistort(true){};
int addChessboardPoints(const std::vector<std::string>& filelist,cv::Size& boardSize){
std::vector<std::string>::const_iterator itImg;
std::vector<cv::Point2f> imageCorners;
std::vector<cv::Point3f> objectCorners;
//initialize the chessboard corners in the chessboard reference frame
//3d scene points
for(int i = 0; i<boardSize.height; i++){
for(int j=0;j<boardSize.width;j++){
objectCorners.push_back(cv::Point3f(float(i)*squareLenght,float(j)*squareLenght,0.0f));
}
}
//2D Image points:
cv::Mat image; //to contain chessboard image
int successes = 0;
//cv::namedWindow("Chess");
for(itImg=filelist.begin(); itImg!=filelist.end(); itImg++){
image = cv::imread(*itImg,0);
bool found = cv::findChessboardCorners(image, boardSize, imageCorners);
//cv::drawChessboardCorners(image, boardSize, imageCorners, found);
//cv::imshow("Chess",image);
//cv::waitKey(1000);
cv::cornerSubPix(image, imageCorners, cv::Size(5,5),cv::Size(-1,-1),
cv::TermCriteria(cv::TermCriteria::MAX_ITER+cv::TermCriteria::EPS,30,0.1));
//if we have a good board, add it to our data
if(imageCorners.size() == boardSize.area()){
addPoints(imageCorners,objectCorners);
successes++;
}
}
return successes;
}
void addPoints(const std::vector<cv::Point2f>& imageCorners,const std::vector<cv::Point3f>& objectCorners){
//2D image point from one view
imagePoints.push_back(imageCorners);
//corresponding 3D scene points
objectPoints.push_back(objectCorners);
}
double calibrate(cv::Size &imageSize){
mustInitUndistort = true;
std::vector<cv::Mat> rvecs,tvecs;
return
cv::calibrateCamera(objectPoints, //the 3D points
imagePoints,
imageSize,
cameraMatrix, //output camera matrix
distCoeffs,
rvecs,tvecs,
flag);
}
void remap(const cv::Mat &image, cv::Mat &undistorted){
std::cout << cameraMatrix;
if(mustInitUndistort){ //called once per calibration
cv::initUndistortRectifyMap(
cameraMatrix,
distCoeffs,
cv::Mat(),
cameraMatrix,
image.size(),
CV_32FC1,
map1,map2);
mustInitUndistort = false;
}
//apply mapping functions
cv::remap(image,undistorted,map1,map2,cv::INTER_LINEAR);
}
};
Je suis en utilisant 10 échiquier des images (en supposant que c'est assez pour calibation) avec une résolution de 640 x 480. La fonction principale ressemble à ceci:
int main(){
CameraCalibrator calibrateCam;
std::vector<std::string> filelist;
filelist.push_back("img10.jpg");
filelist.push_back("img09.jpg");
filelist.push_back("img08.jpg");
filelist.push_back("img07.jpg");
filelist.push_back("img06.jpg");
filelist.push_back("img05.jpg");
filelist.push_back("img04.jpg");
filelist.push_back("img03.jpg");
filelist.push_back("img02.jpg");
filelist.push_back("img01.jpg");
cv::Size boardSize(8,6);
double calibrateError;
int success;
success = calibrateCam.addChessboardPoints(filelist,boardSize);
std::cout<<"Success:" << success << std::endl;
cv::Size imageSize;
cv::Mat inputImage, outputImage;
inputImage = cv::imread("img10.jpg",0);
outputImage = inputImage.clone();
imageSize = inputImage.size();
calibrateError = calibrateCam.calibrate(imageSize);
std::cout<<"Calibration error:" << calibrateError << std::endl;
calibrateCam.remap(inputImage,outputImage);
cv::namedWindow("Original");
cv::imshow("Original",inputImage);
cv::namedWindow("Undistorted");
cv::imshow("Undistorted",outputImage);
cv::waitKey();
return 0;
}
Tout fonctionne sans erreurs. cameraMatrix ressemble à ceci (environ):
685.65 0 365.14
0 686.38 206.98
0 0 1
Erreur d'étalonnage est 0.310157, ce qui est acceptable.
Mais lorsque j'utilise le reconfigurer, de l'image de sortie est encore pire que l'original. Voici un exemple:
Image d'origine: ]
Sans distorsion de l'image: ]
Donc la question est, suis-je en train de faire quelque chose de mal dans le processus de calibrage? Est 10 échiquier des images assez pour l'étalonnage? Avez-vous des suggestions?
salut, je suis à l'aide de la classe. Il fonctionne parfaitement bien avec moi. le seul problème que j'ai est de savoir comment lire le intrinsèques de la caméra. Je suis en train d'utiliser .at<float>(0,0), mais j'obtiens le message d'erreur. . .
peut-être que le type qui est mal, essayer .at<double>(0,0)
OriginalL'auteur Banana | 2012-04-05
Vous devez vous connecter pour publier un commentaire.
L'appareil photo de la matrice n'est pas undistort la lentille, ces 4 valeurs sont simplement la longueur focale (H et V) et le centre de l'image (en X et Y)
Il y a encore 3 ou 4 ligne de valeur de la matrice (
distCoeffs
dans votre code) qui contient l'objectif de la cartographie - voir Karl Réponse par exemple, le codedistCoeffs
sont inclus dans la fonctioncv::initUndistortRectifyMap
et je veux savoir, ai-je écrire cette fonction correctement, parce que, après l'utilisation decv::remap
- je obtenir de moins bons résultats que l'original, comme vous pouvez le voir dans mes photos de l'échantillon. Merci pour l'aide.vérifier les valeurs dans distcoefs, sont-ils vides ou étrange (je comprends qu'il est difficile de ot de savoir quelles sont les bonnes valeurs!) mais vous pourriez exécuter la opencv exemple de logiciel avec votre appareil photo et voir ce qu'il calcualtes
BTW, ayant le centre de l'image à 365.14,206.98 est moyen pour une image de 640x480. Il est très probable que beaucoup plus proche de 320,240. J'ai un 640 x 480 appareil photo avec le point central de 317.66,240.11.
OriginalL'auteur Martin Beckett
La calibration est effectuée avec une optimisation numérique qui a une jolie pente peu profonde près de la solution. Aussi, la fonction à minimiser est très non-linéaires. Donc, je suppose que votre 10 images ne sont pas assez. - Je calibrer les caméras à très grand angle (c'est à dire très déformé images), et j'essaie d'obtenir de 50 ou 60 images.
J'essaie d'obtenir des images avec l'échiquier à 3 ou 4 positions le long de chaque bord de l'image, en plus de certains dans le milieu, avec plusieurs orientations par rapport à la caméra et à 3 distances différentes (proche super, typique, et aussi loin que vous pouvez obtenir et encore résoudre le damier).
L'obtention de l'échiquier près des coins est très important. Votre exemple, les images n'ont pas l'échiquier très près du coin de l'image. Ce sont ces points qui limitent la capacité de l'étalonnage de faire la bonne chose dans le très déformée des parties de l'image (les coins).
OriginalL'auteur cape1232