Matlab MEX文件 - 索引正确,UINT32值不正确

时间:2022-09-06 15:15:09

This is the next step of my previous question here

这是我上一个问题的下一步

With the same Matlab testmatrix as in my question:

使用与我的问题相同的Matlab testmatrix:

testmatrix code here:

testmatrix代码在这里:

%Create a 4D array 2x,2y, rgb(3), framenumber(from 1 to 5)
%Framenumber from 1 to 5

testmatrix(1,1,1,1) = 0;
testmatrix(1,1,1,2) = 1;
testmatrix(1,1,1,3) = 2;
testmatrix(1,1,1,4) = 3;
testmatrix(1,1,1,5) = 4;

testmatrix(1,1,2,1) = 5;
testmatrix(1,1,2,2) = 6;
testmatrix(1,1,2,3) = 7;
testmatrix(1,1,2,4) = 8;
testmatrix(1,1,2,5) = 9;

testmatrix(1,1,3,1) = 10;
testmatrix(1,1,3,2) = 11;
testmatrix(1,1,3,3) = 12;
testmatrix(1,1,3,4) = 13;
testmatrix(1,1,3,5) = 14;

testmatrix(1,2,1,1) = 15;
testmatrix(1,2,1,2) = 16;
testmatrix(1,2,1,3) = 17;
testmatrix(1,2,1,4) = 18;
testmatrix(1,2,1,5) = 19;

testmatrix(1,2,2,1) = 20;
testmatrix(1,2,2,2) = 21;
testmatrix(1,2,2,3) = 22;
testmatrix(1,2,2,4) = 23;
testmatrix(1,2,2,5) = 24;

testmatrix(1,2,3,1) = 25;
testmatrix(1,2,3,2) = 26;
testmatrix(1,2,3,3) = 27;
testmatrix(1,2,3,4) = 28;
testmatrix(1,2,3,5) = 29;

testmatrix(2,1,1,1) = 30;
testmatrix(2,1,1,2) = 31;
testmatrix(2,1,1,3) = 32;
testmatrix(2,1,1,4) = 33;
testmatrix(2,1,1,5) = 34;

testmatrix(2,1,2,1) = 35;
testmatrix(2,1,2,2) = 36;
testmatrix(2,1,2,3) = 37;
testmatrix(2,1,2,4) = 38;
testmatrix(2,1,2,5) = 39;

testmatrix(2,1,3,1) = 40;
testmatrix(2,1,3,2) = 41;
testmatrix(2,1,3,3) = 42;
testmatrix(2,1,3,4) = 43;
testmatrix(2,1,3,5) = 44;

testmatrix(2,2,1,1) = 45;
testmatrix(2,2,1,2) = 46;
testmatrix(2,2,1,3) = 47;
testmatrix(2,2,1,4) = 48;
testmatrix(2,2,1,5) = 49;

testmatrix(2,2,2,1) = 50;
testmatrix(2,2,2,2) = 51;
testmatrix(2,2,2,3) = 52;
testmatrix(2,2,2,4) = 53;
testmatrix(2,2,2,5) = 54;

testmatrix(2,2,3,1) = 55;
testmatrix(2,2,3,2) = 56;
testmatrix(2,2,3,3) = 57;
testmatrix(2,2,3,4) = 58;
testmatrix(2,2,3,5) = 59;

testmatrix = uint8(testmatrix);

I have created the following Mex file:

我创建了以下Mex文件:

    #include <stdint.h>
#include "mex.h"

