25

Typically if my data is non-const, I can initialize a cv::Mat header on top of it for algebraic manipulation.

float awesome_data[24] = {0};
cv::Mat awesome_mat = cv::Mat(6, 4, CV_32F, awesome_data);

But, if my data is const

const float awesome_data[24] = {0};
cv::Mat awesome_mat = cv::Mat(6, 4, CV_32F, awesome_data);

will have an error: unable to convert from const void * to void *. I know that I won't be changing awesome_mat, what is the best way to do this?

Currently, I have to do a const cast

const float awesome_data[24] = {0};
cv::Mat awesome_mat = cv::Mat(6, 4, CV_32F, const_cast<float *>(awesome_data));
Dat Chu
  • 10,822
  • 13
  • 58
  • 82
  • and what are you trying to achieve with that? – fazo Apr 13 '11 at 19:43
  • If an object is cv::Mat, I can perform any linear algebraic, image processing, ... operations. What can I not do with it? :-) – Dat Chu Apr 13 '11 at 19:46
  • I don't mean that. const_cast works - is there something else that you want or expect? – fazo Apr 13 '11 at 19:53
  • I was hoping that there is a better way to do this than using const_cast. Perhaps someone knows if OpenCV has a cv::const_Mat equivalent. – Dat Chu Apr 13 '11 at 19:56
  • sorry but for me your question sounds like 'is there any way to add 2 values without using +'. – fazo Apr 13 '11 at 20:10
  • 4
    @fazo: Not at all. const_cast is semantically wrong. By casting constness away, you remove the protection layer that prevents you from accidently changing the data. – etarion Apr 14 '11 at 11:40
  • @DatChu: Did you try what happens if you do 'cv::Mat const mat(6,4,CV_32F, awesome_data)? (the cv::Mat foo = cv::Mat(...) is useless, you can just do cv::Mat foo(...)). – etarion Apr 14 '11 at 11:44
  • 1
    There just is no cv::Mat constructor that lets you pass a const pointer, so no, this is not possible. Neither is there a special const_Mat... – Martin Apr 29 '11 at 13:40

3 Answers3

8

The data in cv::Mat can always be modified. To be more safe you should copy the data:

const float awesome_data[24] = {0};
cv::Mat awesome_mat = cv::Mat(6, 4, CV_32F, const_cast<float *>(awesome_data)).clone();

With const cv::Mat only the matrix header is readonly but not the data (Differences of using "const cv::Mat &", "cv::Mat &", "cv::Mat" or "const cv::Mat" as function parameters?):

const cv::Mat mat = cv::Mat::zeros(6, 4, CV_32F);
mat += 1; // compiles and runs fine!
Community
  • 1
  • 1
R1tschY
  • 3,032
  • 1
  • 24
  • 30
3

The only way to do this completely safely is to make a copy of awesome_data (one way or another). The solution by @R1tschY makes a copy of the data using an OpenCV method, which itself requires a const_cast. To avoid the const_cast altogether, the memory should be copied outside of OpenCV (since OpenCV does not respect const data). This would be one way:

const float awesome_data[24] = {0};
cv::Mat awesome_mat = cv::Mat(6, 4, CV_32F); //Allocates its own memory
memcpy(awesome_mat.data, awesome_data, 24*sizeof(float)); //Copy into the allocated memory.
ianinini
  • 630
  • 6
  • 13
0

As far as I know, OpenCV does not have a const_Mat class. However, by using

const float awesome_data[24] = {0};
const cv::Mat awesome_mat = cv::Mat(6, 4, CV_32F, const_cast<float *>(awesome_data));

you preserve constness.

Jakob
  • 2,360
  • 15
  • 21
  • 2
    Your post seems not to be in agreement with the @R1tschY 's one (and with my experience). Could you comment on what kind of 'constness' you mean, not to confuse anyone? – MaciekS May 19 '17 at 14:51
  • 1
    I think this would be bad advice. With this solution, the very next line might modify awsome_data itself. This is not const data in any meaningful sense. – ianinini Aug 01 '18 at 16:52