Matlab имеет разные типы данных, например, uint8, in32 и, чаще всего, double.Вы можете увидеть их в рабочей области или с помощью команды whos .
Эти типы данных очень похожи нав C (++).Так, например, мы могли бы написать этот фрагмент кода c ++ / mex printint.cpp :
#include <matrix.h>
#include <mex.h>
void mexFunction(int nargout, mxArray *argout[], int nargin, const mxArray *argin[]) {
int nCols = mxGetDimensions(argin[0])[1];
int nRows = mxGetDimensions(argin[0])[0];
int *data = (int *)mxGetData(argin[0]);
for(int row=0; row<nRows; ++row) {
for(int col=0; col<nCols-1; ++col) {
mexPrintf("%3d, ", data[nRows*col + row]);
}
mexPrintf("%3d\n", data[nRows*(nCols-1) + row]);
}
}
Этот код просто печатает все числа в матрице, но он предполагает что элементы в матрице являются целыми числами.То есть mxGetData возвращает пустой указатель, который может указывать на любой тип данных, также удваивается.Я приведу пустой указатель к целочисленному указателю, что сложно, но допустимо в C (++).
Это, однако, позволяет мне запускать printint для двойных чисел или любой другой матрицы в этом отношении:
>> doubles=randi(10,[2,5])
doubles =
8 3 1 7 10
1 1 9 4 1
>> whos('doubles')
Name Size Bytes Class Attributes
doubles 2x5 80 double
>> printint(doubles)
0, 0, 0, 0, 0
1075838976, 1072693248, 1074266112, 1072693248, 1072693248
Можно видеть, что выходные данные являются мусором, я интерпретировал двойные числа, как если бы они были целыми числами.Это также может привести к ошибкам сегментации, а именно, если фактический размер данных, вводимых одним, меньше, чем размер целого;как уинт8.Если один вводит целые числа, метод работает:
>> integers = int32(doubles)
integers =
8 3 1 7 10
1 1 9 4 1
>> whos('integers')
Name Size Bytes Class Attributes
integers 2x5 40 int32
>> printint(integers)
8, 3, 1, 7, 10
1, 1, 9, 4, 1
Я обычно предполагаю ввод определенного типа данных, так как я использую mex для ускорения определенных частей кода и не хочу тратить времяна создание гибких и надежных API.Это происходит за счет неожиданного поведения, когда входные и предполагаемые типы данных не совпадают.Таким образом, можно рассмотреть возможность программного тестирования вводимого типа данных, чтобы правильно его обработать.
Ваша проблема: В случае использования I = imread (имя файла) , Matlab возвращает трехмерную матрицу строк x cols x каналов типа uint8 , что равно unsigned char в C (++).Чтобы работать с этими данными, можно написать простой класс для переноса изображения.Это делается здесь:
#include <matrix.h>
#include <mex.h>
class MatlabImage {
public:
MatlabImage(const mxArray *data) {
this->data = (unsigned char*)mxGetData(data);
this->rows = mxGetDimensions(data)[0];
this->cols = mxGetDimensions(data)[1];
this->channels = mxGetDimensions(data)[2];
}
unsigned char *data;
int rows, cols, channels;
int get(int row, int col, int channel) {
return this->data[row + rows*(col + cols*channel)];
}
};
void mexFunction(int nargout, mxArray *argout[], int nargin, const mxArray *argin[]) {
MatlabImage image(argin[0]);
int row=316; int col=253;
mexPrintf("I(%d, %d) = (%3d, %3d, %3d)\n", row, col, image.get(row,col,0), image.get(row,col,1), image.get(row,col,2));
}
Это можно затем использовать в Matlab следующим образом:
>> I = imread('workspace.png');
>> whos('I')
Name Size Bytes Class Attributes
I 328x344x3 338496 uint8
>> getpixel(I)
I(316, 253) = (197, 214, 233)
>> I(317,254,:)
ans(:,:,1) =
197
ans(:,:,2) =
214
ans(:,:,3) =
233
Можно также работать с двойными аналогичным образом. double (I) конвертирует изображение в double, а im2double (I) делает то же самое, но затем делит все значения на 255, так что они лежат между 0 и 1. Вв обоих случаях необходимо привести результат mxGetData (...) к (double *) вместо (unsigned char *) .C (++) начинает индексирование с 0 и Matlab с 1, поэтому для передачи индексов от одного к другому всегда требуется их увеличение или уменьшение.