2009-12-06 2 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]; 

А затем увидеть, если появляется максимум вдоль 3-го измерения в 1-ом слое (то есть: 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) –

ответ

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

yep, этот еще быстрее :) – Amro

+0

+1 Я забыл, как IMDILATE будет работать с изображениями в оттенках серого (обычно я использую его только с логическими масками). – gnovice

+0

Можете ли вы объяснить, как это работает? –

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 
+0

Спасибо! Я вижу, что imregionalmax находит максимумы, которые больше или равны их соседям. Вы знаете, как я могу найти только те, которые больше и не равны своим соседям? –

+0

@Nathan: Итак, если бы вы нашли набор соседних максимумов, равных, вы бы хотели просто выбрать один из них или исключить все из них? – gnovice

+1

Я хочу их исключить. –

11

В качестве альтернативы, вы можете использовать nlfilter и поставить свою собственную функцию, которая будет применяться к каждым окрестностям.

Эта функция «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

Спасибо mate .. :) – G453

2

В дополнение к imdilate, который находится в Image Processing Toolbox, вы можете также использовать 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. Выберите самый большой (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 
    
+1

Это самое правильное решение здесь. Это изначально в Matlab и занимает гораздо меньше времени для вычисления, чем nfilter. – iamseiko

+0

@ Franzd'Anconia Но я ответил на 5 лет позже, так что вот он внизу. :) – chappjc

+0

Отличный ответ. Можно ли включить исходную матрицу 'A'? Кажется, что в вашей цепочке обработки отсутствует. Я могу легко перестроить его, но было бы неплохо включить то, что было для сдержанности :). Благодаря! – rayryeng

Смежные вопросы