Thank you very much for the reply and the advice. I wanted to try and avoid posting huge blocks of code as text, but I understand where you’re coming from! I’ll make sure to use text for future code!
The file containing the camera calibration data, contains only the following lines:
camera.xml file
<!-- Pixel ratio-->
<px>606.20444013030078</px>
<py>612.35364294795841</py>
<!-- Principal point-->
<u0>507.66415593888757</u0>
<v0>521.7748417433304</v0>
<!--Undistorted to distorted distortion parameter-->
<kud>-0.24054321189834804</kud>
<!--Distorted to undistorted distortion parameter-->
<kdu>0.40028260701410684</kdu>
As for the camera class, it is simply written as follows. For sake of brevity, I’ve combined both the *.h and *.cpp files into the header:
CameraClass (h/cpp combined)
#include <opencv2/core.hpp>
#include <fstream>
#include <iostream>
#include <unistd.h>
#include <string>
class CameraClass
{
public:
CameraClass();
// core functions
bool getValues() {
// create path variable pointing to intrinsic file
std::string intrinsicPath = getcwd(nullptr, 0);
intrinsicPath = intrinsicPath.substr(0, intrinsicPath.find_last_of("/")) + "/TestLoadCalib/Calibration/camera.xml";
std::cout << intrinsicPath << std::endl;
std::ifstream stream(intrinsicPath);
if (stream.is_open()) {
std::string line;
// parse through file for intrinsic values
if (int(line.find("<px>")) >= 0) {
line = line.substr(line.find("<px>") + 4, line.find("</px>") - (line.find("<px>") + 4));
px = std::stod(line);
}
else if (int(line.find("<u0>")) >= 0) {
line = line.substr(line.find("<u0>") + 4, line.find("</u0>") - (line.find("<u0>") + 4));
u0 = std::stod(line);
}
else if (int(line.find("<py>")) >= 0) {
line = line.substr(line.find("<py>") + 4, line.find("</py>") - (line.find("<py>") + 4));
py = std::stod(line);
}
else if (int(line.find("<v0>")) >= 0) {
line = line.substr(line.find("<v0>") + 4, line.find("</v0>") - (line.find("<v0>") + 4));
v0 = std::stod(line);
}
else if (int(line.find("<kud>")) >= 0) {
line = line.substr(line.find("<kud>") + 5, line.find("</kud>") - (line.find("<kud>") + 5));
kud = std::stod(line);
}
}
else {
std::cout << "There was an issue opening the file!" << std::endl;
return false;
}
return true;
}
bool fillMatrices() {
// initialize camera matrix
cam = cv::Mat::zeros(3, 3, CV_64F);
// | px 0 u0 |
// cam = | 0 py v0 |
// | 0 0 1 |
cam.at<double>(0, 0) = px;
cam.at<double>(0, 2) = u0;
cam.at<double>(1, 1) = py;
cam.at<double>(1, 2) = v0;
cam.at<double>(2, 2) = 1.0;
// initialize distortion matrix
dist = cv::Mat::zeros(5, 1, CV_64F);
dist.at<double>(0, 0) = kud;
return true;
}
void printMatrices() {
std::cout << "Camera Matrix:" << std::endl;
std::cout << cam.at<double>(0, 0) << " | " << cam.at<double>(0, 1) << " | " << cam.at<double>(0, 2) << std::endl;
std::cout << cam.at<double>(1, 0) << " | " << cam.at<double>(1, 1) << " | " << cam.at<double>(1, 2) << std::endl;
std::cout << cam.at<double>(2, 0) << " | " << cam.at<double>(2, 1) << " | " << cam.at<double>(2, 2) << std::endl;
std::cout << "Distortion Matrix:" << std::endl;
std::cout << dist.at<double>(0, 0) << " | " << dist.at<double>(0, 1) << " | " << dist.at<double>(0, 2) << " | " << dist.at<double>(0, 3) << " | " << dist.at<double>(0, 4) << std::endl;
}
// camera matrices
cv::Mat cam;
cv::Mat dist;
private:
// camera intrinsic values read from file
double px = 0.0;
double py = 0.0;
double u0 = 0.0;
double v0 = 0.0;
double kud = 0.0;
};
The main program simply creates an instance of the camera class, calls the function to populate the camera and distortion matrices, and displays these matrices with a print function. (This is for later use with the cv::undistort()
function for images taken with the calibrated camera!)
Main Program
#include "cameraclass.h"
int main()
{
CameraClass *camera = new CameraClass();
camera->getValues();
camera->fillMatrices();
camera->printMatrices();
delete camera; // clean up
return 0;
}
Perhaps I should have the title of this question changed to reflect the fact that the problem lies more-so with the further implementation of these matrices, and not the population of the matrices itself. After further deliberation and debugging, I have found that the matrices do in fact contain the values of the variables passed to them. However, the issue still stands, that these variables are not read properly from the matrix when using them with the aforementioned cv::undistort()
function.
To reiterate, when hard-coding the variable by hand as such:
dist.at<double>(0, 0) = -0.24054321189834804;
it works as intended. However, for whatever reason, when passing a double
variable which contains the exact same number:
double kud = -0.24054321189834804;
dist.at<double>(0, 0) = kud;
it does not have the desired effect. During debugging, I’ve tried to check the value of the variable in the matrix, and even tried using the standard manipio
library to set the precision of the output variable when printing it out, and have ensured that the number in its entirety is held within the matrix. Regardless, the matrices are not properly being read and utilized when the variable-version is used. I’m really at my wits end with this one!
Thanks for any insight anyone can provide!
Best regards,
C.Fox