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

1 人关注

我在 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相等。

编辑:我的多维数组大小是[1x10x8x8]

3 个评论
这些答案中是否有帮助你解决问题的?对有帮助的答案投上一票,并点击复选框,选择这个问题的最佳答案。通过做这些事情,你在帮助像你一样的未来访客。
同样的问题,新的一年。
@karlphillip,我完全忘记了这个问题,如果我找到关于caffe的文档,我会把这个问题的答案贴出来 :)
python
c++
arrays
opencv
Saeed Masoomi
Saeed Masoomi
发布于 2018-02-16
3 个回答
karlphillip
karlphillip
发布于 2020-01-30
0 人赞同

为了像访问一个形状为 [640][1] 的二维数组一样访问三维数组,你可以写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。

如果你想把一个二维数组作为一维来访问。检查这个答案.

gokart23
gokart23
发布于 2020-01-30
0 人赞同

如果你的模型数据是以行为主的形式排序的,你可以让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;

替换代码5】是为了通知OpenCV将数据解释为有符号的32位整数。

References: 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,

Why is the number of dimensions 3 ?
谢谢你在我的工作中测试了你的代码,我意识到我的数据尺寸是[1x10x8x8],但是我不明白如何在opencv中访问一个元素,你能用一个简单的代码澄清吗?
Saeed Masoomi
Saeed Masoomi
发布于 2020-01-30
已采纳
0 人赞同

第一步,我们需要获得一个指向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) {