在opencv(C ++)中从caffe读取多维数组

时间:2018-02-15 17:42:47

标签: python c++ arrays opencv

我在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]

3 个答案:

答案 0 :(得分:1)

如果您的模型数据以行主格式排序,您可以让OpenCV将数据解释为所需大小的Mat。然后,可以使用Mat访问multidim_mat.row( row_number )的平面。

为了从数据中创建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#a5fafc033e089143062fd31015b5d0f40https://docs.opencv.org/3.4.0/d3/d63/classcv_1_1Mat.html#details

答案 1 :(得分:1)

第一步,我们需要获取一个指向OpenCV Mat对象的指针,您可以通过以下命令进行操作。(我假设代表您的数据的数据主要是float,并且考虑Mat的概率为{{1 }},我们从caffe那里得到了Mat

prob

此指针将指向数据在内存中的驻留位置。因此,例如,如果我们要访问(1,3,7,7)位置中的元素,可以执行以下操作:

float* p = (float*)(prob.data);

因此,要遍历概率矩阵,您可以像下面这样进行操作:

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

答案 2 :(得分:0)

要像使用形状为[640][1]的2D数组一样访问3D数组,您可以使用 [x,y,z] 格式编写3个循环来迭代元素像:

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