Search code examples
c++opencvmatrixassignment-operator

opencv: matrix assignment confusion


Could anyone verify/answer my understandings/questions?

In OpenCV, suppose

Mat A; // Suppose A has some values in it
Mat B=A;
  1. If I update B, A is also affected. right? It seems basically assigning by reference.

Suppose a function "void a_function(Mat argument) {..//change argument..}".

  1. After you call "a_function(A)", A is also affected, right?

  2. Then, why (or in which case) do we need "void a_function(Mat &argument)" if it is already calling by reference? Can & have a special meaning here?

  3. If you don't want A to be affected by the function call, which one is better habit?

    • calling by a_function(A.clone())?
    • calling by a_function(A) and declaring the function using const Mat &argument and leaving the responsibility to the function?

Suppose you need to calculate row-wise cross product like

L.row(i) = A.row(i).cross(B.row(i));
  1. In this case, the reason that I can safely use this assignment without 'clone()' is that the intermediate result matrix (from cross function) will be gone/disappear(?) soon (when exiting the current local scope), right?

Solution

  • 1. Yes.

    Proof:

    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. Yes.

    Proof:

    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. When a Mat is specified as a function parameter with or without the reference &, the class uses smart pointers internally to point to the original data instead of copying it.

    Proof:

    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;
    

    Since the use of & in this case doesn't make a difference, as you pointed out, I do believe using it improves readability: people that are not aware of the internal workings of a Mat might fear that a copy is being made if the parameter is specified without &.

    4. It's a matter of taste. I prefer const Mat& img because I think its cleaner and more obvious to C/C++ programmers.

    And to answer the last question:

    5. Yes.

    Proof:

    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;