Contents
Segmentacion Watershed usando marcadores
1. Calcular una funcion de segmentacion. Es una imagen cuyas regiones oscuras son los objetos que tratamos de identificar
2. Calcular los marcadores de los objetos. Son pequeñas zonas conexas dentro de cada objeto.
3. Calcular los marcadores del fondo. Son pixels que no pertenecen a ningún objeto
4. Modificar la funcion de segmentacion para que son tenga minimos en los marcadores de fondo y objeto.
5. Calcular la transformada watershed
% Leer la imagen I = imread('Tuto_1.bmp'); figure; imshow(I); title('Imagen original')
Usar la magnitud del gradiente como funcion de segmentacion
% kernel del filtro de soble para detectar contorno horizontales hy = fspecial('sobel'); % kernel para contornos verticales hx = hy'; % filtramos la imagen Iy = imfilter(double(I), hy, 'replicate'); % filtramos la imagen Ix = imfilter(double(I), hx, 'replicate'); % calculamos la magnitud del gradiente gradmag = sqrt(Ix.^2 + Iy.^2); figure, imshow(gradmag,[]), title('Magnitud del gradiente')
Aplicamos el algoritmo de segmentacion directamente a la imagen
L = watershed(gradmag); % pasamos de etiquetas a falso color Lrgb = label2rgb(L); figure, imshow(Lrgb), title('Transformada watershed sobre la imagen del gradiente')
Marcamos los objetos de interes
Se pueden aplicar muchos procedimientos. En este caso utilizaremos técnicas basadas en filtros morfologicos. El objetivo es crear zonas planas de maximos dentro de cada objeto para que puedan ser facilmente localizados.
Aplicamos el filtro de apertura a la imagen original
se = strel('disk', 20); Io = imopen(I, se); figure, imshow(Io), title('Apertura') % Aplicamos un filtro de erosion Ie = imerode(I, se); % aplicamos un filtro morfologico de reconstruccion. Mediante sucesivas % dilataciones de la imagen erosionada Iobr = imreconstruct(Ie, I); figure, imshow(Iobr), title('Apertura por reconstruccion')
Aplicamos una operacion de cierre sobre la imagen en la que habiamos practicado la apertura
Ioc = imclose(Io, se); figure, imshow(Ioc), title('Apertura y cierre de la imagen') % Comparamos el resultado con la aplicacion de un filtro de reconstruccion % dilatamos la imagen abierta por reconstruccion Iobrd = imdilate(Iobr, se); % aplicamos el filtro de reconstruccion. Observese que trabajamos con el % complemento del imagen Iobrcbr = imreconstruct(imcomplement(Iobrd), imcomplement(Iobr)); % complementamos de nuevo el resultado anterior para volver a la escala % original Iobrcbr = imcomplement(Iobrcbr); figure, imshow(Iobrcbr), title('Apertura y cierre por reconstruccion')
El segundo procedimiento es más efectivo para eliminar pequeños defectos sin alterar la forma de los objetos. El siguiente paso es calcular los maximos regionales, con lo que tendremos los marcadores de los objetos
fgm = imregionalmax(Iobrcbr);
figure, imshow(fgm), title('Marcadores obtenidos para los objetos')
Superponemos los marcadores a la imagen original para interpretar el resultado (observese que fmg es una imagen binaria)
I2 = I;
I2(fgm) = 255;
figure, imshow(I2), title('marcadores sobre la imagen inicial')
Algunos marcadores llegan hasta el contorno del objeto. Aplicamos un filtro de cierre y uno de erosion para evitar este problema
se2 = strel(ones(5,5)); fgm2 = imclose(fgm, se2); fgm3 = imerode(fgm2, se2); % Como pueden quedar pixels sueltos, eliminamos aquellos bloques que no % alcancen un area minima, en el ejemplo 20 pixels fgm4 = bwareaopen(fgm3, 20); I3 = I; I3(fgm4) = 255; figure, imshow(I3); title('Marcadores modificados sobre la imagen original')
Calculo de los marcadores del fondo
En la imagen obtenida tras la apertura y cierre por reconstruccion, los pixels mas oscuros pertenecen al fondo, asi que empezamos directamente con dicha imagen
% hacemos una binarizacion bw = im2bw(Iobrcbr, graythresh(Iobrcbr)); figure, imshow(Iobrcbr), title('Imagen reconstruida'); figure, imshow(bw), title('Binarizacion de la imagen reconstruida')
No interesa que los marcadores del fondo puedan tocar los contornos de los objetos. Como estos marcadores nos interesa que sean muy finos, calcuremos la transformacion de distancia, aplicaremos la transformacion watershed a dicho resultado y nos quedaremos con las divisorias
D = bwdist(bw); DL = watershed(D); bgm = DL == 0; figure, imshow(D), title('transformada de distancia') figure, imshow(DL), title('resultado de aplicar watershed') figure, imshow(bgm), title('puntos usados como marcadores del fondo')
Calcular la transformada watershed
Imponenmos valores minimos en las zonas de la imagen de gradientes correspondientes a los marcadores. Observese que al ser estos imagenes binarias, usamos el operador o-logico para hacer la suma.
gradmag2 = imimposemin(gradmag, bgm | fgm4); figure, imshow(gradmag2), title('gradiente con los marcadores') % Hacemos la segmentacion L = watershed(gradmag2);
Visualizar el resultado
Las froteras de los objetos se corresponden con los valores de L==0. Superponemos a la imagen original los marcadores y las lineas divisorias dilatadas para facilitar su visualizacion
I4 = I; I4(imdilate(L == 0, ones(3, 3)) | bgm | fgm4) = 255; figure, imshow(I4), title('marcadores y divisorias sobre la imagen original'); % visualizacion de las etiquetas en falso color Lrgb = label2rgb(L, 'jet', 'w', 'shuffle'); figure, imshow(Lrgb), title('Etiquetas en falso color') % Superposicion de ambas imagenes usando transparencias figure, imshow(I), hold on himage = imshow(Lrgb); set(himage, 'AlphaData', 0.3); title('Supeposicion de las etiquetas sobre la imagen original')