洛伦(Matlab)的艺术

将想法变成MATLAB

在阵列中查找模式

Recently, my colleagueJeff问我是否会查看他写的一些代码,以在较大的数组中找到数字模式。没有查看他的代码,我问他是否尝试过Strfind,尽管他的数据不是字符串。他发现它解决了他的问题,比他的M文件更快。同时,我想看看我在M-File中想写的简单算法所花费的时间。我在这里显示并讨论结果。

内容

简单的测试数据

让我从非常简单的测试数据开始,以确保所有算法都得到正确的答案。

a = [0 1 4 9 16 4 9];b = double(“这一年是2003年。”);

第一个算法:findpattern

这是第一个Findpattern算法。

类型Findpattern
函数idx = findPattern(in_array,模式)%findPattern在数组中找到模式。%k = findpattern(数组,模式)返回阵列中任何发生模式发生的起始索引%。阵列和模式%可以是字符和数字类型的任何混合物。%%示例:%a = [0 1 4 9 16 4 9];%b = double('年份是2003年。);%findpattern(a,[4 9])返回[3 6]%findpattern(a,[9 4])返回[]%findpattern(b,'2003')返回13%的findpattern(b,uint8('2003'))返回13%的人,另请参见Strfind,StrcMP,StrnCMP,Strmatch。%算法:%找到每个模式数量的所有发生。N元素模式的%%%,结果是N元素单元格数。%i-th单元格包含匹配图案的i-th%元素的输入阵列中的位置。当输入流中存在该模式时,连续细胞中连续整数的序列百分比将达到一个%。 % As currently implemented, this routine has poor performance for patterns % with more than half a dozen elements where the first element in the % pattern matches many positions in the array. locations = cell(1, numel(pattern)); for p = 1:(numel(pattern)) locations{p} = find(in_array == pattern(p)); end % Find instances of the pattern in the array. idx = []; for p = 1:numel(locations{1}) % Look for a consecutive progression of locations. start_value = locations{1}(p); for q = 2:numel(locations) found = true; if (~any((start_value + q - 1) == locations{q})) found = false; break; end end if (found) idx(end + 1) = locations{1}(p); end end

You'll notice that Jeff chooses to store derived information on the pattern being present in a cell array, and then looks for consecutive locations.

这里有一些结果Findpattern。First I setFto be a function handle to the function in question. Then I can reuse the same code for the other cases simply by redefining the function.

F= @findpattern t(4) = false; t(1) = isequal(f(a, [4 9]), [3 6]); t(2) = isempty(f(a, [9 4])); t(3) = isequal(f(b,'2003'),13);t(4)= iSequal(f(b,uint8(uint8)('2003'),13);aok = all(t == true)
F= @findpattern AOK = 1

我的自制算法:findpattern2

这是我自己的算法。这里的想法是为了找到可能图案locations first, and winnow them out, marching through the图案,我认为通常比数据小,而且通常要小得多。

类型FindPattern2
函数start = findpattern2(数组,模式)%findPattern2在数组中定位图案。%%indices = findPattern2(数组,模式)在数组中找到%模式的起始索引。%%示例:%a = [0 1 4 9 16 4 9];%patt = [4 9];%indices = findPattern2(a,patt)%indices =%3 6%,让我们假设模式和数组都是非空的%向量,但是没有对此进行检查。%对于此算法,我在模式元素上循环。len =长度(模式);%首先,找到候选地点;即,匹配%模式中的第一个元素。start = find(array ==模式(1)); % Next remove start values that are too close to the end to possibly match % the pattern. endVals = start+len-1; start(endVals>length(array)) = []; % Next, loop over elements of pattern, usually much shorter than length of % array, to check which possible locations are valid still. for pattval = 2:len % check viable locations in array locs = pattern(pattval) == array(start+pattval-1); % delete false ones from indices start(~locs) = []; end

获得结果和时间。

f = @findpattern2 t(1)= iSequal(f(a,[4 9]),[3 6]);t(2)= Isempty(f(a,[9 4]));t(3)= iSequal(f(b,'2003'),13);t(4)= iSequal(f(b,uint8(uint8)('2003'),13);aok = all(t == true)
f = @findpattern2 aok = 1

使用strfind

接下来,我使用相同的数据测试Strfind。尽管有名字Strfind可以快乐地处理非字符的数据类型,尤其是双打和整数。

f = @strfind t(1)= iSequal(f(a,[4 9]),[3 6]);t(2)= Isempty(f(a,[9 4]));t(3)= iSequal(f(b,'2003'),13);t(4)= iSequal(f(b,uint8(uint8)('2003'),13);aok = all(t == true)
F= @strfind AOK = 1

Use Case and Performance

杰夫描述了他更详细地解决的问题。他的文件中有多个图像,数据存储为UINT8。图像通过特定的位模式分开。在处理和提取帧后,让我向您展示序列中的图像之一。

加载forloren图像(x(:,:,:,:17)),轴离开谁是X
名称大小字节类属性X 4-D 26726400 UINT88

现在,让我显示和时间在原始数据中找到模式。数据包含29张图像。

清除负载imrawdata谁模式= [254 255 0 224];f = @()tfind = timeit(f);f = @()findpattern2(rawdata,pattess);tfind(2)= timeIt(f);f = @()strfind(rawdata,pattess);tfind(3)= TimeIt(F)
名称大小字节类属性RAWDATA 1X1259716 1259716 UINT8 TFIND = 0.80941 0.011273 0.019194

难题和下一步

In the case of the larger dataset,Strfind不是最快的算法,尽管我发现数据较小,但Strfind表现优越FindPattern2。Some possible reasons whyFindPattern2是三种算法中最快的:

  • 它不是通用的,也没有错误检查,
  • 它只是写在媒介上的工作,
  • 它无助于处理可能涉及的情况的情况。
  • 如果我发现原因,我会告诉你。同时,如果您有任何想法要添加,请评论here




    以MATLAB®7.6出版

    |

    注释

    要发表评论,请单击here登录您的数学帐户或创建一个新帐户。