Конвертировать файл OpenCV Mat в матрицу Matlab

Я создаю движок Matlab для преобразования файла OpenCV Mat в матрицу Matlab. Однако я получил неправильные результаты. Я приложил свой код, чтобы вы могли непосредственно проверить его.

#pragma comment (lib, "libmat.lib")
#pragma comment (lib, "libmx.lib")
#pragma comment (lib, "libmex.lib")
#pragma comment (lib, "libeng.lib")

void cvLoadMatrixToMatlab(const Mat& m, const string name, Engine *m_pEngine)
{
int rows=m.rows;
int cols=m.cols;
string text;
mxArray *T=mxCreateDoubleMatrix(cols, rows, mxREAL);

memcpy((char*)mxGetPr(T), (char*)m.data, rows*cols*sizeof(char));
engPutVariable(m_pEngine, name.c_str(), T);
text = name + "=" + name + "'";                    // Column major to row major
engEvalString(m_pEngine, text.c_str());

mxDestroyArray(T);
}

int main(int argc, char **argv)
{
/*Open Matlab Engine*/
Engine *m_pEngine;
m_pEngine = engOpen("null");

cv::Mat img = imread("panda.jpg",0);

cvLoadMatrixToMatlab(img,"imgMatlab", m_pEngine);
engEvalString(m_pEngine, "imshow(imgMatlab)");
cv::waitKey(0);

}

Исходное изображение
Результат показывает в Matlab

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

memcpy((char*)mxGetPr(T), (char*)m.data, rows*cols*sizeof(char));

1

Решение

При копировании данных из cv::Mat На матрицу Матлаба следует обратить внимание:

  1. В OpenCV вся матрица является мажорной строкой, а мажорной — для Matlab. Вы должны транспонировать перед копированием.

  2. Для копирования цветных изображений необходимо передавать данные по каналам.


Как вы собираетесь копировать цветное изображение cv::Mat Для Matlab, вы должны сделать следующее:

mwSize dims[] = {rows, cols, 3};
mxArray *T = mxCreateNumericArray(3, dims, mxUINT8_CLASS, mxREAL);
UINT8 *ptr = (UINT8 *) mxGetData(T);

std::vector<cv::Mat> channels; // B, G, R channels
cv::split(m, channels);

// remember to transpose first because MATLAB is col-major!!!
cv::transpose(channels[0], channels[0]);
cv::transpose(channels[1], channels[1]);
cv::transpose(channels[2], channels[2]);

memcpy(ptr, channels[2].ptr(), rows*cols*sizeof(UINT8));
memcpy(ptr+rows*cols, channels[1].ptr(), rows*cols*sizeof(UINT8));
memcpy(ptr+2*rows*cols, channels[0].ptr(), rows*cols*sizeof(UINT8));

engPutVariable(m_pEngine, name.c_str(), T); // put into matlab

Обновлено: Если вы копируете серое изображение, оно должно выглядеть так:

mwSize dims[] = {rows, cols};
mxArray *T = mxCreateNumericArray(2, dims, mxUINT8_CLASS, mxREAL);
UINT8 *ptr = (UINT8 *) mxGetData(T);

cv::transpose(m, m); // remember to tranpose first because MATLAB is col-major!!!
memcpy(ptr, m.ptr(), rows*cols*sizeof(UINT8));

engPutVariable(m_pEngine, name.c_str(), T); // put into matlab

Обратите внимание, что, UINT8 здесь, чтобы соответствовать Matlab’s uint8 тип используется для изображений.

3

Другие решения

Хорошо. Я использую для цикла для копирования данных, и, наконец, это работает.

int rows=m.rows;
int cols=m.cols;

mwSize dims[] = {rows, cols};
mxArray *T = mxCreateNumericArray(2, dims, mxUINT8_CLASS, mxREAL);
char *ptr = (char *) mxGetData(T);

for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
ptr[j*rows + i] =  (* m.row(i).col(j).data);
}
}

engPutVariable(m_pEngine, name.c_str(), T); // put into matlab

Для ответа, опубликованного выше, я все еще работаю над этим. Благодаря помощи @herohuyongtao упомянуть проблему транспонирования.

0

По вопросам рекламы [email protected]