我正试图弄清楚为什么我的OpenCV矩阵的填充在调试模式中与我所期望的完全一样,但是当我试图释放项目时,它会截断给它的所有值,并错误地填充矩阵!
对我的设置的简短描述:
!
进入密码!
首先,我使用ViSP的内置类从文件中加载已经保存的参数。为了调试的目的(并确保我没有失去理智),我还将值保存到全局变量中,以便快速引用:
bool load_intrinsics()
{
vpCameraParameters cam;
vpXmlParserCaemra parser;
std::string intrinsicFilePath = "...path to file...";
std::string cameraName = "Camera";
if (parser.parse(cam, intrinsicFilePath, camera_name, vpCameraParameters::perspectiveProjWithDistortion) != vpXmlParserCamera::SEQUENCE_OK)
{
std::cout << "ERROR WITH LOADING INTRINSICS" << std::endl;
return false;
}
else
{ // variables here are <double> variables, defined globally
global_px = cam.get_px();
global_py = cam.get_py();
global_u0 = cam.get_u0();
global_v0 = cam.get_v0();
global_kud = cam.get_kud();
return true;
}
}`
这一切都如预期的那样起作用。该函数正确读取所有值,并存储这些值(不是截断的!)到全局变量。
接下来,我尝试将这些变量传递给cv::Mat对象,这就是事情开始走下坡路的地方.
void createCvMat()
{
// create camera matrix
cv::Mat tempCamMat = cv::Mat::zeros(3, 3, CV_64F);
tempCamMat.at<double>(0, 0) = global_px;
tempCamMat.at<double>(0, 2) = global_u0;
tempCamMat.at<double>(1, 1) = global_py;
tempCamMat.at<double>(1, 2) = global_v0;
tempCamMat.at<double>(2, 2) = 1.0;
// create distortion matrix
cv::Mat tempDisMat = cv::Mat::zeros(5, 1, CV_64F);
tempDisMat.at<double>(0, 0) = global_kud;
// pass temporary matrices to empty global matrices
tempCamMat.copyTo(cameraMatrix);
tempDisMat.copyTo(distortionMatrix);
}现在,正如第一个代码片段中提到的,我已经确保全局变量中有正确的值。然而,当我使用这些矩阵,例如,使用cv::undistort(...)时,很明显,这些矩阵没有正确加载。
作为正常检查,我尝试将矩阵写入控制台,并确保正确地加载了值:
void sanityCheck(cv::Mat checkMatrix)
{
std::cout << std::endl << "Matrix holds:" <<std::endl;
for (int r = 0; r < checkMatrix.rows; r++)
{
for (int c = 0; c < checkMatrix.cols; c++)
{
std::cout << checkMatrix.at<double>(r, c) << " | ";
}
std::cout << std::endl;
}
}在调试模式下调用两个矩阵的正常检查,得到以下输出:
`
Camera
Matrix Includes:
606.204 | 0 | 607.664 |
0 | 612.354 | 521.775 |
0 | 0 | 1 |
Distortion
Matrix Includes:
-0.240543 |
0 |
0 |
0 |
0 |`
请注意,std::cout控制台输出确实截断了写入六个重要数字的值,因为从文件中读取的数字有将近20个重要数字。结合使用iomanip库和std::setprecision(...),我已经确认了完整的数字被正确地携带并插入到矩阵中。
在版本中调用相同的函数,我得到以下输出:
Camera
Matrix Includes:
606 | 0 | 607 |
0 | 612 | 521 |
0 | 0 | 1 |
Distortion
Matrix Includes:
-0 |
0 |
0 |
0 |
0 |‘请注意,即使双变量被传递给能够容纳双变量的矩阵,也只有整数在填充矩阵!在我的生活中,我不明白为什么它会在项目的发布版本中这样做,而不是在调试版本中!
作为当前的工作,我尝试将数字从"*.xml“文件作为常量直接复制到变量中,然后将它们传递给cv::Mat对象:
// define each global variable (don't read from file)
global_px = 606.20444013030078;
...
global_kud = -0.24054321189834804;
// populate matrices
createCvMat();。这很好用..。我不知道为什么,但确实如此。
正如任何程序员很可能会告诉您的那样,应该避免这种常量的“硬编码”。如果我因任何原因改变相机上的设置,并且不得不重新校准,或者如果最终用户希望校准他们自己的相机,最好从外部文件中读取这些内在值。
发布于 2021-02-05 14:57:38
详细信息:
将double变量加载到cv::Mat<double>对象的问题与已安装的Ubuntu16.04操作系统的本地化问题有关。由于PC是在德国配置的,不管事实上所有参数都是为了模仿安装上的EN标准,PC仍然将其数字、货币、时间等解释设置为DE标准。
这意味着,从外部文件中解析double变量将导致操作系统将EN标准小数位(即句点(.) )错误为DE标准千分之一分隔符。这导致double变量的分数部分被截断!
解决方案:
使用Ubuntu16.04操作系统,可以通过在终端中更改系统区域设置来解决这一问题。打开终端并输入locale命令将为用户提供用于系统本地化解释的语言标准列表,如下所示:
LANG=en_US.UTF-8
LANGUAGE=en_US
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC=en_US.UTF-8
LC_TIME=de_DE.UTF-8
LC_COLLATE="en_US.UTF-8"
LC_MONETARY=en_US.UTF-8
...将LC_CTYPE、LC_NUMERIC和LC_MEASUREMENT标记更改为en_US.UTF-8解决了我这边的问题。这可以通过终端完成,可以使用以下命令:
sudo update-locale LC_CTYPE=en_US.UTF-8
sudo update-locale LC_NUMERIC=en_US.UTF-8
sudo update-locale LC_MEASUREMENT=en_US.UTF-8或者在您选择的文本编辑器中,使用根权限编辑/etc/default/locale文件。一旦文件已经更新,请确保重新启动以完成更改!
感谢@Scheff对这件事的洞察力。如果没有他们的建议,我不太可能解决这个问题!非常感谢,哇!
https://stackoverflow.com/questions/66033013
复制相似问题