Ошибка сборки Matlab Codegen

Я пытаюсь преобразовать приведенный ниже код Matlab в C++ с помощью codegen. Однако он не работает при сборке, и я получаю сообщение об ошибке:

«??? Если не указано «строки», первый вход должен быть вектором. Если вектор имеет переменный размер, либо первое измерение, либо второе должны иметь фиксированную длину, равную 1. Вход [] не поддерживается , Используйте ввод 1 на 0 или 0 на 1 (например, нули (1,0) или нули (0,1)) для представления пустого набора».

Затем он указывает на [id,m,n] = unique(id); будучи виновником. Почему он не строится и как это исправить?

function [L,num,sz] = label(I,n) %#codegen

% Check input arguments
error(nargchk(1,2,nargin));
if nargin==1, n=8; end

assert(ndims(I)==2,'The input I must be a 2-D array')

sizI = size(I);
id = reshape(1:prod(sizI),sizI);
sz = ones(sizI);

% Indexes of the adjacent pixels
vec = @(x) x(:);
if n==4 % 4-connected neighborhood
idx1 = [vec(id(:,1:end-1)); vec(id(1:end-1,:))];
idx2 = [vec(id(:,2:end)); vec(id(2:end,:))];
elseif n==8 % 8-connected neighborhood
idx1 = [vec(id(:,1:end-1)); vec(id(1:end-1,:))];
idx2 = [vec(id(:,2:end)); vec(id(2:end,:))];
idx1 = [idx1; vec(id(1:end-1,1:end-1)); vec(id(2:end,1:end-1))];
idx2 = [idx2; vec(id(2:end,2:end)); vec(id(1:end-1,2:end))];
else
error('The second input argument must be either 4 or 8.')
end

% Create the groups and merge them (Union/Find Algorithm)
for k = 1:length(idx1)
root1 = idx1(k);
root2 = idx2(k);

while root1~=id(root1)
id(root1) = id(id(root1));
root1 = id(root1);
end
while root2~=id(root2)
id(root2) = id(id(root2));
root2 = id(root2);
end

if root1==root2, continue, end
% (The two pixels belong to the same group)

N1 = sz(root1); % size of the group belonging to root1
N2 = sz(root2); % size of the group belonging to root2

if I(root1)==I(root2) % then merge the two groups
if N1 < N2
    id(root1) = root2;
    sz(root2) = N1+N2;
else
    id(root2) = root1;
    sz(root1) = N1+N2;
end
end
end

while 1
id0 = id;
id = id(id);
if isequal(id0,id), break, end
end
sz = sz(id);

% Label matrix
isNaNI = isnan(I);
id(isNaNI) = NaN;
[id,m,n] = unique(id);
I = 1:length(id);
L = reshape(I(n),sizI);
L(isNaNI) = 0;

if nargout>1, num = nnz(~isnan(id)); end 

person user3926194    schedule 15.09.2014    source источник


Ответы (2)


Просто к вашему сведению, если вы используете MATLAB R2013b или новее, вы можете заменить error(nargchk(1,2,nargin)) на narginchk(1,2).

Как говорится в сообщении об ошибке, для codegen unique требуется, чтобы вход был вектором, если не переданы «строки».

Если вы посмотрите на отчет (нажмите показанную ссылку «Открыть отчет») и наведите указатель мыши на идентификатор, вы, вероятно, увидите, что его размер не равен ни 1-by-N, ни N-by-1. Требование для unique можно увидеть, если вы ищете unique здесь:

http://www.mathworks.com/help/coder/ug/functions-supported-for-code-generation--alphabetical-list.html

Вы можете сделать одну из нескольких вещей:

Сделайте id вектором и обработайте его как вектор для вычислений. Вместо декларации:

id = reshape(1:prod(sizI),sizI);

вы можете использовать:

id = 1:numel(I)

Тогда id будет вектором-строкой.

Вы также можете оставить код как есть и сделать что-то вроде:

[idtemp,m,n] = unique(id(:));
id = reshape(idtemp,size(id));

Очевидно, что это приведет к созданию копии idtemp, но это может привести к меньшему количеству изменений в вашем коде.

person Ryan Livingston    schedule 16.09.2014

  1. Удалите анонимную функцию, хранящуюся в переменной vec, и сделайте vec подфункцией:

    function y = vec(x)
    coder.inline('always');
    y = x(:);
    
  2. Без опции 'rows' ввод функции unique всегда интерпретируется как вектор, и в любом случае вывод всегда является вектором. Так, например, что-то вроде id = unique(id) имело бы эффект id = id(:), если бы все элементы матрицы id были уникальными. Нет ничего плохого в том, чтобы сделать ввод векторным. Поэтому измените строку

    [id,m,n] = unique(id);
    

to

    [id,m,n] = unique(id(:));
person Michael Hosea    schedule 16.09.2014