segmentaciÓn de imÁgenes basada en el...

21
SEGMENTACIÓN DE IMÁGENES BASADA EN EL HISTOGRAMA GONZALO LUZARDO M. [email protected] [email protected]

Upload: dotuyen

Post on 02-Nov-2018

213 views

Category:

Documents


0 download

TRANSCRIPT

SEGMENTACIÓN DE

IMÁGENES BASADA EN EL

HISTOGRAMA

GONZALO LUZARDO M.

[email protected]

[email protected]

1. Introducción

Este trabajo consiste en tratar de resolver un problema clásico del campo de la visión artificial, que

se denomina segmentación de imágenes. La segmentación en visión artificial consiste en identificar

individualmente cada uno de los objetos o elementos presentes en una escena. En nuestro caso en

particular, lo que buscamos es identificar una puerta y discriminarla de los demás objetos que

pudieran estar presentes. Las imágenes que vamos a analizar, las cuales son claros ejemplos de los

cuatro problemas a los que nos podríamos enfrentar al momento de tratar de identificar la puerta,

son las siguientes:

CASO 1:

Puerta cerrada vista de frente(imagen1.jpg)

CASO 2: Puerta cerrada vista desde un lado

(imagen2.jpg)

CASO 3:

Puerta abierta (imagen3.jpg)

CASO 4: Puerta semiabierta (imagen4.jpg)

Para resolver nuestro problema de identificar la puerta en cada una de nuestras imágenes, las

técnicas de segmentación que vamos a utilizar serán las siguientes:

1. Umbralización basada en el histograma

2. Umbralización basada en la determinación de contornos

2. Umbralización basada en el histograma

En primer lugar, utilizando el código MATLAB de la sección 6.1 vamos a extraer el histograma para

cada una de las imágenes que forman parte de nuestro problema y de esta forma obtener una

primera aproximación a la segmentación que queremos realizar sobre cada una de ellas. Los

histogramas obtenidos para cada caso son los siguientes:

CASO 1

CASO 2

CASO 3 CASO 4

Observando los histogramas podemos notar claramente la naturaleza altamente ruidosa de los

mismos. Podemos identificar algunos picos que podrían considerarse como objetos identificables

dentro de la imagen, así como una multitud de falsos mínimos y falsos máximos. Esta información

obtenida servirá para realizar nuestra primera aproximación de segmentación para cada una de las

imágenes.

La primera segmentación que vamos a hacer será la siguiente: aplicar un filtro de la mediana sobre

el histograma para tratar de eliminar los falsos máximos y falsos mínimos, para luego considerar los

picos (modas) como el número de objetos (clases) presentes en nuestra imagen y el umbral de

separación entre dos clases como la media suma de sus picos.

0 50 100 150 200 2500

1000

2000

3000

4000

5000

6000

Histograma Original

0 50 100 150 200 2500

500

1000

1500

2000

2500

3000

3500

4000

Histograma Original

0 50 100 150 200 2500

1000

2000

3000

4000

5000

Histograma Original

0 50 100 150 200 2500

500

1000

1500

2000

2500

3000

3500

4000

Histograma Original

Utilizando el código MATLAB para segmentar una imagen de la sección 6.2, para cada caso

obtuvimos los siguientes resultados.

0 50 100 150 200 2500

1000

2000

3000

4000

5000

6000

Histograma con maximos y fronteras (Euclideas)

*Numero de clases identificadas: 7

*Tamaño de la ventana: 11

0 50 100 150 200 2500

500

1000

1500

2000

2500

3000

3500

4000

Histograma con maximos y fronteras (Euclideas)

*Numero de clases identificadas: 11

*Tamaño de la ventana: 11

0 50 100 150 200 2500

500

1000

1500

2000

2500

3000

3500

4000

4500

5000

Histograma con maximos y fronteras (Euclideas)

*Numero de clases identificadas: 9

*Tamaño de la ventana: 11

0 50 100 150 200 2500

500

1000

1500

2000

2500

3000

3500

4000

Histograma con maximos y fronteras (Euclideas)

*Numero de clases identificadas: 15

*Tamaño de la ventana: 11

Los datos que obtuvimos para cada uno de los casos fueron los siguientes:

Identificando las clases (objetos) en la imagen

Clases (objetos) identificadas climbs = 1.0e+003 *

1.6749 5.0431 2.3578 2.4067 1.6709 0.5880 0.4705

Numero de clases identificadas: 7 Buscando las fronteras por suma de medias Fronteras encontradas

