28 mayo 2009

Ejemplo simple de una interfaz gráfica usando GUIDE en MATLAB para procesamiento digital de imágenes

Hace poco que aprendí lo básico de crear interfaces gráficas en Matlab. En realidad es hasta cierto punto simple, pero también creo que no es del todo amigable para crear GUIs. Si, estoy de acuerdo que tiene un estilo de editor para hacernos más fácil la existencia. Pero no es del todo intuitivo, o al menos es lo que pienso en el par de programitas que he tenido oportunidad de hacer. Bueno dejando las quejas a un lado, voy a empezar con el ejemplo. Voy a crear una ventana en la que se cargue una imagen por medio de un botón y desplegarla en la ventana, y hacer un procesamiento sencillo y también mostrarlo en pantalla, se que es un ejemplo muy básico, pero creo que es perfecto para empezar. (o al menos es lo que andaba buscando yo cuando quise hacer esto)


Lo primero que tenemos que hacer es iniciar el editor GUIDE que se puede hacer de dos maneras, la primera es desde el menú de inicio: File –> New –> GUI como se muestra en la siguiente imagen.


Guide1


También se puede iniciar desde la línea de comandos o “command window” de Matlab poniendo “guide”.  Aparece una ventana de inicio del GUIDE.


guidestart




La ventana anterior es (como su nombre lo indica) el lanzador rápido para el GUIDE con varias opciones, la que vamos a seleccionar es la que viene por default y presionamos “OK” y nos aparece el editor de interfaces gráficas en blanco, como se muestra a continuación:


Untitled Como primer paso vamos a insertar el objeto que nos va a servir para desplegar la imagen en la ventana. En este caso Matlab lo maneja con “axes”, así que presionamos el botón que esta en la barra de herramientas de la izquierda y ponemos dos “axes” que es donde vamos a cargar la imagen original y la procesada, como se muestra en la siguiente imagen.


ConAxes


Luego presionando el botón “Push Button” (1) ponemos dos botones (2) que el primero nos va a servir para seleccionar el archivo de la imagen y el segundo para procesarla, también vamos a mostrar donde se seleccionan y se cambian las propiedades del objeto (3).


PonerBotones


En la figura siguiente se muestra el inspector de propiedades “property inspector” en donde podemos modificar las propiedades del botón. En el (1)  se modifica el texto del botón, y en (2), se modifica el nombre del botón.


PropertyInspectorModificamos (1) y (2) para cada botón de manera que nos quede como en la imagen siguiente.


Cambios 


En donde dice String simple y sencillamente cambiamos el texto que tiene el botón y en donde dice tag se define el nombre del botón, esto es importante, porque aquí es donde definimos el nombre que va a tener la función Callback” que es la que se manda llamar cuando se presiona el botón. En la imagen siguiente se muestra como queda la GUI con los cambios hechos. Tambien se muestra como tener acceso a la función donde vamos a poner el código que nos cargue la imagen en pantalla.


GuimodificadaA continuación se abre la ventana del editor de códigos de MATLAB y nos selecciona el inicio de la función en la que debemos agregarle nuestro código que en este ejemplo nos va a seleccionar un archivo para ponerlo en axes1. 


CallbackUna vez que tenemos el editor de MATLAB abierto, buscamos el siguiente código y le agregamos la línea de código que se muestra a continuación, lo que se esta haciendo es agregar una variable para almacenar en memoria la imagen que vamos a cargar .


% --- Executes just before GuiBasica is made visible.
function GuiBasica_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% varargin   command line arguments to GuiBasica (see VARARGIN)


% Choose default command line output for GuiBasica
handles.output = hObject;


%Add variable to hold images (Agregar variable para almacenar imágenes)
handles.myImage = [];


% Update handles structure
guidata(hObject, handles);



La línea que agregué en el código anterior es donde dice handles.myImage = []; que nos va a servir para almacenar la imagen temporalmente para procesarla cuando tengamos que hacerlo en el botón que definimos para procesar la imagen.


El código siguiente se agrega en el callback del botón CargarImagen.


