在OpenCV(C )中读取来自Caffe的多维阵列

Read multi-dimensional array from caffe in opencv (C++)

本文关键字:Caffe 阵列 读取 OpenCV      更新时间:2023-10-16

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

访问3D数组,就好像它是带有Shape [640][1]的2D数组一样,您可以使用 [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,请检查此答案。

如果您的模型数据是以行 - 尺寸表单排序的,则可以让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/d63/classcv_1_1mat.html#a5fafc033e089143062fd31015b5b5b5d0f40f40f40f40f40f40f40f40 f40f40 l#details,

在第一步中,我们需要获取一个指向OpenCV Mat Object的指针,您可以通过以下命令来执行此操作(我假设代表您数据的数据主要是float,并且考虑概率垫是prob,我们从Caffe获得此垫子(

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)];
        }
    }
}