hills = 1.0e+003 * 0 1.6782 0.5553 1.6395 1.4181 0.2833 0.4807 0

Dibujamos el histograma identificando las clases encontradas Identificando las clases en la imagen original Clases identificadas...Dibujando

Identificando las clases (objetos) en la imagen Clases (objetos) identificadas

climbs = 1.0e+003 * 1.2060 3.6765 2.7442 2.3056 2.2946 2.2915 2.2948 2.4166 0.0395 0.0520 0.0671

Numero de clases identificadas: 11 Buscando las fronteras por suma de medias Fronteras encontradas

hills = 1.0e+003 * 0 1.0763 0.3354 2.4060 2.2898 2.2813 2.2805 1.9018 1.4511

0.0145 0.0592 0.0030 Dibujamos el histograma identificando las clases encontradas Identificando las clases en la imagen original

Clases identificadas...Dibujando

Identificando las clases (objetos) en la imagen

Clases (objetos) identificadas climbs = 1.0e+003 *

2.3519 1.5530 3.2618 3.2588 4.2558 0.0454 0.0500 0.0551 0.1112 Numero de clases identificadas: 9 Buscando las fronteras por suma de medias

Fronteras encontradas hills = 1.0e+003 * 0 1.1428 0.6130 3.2555 2.3837 0.1525 0.0457 0.0515 0.0708

0.0010 Dibujamos el histograma identificando las clases encontradas

Identificando las clases en la imagen original

Clases identificadas...Dibujando

Identificando las clases (objetos) en la imagen

Clases (objetos) identificadas climbs = 1.0e+003 *

Columns 1 through 12 0.0002 1.6293 2.5529 3.0752 2.7458 3.8296 0.0645 0.0641 0.0142 0.0145 0.0140 0.0153

Columns 13 through 15 0.0185 0.0958 0.1040 Numero de clases identificadas: 15

Buscando las fronteras por suma de medias

Fronteras encontradas hills = 1.0e+003 *

Columns 1 through 12 0 0.4703 1.9062 0.4623 2.7878 2.0541 0.8313 0.0639 0.0275 0.0139 0.0136 0.0145

Columns 13 through 16 0.0169 0.0216 0.0912 0.0030 Dibujamos el histograma identificando las clases encontradas

Identificando las clases en la imagen original Clases identificadas...Dibujando

El tamaño de ventana que hemos utilizado para el filtrado del histograma es de 11. Como podemos

apreciar los histogramas filtrados lucen mucho mejor que los originales, observamos que aquellos

que podríamos considerar como falsos máximos y falsos mínimos han sido eliminados.

Podemos notar que esta primera segmentación que hemos aplicado resulta ser bastante buena,

claramente podemos apreciar como los diferentes elementos presentes en la imagen han sido “por

así decirlo” identificados. Adicionalmente esta primera segmentación nos ayuda a poder estimar de

manera heurística el intervalo en niveles de gris que corresponde a la puerta la cual queremos

identificar, en nuestro caso este intervalo se encuentra cercano a 50. Esta información la

utilizaremos para poder etiquetar dentro del histograma a aquellos pixeles que corresponden a la

puerta.

Otra manera de estimar el umbral o fronteras entre dos clases es mediante restitución sucesiva del

umbral, el cual, dada dos clases con una distribución normal de los pixeles en cada una, y una misma

varianza entre clases, estima el umbral de manera reiterada a través de la media suma de sus

medias estimadas utilizando las muestra presentes en la clase hasta que el umbral se estabilice

(Umbralización Semi-Bayes).

Lo que vamos hacer es implementar esta técnica de umbralización y comparar con los resultados

obtenidos mediante la umbralización a través de media suma de los picos.

Utilizando el código de MATLAB 6.3 que contiene un algoritmo para de umbralización mediante

restituciones sucesivas del umbral, para cada caso obtuvimos los siguientes resultados:

0 50 100 150 200 2500

1000

2000

3000

4000

5000

6000

Histograma con maximos y fronteras (Semi Bayes)

*Numero de clases identificadas: 7

*Tamaño de la ventana: 11

0 50 100 150 200 2500

500

1000

1500

2000

2500

3000

3500

4000

Histograma con maximos y fronteras (Semi Bayes)

*Numero de clases identificadas: 11

*Tamaño de la ventana: 11

Si observamos los resultados obtenidos notamos que no son muy buenos e incluso son peores a los

que obtuvimos estimando los umbrales como las medias sumas de los picos. Al parecer considerar

que cada una de las clases posee la misma varianza, algo que en realidad claramente no sucede,

