21

我在 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);

有没有更优雅的方法来做到这一点?这似乎有点杂乱无章。

4

5 回答 5

37
bw = pic > imdilate(pic, [1 1 1; 1 0 1; 1 1 1]);
于 2009-12-06T21:28:59.083 回答
18

如果你有Image Processing Toolbox,你可以使用IMREGIONALMAX函数:

BW = imregionalmax(y);

该变量BW将是一个逻辑矩阵,其大小y与指示局部最大值的逻辑矩阵相同,否则为零。

注意:正如您所指出的,IMREGIONALMAX 将找到大于或等于其邻居的最大值。如果您想排除具有相同值的相邻最大值(即找到单个像素的最大值),您可以使用BWCONNCOMP函数。以下应该删除BW具有任何邻居的点,只留下单个像素:

CC = bwconncomp(BW);
for i = 1:CC.NumObjects,
  index = CC.PixelIdxList{i};
  if (numel(index) > 1),
    BW(index) = false;
  end
end
于 2009-12-06T19:00:23.083 回答
11

或者,您可以使用nlfilter并提供您自己的函数以应用于每个邻域。

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

I = imread('tire.tif');
BW = nlfilter(I, [3 3], @(x) all(x(5) > x([1:4 6:9])) );
imshow(BW)
于 2009-12-06T21:18:35.790 回答
3

除了imdilate图像处理工具箱中的 ,您还可以使用ordfilt2.

ordfilt2对本地邻域中的值进行排序并选择第 n 个值。(MathWorks 示例演示了如何实现最大滤波器。)您还可以ordfilt2使用以下逻辑实现 3x3 峰值查找器:

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

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

    >> 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
    
于 2015-04-27T03:14:05.980 回答
2

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

于 2009-12-08T17:19:19.753 回答