OpenCV:矩阵赋值混淆

3

你能验证/回答我的理解/问题吗?

在OpenCV中,假设

Mat A; // Suppose A has some values in it
Mat B=A;
  1. 如果我更新B,A也会受影响。这似乎基本上是赋值引用。

假设有一个函数 "void a_function(Mat argument) {..//change argument..}".

  1. 在你调用"a_function(A)"之后,A也会受影响,对吗?

  2. 那么,为什么(或在哪种情况下)我们需要 "void a_function(Mat &argument)" 如果它已经通过引用调用了?这里的 & 有特殊的含义吗?

  3. 如果您不希望 A 受到函数调用的影响,哪种方法更好呢?

    • 通过 a_function(A.clone()) 调用?
    • 通过 a_function(A) 调用并使用 const Mat &argument 声明函数,并将责任留给函数?

假设您需要计算逐行叉积,例如

L.row(i) = A.row(i).cross(B.row(i));
  1. 在这种情况下,我可以安全地使用此赋值操作而不需要使用 'clone()' 的原因是中间结果矩阵(来自 'cross' 函数)将很快消失(当退出当前局部作用域时),对吗?
1个回答

10

1. 是的。

证明:

cv::Mat A = (cv::Mat_<double>(2,2) << 1.0, 2.0, 3.0, 4.0);
std::cout << "Original A:\n" << A << std::endl;

cv::Mat B = A;
B.at<double>(0, 1) = 2.5;
std::cout << "A:\n" << A << std::endl;
std::cout << "B:\n" << B << std::endl;

2. 是的。

证明:

void a_function(cv::Mat C)
{
    C.at<double>(1, 0) = 3.5;
}

cv::Mat A = (cv::Mat_<double>(2,2) << 1.0, 2.0, 3.0, 4.0);
std::cout << "Original A:\n" << A << std::endl;
a_function(A);
std::cout << "A:\n" << A << std::endl;

3. 当将一个Mat作为函数参数带或不带参考&指定时,该类在内部使用智能指针来指向原始数据而不是复制它。

证明:

void some_function(cv::Mat C)
{
    C.at<double>(1, 0) = 3.5;
}

void another_function(cv::Mat& C)
{
    C.at<double>(1, 0) = 3.6;
}

cv::Mat A = (cv::Mat_<double>(2,2) << 1.0, 2.0, 3.0, 4.0);
std::cout << "Original A:\n" << A << std::endl;
a_function(A);
std::cout << "A:\n" << A << std::endl;

cv::Mat B = (cv::Mat_<double>(2,2) << 1.0, 2.0, 3.0, 4.0);
std::cout << "Original B:\n" << B << std::endl;
a_function(B);
std::cout << "B:\n" << B << std::endl;

因为你指出,这种情况下使用&没有任何区别,我认为使用&可以提高可读性: 那些不了解Mat内部工作原理的人可能会担心没有指定&参数会产生一个副本。

4. 这是个人口味问题。我更喜欢const Mat& img,因为我认为对C/C++程序员更清晰和明显。

回答最后一个问题:

5. 是的。

证明:

cv::Mat L = (cv::Mat_<double>(1,3) << 0.0, 0.0, 0.0);
cv::Mat E = (cv::Mat_<double>(1,3) << 1.0, 2.0, 3.0);
cv::Mat F = (cv::Mat_<double>(1,3) << 4.0, 5.0, 6.0);
L = E.row(0).cross(F.row(0));

std::cout << "E:\n" << E << std::endl;
std::cout << "F:\n" << F << std::endl;
std::cout << "L:\n" << L << std::endl;

您的问题似乎已经有了几个答案。只需使用页面上的搜索框即可。这里是一个可能的答案:https://stackoverflow.com/q/63930667/176769 - karlphillip
谢谢,那就是我问的问题。 - VimNing

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接