Search code examples
opencvopencv-mat

OpenCV::Mat how to efficiently add a column of ones?


GIVEN:

A matrix (N, 3) build from a point cloud, i.e. a vector<Point3d>

std::vector<cv::Point3d> pcVector = ... // from somewhere
cv::Mat                  pcMat = cv::Mat(pcVector).reshape(1);

Thus having pcMat to be something like:

[  0.1, 1.3, 4.5 ]
[  3.1, 1.4, 7.6 ]
   ...
[  1.1, 3.4, 4.1 ]

GOAL:

An efficient method to get a column of ones added to the matrix. That is to receive a matrix like the following from the above.

[  0.1, 1.3, 4.5, 1.0 ]
[  3.1, 1.4, 7.6, 1.0 ]
   ...
[  1.1, 3.4, 4.1, 1.0 ]

CURRENTLY:

cv::Mat  result(N, 4);
cv::Mat  ones = cv::Mat_<double>::ones(N, 1);

cv::hconcat(pcMat, ones, result);

QUESTION:

This seems to be inefficient since a temporary matrix full of ones needs to be created. Are there any tricks to get this done faster?


Solution

  • Use cv::convertPointsToHomogeneous

    The function converts points from Euclidean to homogeneous space by appending 1's to the tuple of point coordinates. That is, each point (x1, x2, ..., xn) is converted to (x1, x2, ..., xn, 1).

    // given
    std::vector<cv::Point3d> pcVector = ... // from somewhere
    cv::Mat                  pcMat = cv::Mat(pcVector).reshape(1);
    
    // I did not run this
    cv::Mat dst;
    cv::convertPointsToHomogeneous(pcMat, dst); // pcVector oughta work too
    

    As always, these things will accept both Nx1 K-channel Mats as well as NxK 1-channel Mats. The result seems to always be Nx1 (K+1)-channel though.

    And... you can imagine what convertPointsFromHomogeneous would do.