2009-12-06 1245 views
20

我有一个形象在MATLAB:如何在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]; 

,然后看看沿第三维的最大出现在第一层(即:three_d(:,:,1)):

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

是否有更优雅如何做到这一点?这似乎有点混乱。

+0

相关的问题:我如何才能找到在嘈杂的图像许多局部极大值?( http://stackoverflow.com/questions/2706528/finding-many-local-max-in-an-image-using-matlab) – 2011-12-29 13:35:33

回答

37
bw = pic > imdilate(pic, [1 1 1; 1 0 1; 1 1 1]); 
+0

是的,这个更快:) – Amro 2009-12-06 21:45:54

+0

+1我忘记了IMDILATE如何处理灰度图像(我通常只使用它与逻辑掩码)。 – gnovice 2009-12-06 22:34:24

+0

你能解释这是如何工作的吗? – 2009-12-07 04:54:43

18

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

BW = imregionalmax(y); 

变量BW将是一个合乎逻辑的矩阵大小相同y与指示局部最大值1和0,否则。

注:正如你指出,IMREGIONALMAX会发现最大值是大于或等于他们的邻居。如果要排除具有相同值的相邻最大值(即查找单个像素的最大值),可以使用BWCONNCOMP函数。以下应在BW有任何邻居删除点,只留下一个像素:

CC = bwconncomp(BW); 
for i = 1:CC.NumObjects, 
    index = CC.PixelIdxList{i}; 
    if (numel(index) > 1), 
    BW(index) = false; 
    end 
end 
+0

谢谢!我看到imregionalmax发现的最大值大于或等于它们的邻居。你知道我怎样才能找到那些更大的,不等于邻居的东西? – 2009-12-06 19:16:46

+0

@Nathan:那么,如果你要找到一组相邻的最大值是相等的,你想要选择其中一个还是排除所有这些? – gnovice 2009-12-06 19:19:42

+1

我想排除他们。 – 2009-12-06 19:32:09

11

或者,你可以使用nlfilter,并提供自己的函数被应用到每个社区。

This “find strict max”函数只会检查邻域的中心是否严格大于该邻域中的所有其他元素,为此目的总是3x3。因此:

I = imread('tire.tif'); 
BW = nlfilter(I, [3 3], @(x) all(x(5) > x([1:4 6:9]))); 
imshow(BW) 
+0

Thanks mate .. :) – G453 2014-06-27 11:38:46

2

除了imdilate,这是在图像处理工具箱,你也可以使用ordfilt2

ordfilt2在当地社区排序值并选取第n个值。 (The MathWorks example演示了如何实现的最大滤波器。)您也可以实现一个3x3的峰值取景器与ordfilt2具有以下逻辑:

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

    >> mask = ones(3); mask(5) = 0 % 3x3 max 
    mask = 
        1  1  1 
        1  0  1 
        1  1  1 
    
  2. 选择与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 
    
+1

这是这里最正确的解决方案。它本身在Matlab中,并且比nfilter花费的时间少得多。 – iamseiko 2015-09-13 22:58:58

+0

@ Franzd'Anconia但我回答迟了5年,所以在这里它是在底部。 :) – chappjc 2015-09-13 23:13:39

+0

很好的答案。是否可以包含原始矩阵“A”?它似乎从您的处理链中缺失。我可以很容易地对其进行逆向工程,但包括自我控制的内容是很好的:)。谢谢! – rayryeng 2018-01-02 16:41:09