9

I'm dealing with some code in which a do a lot of 3x3 matrix multiplications an also some translation of 3d points using rotation matrices, etc. I decided to use OpenCV core functionalities for the mathematical operations. The possibility to use the recent constructor added to the cv::Mat class to convert a cv::Point3d directly to a 3x1 cv::Mat reduces and simplifies the code greatly.

What I am wondering now is if there is a simple way to convert a 3x1 or 1x3 cv::Mat to an cv::Point3d? I always can do something like:

cv::Mat mat(3,1,CV_64FC1);
cv::Point3d p (mat.at<double>(0,0), mat.at<double>(1,0), mat.at<double>(2,0));

or

cv::Mat mat(3,1,CV_64FC1);
const double *data = mat.ptr<double>(0);
cv::Point3d p (data[0], data[1], data[2]);

I am very worried about the performance (avoid the 3 calls to at method).

Amro
  • 123,847
  • 25
  • 243
  • 454
piponazo
  • 478
  • 2
  • 4
  • 10

1 Answers1

13

cv::Point3d has a constructor which allows direct creation from cv::Mat:

cv::Mat mat(3,1,CV_64FC1);
cv::Point3d p(mat);

Another possibility you may not have considered is using cv::Matx instead of cv::Mat for your mathematical operations. I find it is easier to use, and offers more functionality, like multiplication of Point types without needing a conversion:

cv::Point3d p(1,2,3);
cv::Matx33d m = cv::Matx33d::eye();
cv::Point3d p2 = m * p;

cv::Matx is also statically allocated, rather than dynamically (like cv::Mat), in case you really need that extra little bit of performance. However, as in all performance-related advice: make sure what you're optimizing is actually a bottleneck by profiling.

Aurelius
  • 11,111
  • 3
  • 52
  • 69
  • Great! I was looking in the opencv core.hpp header for a constructor for the Point_ class like: `Point_(const Mat& sz);` As I didn't found it I thought there was no way to do it. Furthermore I didn't notice the existence of `Point_(const Vec<_Tp, 2>& v);` The usage of Matx seems to be very useful for my purposes. Thanks a lot! – piponazo Aug 31 '13 at 00:28
  • 1
    to be exact, there is no constructor for `Point_`/`Point3_` that takes a `cv::Mat`, rather there is an implicit [cast operator](https://github.com/Itseez/opencv/blob/2.4/modules/core/include/opencv2/core/core.hpp#L1856) in `cv::Mat` that converts it to other fixed-size classes like `Vec` or `Matx` (`Vec` is accepted by Point constructor) – Amro Sep 12 '14 at 17:14
  • I wonder why we can transform `cv::Point` with matrix, but not `cv::Vec`. In the latter case we need to convert `cv::Vec` into `cv::Point` first. – Maksym Ganenko Aug 02 '17 at 15:42
  • @MaksymGanenko It may be an oversight. However, the most common use for `cv::Vec` types is element access for multi-channel images, rather than as a mathematical construct. – Aurelius Aug 10 '17 at 17:03