void
mexFunction(int nlhs,mxArray *plhs[],int nrhs,const mxArray *prhs[])
{
//Check - expect 1 input, expect 1 outputs
    if (nrhs != 1) {
        mexErrMsgIdAndTxt( "MATLAB:24bit_pixel_from_uint8_rgb:invalidNumInputs",
                "One input argument required.");
    }
    if (nlhs > 1) {
        mexErrMsgIdAndTxt( "MATLAB:24bit_pixel_from_uint8_rgb:maxlhs",
                "Too many output arguments.");
    }    

    //declare variables
    mwSize *dim_array, dims;
    mxArray *a_in_m, *b_out_m;
    uint8_T *a,b;
    int X,Y,RGB,FRAMENUMBER;
    int X_INDX,Y_INDX,RGB_INDX,FRAMENUMBER_INDX;

    dims             = mxGetNumberOfDimensions(prhs[0]);
    dim_array        = mxGetDimensions(prhs[0]);   
    X                = dim_array[0];
    Y                = dim_array[1];
    RGB              = dim_array[2];
    FRAMENUMBER      = dim_array[3];
    mexPrintf("dims: %d\n",dims);
    mexPrintf("X: %d\n",X);
    mexPrintf("Y: %d\n",Y);
    mexPrintf("RGB: %d\n",RGB);
    mexPrintf("FRAMENUMBER: %d\n",FRAMENUMBER);

    a = mxGetData(prhs[0]);
    mexPrintf("a is: %d\n",a[0]); //IS zero, now the other values aren't what I expected...

    b_out_m = plhs[0] = mxCreateNumericArray(dims, dim_array, mxUINT32_CLASS, 0);
    //b = mxGetData(b_out_m);

    int linear_index = 0;
    for(X_INDX=0;X_INDX<X;X_INDX++)
    {
        for(Y_INDX=0;Y_INDX<Y;Y_INDX++)
        {
            for(RGB_INDX=0;RGB_INDX<RGB;RGB_INDX++)
            {
                for(FRAMENUMBER_INDX=0;FRAMENUMBER_INDX<FRAMENUMBER;FRAMENUMBER_INDX++)
                {
                   mexPrintf("Linear Index: %u\n",linear_index); 
                   mexPrintf("Value[%u]: %u\n",FRAMENUMBER_INDX + (RGB_INDX*FRAMENUMBER)+(Y_INDX*RGB*FRAMENUMBER)+(X_INDX*Y*RGB*FRAMENUMBER),(uint8_T)a[linear_index]);//FRAMENUMBER_INDX + (RGB_INDX*FRAMENUMBER)+(Y_INDX*RGB*FRAMENUMBER)+(X_INDX*Y*RGB*FRAMENUMBER)
                   linear_index += 1;
                }
            }
        }

    }
}

My indexing looks correct, but when I print the values out, I get the following:

我的索引看起来是正确的,但是当我打印出值时,我得到以下内容:

>> rgb_to_uint8(testmatrix)
dims: 4
X: 2
Y: 2
RGB: 3
FRAMENUMBER: 5
a is: 755965440
Linear Index: 0
Value[0]: 755965440
Linear Index: 1
Value[1]: 840180485
Linear Index: 2
Value[2]: 924395530
Linear Index: 3
Value[3]: 772808449
...etc

I am clearly accessing something wrong; can somebody point me in the right direction? I'll edit it as I go along and see if I can figure it out.

我显然是在搞错了;有人能指出我正确的方向吗?我会随着时间编辑它,看看能不能搞清楚。

[EDIT] I updated the code with the suggestions below - I changed to uint8_T, and it did wonders, but I expected this setup to read the array out of memory as 0,1,2,3... etc. It appears to be "skipping around", which means that the arrays aren't stored in memory as I tried to access them - I thought Matlab was column-major, so I indexed by the 4th dimension, then the third, then the second, then the first...

[编辑]我更新了代码与下面的建议 - 我改为uint8_T,它确实奇迹,但我期望这个设置读取内存的数据为0,1,2,3 ...等。它似乎是“跳过”,这意味着当我试图访问它们时,数组没有存储在内存中 - 我认为Matlab是列专业的,所以我用第4维索引,然后是第3维,然后是第2维,然后是第一...

I'm creating another test matrix, but I'll index it the other way, and see if I get the values to read out linearly. Thanks for the notes, all, and the pointer to uint8_T (which made it start clicking along much better, and the void* cast was missing).

我正在创建另一个测试矩阵,但我会用另一种方式对其进行索引,看看我是否得到了线性读出的值。感谢笔记,全部和指向uint8_T的指针(这使得它开始点击更好,并且缺少void * cast)。

1 个解决方案

#1


2  

Update from my comment: When you do testmatrix(:) it reads out all the elements of an array of any dimensionality in in linear order. It goes down then across and then the remaining dimensions. You are traversing the last dimension with testmatrix(1,1,1,1),testmatrix(1,1,1,2),testmatrix(1,1,1,3).

从我的评论更新:当你执行testmatrix(:)时,它以线性顺序读出任何维度的数组的所有元素。然后它向下,然后是剩余的尺寸。您正在使用testmatrix(1,1,1,1),testmatrix(1,1,1,2),testmatrix(1,1,1,3)遍历最后一个维度。


