在opencv(C++)中从caffe读取多维数组
Posted
技术标签:
【中文标题】在opencv(C++)中从caffe读取多维数组【英文标题】:Read multi-dimensional array from caffe in opencv (C++) 【发布时间】:2018-02-15 17:42:46 【问题描述】:我在caffe
中有一个模型,它产生一个多维数组。这个数组的大小是[1x10x8x8]
,所以在python中我对这个大小没有问题,因为python会自动管理这个数组并且我知道其中元素的顺序。但是当我用 c++ 切换到opencv
时,整个数组是一个向量,我不知道如何重新生成类似 python 数组的东西,我使用cv::NAryMatIterator
来访问下面这样的多维数组
const cv::Mat* arrays[]=&prob,0; //my multi-dimensional array is prob
cv::Mat my_planes[1];
cv::NAryMatIterator it(arrays,my_planes);
cv::Mat Multi_Array ; //temporary Mat
for (int p = 0; p < it.nplanes; ++p,++it)
Multi_Array = it.planes[0];
这样做之后,我看到Multi_Array
的大小是[640x1]
,这似乎等于python 产生的8x8x10
。有没有办法一一访问8x8
飞机?
编辑:我的多维数组大小是[1x10x8x8]
【问题讨论】:
这些答案是否有助于您解决问题?投票给那些做过的人,然后点击复选框来选择这个问题的最佳答案。通过做这些事情,您正在帮助像您这样的未来访客。 同样的问题,新的一年。 @karlphillip,我完全忘记了这个问题,如果我找到关于 caffe 的文档,我会发布我对这个问题的答案:) 【参考方案1】:要像访问形状为 [640][1]
的 2D 数组一样访问 3D 数组,您可以编写 3 个循环以使用 [x,y,z] 格式对元素进行迭代,例如:
int data[640][1] = 0 ;
int width = 8, height = 8, depth = 10;
for (int x = 0; x < width; x++)
for (int y = 0; y < height; y++)
for (int z = 0; z < depth; z++)
int idx = x * height * depth + y * depth + z;
data[idx][0] = idx;
这会用 0 到 639 之间的数字填充数组。
如果您希望将 2D 数组作为 1D 访问,check this answer。
【讨论】:
【参考方案2】:如果您的模型数据以行优先格式排序,您可以让 OpenCV 将数据解释为所需大小的 Mat
。然后,可以使用multidim_mat.row( row_number )
访问Mat
的平面。
为了从数据中创建Mat
:
int data[640] = 0 ;
const int size[] = 8, 8, 10 ;
cv::Mat multidim_mat(3, size, CV_32S, data);
std::cout << multidim_mat.dims << std::endl;
for (int i = 0; i < multidim_mat.dims; i++)
std::cout << "Dimension " << i << " is of size " << multidim_mat.size[i] << std::endl;
CV_32S
用于通知 OpenCV 将数据解释为带符号的 32 位整数。
参考:https://docs.opencv.org/3.4.0/d3/d63/classcv_1_1Mat.html#a5fafc033e089143062fd31015b5d0f40、https://docs.opencv.org/3.4.0/d3/d63/classcv_1_1Mat.html#details、
【讨论】:
为什么维数是3? 感谢在我的工作上测试了你的代码后,我意识到我的数据维度是 [1x10x8x8] ,但是我不明白如何访问 opencv 中的一个元素,你能用一个简单的代码来澄清一下吗?! !【参考方案3】:在第一步中,我们需要获取指向 OpenCV Mat 对象的指针,您可以通过以下命令执行此操作。(我假设表示您的数据的数据主要是 float
并考虑概率 Mat 是 prob
,我们从 caffe 获取这个 Mat)
float* p = (float*)(prob.data);
此指针将指向数据驻留在内存中的位置。例如,如果我们想访问 (1,3,7,7) 位置的元素,我们可以这样操作:
int S= sizeof(float);
float val = p[(
7*p.step[3]/S + //forth dimension
7*p.step[2]/S + //third dimension
3*p.step[1]/S //second dimension
)]
//first dimension is not needed, because it is decoded in address of p
//and if you have any higher number than 1 in first dimension you need to add it to the above command
所以要遍历概率矩阵,你可以像下面这样:
auto S=sizeof(float);
for (int d2 = 0; d2 < 129; ++d2)
for (int d3 = 0; d3 < 129; ++d3)
for (int d4 = 0; d4 < 10; ++d4)
float val = p[(d2*prob.step[3]/S + d3*prob.step[2]/S + d4* prob.step[1]/S)];
【讨论】:
以上是关于在opencv(C++)中从caffe读取多维数组的主要内容,如果未能解决你的问题,请参考以下文章