ocasiona que las fronteras entre clases se inclinen más hacia la clase con mayor número de

muestras. Una manera de corregir este error sería utilizando una estimación del umbral con Bayes

completo el cual si considera la varianza en cada una de las clases. El problema de aplicar un Bayes

completo radica en el incremento de la cantidad de cálculos que debemos realizar.

En vez de utilizar Bayes-completo, hemos optado por estimar los umbrales de una manera diferente:

el umbral entre dos clases dadas estará ubicado en el valor mínimo presente entre los picos de

ambas clases. Como vemos esta estimación resulta ser más sencilla y mucho más fácil de calcular.

Adicionalmente vamos a etiquetar el histograma utilizando el valor obtenido del nivel de gris donde

puede localizarse la puerta, de tal forma que aquella clase que contenga dentro el valor de gris igual

a 50 corresponderá a la puerta.

Utilizando el código de MATLAB 6.4 el cual establece el umbral entre las clases como el valor mínimo

entre sus picos, para cada caso obtuvimos los siguientes resultados:

0 50 100 150 200 2500

500

1000

1500

2000

2500

3000

3500

4000

4500

5000

Histograma con maximos y fronteras (Semi Bayes)

*Numero de clases identificadas: 9

*Tamaño de la ventana: 11

0 50 100 150 200 2500

500

1000

1500

2000

2500

3000

3500

4000

Histograma con maximos y fronteras (Semi Bayes)

*Numero de clases identificadas: 15

*Tamaño de la ventana: 11

0 50 100 150 200 2500

1000

2000

3000

4000

5000

6000

Histograma con maximos y fronteras

*Numero de clases identificadas: 7

*Tamaño de la ventana: 11

Clase Puerta

0 50 100 150 200 2500

500

1000

1500

2000

2500

3000

3500

4000

Histograma con maximos y fronteras

*Numero de clases identificadas: 11

*Tamaño de la ventana: 11

Clase Puerta

0 50 100 150 200 2500

500

1000

1500

2000

2500

3000

3500

4000

4500

5000

Histograma con maximos y fronteras

*Numero de clases identificadas: 9

*Tamaño de la ventana: 11

Clase Puerta

0 50 100 150 200 2500

500

1000

1500

2000

2500

3000

3500

4000

Histograma con maximos y fronteras

*Numero de clases identificadas: 15

*Tamaño de la ventana: 11

Clase Puerta

Analizando los resultados podemos darnos cuenta de algunas mejoras respecto a los resultados

obtenidos anteriormente. Podemos observar que existen regiones de la puerta que en un principio

fueron clasificadas erróneamente, esta vez clasificadas de manera correcta; estas regiones

corresponden a las zonas oscuras correspondientes al marco de la puerta. Aun podemos mejorar

nuestros resultados realizando un preprocesamiento sobre la imagen.

Este preprocesamiento consistirá en aplicar un filtro gausiano sobre la imagen original. De esta

forma eliminaremos las frecuencias altas presentes en la imagen, y en teoría una mejor clasificación.

Adicionalmente vamos a marcar sobre la imagen sólo aquellos pixeles que según el histograma

corresponden a la puerta. Utilizando el código MATLAB de la sección 6.5 donde realizamos

preprocesado de imágenes, obtuvimos los siguientes resultados:

0 50 100 150 200 2500

1000

2000

3000

4000

5000

6000

7000

Histograma con maximos y fronteras

*Numero de clases identificadas: 8

*Tamaño de la ventana: 11

Clase Puerta

0 50 100 150 200 2500

500

1000

1500

2000

2500

3000

3500

4000

Histograma con maximos y fronteras

*Numero de clases identificadas: 15

*Tamaño de la ventana: 11

Clase Puerta

0 50 100 150 200 2500

1000

2000

3000

4000

5000

Histograma con maximos y fronteras

*Numero de clases identificadas: 13

*Tamaño de la ventana: 11

Clase Puerta

Al observar los resultados obtenidos notamos que la segmentación realizada es relativamente

buena. Hemos podido identificar claramente las regiones pertenecientes a la puerta las cuales se

encuentran marcadas de color verde.

Como vemos también existen pixeles o regiones mal clasificadas (regiones que no forman parte de la

puerta marcados como parte de ella), esto se debe a que a que dichos pixeles poseen una intensidad

en niveles de gris igual o similar a aquellos pixeles que si forman parte de la puerta. Para mejorar

aún más nuestra segmentación podríamos optar por:

