Matlab中的运行长度编码

4

我可以协助你翻译。以下是需要翻译的内容:

我在MatLab方面很新,请问能否帮我解决一下运行长度编码代码无法工作的问题?

以下是输入内容:

ChainCode  = 11012321170701000700000700766666666666665555555544443344444333221322222322 

我希望你能够将其转换成RLE输出:
(1,2), (0,1), (1,1), (2,1), (3,1), (2,1), (1,2), (7,1), (0,1), (7,1), (0,1), 
(1,1), (0,3), (7,1), (0,5), (7,1), (0,2), (7,1), (6,13), (5,8), (4,4), (3,2), 
(4,5), (3,3), (2,2), (1,1), (3,1), (2,5), (3,1), (2,2) 

这是我的代码:
lengthcode = 1;
N = 1;

for i = 2:length(ChainCode)

    if x(i)==x(i-1)
        N = N + 1; 
        valuecode(N)  = x(i);
        lengthcode(N) = lengthcode(N) + 1;
    else 
        N = 1;
        lengthcode = 1;
    end

    i = i + 1;

end

但是这个方法无效,而且我仍然感到困惑,不知如何打印出那样的输出。希望你能帮助我。谢谢。

如果有人能帮助计算现有输出的出现频率,可以像这样进行:例如:(1.2), (0.1), (1.1), (2.1), (3.1), (2.1), (1.2), (7.1), (0,1)(1,2) = 2 次 (0,1) = 2 次 (1,1) = 1 次以此类推。谢谢。 - user1146895
如果您需要与原帖不同的内容,应修改原始帖子/问题(或发布新问题)。请查看下面更新的答案以查找出现频率。 - gevang
4个回答

11

这里有一个紧凑的解决方案,没有循环、cellfun或arrayfun:

chainCode = '11012321170701000700000700766666666666665555555544443344444333221322222322';
numCode = chainCode - '0'; % turn to numerical array

J=find(diff([numCode(1)-1, numCode]));
relMat=[numCode(J); diff([J, numel(numCode)+1])];

1

通过坚持您原始的实现,以下简单的更改应该可以工作。

chainCode = '11012321170701000700000700766666666666665555555544443344444333221322222322';
numCode = chainCode - '0'; % turn to numerical array
relMat = [];
numCode = [numCode nan]; % dummy ending

N = 1;
for i = 1:length(numCode)-1   
    if numCode(i)==numCode(i+1)
        N = N + 1;
    else
        valuecode = numCode(i);
        lengthcode =  N;
        relMat = [relMat; valuecode lengthcode];
        N = 1;
    end
end

您可以按照自己的喜好格式化输出。例如,作为一个序列:

relMatT = relMat';
relSeq = relMatT(:)';

或将字符串格式化为建议的输出:

relString = [];
for i = 1:length(relMat)
    relString = [relString, sprintf('(%d, %d), ', relMat(i,1), relMat(i,2))];
end

作为扩展,如果您的源序列中有字母数字,则应修改上述内容以比较字符串而不是数字。 更新:要计算原始relMat中唯一代码对的出现次数,请尝试按行查找这些对并计算零差异。例如:
relMatUnique = unique(relMat, 'rows'); % find unique pairs 
nPairs = length(relMatUnique);
nOccur = zeros(nPairs, 1);
for i = 1:nPairs
    pairInMat = bsxfun(@minus, relMat, relMatUnique(i,:)); % find pair in relMat
    nOccur(i) = sum(~sum(pairInMat, 2));
end
relMatOccur = [relMatUnique nOccur]; % unique pairs and number of occurrences 

谢谢,这真的很有帮助,它帮助我理解了MatLab :) - user1146895

1
您可以避免使用 for 循环:

chainCode = '11012321170701000700000700766666666666665555555544443344444333221322222322';
numCode = chainCode - '0'; % turn to numerical array

% detect edges (changes)
edges = arrayfun( @(x,y) x ~= y,    ...
                  numCode(1:end-1), ...
                  numCode(2:end));
% get indexes
idx = find(edges);

% create tuples
relMat = cell2mat(arrayfun(         ...
  @(b,e) [ numCode(b) ; e-b+1 ],    ...
  [ 1 (idx + 1) ],                  ...
  [ idx length(numCode) ],          ...
  'UniformOutput', false));

谢谢你们,因为你们的帮助我才完成了这个任务。 - user1146895

0
% Convert string to numeric array
ChainCodeString  = '11012321170701000700000700766666666666665555555544443344444333221322222322';
ChainCodeArray = ChainCodeString - '0';

% Initialize
CurrentRleValue = ChainCodeArray(1);
CurrentRleCount = 1;
RleCodeIndex = 1;

for i = 2 : length(ChainCodeArray)
    if ChainCodeArray(i)==ChainCodeArray(i-1)
        % Increment current run-length count
        CurrentRleCount = CurrentRleCount + 1;
    else
        % Store current run-length
        valuecode(RleCodeIndex) = CurrentRleValue;
        lengthcode(RleCodeIndex) = CurrentRleCount;
        RleCodeIndex = RleCodeIndex + 1;

        % Initialize next run-length
        CurrentRleValue = ChainCodeArray(i);
        CurrentRleCount = 1;
    end;
end;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接