There are several issues to address, but the core of the issue is the data type, as jucestain said. When you use mxGetData, you get a void* and it is your responsibility to ensure that whatever you cast to is the actual underlying data type (in the MATLAB array).

有几个问题需要解决,但问题的核心是数据类型,正如jucestain所说。当你使用mxGetData时,你得到一个void *,你有责任确保你所投射的是实际的底层数据类型(在MATLAB数组中)。

A few notes:

几点说明:

  • Get used to using mxIsClass to check the input type and you won't have these problems as easily. It takes a string type for the class, one of the types listed when you type help class, just as if you were calling isa in MATLAB. Just coding the check is a good way for you to double check the intended use of the function.
  • 习惯使用mxIsClass来检查输入类型,你不会轻易地遇到这些问题。它需要一个字符串类型,类型是键入帮助类时列出的类型之一,就像在MATLAB中调用isa一样。只需对支票进行编码,您就可以仔细检查功能的预期用途。
  • You don't need to mxDuplicate from prhs[] to get the data. Just read the data, but don't write to it.
  • 您不需要从prhs []获取mxDuplicate来获取数据。只需读取数据,但不要写入数据。
  • Use mxGetPr only to get a double* (and only if mxIsClass says it's a double!). If you have any other data type, use mxGetData.
  • 使用mxGetPr只能得到一个双*(并且只有当mxIsClass表示它是双倍时!)。如果您有任何其他数据类型,请使用mxGetData。
  • mxGetData returns a void*, and you need and explicit cast (e.g. (uint32_t*)) to access the data, but again, it doesn't convert the underlying data so be sure it is already correct.
  • mxGetData返回一个void *,你需要和显式转换(例如(uint32_t *))来访问数据,但同样,它不会转换底层数据,所以要确保它已经是正确的。
  • mxGetDimensions returns a const mwSize*, so remember the const.
  • mxGetDimensions返回一个const mwSize *,所以请记住const。

#1


2  

Update from my comment: When you do testmatrix(:) it reads out all the elements of an array of any dimensionality in in linear order. It goes down then across and then the remaining dimensions. You are traversing the last dimension with testmatrix(1,1,1,1),testmatrix(1,1,1,2),testmatrix(1,1,1,3).

从我的评论更新:当你执行testmatrix(:)时,它以线性顺序读出任何维度的数组的所有元素。然后它向下,然后是剩余的尺寸。您正在使用testmatrix(1,1,1,1),testmatrix(1,1,1,2),testmatrix(1,1,1,3)遍历最后一个维度。


There are several issues to address, but the core of the issue is the data type, as jucestain said. When you use mxGetData, you get a void* and it is your responsibility to ensure that whatever you cast to is the actual underlying data type (in the MATLAB array).

有几个问题需要解决,但问题的核心是数据类型,正如jucestain所说。当你使用mxGetData时,你得到一个void *,你有责任确保你所投射的是实际的底层数据类型(在MATLAB数组中)。

A few notes:

几点说明:

  • Get used to using mxIsClass to check the input type and you won't have these problems as easily. It takes a string type for the class, one of the types listed when you type help class, just as if you were calling isa in MATLAB. Just coding the check is a good way for you to double check the intended use of the function.
  • 习惯使用mxIsClass来检查输入类型,你不会轻易地遇到这些问题。它需要一个字符串类型,类型是键入帮助类时列出的类型之一,就像在MATLAB中调用isa一样。只需对支票进行编码,您就可以仔细检查功能的预期用途。
  • You don't need to mxDuplicate from prhs[] to get the data. Just read the data, but don't write to it.
  • 您不需要从prhs []获取mxDuplicate来获取数据。只需读取数据,但不要写入数据。
  • Use mxGetPr only to get a double* (and only if mxIsClass says it's a double!). If you have any other data type, use mxGetData.
  • 使用mxGetPr只能得到一个双*(并且只有当mxIsClass表示它是双倍时!)。如果您有任何其他数据类型,请使用mxGetData。
  • mxGetData returns a void*, and you need and explicit cast (e.g. (uint32_t*)) to access the data, but again, it doesn't convert the underlying data so be sure it is already correct.
  • mxGetData返回一个void *,你需要和显式转换(例如(uint32_t *))来访问数据,但同样,它不会转换底层数据,所以要确保它已经是正确的。
  • mxGetDimensions returns a const mwSize*, so remember the const.
  • mxGetDimensions返回一个const mwSize *,所以请记住const。