首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么cv::Mat对象在调试和发布之间的行为有所不同?

为什么cv::Mat对象在调试和发布之间的行为有所不同?
EN

Stack Overflow用户
提问于 2021-02-03 17:53:09
回答 1查看 132关注 0票数 0

我正试图弄清楚为什么我的OpenCV矩阵的填充在调试模式中与我所期望的完全一样,但是当我试图释放项目时,它会截断给它的所有值,并错误地填充矩阵!

对我的设置的简短描述:

  • 我正在使用OpenCV和ViSP库来处理USB飞行捕捉相机。
  • 在Qt-Creator中的Ubuntu 16.04上运行所有的东西,因为我计划在这个项目中有一个图形用户界面。
  • 填充矩阵的参数对于摄像机的校准很重要,所以截断是绝对不去的!

进入密码!

首先,我使用ViSP的内置类从文件中加载已经保存的参数。为了调试的目的(并确保我没有失去理智),我还将值保存到全局变量中,以便快速引用:

代码语言:javascript
复制
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对象,这就是事情开始走下坡路的地方.

代码语言:javascript
复制
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(...)时,很明显,这些矩阵没有正确加载。

作为正常检查,我尝试将矩阵写入控制台,并确保正确地加载了值:

代码语言:javascript
复制
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;
  }
}

在调试模式下调用两个矩阵的正常检查,得到以下输出:

`

代码语言:javascript
复制
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(...),我已经确认了完整的数字被正确地携带并插入到矩阵中。

在版本中调用相同的函数,我得到以下输出:

代码语言:javascript
复制
Camera
Matrix Includes:
606 | 0 | 607 |
0 | 612 | 521 |
0 | 0 | 1 |

Distortion
Matrix Includes:
-0 |
0 |
0 |
0 |
0 |

‘请注意,即使双变量被传递给能够容纳双变量的矩阵,也只有整数在填充矩阵!在我的生活中,我不明白为什么它会在项目的发布版本中这样做,而不是在调试版本中!

作为当前的工作,我尝试将数字从"*.xml“文件作为常量直接复制到变量中,然后将它们传递给cv::Mat对象:

代码语言:javascript
复制
// define each global variable (don't read from file)
global_px = 606.20444013030078;
...
global_kud = -0.24054321189834804;
// populate matrices
createCvMat();

。这很好用..。我不知道为什么,但确实如此。

正如任何程序员很可能会告诉您的那样,应该避免这种常量的“硬编码”。如果我因任何原因改变相机上的设置,并且不得不重新校准,或者如果最终用户希望校准他们自己的相机,最好从外部文件中读取这些内在值。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-02-05 14:57:38

详细信息:

double变量加载到cv::Mat<double>对象的问题与已安装的Ubuntu16.04操作系统的本地化问题有关。由于PC是在德国配置的,不管事实上所有参数都是为了模仿安装上的EN标准,PC仍然将其数字、货币、时间等解释设置为DE标准。

这意味着,从外部文件中解析double变量将导致操作系统将EN标准小数位(即句点(.) )错误为DE标准千分之一分隔符。这导致double变量的分数部分被截断!

解决方案:

使用Ubuntu16.04操作系统,可以通过在终端中更改系统区域设置来解决这一问题。打开终端并输入locale命令将为用户提供用于系统本地化解释的语言标准列表,如下所示:

代码语言:javascript
复制
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_CTYPELC_NUMERICLC_MEASUREMENT标记更改为en_US.UTF-8解决了我这边的问题。这可以通过终端完成,可以使用以下命令:

代码语言:javascript
复制
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对这件事的洞察力。如果没有他们的建议,我不太可能解决这个问题!非常感谢,哇!

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66033013

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档