1. Ecualizar la imagen de entrada para incrementar su contraste.

2. Postprocesar la imagen segmentada: Una vez segmentada la imagen, eliminar aquellos

pixeles que se encuentran fuera de una zona rectangular con una relación de aspecto que no

corresponde a la puerta que estamos buscando.

3. Utilizar un clasificador que no sólo considere la información de la intensidad de luz de la

imagen sino también su croma (color).

Una posible desventaja de utilizar algunas de estas “mejoras” radica en la necesidad de hacer

cálculos adicionales a los que hemos hecho hasta el momento, lo que no podría ser un

inconveniente para una aplicación montada sobre un robot que en tiempo real está

constantemente buscando una puerta para luego dirigirse hacia ella.

3. Umbralización basada en la determinación de contornos

Es estas sección vamos a realizar una segmentación basada en contornos o también llamada basada

en detección de bordes. La idea básica consiste en buscar cambios bruscos en los niveles de gris

presentes en una imagen, lo que resulta ser un indicativo de la presencia de bordes en la misma.

Para la detección de bordes vamos a utilizar los operadores de derivación (filtros del gradiente y

laplacianos) los cuales se ha comprobado que dan muy buenos resultados.

La detección de bordes puede ser particularmente útil en nuestro caso ya que la puerta (con niveles

de intensidad bajos) tiene los bordes muy bien definidos debido a que se encuentra sobre la pared

que tiene un nivel de intensidad mucho más altos.

0 50 100 150 200 2500

500

1000

1500

2000

2500

3000

3500

4000

Histograma con maximos y fronteras

*Numero de clases identificadas: 13

*Tamaño de la ventana: 11

Clase Puerta

Utilizando el código MATLAB de la sección 6.6 la cual realiza una extracción de bordes aplicando el

filtro del gradiente de Prewitt, obtuvimos los siguientes resultados:

Si observamos los resultados notamos la eficacia del filtro aplicado. Los bordes de los objetos,

especialmente los de la puerta, han sido identificados muy bien.

Podríamos detenernos aquí, pero por cuestiones de curiosidad, aplicaremos un filtro laplaciano para

la extracción de bordes. Utilizando el código MATLAB de la sección 6.7 pudimos obtener los

siguientes resultados:

Si observamos los resultados obtenidos al aplicar ambos filtros podemos notar que ambos son igual

de buenos, de tal forma que cualquiera de los dos se los podría considerar como válido.

Adicionalmente, se investigaron los filtros de Canny para la detección de bordes. El filtro de Canny

combina un operador diferencial con un filtro gausiano para la detección de bordes. Utilizando el

código MATLAB de la sección 6.8 pudimos obtener los siguientes resultados:

Podemos observar que el filtro de Canny nos da mejores resultados, esto es, el aplicar un filtro

gausiano antes de la detección de bordes nos ayudará a eliminar las altas frecuencias presentes en la

señal y que pueden ser consideradas como falsos bordes, obteniendo al final mejores resultados.

4. Conclusiones

Una vez culminado el presente trabajo podemos sacar las siguientes conclusiones:

• Mientras más complejo resulta ser un algoritmo, más difícil es su implementación y los

resultados no necesariamente serán mucho mejores a los obtenidos por un algoritmo mucho

más simple.

• Es mejor tener algoritmos simples que den buenos resultados a algoritmos complejos que den

resultados un poco mejores (algo parecido a la Ley de Parsimonia1). El menor rendimiento

obtenido con los algoritmos simples es recompensado con la simplicidad y rapidez que estos nos

proporcionan.

• No podemos tener un algoritmo que funcione perfectamente en todos los casos. Si mejoramos

cada vez más un algoritmo, este funcionará muy bien para los casos objetos de de nuestro

estudio y muy mal para los demás casos, esto quiere decir que el algoritmo se vuelve específico

y es incapaz de generalizar.

• La segmentación se vuelve mucho más dificultosa con imágenes de naturaleza compleja, donde

existen una multitud de objetos a ser identificados, ruido ocasionado por la luz, por texturas

complejas en los objetos, entre otros.

• La segmentación basada en histograma en muy potente en imágenes no complejas y bajo

condiciones preestablecidas que favorezcan a la detección. Por ejemplo detección de objetos

sobre un fondo de un color prefijado. Sería muy útil por ejemplo para contar elementos sobre

una banda transportadora.

5. Referencias

• GONZALEZ, WOODS, EDDINS. “Digital Image Processing using MATLAB”. Prentice Hall. 2004.

