Ответ 1
bw = pic > imdilate(pic, [1 1 1; 1 0 1; 1 1 1]);
У меня есть изображение в 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];
И затем посмотрите, появится ли максимум в третьем измерении в 1-м слое (т.е.: three_d(:,:,1)
):
(max_val, max_i) = max(three_d, 3);
result = find(max_i == 1);
Есть ли более элегантный способ сделать это? Это похоже на клочок.
bw = pic > imdilate(pic, [1 1 1; 1 0 1; 1 1 1]);
Если у вас есть 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
В качестве альтернативы вы можете использовать nlfilter и предоставить свою собственную функцию для каждого района.
Эта функция "найти строгий макс" просто проверит, если центр окрестности строго больше всех остальных элементов в этой окрестности, для этой цели всегда 3х3. Поэтому:
I = imread('tire.tif');
BW = nlfilter(I, [3 3], @(x) all(x(5) > x([1:4 6:9])) );
imshow(BW)
или просто используйте отличный: extrema2.m
В дополнение к imdilate
, который находится в панели обработки изображений, вы также можете использовать ordfilt2
.
ordfilt2
сортирует значения в локальных окрестностях и выбирает n-е значение. (Пример MathWorks демонстрирует, как реализовать максимальный фильтр.) Вы также можете реализовать пиковый искатель 3x3 с ordfilt2
со следующей логикой:
Определите домен 3x3, который не включает центральный пиксель (8 пикселей).
>> mask = ones(3); mask(5) = 0 % 3x3 max
mask =
1 1 1
1 0 1
1 1 1
Выберите наибольшее (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
Сравните этот вывод с центральным значением каждой окрестности (просто 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