Question

This might seem like a stupid ? but I just found out something I thought was impossible in another language was possible so I have to try.

double cv_Mat_at_double(Mat* self, int i, int j) {
  return self->at<double>(i, j);
}

is the function I'm referring to.. In opencv you can assign data to a Matrix M by calling 'M.at(i, j) = 1' for instance. On my above function I was wondering if there was any way to snake into a double return and get at the object it just came from to set data to it. Anyway at all, I'm not opposed to hackery or breaking convention. But its gotta be using the .at object wrapper though. I tried:

With function called as:

  double cv_Mat_at_double(Mat* self, int i, int j) {
     return self->at<double>();
  }

 //Imagine a 2x2 Matrix filled with data,  (a 1 at element 0x0) here
 double i = cv_Mat_at_double(H, 0, 0);
 cout << i; (output> 1)
 i = 2;
 cout << i; (output> 2)
 cout << cv_Mat_at_double(H, 0, 0); (output> 1)

change to

double cv_Mat_at_double(Mat* self, int i, int j) {
  return self->at();
}

Error = .at expects an argument

Mat* cv_Mat_at_double(Mat* self, int i, int j) {
  return self->at<double>();
}
Error = can't return double as pointer

I know I can do this

double cv_Mat_at_double_Val(Mat* self, int i, int j, double val) {
   return  self->at<double>(i,j)=val;
}

But I'd like the function cv_Mat_at_double, above, the one that just returns the value at of an i,j element of a Mat object, to also, instead of just reading the value or a matrix element, to also be able to set the value of a matrix element, while not making it any heavier the the above 3 functions. Like if I can take the first function I posted at the top...and just hack through the idea of the double return and use it to set a matrix element as well. But at the very least I'd be happy if I can just get a wrapper of Mat::at that can both read and write a matrix element while being no heavier(cpu usage) than cv_Mat_at_double. This post is about breaking convention and just making it happen so I do stress the hack idea because I haven't read you can do that yet but maybe I didn't ask the right questions. thanks in advance for any help on this.

Edit:

I was wondering If there was a way to write the function you posted as below...changing the Mat object parameter, to a Mat*. I'm sorry I neglected to mention that as one of requirements before =) I will be more careful in the future.

All my Mat class wrappers use Mat* returns and accept Mat* parameters and there is about 2000 lines code...This was actually meant to be a C wrapper for C++ OpenCV function Mat::at. Wrapping as below I get an error message, not in the compiler, that compiles fine but I'm actually wrapping In a third language and that's getting an unhandled memory fault error and compiling the wrapper as is (below)in emacs with g++ on ubuntu trusty I'm getting a lot of errors...Didn't post them because it would be long.

Don't know why compiling with g++ in terminal works but emacs and my other language don't compile...Any more help is appreciated

 double &cv_Mat_at_double(Mat* &M, int i, int j) { 
    return M->at<double>(i,j); }
Was it helpful?

Solution

You can return a reference to double instead of value:

double &cv_Mat_at_double(cv::Mat &M, int i, int j) {
    return M.at<double>(i,j);
}

And then you can use cv_Mat_at_double either as l-value or r-value:

cv::Mat M = (cv::Mat_<double>(2,2) << 1, 0, 0, 0);
std:: cout << cv_Mat_at_double(M, 0, 0) << std::endl; // prints 1
cv_Mat_at_double(M, 0, 0) = 2;
std:: cout << cv_Mat_at_double(M, 0, 0) << std::endl; // prints 2

EDIT: Version with a pointer to cv::Mat:

double &cv_Mat_at_double(cv::Mat* M, int i, int j) { 
    return M->at<double>(i,j); 
}

(you just drop the '&').

EDIT2: Just reference Mat object.

cv::Mat M = (cv::Mat_<double>(2,2) << 1, 0, 0, 0);
std:: cout << cv_Mat_at_double(&M, 0, 0) << std::endl; // prints 1
cv_Mat_at_double(&M, 0, 0) = 2;
std:: cout << cv_Mat_at_double(&M, 0, 0) << std::endl; // prints 2
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top