• MARAVALL DARIO. ``Reconocimiento de formas y visión artificial''. RAMA. 1993.

1 Determina que, entre dos soluciones, es probable que la correcta sea la más sencilla.

6. Código MATLAB

6.1. Extracción y Trazado del histograma de una imagen

image_name = 'imagen1.jpg'; img = imread(image_name); [counts,x]=imhist(img); maxcounts = max(counts); h = bar(x,counts); set(h,'FaceColor',[102/255,153/255,102/255],'EdgeColor',[102/255,153/255,102/255]); title 'Histograma Original'; axis([0 255 0 maxcounts+300]);

6.2. Segmentación basada en histograma con filtrado de bordes y

estimación de fronteras mediante la suma de las medias de los picos del

histograma

%<image_name> es el nombre del a imagen que vamos a procesar image_name = 'imagen4.jpg'; %nombre de la imagen que vamos a tratar hist_mean_filter = 11; %debe ser impar, filtro de histograma, minimo 1 maximo 256 filter_text = ''; img = imread(image_name); [m,n] = size(img); %Convertir a blanco y negro img = rgb2gray(img); bar_width = hist_mean_filter; [shist, err] = sprintf('Tamaño de la ventana: %i\n',bar_width); %Obtenemos el histograma de la imagen original [counts,x]=imhist(img); maxcounts = max(counts); %Aplicamos un filtro de la media sobre el histograma counts_filtered = smooth(counts,bar_width); %Buscamos los mayores locales dentro de la imagen fprintf('Identificando las clases (objetos) en la imagen\n'); [climbs,xclimbs] = FindLocalMax(counts_filtered); fprintf('Clases (objetos) identificadas'); climbs clases = length(climbs); %numero de clases fprintf('Numero de clases identificadas: %i\n',clases); [sclases, err] = sprintf('*Numero de clases identificadas: %i\n *',clases); fprintf('Buscando las fronteras por suma de medias\n'); [hills,xhills]=FindFrontiers(counts_filtered,xclimbs); fprintf('Fronteras encontradas\n'); tit_s = 'Histograma con maximos y fronteras (Euclideas)'; hills figure %Dibujamos el histograma fprintf('Dibujamos el histograma identificando las clases encontradas\n'); color_clases = DrawHistClases(x,counts_filtered,xhills); %Dibujamos el histograma de clases title(tit_s); hold on; %Dibujamos los maximos en el histograma h = stem(xclimbs,climbs); set(h,'Color','r','LineStyle','--','Marker','s','MarkerEdgeColor','r','MarkerFaceColor','r','MarkerSize',2); axis([0 255 0 maxcounts+300]); xlabel(strcat(sclases, shist)); hold off; figure %Dibujamos la imagen original;

%Utilizamos los colores que representan a cada clase %para poder ser representados en una imagen de las mismas dimensiones de %la imagen original donde podamos visualizara a que clase corresponde cada pixel en una imagen fprintf('Identificando las clases en la imagen original\n'); img_clases = GetImgClases(img,xhills,color_clases); %imagen en nivel de gris, fronteras, colores para cada clase fprintf('Clases identificadas...Dibujando\n'); imshow(img_clases); title 'Imagen Segmentada';

%Busca los maximos y minimos locales function [max_arr,in] = FindGlobalMax(img_hist) ant = img_hist(1); sentido = 1; %1 sube y -1 baja cont = 1; max_arr(1) = 0; in(1) = 0; for N=1:length(img_hist) %fprintf('\nAnalizando %d \n', img_hist(N)); %La recta no ha cambiado if(img_hist(N) ~= ant) if(ant > img_hist(N)) if(sentido == 1) max_arr(cont) = ant; in(cont) = N-1; cont = cont + 1; sentido = -1; %fprintf('Maximo %d \n', img_hist(N)); end else sentido = 1; end end ant = img_hist(N); end

function[frontier,findex]=FindFrontiers(values,maxindex) findex = zeros(1,length(maxindex)+1); frontier = zeros(1,length(maxindex)+1); findex(1)= 1; frontier(1)= values(1); for N=1:length(maxindex)-1 findex(N+1) = round(maxindex(N) + (maxindex(N+1) - maxindex(N))/2); frontier(N+1) = values(findex(N+1)); end findex(length(maxindex)+1)= 256; %Maximo valor de un pixel frontier(length(maxindex)+1) = values(256)

