opencv - What are the different ways of constructing cv::Mat? -
opencv version 3.2.0
i reading bradski , trying make different cv::mat constructors - single channel. can please tell, why constructors not work?
float data1[6] = {1,2,3,4,5,6}; float data2[6] = {10,20,30,40,50,60}; float data3[6] = {100,200,300,400,500,600}; cv::mat mat1(3,4,cv_32fc1); //ok cv::mat mat2(3,4,cv_32fc1,cv::scalar(33.3)); //ok cv::mat mat3(3,4,cv_32fc1,data1,sizeof(float)); //ok cv::mat mat4(cv::size(3,4),cv_32fc1); //ok cv::mat mat5(cv::size(3,4),cv_32fc1,cv::scalar(66.6)); //ok cv::mat mat6(cv::size(3,4),cv_32fc1,data2,sizeof(float)); //ok int sz[] = {8, 8, 8}; cv::mat bigcube1(3, sz, cv_32fc1); // ok cv::mat bigcube2(3, sz, cv_32fc1, cv::scalar::all(99)); // ok cv::mat bigcube3(3, sz, cv_32fc1, data3, 4); // not ok, how initialise 3d data? std::cout << mat1 << std::endl << mat2 << std::endl << mat3 << std::endl << mat4 << std::endl << mat5 << std::endl << mat6 << std::endl; // ok std::cout << bigcube1.at<float>(10,10,10) << std::endl << bigcube2.at<float>(10,10,10) << std::endl; // ok cv::mat img_rgb = cv::imread("lena.jpg", cv_load_image_color); std::vector<cv::range> ranges(3, cv::range(2,3)); cv::mat roirange( img_rgb, cv::range(100, 300), cv::range(0, 512)); //ok cv::mat roirect( img_rgb, cv::rect(0,100,512,200)); // ok cv::mat roirangemultiple( bigcube1, ranges); // ok cv::namedwindow("range", cv_window_autosize); imshow("range", roirange); // ok cv::namedwindow("rect", cv_window_autosize); imshow("rect", roirect); // ok std::cout << roirangemultiple.at<float>(0,1,1); // not ok. expecting float value answer cv::waitkey(0);
the corresponding answers are:
[4.6634629e-10, 0, 0, 0; 0, 0, 0, 0; 127.62516, 2.8025969e-45, 0, 0] [33.299999, 33.299999, 33.299999, 33.299999; 33.299999, 33.299999, 33.299999, 33.299999; 33.299999, 33.299999, 33.299999, 33.299999] [1, 2, 3, 4; 2, 3, 4, 5; 3, 4, 5, 6] [0, 0, 0; 0, 0, 0; 0, 0, 0; 0, 0, 0] [66.599998, 66.599998, 66.599998; 66.599998, 66.599998, 66.599998; 66.599998, 66.599998, 66.599998; 66.599998, 66.599998, 66.599998] [10, 20, 30; 20, 30, 40; 30, 40, 50; 40, 50, 60] 0 // bigcube1 99 // bigcube2
and corresponding answers lena.jpg cropped version range , rect. dont know how use ranges though.
multiple issues.
cv::mat mat3(3,4,cv_32fc1,data1,sizeof(float));
this crash in debug mode, failing an assertion. though not in documentation, step size must @ least length of row (i.e. no overlap allowed).
the correct code scenario like.
float data1[12] = { 1, 2, 3, 4, 2, 3, 4, 5, 3, 4, 5, 6 }; cv::mat mat3(3, 4, cv_32fc1, data1, 4 * sizeof(float));
cv::mat mat6(cv::size(3,4),cv_32fc1,data2,sizeof(float));
similar situation in previous case. note produces differently shaped array -- previous 3 rows, 4 columns, 1 has 4 rows , 3 columns (see docs of cv::size).
float data2[12] = { 10, 20, 30, 40, 20, 30, 40, 50, 30, 40, 50, 60 }; cv::mat mat6(cv::size(3, 4), cv_32fc1, data2, 3 * sizeof(float));
cv::mat bigcube1(3, sz, cv_8uc1); std::cout << bigcube1 << std::endl;
formatting of arrays more 2 dimensions not supported.
you can test array correctly created manually printing values:
for (auto const& v : cv::mat1b(bigcube2)) { std::cout << uint(v) << " "; } std::cout << "\n";
cv::mat bigcube3(3, sz, cv_32fc1, data3, 4);
the problem here last parameter. the docs
cv::mat::mat(int ndims, const int * sizes, int type, void * data, const size_t * steps = 0 )
steps - array of ndims-1 steps in case of multi-dimensional array (the last step set element size). if not specified, matrix assumed continuous.
- you're not passing array of steps last parameter (only single integer)
- you don't pass enough data
- and rows again overlap.
one way like
float data3[8 * 8 * 8]; // populate data sequence 0..511 std::iota(std::begin(data3), std::end(data3), 0.0f); int sz[] = { 8, 8, 8 }; size_t steps[] = { 8 * 8 * sizeof(float), 8 * sizeof(float) }; cv::mat bigcube3(3, sz, cv_32fc1, data3, steps);
cv::mat bigcube1(3, sz, cv_8uc1); // ... std::cout << roirangemultiple.at<float>(0,1,1); // not ok. expecting float value answer
the data type cv_8uc1
, each element unsigned char. means shouldn't extracting float
values it. expectation incorrect. (now see changed code in question).
also, note cv::range
"start inclusive left boundary of range , end exclusive right boundary of range". since extract cv::range(2,3)
in each axis, resulting mat
1 x 1 x 1. hence, you're accessing elements out of range (again, trigger debug mode assertion).
std::cout << roirangemultiple.at<unsigned char>(0,0,0);
after change have correct type. notice never initialize bigcube1
. 0.0f result, print 0
. can try yourself, execute std::cout << 0.0f;
, see.
wiki
Comments
Post a Comment