sábado, 13 de septiembre de 2014

ML VI: Procesamiento de Imágenes I

Imagen Digital.
Una imagen representada digitalmente es una matriz de tres dimensiones: ancho, alto y color. Si el color es solo uno, como en una imagen en escala de grises, es una matriz de solo dos dimensiones.
Como las imágenes solos se ven en las dos dimensiones, son estas las que más importan y a cada pedacito se le llama píxel, el cual nos da la información de cuanto color hay en ese espacio.

Filtro de Imágenes.
Una de las herramientas usadas para procesar las imágenes es reemplazar en cada píxel una contribución ponderada de si mismo y de sus vecinos, los coeficientes de esta ponderación se representan en una matriz por lo general de 3 por 3 elementos, el central es el pixel al que se le rremplazara su valor, esto se hace recorriendo la imagen y realizando dicho proceso en cada píxel.
Matriz de Ponderación
Así por ejemplo a partir de esta imagen:

Aplicando el filtro de la imagen anterior se tiene:
Lo cual resalta las texturas de la imagen.
Así mismo aplicando el filtro con distintos coeficientes se tiene:

Aclarecer:


 Detección de bordes horizontal:

Detección de bordes vertical:


Fitro de media o promedio:


 Oscurecer:

 Por último el programa de Scilab con el cual se obtuvieron las imágenes de este post.

//variables iniiciales
dirimagen="";

//Crear ventana
ventana = createWindow();
//evitar warnings, si no se ejecuta correctamente comentar esta linea
funcprot(0);
//setlookandfeel("it.unitn.ing.swing.plaf.macos.MacOSLookAndFeel");

//funcion del boton "Abrir"
function SeleccionarImagen (botonSeleccionar,txtDirectorio)
    dirimagen=uigetfile(["*.png*";"*.jpg";"*.bmp"]);
    imagen=imread(dirimagen);
    txtDirectorio.String=dirimagen;
    imshow(imagen)
endfunction

//funcion del boton "Filtrar"
function Filtrar (botonFiltrar)
    h1=eval(txt1.String)
    h2=eval(txt2.String)
    h3=eval(txt3.String)
    h4=eval(txt4.String)
    h5=eval(txt5.String)
    h6=eval(txt6.String)
    h7=eval(txt7.String)
    h8=eval(txt8.String)
    h9=eval(txt9.String)
    //vuelve a cargar el archivo para quitar cambios
    dirimagen=txtDirectorio.String;
    imagen=imread(dirimagen);
    //Crear el filtro de 3x3
    filtro=[h1 h2 h3; h4 h5 h6; h7 h8 h9]
    //aplicar el filtro a la imagen
    imf = imfilter(imagen, filtro);
    imshow(imf);
endfunction

//Tamaño de la ventana
ventana.axes_size = [600 300];

//Otras propiedades//////////////////
//ventana.dockable="on";
//ventana.menubar_visible = "on"
//ventana.default_axes = "off"
//ventana.infobar_visible = "off"
ventana.toolbar_visible = "on";
ventana.figure_name="Filtros Imagenes"

//Caja de texto para la direccion(path) de la imagen
txtDirectorio=uicontrol(ventana, "style", "edit", "units", "normalized", "position", [0.0 0.9 0.7 0.1], "string", "lena512.bmp", "horizontalalignment", "center");

//Cajas de texto para los coeficientes del filtro
txt1=uicontrol(ventana, "style", "edit", "units", "normalized", "position", [0.2 0.6 0.1 0.1], "string", "1", "horizontalalignment", "center");
txt2=uicontrol(ventana, "style", "edit", "units", "normalized", "position", [0.3 0.6 0.1 0.1], "string", "2", "horizontalalignment", "center");
txt3=uicontrol(ventana, "style", "edit", "units", "normalized", "position", [0.4 0.6 0.1 0.1], "string", "1", "horizontalalignment", "center");
txt4=uicontrol(ventana, "style", "edit", "units", "normalized", "position", [0.2 0.5 0.1 0.1], "string", "0", "horizontalalignment", "center");
txt5=uicontrol(ventana, "style", "edit", "units", "normalized", "position", [0.3 0.5 0.1 0.1], "string", "0", "horizontalalignment", "center");
txt6=uicontrol(ventana, "style", "edit", "units", "normalized", "position", [0.4 0.5 0.1 0.1], "string", "0", "horizontalalignment", "center");
txt7=uicontrol(ventana, "style", "edit", "units", "normalized", "position", [0.2 0.4 0.1 0.1], "string", "-1", "horizontalalignment", "center");
txt8=uicontrol(ventana, "style", "edit", "units", "normalized", "position", [0.3 0.4 0.1 0.1], "string", "-2", "horizontalalignment", "center");
txt9=uicontrol(ventana, "style", "edit", "units", "normalized", "position", [0.4 0.4 0.1 0.1], "string", "-1", "horizontalalignment", "center");

//Boton Seleccionar
botonSeleccionar=uicontrol(ventana, "style", "pushbutton", "units", "normalized", "position", [0.7 0.9 0.3 0.1], "string","Seleccionar Imagen", "horizontalalignment", "center", "callback", "SeleccionarImagen(botonSeleccionar,txtDirectorio)");

//Boton Filtrar
botonFiltrar=uicontrol(ventana, "style", "pushbutton", "units", "normalized", "position", [0.6 0.4 0.3 0.3], "string","Filtrar Imagen", "horizontalalignment", "center", "callback", "Filtrar(botonFiltrar)");