function [colors] = DrawHistClases(x,counts,xhills) %En base al numero de clases obtenemos los colores que vamos a usar para %representar cada clase clases = length(xhills)-1; colors=zeros(clases,3); colors(:,1) = rand(1,clases); colors(:,2) = rand(1,clases); colors(:,3) = rand(1,clases); %Para colorearla de un color especifico la clase que corresponde a la %puerta

clase = 3; colors(clase,1) = 0.5; colors(clase,2) = 1; colors(clase,3) = 0.2; %Voy dibujando poco a poco cada una de las clases for c=1:length(xhills)-1 x = (xhills(c):xhills(c+1)); y = counts(xhills(c):xhills(c+1)); hold on h=bar(x,y); set(h,'FaceColor',colors(c,:),'EdgeColor',colors(c,:)); end hold off

function [img_clases] = GetImgClases(img,pos_clases,color_clases) [M,N] = size(img); img_clases = zeros(M,N,3); %Retorna una imagen a colores for m=1:M for n=1:N pixel = img(m,n); %Un for para verificar si el punto pertenece a una clase en %particular for c=1:length(pos_clases-1) if(pixel >= pos_clases(c) && pixel < pos_clases(c+1)) pcolor = color_clases(c,:); end end img_clases(m,n,:)=round(pcolor.*255); end end img_clases = cast(img_clases,'uint8');

6.3. Segmentación basada en histograma con estimación de fronteras

mediante restitución sucesiva del umbral

