我在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);
还有更优雅的方法吗?这看起来像是一块垃圾。
答案 0 :(得分:37)
bw = pic > imdilate(pic, [1 1 1; 1 0 1; 1 1 1]);
答案 1 :(得分:18)
如果您拥有Image Processing Toolbox,则可以使用IMREGIONALMAX功能:
BW = imregionalmax(y);
变量BW
将是与y
大小相同的逻辑矩阵,其中1表示局部最大值,否则为零。
注意:正如您所指出的,IMREGIONALMAX会发现大于或等于其邻居的最大值。如果要使用相同的值排除相邻最大值(即查找单个像素的最大值),可以使用BWCONNCOMP函数。以下内容应删除BW
中包含任何邻居的点,只留下单个像素:
CC = bwconncomp(BW);
for i = 1:CC.NumObjects,
index = CC.PixelIdxList{i};
if (numel(index) > 1),
BW(index) = false;
end
end
答案 2 :(得分:11)
或者,您可以使用nlfilter并提供自己的功能以应用于每个社区。 p>
这个“find strict max”函数只是检查邻域的中心是否严格大于该邻域中的所有其他元素,为此目的总是3x3。因此:
I = imread('tire.tif');
BW = nlfilter(I, [3 3], @(x) all(x(5) > x([1:4 6:9])) );
imshow(BW)
答案 3 :(得分:2)
或者,只需使用优秀:extrema2.m
答案 4 :(得分:2)
除了图像处理工具箱中的imdilate
之外,您还可以使用ordfilt2
。
ordfilt2
对本地社区中的值进行排序并选择第n个值。 (The MathWorks example演示了如何实现最大过滤器。)您还可以使用ordfilt2
实现具有以下逻辑的3x3峰值查找器:
定义不包含中心像素的3x3域(8像素)。
>> mask = ones(3); mask(5) = 0 % 3x3 max
mask =
1 1 1
1 0 1
1 1 1
使用ordfilt2
选择最大(第8个)值。
>> 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
将此输出与每个邻域的中心值(仅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