Como punto extra vale mencionar que se usa el modulo ATOM SIVP, que se puede instalar desde el menú Aplicaciones.
Además se creo una interfaz gráfica, con lo cual es más fácil interactuar con el programa.



Para probar el programa pueden copiar el código anterior o descargar el script.
El enlace para descargar este programa "filtro_imagens.sci" y otros de artículos anteriores es el siguiente:


Si quieren conocer más sobre el procesamiento de imagenes y acorde con los que nos interesa les recomiendo el libro Visión por Computador  de José Francisco Vélez Serrano y otros autores.
También estas diapositivas, que son un resumen del mismo libro. 

lunes, 16 de junio de 2014

REDES NEURONALES - BACK PROPAGATION PERCEPTRON CON UNA CAPA OCULTA

Una de las bases de la inteligencia artificial es la neurona artificial. Las capas ocultas en una red neuronal permite resolver problemas no linealmente separables. A continuacion se muestra el esquema, codigo y programa en MATLAB para resolver la compuerta logica XOR a traves del entrenamiento por el metodo de BACK PROPAGATION de una red neuronal con una capa oculta.

Esta red neuronal se compone de dos entradas, una capa oculta con 2 neuronas y una salida en la ultima capa. El esquema de la red neuronal se muestra en la siguiente figura:


El programa calcula los pesos del esquema utiiliando el metodo de Back Propagation con el metodo de aprendizaje delta.

PERCEPTRON CON UNA CAPA OCULTA Back Propagation XOR


%BOTON ENTRENAR.
function btEntrenar_Callback(hObject, eventdata, handles)
    %Obtener Datos de Tabla
    datos=get(handles.Tabla,'Data');
    x1=datos(:,1);
    x2=datos(:,2);
    yd=datos(:,3);

    %Otener datos iniciales de pesos y bias
    w110= str2double(get(handles.w110,'String'));
    w120= str2double(get(handles.w120,'String'));
    w210= str2double(get(handles.w210,'String'));
    w220= str2double(get(handles.w220,'String'));
    v10= str2double(get(handles.v10,'String'));
    v20= str2double(get(handles.v20,'String'));
    u210= str2double(get(handles.u210,'String'));
    u220= str2double(get(handles.u220,'String'));
    u30= str2double(get(handles.u30,'String'));
    alfa= str2double(get(handles.alfa,'String'));
 
    %Otener datos de iteraciones y error
    iteracionmax = str2double(get(handles.Iteraciones,'String'));
    errormax = str2double(get(handles.Error,'String'));

    %ENTRENAMIENTO
    w11= w110;
    w12=w120;
    w21= w210;
    w22= w220;
    v1= v10;
    v2= v20;
    u21= u210;
    u22= u220;
    u3= u30;
    condicion = 0;
    iteracion = 0;
    error_Total = zeros(1,iteracionmax+1);
    while(condicion == 0)
        for j = 1 : 4
            %Calcular la yObtenida
            %Capa Entrada
            z1 = x1(j);
            a11 = z1;
            z2 = x2(j);
            a12 = z2;

            %Capa Oculta
            z3 = a11*w11+a12*w21 + u21;
            a21 = funcion_activ(z3);
            z4 = a11*w12+a12*w22 + u22;
            a22 = funcion_activ(z4);

            %Capa Salida
            z5 = a21*v1 + a22*v2 + u3;
            yObtenida = funcion_activ(z5);

            %Calculamos error yObtenida*(1-yObtenida)*
            err = (yd(j)- yObtenida);

            %Correccion pesos Capa 2-3
            z= v1*a21+v2*a22+u3;
            d3 = err*derivada_fun_act(z);
            v1 = v1 + alfa*d3*a21;
            v2 = v2 + alfa*d3*a22;
            u3 = u3 + alfa*d3;

            %Correccion pesos Capa 1-2
            d21 = derivada_fun_act(z3)*v1*d3;
            w11 = w11 + alfa*d21*a11;
            w21 = w21 + alfa*d21*a12;
            u21 = u21 + alfa*d21;

            d22 = derivada_fun_act(z4)*v2*d3;
            w12 = w12 + alfa*d22*a11;
            w22 = w22 + alfa*d22*a12;
            u22 = u22 + alfa*d22;

            %Contar error total
            error_Total(iteracion+1) = error_Total(iteracion+1)+abs(err);
        end
        iteracion = iteracion +1
        if(iteracion >= iteracionmax)
            condicion =1;
        end
        if (error_Total(iteracion) <= errormax)
            condicion =1;
        end
    end

    %Mostrar los Resultados
    set(handles.w11,'String',num2str(w11));
    set(handles.w12,'String',num2str(w12));
    set(handles.w21,'String',num2str(w21));
    set(handles.w22,'String',num2str(w22));
    set(handles.v1,'String',num2str(v1));
    set(handles.v2,'String',num2str(v2));
    set(handles.u21,'String',num2str(u21));
    set(handles.u22,'String',num2str(u22));
    set(handles.u3,'String',num2str(u3));

    %Dibujar el error
    axes(handles.axes1);
    x=0:1:iteracionmax;
    plot(x,error_Total,'color','r', 'LineWidth', 2);
end

function f = funcion_activ(z)
    %SIGNOIDE
    f = 1/(1+exp(-z));
end

function fp = derivada_fun_act(z)
    %SIGNOIDE
    fp = (1-funcion_activ(z))*funcion_activ(z);
end