Чтение изображения в matlab в формате, приемлемом для mex - PullRequest
0 голосов
/ 02 июня 2011

Привет, я использую функцию imread в matlab для чтения изображения. Но теперь, если я хочу использовать это изображение в мекс-файле, что мне делать? Я использовал функцию im2double к изображению, а затем передал его в mex-файл, но полученные результаты неприемлемы.

так есть ли другая функция, которую можно использовать

Ответы [ 2 ]

1 голос
/ 13 мая 2014

Matlab имеет разные типы данных, например, uint8, in32 и, чаще всего, double.Вы можете увидеть их в рабочей области или с помощью команды whos .

Matlab workspace

Эти типы данных очень похожи нав 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, поэтому для передачи индексов от одного к другому всегда требуется их увеличение или уменьшение.

0 голосов
/ 02 июня 2011

Преобразовать в двойное и разделить на 255. В файле Mex двойной массив Matlab используется для представления изображения

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...