Pregunta

Tengo una imagen en MATLAB:

y = rgb2gray(imread('some_image_file.jpg'));

y quiero hacer algo de procesamiento en él:

pic = some_processing(y);

y encontrar los máximos locales de la salida. Es decir, todos los puntos en y que son mayores que todos sus vecinos.

Me parece que no puede encontrar una función MATLAB para hacer eso muy bien. Lo mejor que puedo llegar a decir:

[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];

Y luego ver si el máximo a lo largo de la tercera dimensión aparece en la primera capa (es decir: three_d(:,:,1)):

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

¿Hay alguna forma más elegante de hacer esto? Este parece ser un poco de una chapuza.

¿Fue útil?

Solución

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

Otros consejos

Si usted tiene la Imagen Processing Toolbox , se puede usar la IMREGIONALMAX función:

BW = imregionalmax(y);

El BW variable será una matriz lógica del mismo tamaño que y con los que indican los máximos y ceros local de lo contrario.

Nota: Como usted señala, IMREGIONALMAX encontrará máximos que son mayores que o igual a sus vecinos. Si desea excluir máximos vecino con el mismo valor (es decir, se encuentran los máximos que son píxeles individuales), se puede utilizar el función BWCONNCOMP . Lo siguiente debe quitar puntos en BW que tiene ningún vecinos, dejando sólo los píxeles individuales:

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

Como alternativa, puede utilizar nlfilter y proporcionar su propia función que se aplicará a cada barrio.

Este "encontrar estricta max" función simplemente comprobar si el centro del barrio es estrictamente mayor que todos los demás elementos de ese barrio, que siempre es 3x3 para este propósito. Por lo tanto:

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

o, sólo tiene que utilizar la excelente: extrema2.m

Además de imdilate, que está en el procesamiento de imágenes caja de herramientas, también se puede utilizar ordfilt2.

ordfilt2 ordena valores en vecindarios locales y recoge el valor de n-ésimo. ( The MathWorks ejemplo muestra cómo implementar un filtro máx .) también puede implementar un buscador de pico de 3x3 con ordfilt2 con la siguiente lógica:

  1. Definir un dominio de 3x3 que no incluye el píxel central (8 píxeles).

    >> mask = ones(3); mask(5) = 0 % 3x3 max
    mask =
         1     1     1
         1     0     1
         1     1     1
    
  2. Seleccione el valor más grande (8º) con 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. Comparar esta salida en el valor central de cada barrio (justo 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
    
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top