Hello, I’m very new to C++ programming with OpenCV. I want to calibrate a drone camera . I have 37 images with a resolution of 4000 x 2250 containing a chessboard pattern with inner corners of width 7 and height 10. I know they are big and may take time to process, but I thought that C++ would be faster than in MATLAB. I don’t have much experience in C++, so I don’t know if my code can be improved. Here are some of the images I took. I know they are not the best ones, but in MATLAB it works pretty well:
Here is the code I’m using:
#include <iostream>
#include <fstream>
#include <algorithm>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
// Define the size of the chessboard pattern
const Size patternSize(10, 7);
// Define the chessboard square size in millimeters
const float squareSize = 140.0f; // assuming 1 inch squares
// Load the images from a directory
vector<String> imagePaths;
glob("../CalibracionDJI/*.jpg", imagePaths);
cout << "Num. Imagenes encontradas: " << imagePaths.size() << endl;
cout << imagePaths[0] << endl;
// Create object points for the corners of the chessboard
vector<vector<Point3f>> objectPoints;
for (int i = 0; i < imagePaths.size(); i++) {
vector<Point3f> corners;
for (int y = 0; y < patternSize.height; y++) {
for (int x = 0; x < patternSize.width; x++) {
corners.push_back(Point3f(x*squareSize, y*squareSize, 0));
}
}
objectPoints.push_back(corners);
}
// Find the chessboard corners in each image
vector<vector<Point2f>> imagePoints;
vector<Mat> images;
for (int i = 0; i < imagePaths.size(); i++) {
cout << "Imagen " << i << ": " << imagePaths[i] << endl;
Mat image = imread(imagePaths[i], IMREAD_COLOR);
if (image.empty()) {
std::cerr << "Error: Could not read the image file" << std::endl;
return -1;
}
Mat gray;
namedWindow("Patron calibracion", WINDOW_NORMAL );
cvtColor(image, gray, COLOR_BGR2GRAY);
imshow("Patron calibracion", gray);
waitKey(5);
vector<Point2f> corners;
bool found = findChessboardCorners(gray, patternSize, corners,
CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE + CALIB_CB_FAST_CHECK);
if (found) {
cout << "Esquinas encontradas" << endl;
cornerSubPix(gray, corners, Size(11, 11), Size(-1, -1),
TermCriteria(TermCriteria::EPS + TermCriteria::MAX_ITER, 50, 0.1));
// drawChessboardCorners(image, patternSize, corners, found);
imagePoints.push_back(corners);
images.push_back(image);
cout << "Puntos añadidos";
}
}
// Calibrate the camera
Mat cameraMatrix, distCoeffs;
vector<Mat> rvecs, tvecs;
calibrateCamera(objectPoints, imagePoints, images[0].size(), cameraMatrix, distCoeffs, rvecs, tvecs);
// Print the camera matrix and distortion coefficients
cout << "Camera matrix:" << endl << cameraMatrix << endl;
cout << "Distortion coefficients:" << endl << distCoeffs << endl;
// Save the camera matrix and distortion coefficients to a YAML file
FileStorage fs("../camera_params.yml", FileStorage::WRITE);
fs << "cameraMatrix" << cameraMatrix;
fs << "distCoeffs" << distCoeffs;
fs.release();
// Undistort an image
Mat image = imread("../CalibracionDJI/dji_fly_20230313_162404_150_1678746261861_photo_optimized.jpg");
Mat undistorted;
undistort(image, undistorted, cameraMatrix, distCoeffs);
imshow("Original image", image);
imshow("Undistorted image", undistorted);
waitKey();
return 0;
}