%<image_name> es el nombre del a imagen que vamos a procesar image_name = 'imagen4.jpg'; %nombre de la imagen que vamos a tratar hist_mean_filter = 11; %debe ser impar, filtro de histograma, minimo 1 maximo 256 filter_text = ''; img = imread(image_name); [m,n] = size(img); %Convertir a blanco y negro img = rgb2gray(img); bar_width = hist_mean_filter; [shist, err] = sprintf('Tamaño de la ventana: %i\n',bar_width); %Obtenemos el histograma de la imagen original [counts,x]=imhist(img); maxcounts = max(counts); %Aplicamos un filtro de la media sobre el histograma counts_filtered = smooth(counts,bar_width); %Buscamos los mayores locales dentro de la imagen fprintf('Identificando las clases (objetos) en la imagen\n'); [climbs,xclimbs] = FindLocalMax(counts_filtered); fprintf('Clases (objetos) identificadas'); climbs clases = length(climbs); %numero de clases fprintf('Numero de clases identificadas: %i\n',clases); [sclases, err] = sprintf('*Numero de clases identificadas: %i\n *',clases); fprintf('Buscando las fronteras por suma de medias\n'); [hills,xhills]=FindFrontiersSemiBayes(counts_filtered',xclimbs); fprintf('Fronteras encontradas\n'); tit_s = 'Histograma con maximos y fronteras (Semi Bayes)';

hills figure %Dibujamos el histograma fprintf('Dibujamos el histograma identificando las clases encontradas\n'); color_clases = DrawHistClases(x,counts_filtered,xhills); %Dibujamos el histograma de clases title(tit_s); hold on; %Dibujamos los maximos en el histograma h = stem(xclimbs,climbs); set(h,'Color','r','LineStyle','--','Marker','s','MarkerEdgeColor','r','MarkerFaceColor','r','MarkerSize',2); axis([0 255 0 maxcounts+300]); xlabel(strcat(sclases, shist)); hold off; figure fprintf('Identificando las clases en la imagen original\n'); img_clases = GetImgClases(img,xhills,color_clases); %imagen en nivel de gris, fronteras, colores para cada clase fprintf('Clases identificadas...Dibujando\n'); imshow(img_clases); title 'Imagen Segmentada';

function[hills,xhills,climbs,xclimbs]=FindFrontiersSemiBayes(values,xmodes) xhills = zeros(1,length(xmodes)+1); hills = zeros(1,length(xmodes)+1); xclimbs = xmodes; climbs = values(xmodes); xhills(1)= 1; hills(1)= values(1); %Inicializacion for N=1:length(xmodes)-1 xhills(N+1) = round(xmodes(N) + (xmodes(N+1) - xmodes(N))/2); hills(N+1) = values(xhills(N+1)); end xhills(length(xmodes)+1)= 256; %Maximo valor de un pixel hills(length(xmodes)+1) = values(256); %Comenzamos con cada una de las clases %Para cada una de las clases for N=1:length(xmodes)-2 fprintf('Estabilizando clases: %i y %i\n',N,N+1); min_sec = xhills(N); uf = xhills(N+1); %la que iremos modificando paulatinamente fprintf('Frontera inicial: %i\n',uf); max_sec = xhills(N+2); stable = 0; %establece si se stabilizo la busqueda while(stable == 0) m1 = sum((values(min_sec:uf) .* [min_sec:uf]))/sum(values(min_sec:uf)); m2 = sum((values(uf:max_sec) .* [uf:max_sec]))/sum(values(uf:max_sec)); mc = round((m1+m2)/2); fprintf('Frontera obtenida: %i\n',mc); if(mc==uf) stable = 1; else uf = mc; end end xhills(N+1)=uf; end

6.4. Segmentación basada en histograma con filtrado de bordes y

estimación de fronteras mediante la localización de los mínimos entre los

picos

%<image_name> es el nombre del a imagen que vamos a procesar gray_level_element = 50; %nivel de gris de la puerta image_name = 'imagen1.jpg'; %nombre de la imagen que vamos a tratar hist_mean_filter = 11; %debe ser impar, filtro de histograma, minimo 1 maximo 256 filter_text = ''; img = imread(image_name); [m,n] = size(img); %Convertir a blanco y negro img = rgb2gray(img); bar_width = hist_mean_filter; [shist, err] = sprintf('Tamaño de la ventana: %i\n',bar_width); %Obtenemos el histograma de la imagen original [counts,x]=imhist(img); maxcounts = max(counts); %Aplicamos un filtro de la media sobre el histograma counts_filtered = smooth(counts,bar_width); %Buscamos los mayores locales dentro de la imagen fprintf('Identificando las clases (objetos) en la imagen\n'); [climbs,xclimbs] = FindLocalMax(counts_filtered); fprintf('Clases (objetos) identificadas'); climbs clases = length(climbs); %numero de clases fprintf('Numero de clases identificadas: %i\n',clases); [sclases, err] = sprintf('*Numero de clases identificadas: %i\n *',clases); fprintf('Buscando las fronteras como los minimos\n'); [hills,xhills]=FindFrontiersMin(counts_filtered,xclimbs); fprintf('Fronteras encontradas\n'); tit_s = 'Histograma con maximos y fronteras'; hills figure %Dibujamos el histograma fprintf('Dibujamos el histograma identificando las clases encontradas\n'); color_clases = DrawHistClases(x,counts_filtered,xhills); %Dibujamos el histograma de clases title(tit_s); hold on; %Dibujamos los maximos en el histograma h = stem(xclimbs,climbs); set(h,'Color','r','LineStyle','--','Marker','s','MarkerEdgeColor','r','MarkerFaceColor','r','MarkerSize',2); axis([0 255 0 maxcounts+300]); xlabel(strcat(sclases, shist)); [xpos,yval] = FindPrototype(gray_level_element,xhills,xclimbs,climbs); text(xpos,yval + 200, 'Clase Puerta', 'HorizontalAlignment','center','BackgroundColor',[.7 .9 .7],'FontSize', 9); hold off; figure %Dibujamos la imagen original; fprintf('Identificando las clases en la imagen original\n'); img_clases = GetImgClases(img,xhills,color_clases); %imagen en nivel de gris, fronteras, colores para cada clase fprintf('Clases identificadas...Dibujando\n'); imshow(img_clases); title 'Imagen Segmentada';

function[frontier,findex]=FindFrontiersMin(values,maxindex) findex = zeros(1,length(maxindex)+1); frontier = zeros(1,length(maxindex)+1); findex(1)= 1; frontier(1)= values(1);

for N=1:length(maxindex)-1 fin = maxindex(N+1); inicio = maxindex(N); %Obtengo los valores presentes entre los intervalos reg = values(inicio:fin); h = min(reg); p = find(reg == h); f = round(inicio + p(1)); findex(N+1) = f ; frontier(N+1) = values(findex(N+1)); end findex(length(maxindex)+1)= 256; %Maximo valor de un pixel frontier(length(maxindex)+1) = values(256);

function [xpos,yval] = FindPrototype(el,xhills,xclimbs,climbs) for n=1:length(xhills-1) if(el > xhills(n) && el < xhills(n+1)) xpos = xclimbs(n); yval = climbs(n); end end

6.5. Segmentación basada en histograma con preprocesado de imagen,

filtrado de bordes y estimación de fronteras mediante la localización de los

mínimos entre los picos

%<image_name> es el nombre del a imagen que vamos a procesar gray_level_element = 50; %nivel de gris de la puerta image_name = 'imagen4.jpg'; %nombre de la imagen que vamos a tratar hist_mean_filter = 11; %debe ser impar, filtro de histograma, minimo 1 maximo 256 filter_text = ''; img = imread(image_name); [m,n] = size(img); %Convertir a blanco y negro img = rgb2gray(img); %Realizamos el preprocesamiento de la imagen fprintf('Aplicando filtro gausiano\n'); [img,b] = gaussian_low(img,90); img = cast(img,'uint8'); [shist, err] = sprintf('Tamaño de la ventana: %i\n',bar_width); %Obtenemos el histograma de la imagen original [counts,x]=imhist(img); maxcounts = max(counts); %Aplicamos un filtro de la media sobre el histograma counts_filtered = smooth(counts,bar_width); %Buscamos los mayores locales dentro de la imagen fprintf('Identificando las clases (objetos) en la imagen\n'); [climbs,xclimbs] = FindLocalMax(counts_filtered); fprintf('Clases (objetos) identificadas'); climbs clases = length(climbs); %numero de clases fprintf('Numero de clases identificadas: %i\n',clases); [sclases, err] = sprintf('*Numero de clases identificadas: %i\n *',clases); fprintf('Buscando las fronteras como los minimos\n'); [hills,xhills]=FindFrontiersMin(counts_filtered,xclimbs); fprintf('Fronteras encontradas\n'); tit_s = 'Histograma con maximos y fronteras'; hills figure %Dibujamos el histograma fprintf('Dibujamos el histograma identificando las clases encontradas\n');

color_clases = DrawHistClases(x,counts_filtered,xhills); %Dibujamos el histograma de clases title(tit_s); hold on; %Dibujamos los maximos en el histograma h = stem(xclimbs,climbs); set(h,'Color','r','LineStyle','--','Marker','s','MarkerEdgeColor','r','MarkerFaceColor','r','MarkerSize',2); axis([0 255 0 maxcounts+300]); xlabel(strcat(sclases, shist)); [xpos,yval] = FindPrototype(gray_level_element,xhills,xclimbs,climbs); text(xpos,yval + 200, 'Clase Puerta', 'HorizontalAlignment','center','BackgroundColor',[.7 .9 .7],'FontSize', 9); hold off; figure %Dibujamos la imagen original; %Uilizamos los colores que representan a cada clase %para poder ser representados en una imagen de las mismas dimensiones de %la imagen original donde podamos visualizara a que clase corresponde ada pixel en una imagen fprintf('Identificando las clases en la imagen original\n'); img_clases = GetImgClasesDoor(img,xhills,gray_level_element); %imagen en nivel de gris, solo pinta la clase puerta fprintf('Clases identificadas...Dibujando\n'); imshow(img_clases); title 'Imagen Segmentada';

function [img_clases] = GetImgClasesDoor(img,pos_clases,p_door) [M,N] = size(img); img_clases = zeros(M,N,3); %Retorna una imagen a colores ci = 0; cf = 0; %Busco la clase a la cual pertenece la puerta for l=1:length(pos_clases)-1 if (p_door <= pos_clases(l+1) && p_door >= pos_clases(l)) ci = pos_clases(l); cf = pos_clases(l+1); end end for m=1:M for n=1:N pixel = img(m,n); if(pixel >= ci && pixel <= cf) pcolor = [0.5 1 0.2]; %verde img_clases(m,n,:)=round(pcolor.*255); else pcolor = [img(m,n) img(m,n) img(m,n)]; img_clases(m,n,:)=pcolor; end end end img_clases = cast(img_clases,'uint8');

6.6. Segmentación basada en la detección de bordes utilizando un filtro de

gradiente de Prewitt

image_name = 'imagen1.jpg'; %nombre de la imagen que vamos a tratar img = imread(image_name); [m,n] = size(img); %Convertir a blanco y negro

img = rgb2gray(img); [g,tg] = edge(img,'prewitt',0.05); imshow(g);

6.7. Segmentación basada en la detección de bordes utilizando un filtro de

la laplaciana

image_name = 'imagen4.jpg'; %nombre de la imagen que vamos a tratar img = imread(image_name); [m,n] = size(img); %Convertir a blanco y negro img = rgb2gray(img); [g,tg] = edge(img,'log',0.007); imshow(g);

6.8. Segmentación basada en la detección de bordes utilizando un filtro de

Canny

image_name = 'imagen4.jpg'; %nombre de la imagen que vamos a tratar img = imread(image_name); [m,n] = size(img); %Convertir a blanco y negro img = rgb2gray(img); [g,tg] = edge(img,'canny',[0.09 0.12],2.5); imshow(g);