% --- Executes on button press in CargarImagen.
function CargarImagen_Callback(hObject, eventdata, handles)
% hObject    handle to CargarImagen (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
try
    [filename,pathname] = uigetfile('*.pgm','Selecciona imagen para abrir');


    if isequal(filename,0)
        %Do nothing yet
    else
        handles.myImage = imread(fullfile(pathname, filename));


        [X, myMap] = gray2ind(handles.myImage);
        mImagen2 = ind2rgb(X,myMap);


        image(mImagen2, 'Parent', handles.axes1);
        colormap(gray);
    end
    guidata(hObject, handles);
catch
    msgbox('Error')
end



Y agregando el código siguiente al callback del botón ProcesarImagen como se muestra a continuación hacemos nuestro ejemplo de procesamiento, aquí solamente voy a hacer el negativo de la imagen para ilustrar el ejemplo con algo simple, en este caso se pretende mostrar como hacer un GUI en MATLAB, no dar una clase de procesamiento de imágenes.


% --- Executes on button press in ProcesarImagen.
function ProcesarImagen_Callback(hObject, eventdata, handles)
% hObject    handle to ProcesarImagen (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
    guidata(hObject, handles);
    mImage = handles.myImage;   
    mImage2 = 255-mImage;
    [X, myMap] = gray2ind(mImage2);
    mImagen2 = ind2rgb(X,myMap);


    image(mImagen2, 'Parent', handles.axes2);



Y a continuación se muestra como queda el resultado final de nuestra GUI.


Resultado Si todo se ha hecho como se indica, debería de funcionar. jeje. En caso de que me falte un paso o que algo no se entienda solo manden un correo y trataré de corregirlo. gustavo.ramirez.v@gmail.com

19 comentarios:

  1. por favor como seria el proceso aplicando la transformada de fourier.. es decir en fase o magnitud espectral...

    ResponderEliminar
  2. Anónimo,

    Buena sugerencia, ese será el próximo post.

    ResponderEliminar
  3. Gustavo muchas gracias, este blog fue de gran ayuda. Sencillo pero sustancioso. por favor si puedes hacer un ejercicio parecido a este pero usando pop-up menus, seria genial. De nuevo gracias por el aporte loco.

    ResponderEliminar
  4. Muchas gracias por los comentarios, realmente se agradecen.

    He dejado un poco descuidado el blog, pero tenlo por seguro que incluiré algo de pop-ups en un futuro tal vez no muy lejano.

    Saludos!

    ResponderEliminar
  5. no especificaste que tenias que ponerle en el tag del axes myImage

    ResponderEliminar
  6. Anónimo,

    De hecho no tienes que ponerle al tag de axes myImage, esta es una variable que declaré solo para tener un medio de almacenamiento temporal.

    Si te fijas la declaración dice:
    %Add variable to hold images (Agregar variable para almacenar imágenes)
    handles.myImage = [];

    ResponderEliminar
  7. Hey mira estoy tratando hacer lo mismo pero intento cargar una imagen jpg a colores y luego pasarla a Gray:

    try
    [filename,pathname] = uigetfile('*.jpg','Selecciona imagen para abrir');%%Esta es imagen a color en formato jpg


    if isequal(filename,0)
    %Do nothing yet
    else
    handles.myImage = imread(fullfile(pathname, filename));

    %% aqui no se que hacer...
    [X, myMap] = gray2ind(handles.myImage);
    mImagen2 = ind2rgb(X,myMap);

    ResponderEliminar
  8. Hola, mas bien, tienes que hacer pruebas.

    En las primeras lineas cargas la imagen (con la función imread). Ahí la variable handles.myImage ya tiene tu imagen JPG a colores (una matriz de NxMx3, puedes checar la ayuda de Matlab para la función imread ahí viene a detalle).

    Puedes hacer la prueba con la función rgb2gray:

    imagenDePrueba = rgb2gray(handles.myImage);


    y pues luego la despliegas en el axle que quieras.

    Ahorita no tengo matlab a la mano para checarlo, pero ojalá que te ayude un poco.

    Saludos!

    ResponderEliminar
  9. gracias por el ejemplo

    ResponderEliminar
  10. COMO PODRIA SER CON UMBRAL Y GRISES MAS TUROTIALES POR FAVOR

    ResponderEliminar
  11. Buenas tardes,
    estoy tratando de cargar la imagen .bmp pero sale error, el axes lo tengo como graf1:
    try
    [filename,pathname] = uigetfile('*.bmp','Selecciona imagen para abrir');


    if isequal(filename,0)
    %Do nothing yet
    else
    handles.myImage = imread(fullfile(pathname, filename));


    [X, myMap] = rgb2gray(handles.myImage);
    mImagen2 = ind2rgb(X,myMap);


    image(mImagen2, 'Parent', handles.graf1);
    colormap(gray);
    end
    guidata(hObject, handles);
    catch
    msgbox('Error')
    end

    ResponderEliminar
  12. Buenas tardes, ya ejecutaste el código paso a paso? creo que eso te ayudaría a saber exactamente en que línea te está tronando.

    Así a simple vista no encuentro error, pero podría ser al ejecutar la función rgb2gray

    puedes poner un breakpoint en la línea de la función uigetfile y usar whos para ver que tienes en las variables

    ResponderEliminar
  13. Funciona bien con el código que diste,
    pero al ingresar una imagen a color... no funciona..
    Coloque el breakpoint donde me dices "uigetfile", carga la imagen y hay sale el error

    % --- Executes on button press in cargarimagen2.
    function cargarimagen2_Callback(hObject, eventdata, handles)
    % hObject handle to cargarimagen2 (see GCBO)
    % eventdata reserved - to be defined in a future version of MATLAB
    % handles structure with handles and user data (see GUIDATA)

    try
    [filename,pathname] = uigetfile('*.bmp','Selecciona imagen para abrir');


    if isequal(filename,0) %Do nothing yet
    else
    handles.myImage = imread(fullfile(pathname, filename));


    [X, myMap] = rgb2gray(handles.myImage);
    mImagen2 = ind2rgb(X,myMap);


    image(mImagen2, 'Parent', handles.axes1);
    colormap(gray);
    end
    guidata(hObject, handles);
    catch
    msgbox('Error')
    end

    ResponderEliminar
  14. Vamonos por pasos:

    [filename,pathname] = uigetfile('*.bmp','Selecciona imagen para abrir');

    te permite seleccionar un archivo, tiene filtro por default para imágenes con extensión BMP, solo selecciona el archivo. Te regresa dos variables, filename para el nombre del archivo y pathname con la ruta del archivo. Hasta aquí no debe de haber problema.

    luego checa con el if si tienes un nombre de archivo válido

    la siguiente línea:

    handles.myImage = imread(fullfile(pathname, filename));

    la función imread lee una imagen, le pasas como parámetro la ruta con el nombre del archivo y te regresa la imagen que leiste y la almacenas en la variable hanles.myImage

    puedes parar la ejecución justo ahí en imread y ejecutar solo esta línea para ver que tienes en handles.myImage

    de ahí tienes la función:
    [X, myMap] = rgb2gray(handles.myImage);

    esta función simplemente te convierte la imagen handles.myImage RGB en grayscale y te lo regresa en las variables X y myMap.

    de ahí conviertes la imagen ya en escala de grises otra vez a RGB (ya va a estar en escala de grises) para poder mostrarla en el handles.axes1

    esto lo haces con la funcion ind2rgb, pasandole como parametros la imagen X y el mapa de indexamiento myMap y lo almacenas en mImagen2

    de ahí solo lo muestras con:
    image(mImagen2, 'Parent', handles.axes1);

    hice la prueba con:

    http://www.ece.rice.edu/~wakin/images/lena512.bmp

    y con diferentes imagenes BMP a ver que resultados obtienes.

    de cualquier manera me puedes contactar también al correo gustavo.ramirez.v@gmail.com

    ResponderEliminar
  15. hola oye podrias poner un ejemplo pero aplicando varios filtros a la imagen =)

    ResponderEliminar
  16. Hola Amigo...lo intente pero no pude me puedes decir como hago para que reciba cualquier tipo de imgen sin importar el formato y a color

    ResponderEliminar
  17. [nombre, direct] = uigetfile({'*.jpg'},'Abrir imagen');

    if isequal(nombre,0)
    return
    end
    img=imread(fullfile(direct,nombre));
    subplot (handles.axes1),imshow(img),title('Imagen cargada');

    ResponderEliminar
  18. Que tal oye disculpa segui tus pasos y todo salio bien hasta en la parte de procesar imagen ya no responde el programa cual podra ser el problema??

    ResponderEliminar

This is I

Blog dedicado a escribir sobre Sistemas Embebidos y el Internet de las Cosas o IoT que le llaman.