вызов функции memcpy внутри mex

У меня есть интересная проблема. Именно так; Я пытаюсь использовать функцию std::memcpy внутри с помощью функции mex и вызываю эту функцию mex внутри MATLAB таким образом;

I2 = b_filter(I);

Когда я копирую все изображение, оно работает хорошо;

plhs[0] =  mxCreateDoubleMatrix(mxGetM(plhs[0]), mxGetN(plhs[0]), mxREAL);          
memcpy(mxGetPr(plhs[0]), mxGetPr(prhs[0]), sizeof(double) *mxGetM(plhs[0]) * mxGetN(plhs[0]));

Но когда я пытаюсь скопировать часть изображения

plhs[0] =  mxCreateDoubleMatrix(100, 100, mxREAL);              
memcpy(mxGetPr(plhs[0]), mxGetPr(prhs[0]), sizeof(double) * 100 * 100);

он не дает правильную часть изображения, но дает бессмысленные значения пикселей.

и так, что здесь происходит?


person Ali Jimenez    schedule 14.06.2013    source источник


Ответы (2)


Ха Ха! Вы попались на одном из самых неприятных нюансов mex-файла! Меня это тоже достало. Массивы в mex-функциях хранятся в порядке столбцов, а не строк, поэтому вы:

Вы по-прежнему используете индексирование по столбцам, как в Matlab, хотя

URL блога

Попробуйте эту страницу Тоже за красивую картинку заказа.

Рисунок из Mathworks

Наконец, я бы рекомендовал прочитать эту тему, чтобы лучше понять разницу Матричная память C и MATLAB упорядочена по столбцам.

person macduff    schedule 14.06.2013
comment
Я собираюсь проверить это! Ваше здоровье! - person Ali Jimenez; 14.06.2013
comment
Мало того, что есть проблема с порядком, но memcpy будет производить и действовать так же, как reshape. Он, конечно, не будет действовать как оператор среза MATLAB, чего, похоже, и хочет OP. - person Ben Voigt; 15.06.2013

Как объяснил @macduff, MATLAB использует колоночный порядок для хранения массивы, в то время как массивы C являются основными по строкам.

Вот пример реализации, показывающий, как скопировать часть матрицы.

matrix_slice_mex.c

#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    double *in, *out;
    mwIndex i,j;
    mwSize numRows;

    /* input checks */
    if (nrhs != 1 || nlhs > 1) {
        mexErrMsgIdAndTxt("MATLAB:nargchk", "Wrong number of arguments.");
    }
    if (mxGetNumberOfDimensions(prhs[0])>2 || !mxIsDouble(prhs[0])) {
        mexErrMsgIdAndTxt("MATLAB:wrongDims", "Expecting 2D double matrix.");
    }
    if (mxGetM(prhs[0])<100 || mxGetN(prhs[0])<100) {
        mexErrMsgIdAndTxt("MATLAB:wrongDims", "Matrix size must be >= 100x100.");
    }

    /* extract sub-matrix */
    plhs[0] = mxCreateDoubleMatrix(100, 100, mxREAL);
    out = mxGetPr(plhs[0]);
    in = mxGetPr(prhs[0]);
    numRows = mxGetM(prhs[0]);
    for(j=0; j<100; j++) {
        for(i=0; i<100; i++) {
            *out++ = in[i + numRows*j];
        }
    }
}

И чтобы проверить это:

x = rand(1000);
y = x(1:100,1:100);
yy = matrix_slice_mex(x);
isequal(y,yy)

Вы также могли бы использовать memcpy для копирования каждого из столбцов (вместо этого один цикл for)

person Amro    schedule 15.06.2013