tutorial - ¿Cómo puedo encontrar máximos locales en una imagen en MATLAB?
optimization toolbox matlab pdf (5)
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 encuentra los máximos locales de la salida. Es decir, todos los puntos en y
que son mayores que todos sus vecinos.
Parece que no puedo encontrar una función MATLAB para hacerlo bien. Lo mejor que se me ocurre es:
[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? Esto parece un poco complicado.
Además de imdilate
, que se encuentra en Image Processing Toolbox, también puede usar ordfilt2
.
ordfilt2
ordena valores en barrios locales y elige el valor n-ésimo. ( El ejemplo de MathWorks demuestra cómo implementar un filtro máximo.) También puede implementar un buscador de picos de 3x3 con ordfilt2
con la siguiente lógica:
Defina un dominio de 3x3 que no incluya 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
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
Compare esta salida con el valor central de cada vecindario (solo
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
Alternativamente, puede usar nlfilter y proporcionar su propia función para aplicar a cada vecindario.
Esta función de "encontrar máximo estricto" simplemente verificaría si el centro del vecindario es estrictamente mayor que todos los demás elementos en ese vecindario, 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)
Si tiene la Caja de herramientas de procesamiento de imágenes , puede usar la función IMREGIONALMAX :
BW = imregionalmax(y);
La variable BW
será una matriz lógica del mismo tamaño que y
con las que indican los máximos locales y los ceros de lo contrario.
NOTA: Como usted señala, IMREGIONALMAX encontrará máximos que son mayores o iguales que sus vecinos. Si desea excluir los máximos vecinos con el mismo valor (es decir, encontrar máximos que sean píxeles individuales), puede usar la función BWCONNCOMP . Lo siguiente debería eliminar los puntos en BW
que tienen vecinos, dejando solo píxeles individuales:
CC = bwconncomp(BW);
for i = 1:CC.NumObjects,
index = CC.PixelIdxList{i};
if (numel(index) > 1),
BW(index) = false;
end
end
o simplemente usa el excelente: extrema2.m
bw = pic > imdilate(pic, [1 1 1; 1 0 1; 1 1 1]);