0

I want to operate on a vector object directly using OpenCVs matrix functions.

What I am currently doing is using memcpy to copy the data to a matrix, but I would really like operate on it directly because I've very concerned about performance. The following is my current implementation that works as expected.

Working Implementation

void TrajectorySmoother::SmoothTrajectoryOnce(
std::vector<navstack_msgs::location>& path,
const unsigned int& end_remove)
{
  cv::Mat_<double> matrix_orig = cv::Mat(path.size(), sizeof(navstack_msgs::location)/sizeof(double), CV_64F);
  memcpy(matrix_orig.data, path.data(), path.size()*sizeof(navstack_msgs::location));
  ROS_INFO_STREAM("mat: " << matrix_orig);
}

I tried using static_cast and reinterpret_cast but they don't seem to work so I tried casting a pointer to the data as a pointer to an openCV matrix.

Pointer Casting Approach

void TrajectorySmoother::SmoothTrajectoryOnce(
    std::vector<navstack_msgs::location>& path,
    const unsigned int& end_remove)
{
  cv::Mat_<double> matrix_orig = cv::Mat(path.size(), sizeof(navstack_msgs::location)/sizeof(double), CV_64F);
  cv::Mat_<double> * matrix_ptr = reinterpret_cast<cv::Mat_<double> *>(path&);
  ROS_INFO_STREAM("mat: " << (*matrix_ptr));
}

The output from this is a stream of semicolons. I thought it might need to be reshaped, but I get an error that it is not continuous.

Klik
  • 1,757
  • 1
  • 21
  • 38
  • [Doesn't look like `cv::mat` and `std::vector` have a defined relationship](http://docs.opencv.org/3.1.0/d3/d63/classcv_1_1Mat.html) so the odds are quite slim. – user4581301 Mar 09 '17 at 03:16
  • Aren't they both contiguous data types? I thought that since memcpy works, then I should be able to just cast the data as I want. Is there a flaw in my logic? – Klik Mar 09 '17 at 03:18
  • Come to think of it, `vector` is generally just a few pointers pointing to the data allocated to the `vector`, so you've cast a pointer to your data, not the data, to your `mat`. Crom only knows whose memory you marched through there. – user4581301 Mar 09 '17 at 03:20
  • I know the size of the memory region and since I'm [counting on the vector to be contiguous](http://stackoverflow.com/a/849190/1406888). I thought I should be able to cast it. – Klik Mar 09 '17 at 03:24
  • `vector` data is contiguous. Unfortunately `vector` data is over here... and the `vector` itself is somewhere over there. At any rate, you are violating the hell out of the [Strict Aliasing Rule](http://en.cppreference.com/w/cpp/language/reinterpret_cast). Read down to the section on Type Aliasing. – user4581301 Mar 09 '17 at 03:25

1 Answers1

3

You didn't post definition of navstack_msgs::location so it's hard to say if what you asking for makes sense.

OpenCV provides a bunch (4) of cv::Mat constructors for "borrowed" (i.e., non-owned) memory:

Mat (int rows, int cols, int type, void *data, size_t step=AUTO_STEP)

Mat (Size size, int type, void *data, size_t step=AUTO_STEP)

Mat (int ndims, const int *sizes, int type, void *data, const size_t *steps=0)

Mat (const std::vector< int > &sizes, int type, void *data, const size_t *steps=0)

http://docs.opencv.org/3.2.0/d3/d63/classcv_1_1Mat.html#a51615ebf17a64c968df0bf49b4de6a3a

Since OpenCV matrices are row-major, you can use it like this to create a Mat "view":

std::vector<T> path;
cv::Mat mat(path.size(), sizeof(T), CV_8U, path.data());

Now each row has the data of one element in path.

But you must assume here that interpreting T as a sequence of uchars is meaningful. If you think T is a bunch of doubles (e.g. a POD: struct T { double x; double y; };). Then you can do

cv::Mat mat(path.size(), sizeof(T) / 8, CV_64F, path.data());

But if T has something else or if it has pointers (e.g., typedef std::vector<double> T) then you won't be able to view it through a cv::Mat.

szym
  • 5,606
  • 28
  • 34
  • Thank you. I will give this a shot in the morning and if it works out I will take down my answer. – Klik Mar 09 '17 at 08:49
  • I couldn't wait. Yes, this works. Thank you for not complaining and providing a solution. – Klik Mar 09 '17 at 08:58