OpenCV版本3.2.0
我正在阅读Bradski并尝试制作不同的cv :: Mat构造函数 - 单通道。 有人可以告诉,为什么构造函数不起作用?
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 to initialise a 3D from 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 a float value as answer
cv::waitKey(0);
相应的答案是:
[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
然后lena.jpg的相应答案是Range和Rect的裁剪版本。我不知道如何使用范围。
答案 0 :(得分:0)
多个问题。
cv::Mat mat3(3,4,CV_32FC1,data1,sizeof(float));
这将在调试模式下崩溃,失败an assertion。即使文档中没有,步长也必须至少为行的长度(即不允许重叠)。
此方案的正确代码类似于。
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));
与先前案例类似的情况。另请注意,这会产生一个形状不同的数组 - 前一个是3行,4列,这个列有4行3列(参见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;
具有2个以上维度的数组格式为not supported。
您可以通过手动打印所有值来测试数组是否已正确创建:
for (auto const& v : cv::Mat1b(bigCube2)) {
std::cout << uint(v) << " ";
}
std::cout << "\n";
cv::Mat bigCube3(3, sz, CV_32FC1, data3, 4);
这里的问题是最后一个参数。来自the docs
cv::Mat::Mat(int ndims, const int * sizes, int type, void * data, const size_t * steps = 0 )
步骤 - 在多维数组的情况下,ndims-1步骤的数组(最后一步始终设置为元素大小)。如果未指定,则假定矩阵是连续的。
执行此操作的一种方法是
float data3[8 * 8 * 8];
// Populate the data with 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 a float value as answer
数据类型为CV_8UC1
,因此每个元素都是unsigned char。这意味着您不应该从中提取float
值。你的期望是不正确的。 (现在我看到你改变了问题中的代码)。
另外,请注意,cv::Range
&#34; start是范围的包含左边界,end是范围&#34;的专有右边界。由于您在每个轴中提取cv::Range(2,3)
,因此生成的Mat
为1 x 1 x 1.因此,您将访问超出范围的元素(同样,这将触发调试模式断言)。
std::cout << roiRangeMultiple.at<unsigned char>(0,0,0);
更改后,您的类型正确。但请注意,您永远不会初始化bigCube1
。结果最有可能得到0.0f,将打印为0
。您可以自己尝试,只需执行std::cout << 0.0f;
并查看。