代码之家  ›  专栏  ›  技术社区  ›  Nathan Fellman

如何在matlab的图像中找到局部极大值?

  •  20
  • Nathan Fellman  · 技术社区  · 16 年前

    我在Matlab中有一个图像:

    y = rgb2gray(imread('some_image_file.jpg'));
    

    我想对它做一些处理:

    pic = some_processing(y);
    

    并求出输出的局部最大值。也就是说,所有的要点 y 比他们所有的邻居都强。

    我似乎找不到一个matlab函数来很好地实现这一点。我能想到的最好办法是:

    [dim_y,dim_x]=size(pic);
    enlarged_pic=[zeros(1,dim_x+2);
                  zeros(dim_y,1),pic,zeros(dim_y,1);
                  zeros(1,dim_x+2)];
    
    % now build a 3D array
    % each plane will be the enlarged picture
    % moved up,down,left or right,
    % to all the diagonals, or not at all
    
    [en_dim_y,en_dim_x]=size(enlarged_pic);
    
    three_d(:,:,1)=enlarged_pic;
    three_d(:,:,2)=[enlarged_pic(2:end,:);zeros(1,en_dim_x)];
    three_d(:,:,3)=[zeros(1,en_dim_x);enlarged_pic(1:end-1,:)];
    three_d(:,:,4)=[zeros(en_dim_y,1),enlarged_pic(:,1:end-1)];
    three_d(:,:,5)=[enlarged_pic(:,2:end),zeros(en_dim_y,1)];
    three_d(:,:,6)=[pic,zeros(dim_y,2);zeros(2,en_dim_x)];
    three_d(:,:,7)=[zeros(2,en_dim_x);pic,zeros(dim_y,2)];
    three_d(:,:,8)=[zeros(dim_y,2),pic;zeros(2,en_dim_x)];
    three_d(:,:,9)=[zeros(2,en_dim_x);zeros(dim_y,2),pic];
    

    然后查看沿第3维度的最大值是否出现在第1层(即: three_d(:,:,1) ):

    (max_val, max_i) = max(three_d, 3);
    result = find(max_i == 1);
    

    有更优雅的方法吗?这似乎有点笨拙。

    5 回复  |  直到 10 年前
        1
  •  37
  •   Steve Eddins    16 年前
    bw = pic > imdilate(pic, [1 1 1; 1 0 1; 1 1 1]);
    
        2
  •  18
  •   gnovice    16 年前

    如果你有 Image Processing Toolbox ,您可以使用 IMREGIONALMAX 功能:

    BW = imregionalmax(y);
    

    变量 BW 将是与 y 其中一个表示局部最大值,另一个则为零。

    注: 正如你所指出的,imregionalmax会发现最大值大于 或等于 他们的邻居。如果要排除具有相同值的相邻最大值(即查找单个像素的最大值),可以使用 BWCONNCOMP 功能。以下内容应删除 黑白 它有任何邻居,只留下单个像素:

    CC = bwconncomp(BW);
    for i = 1:CC.NumObjects,
      index = CC.PixelIdxList{i};
      if (numel(index) > 1),
        BW(index) = false;
      end
    end
    
        3
  •  11
  •   Amro    13 年前

    或者,您可以使用 nlfilter 并为每个社区提供你自己的功能。

    这个 “查找严格的最大值” 函数将简单地检查邻域中心是否严格大于该邻域中的所有其他元素,为此,通常是3x3。因此:

    I = imread('tire.tif');
    BW = nlfilter(I, [3 3], @(x) all(x(5) > x([1:4 6:9])) );
    imshow(BW)
    
        4
  •  2
  •   Alex Cohen    16 年前

    或者,使用优秀的: extrema2.m

        5
  •  2
  •   chappjc    10 年前

    除了 imdilate ,位于图像处理工具箱中,也可以使用 ordfilt2 .

    OrdFLT2 对本地社区中的值进行排序并选择第n个值。( The MathWorks example 演示如何实现max过滤器。)您还可以使用 OrdFLT2 逻辑如下:

    1. 定义3x3域 不包括中心像素 (8像素)。

      >> mask = ones(3); mask(5) = 0 % 3x3 max
      mask =
           1     1     1
           1     0     1
           1     1     1
      
    2. 选择最大(第8)个值 OrdFLT2 .

      >> B = ordfilt2(A,8,mask)
      B =
           3     3     3     3     3     4     4     4
           3     5     5     5     4     4     4     4
           3     5     3     5     4     4     4     4
           3     5     5     5     4     6     6     6
           3     3     3     3     4     6     4     6
           1     1     1     1     4     6     6     6
      
    3. 将此输出与每个邻域的中心值进行比较(仅 A )以下内容:

      >> peaks = A > B
      peaks =
           0     0     0     0     0     0     0     0
           0     0     0     0     0     0     0     0
           0     0     1     0     0     0     0     0
           0     0     0     0     0     0     0     0
           0     0     0     0     0     0     1     0
           0     0     0     0     0     0     0     0