Google
 

lunes, 13 de abril de 2009

DETECCION DE BORDES: algoritmo de Canny

El operador de detección de bordes de Canny fue desarrollado por un catedrático de la universidad de Berkeley (EEUU) en 1986 y se basa en un algoritmo de múltiples fases para detectar un amplio rango de bordes. Es sin duda el operador más utilizado en la detección de bordes
El objetivo de Canny era descubrir el algoritmo óptimo para la detección de bordes. Un detector óptimo significará una buena detección, el algoritmo debe marcar tantos bordes reales como sea posible, una buena localización, los bordes marcados deben estar lo más cerca posible del borde en la imagen real, y por último una mínima respuesta, es decir, un borde dado debe ser marcado sólo una vez y donde sea posible el ruido presente en la imagen no debería crear falsos bordes.

  1. Operador de Canny:
    Esta técnica, que se caracteriza por estar optimizada para la detección de bordes diferenciales, consta de 3 fases pero algunos autores agregan una ultima fase, siendo en total 4 fases.

  2. Fases de detección de bordes de canny:
    -Obtención del gradiente
    -Supresión no máxima al resultado del gradiente
    -Histéresis de umbral a la supresión no máxima
    -Cierre de contornos abiertos
    Obtención del gradiente:

    ·
    Para obtener el gradiente se tiene que suavizar la imagen
    -Aplicar a la imagen I un suavizado gaussiano G o filtro gaussiano (también se puede aplicar otros filtros ) J = I * G
    - Para calcular el kernel gaussiano G utilizar la siguiente ecuación · En seguida calcular el gradiente:
    - Para cada pixel de la imagen J(i,j)
    ->Calcular las componentes del gradiente Jx y Jy
    ->Calcular la magnitud de los bordes
    ->Estimar la orientación de la normal de los bordes Supresión no máxima al resultado del gradiente
    El objetivo de este paso es Obtener bordes de 1 pixel de grosor al considerar únicamente pixels cuya magnitud es máxima en bordes gruesos y descartar aquellos cuyas magnitudes no alcancen ese máximo.
    a) Para todo punto se obtiene la dirección más cercana dk a 0º, 45º,90º y 135º en Ea(i,j)
    b) Si Em(i,j) es menor que uno de sus dos vecinos en la dirección dk,IN(i,j)=0. Si no IN(i,j)=Em(i,j)
    Histéresis de umbral a la supresión no máxima
    Permite eliminar máximos procedentes de ruido, etc.
    -Entrada IN, Ea, y dos umbrales T1 y T2 (T2>T1)
    -Para todo punto en IN, y explorando en un orden:
    ->Localizar el siguiente punto tal que IN(i,j) > T2
    ->Seguir las cadenas de máximos locales a partir de IN(i,j) en ambas direcciones perpendiculares a la normal al borde siempre que IN>T1. Marcar los puntos explorados.
    -La salida es un conjunto de bordes conectados de contornos de la imagen, así como la magnitud y orientación.
    Cierre de contornos abiertos (Algoritmo de Deriche y Cocquerez)
    a) La imagen de entrada es una imagen de contornos binarizada (1= borde; 0=no borde)
    b) Para cada punto de borde de un extremo abierto se le asigna un código que determina las direcciones de búsqueda para el cierre del contorno
    c) Para los pixels marcados con este código se marca como pixel de borde el de máximo gradiente en las tres direcciones posibles.
    d) Se repiten los pasos hasta que se cierren todos los contornos.


  3. Resultados:
  4. Conclusiones:
    a) Este algoritmo está considerado como uno de los mejores métodos de detección de contornos mediante el empleo de máscaras de convolución.

    b) El algoritmo Canny es adaptable a los varios ambientes. Sus parámetros permiten que sea adaptado al reconocimiento de los bordes de características que diferencian dependiendo de los requisitos particulares de una puesta en práctica dada.

  5. Ejecutable:

    Se implemento en matlab y en el programa se podra selecionar diferentes imagenes de prueba pero bien se puden poner otras imagenes con los mismos nombres. Para ejecutar el programa primero se debe tener instalado el matlab 7.4 si no se tiene intalado ninguna version o otras versiones anteriores se debe instalar el componente (descargar las las 4 partes)
    Descargar Componente parte1
    Descargar Componente parte2
    Descargar Componente parte3
    Descargar Componente parte4

    Descargar Algortimo de Canny

martes, 11 de noviembre de 2008

Recuperación de Imágenes por Contenido Utilizando una Estructura de Datos Espacial Métrica

En el curso de Tópicos en Computación I realizamos un proyecto final con mis compañeros Murrugarra Llerena, Olivo Fukumoto y Linares Mestanza en este proyecto deberíamos aplicar alguna de las estructura de Datos Espacial desarrolladas en Laboratorio y fue de esa manera que realizamos este proyecto.
  1. INTRODUCCION
    Nos ha pasado que cuando queremos buscar una imagen en Google tenemos que ingresar el nombre de la imagen (Ejemplo: gato) y los resultados son imágenes con el mismo nombre o con parte del nombre que ingresamos pero en muchos casos la imagen que nos devuelve no tiene nada que ver con la imagen que quisimos buscar esto sucede por que en la base de datos multimedia de imágenes sus elementos están indexados por sus nombres (sus clave son sus nombre). Ante este problema existe la recuperación de imágenes por contenido (28 de Abril del 2008 científicos de Google han sido capaces de desarrollar un algoritmo similar al PageRank pero que trabaja con el contenido de las imágenes y pronto podrán utilizar este tipo de tecnología).
    En nuestro caso utilizaremos una Estructura de Datos Espacial Métrica M-tree para almacenar las imágenes de acuerdo una distancia entre ellas que se obtendrá aplicando un filtro de Gabor y calculando su vector característico para así poder hallar sus distancias.


  2. TRABAJOS PREVIOS
    Entre los trabajos previos podemos encontrar:
    Recuperación por contenido en bases de datos de imágenes basada en wavelets, Aplicación al Diseño del Textil, Manuel Agustí i Melchor Universidad Politécnica de Valencia: este trabajo estaba planteado para empresas más tradicionales de los sectores textil y cerámico que habían venido acumulando a lo largo de décadas un inmenso patrimonio compuesto por miles de muestras de telas y azulejos, deseaban tener a su disposición una base de datos multimedia para la recuperación según la textura que ellos requerían.
    También podemos encontrar Recuperación de Imágenes Médicas por Contenido Usando Indexamiento medico, Edwin A Niño, Universidad Nacional de Colombia: en este trabajo se necesitaba tener una gran cantidad de imágenes medicas guardadas para después poder comparar o buscar imágenes parecidas que sean de utilidad para los medico y tener así una idea mas experimentada según las enfermedades y tumores ya almacenados en la base de datos multimedia de imágenes medicas. Otro antecedente importante fue Bases de datos para Multimedia, Recuperación por Contenido, José Miguel Valiente González, Universidad Politécnica de Valencia España: ente trabajo solo se centro en el como poder recuperar imágenes por contenido.

  3. PASOS PARA LA RECUPERACION DE IMAGENES POR CONTENIDO
    Para iniciar la recuperación de imágenes por contenido seguimos los siguientes pasos:
    · Construir M-tree con dos archivos: Archivo Registro (Informacion del objeto) y Archivo Indice (Nodos del M-tree).
    · Aplicar filtro de Gabor
    · Calcular Vector Característico

  1. EXPERIMENTOS Y RESULTADOS
    Para la prueba de esta implementación se utilizaron 170 imágenes el tamaño de cada imagen fue de 200 * 200 se tomo en el filtro de Gabor orientaciones=5, escala=5, Ul = 0.1 (frecuencia espacial baja), Uh = 0.4 (frecuencia espacial alta), el T máximo en cada nodo del Mtree fue igual a 4, la distancia que se utilizo fue la distancia euclidiana.




  1. EJECUTABLE
    Se desarrollo en c++ exactamente en wxdev c++ para insertar en la base de datos multimedia se ingresa en la ventana insertar .Para la busquecar en la ventana de busqueda se selecciona el numero de imagenes mas cercanas que se desea buscar ademas se puede visualizar la distancia de cada imagen que devuelve el programa.








Descargar Recuperacion de Imagenes por Contenido

sábado, 27 de septiembre de 2008

Subdivisión Doo-Sabin

En la tercera unidad del curso de geometria computacional se vieron 3 algoritmos para subdivisión de objetos 3D (Doo- Sabin, Catmull-Clark, el esquema de Loop) Se implemento un algoritmo para laboratorio el de Doo-Sabin del cual hablare a continuación.
  1. INTRODUCTION
    Subdivisión de superficies:
    Representación de superficies mediante un mallado
    Refinado de la malla mediante un proceso iterativo
    La superficie será igual al límite de refinamientos sucesivos
    Aplicaciones:
    Utilizada en el corto de animación "Geri's Game" (Pixar), y en las películas "Bichos" y "Toy Story 2" (Pixar/Disney).
    Ventajas de la subdivisión
    Permiten dibujar superficies de topología compleja
    Permiten obtener distintos niveles de detalle
    Son numéricamente estables
    Sencillas de implementar
    Se ejecutan (renderizar) directamente


  2. REGLAS DE DOO-SABIN
    Se debe crear para cada cara un punto para cada uno de los puntos de la cara.
    Cada nuevo punto es el punto medio del segmento que une el centroide de una cara con cada uno de sus vértices.
    Crear con las aristas de todos los puntos internos a una cara una nueva cara.
    Crear con las aristas de todos los puntos generados de aristas adyacentes una nueva cara.
  3. EJECUTABLE
    Se desarrollo en java, el objeto ya esta ingresado solo pueden variar su forma con el
    mouse para obtener otros resultados, la aplicacion se desarrollo para 3 iteraciones.



Descargar Doo-Sabin

Triangulación de Delaunay

En al segunda unidad del curso de geometría computacional se implemento los algoritmos de triangulación de polinomios (Ear Clipping, triangulación monótona) así como triangulación de una nube de puntos en este caso la triangulación de Delaunay de la que hablare a continuación
  1. INTRODUCTION
    Se le denomina así por el matemático ruso Boris Nikolaevich Delone (Борис Николаевич Делоне, 1890 - 1980) quien lo inventó en 1934.
    Es una red de triángulos que cumple la condición de Delaunay. Esta condición dice que la circunferencia circunscrita de cada triángulo de la red no debe contener ningún vértice de otro triángulo.

  2. CONDICIÓN DE DELAUNAY
    La condición de Delaunay dice que una red de triángulos es una triangulación de Delaunay si todas las circunferencias circunscritas de todos los triángulos de la red son vacías. Esa es la definición original para espacios bidimensionales. Es posible ampliarla para espacios tridimensionales usando la esfera circunscrita en vez de la circunferencia circunscrita. También es posible ampliarla para espacios con más dimensiones pero no se usa en la práctica.
    La arista p1p2 es legal mientras que p3p4 es una arista ilegal porque p2 cae dentro del círculo que pasa por p3p1p4.
    Cuando se detecte una arista ilegal hay que hacer un intercambio de la arista para convertirla en una legal.

  3. PROPIEDADES
    · La triangulación forma la envolvente convexa del conjunto de puntos.
    · El ángulo mínimo dentro de todos los triángulos está maximizado.
    · La triangulación es unívoca si en ningún borde de circunferencia circunscrita hay más que tres vértices.

  4. ALGORITMOS
    ·Incremental construction
    ·Divide and conquer
    ·Sweepline
    Algoritmo Aleatorio Incremental
    1. Introducir la nube de puntos P de tamaño n en un gran triángulo conteniendo a dicha nube de puntos Algoritmo Aleatorio Incremental
    2. Para cada uno de la n puntos de P, elegir pr de forma aleatoria y triangular:
    2.1. Encontrar el triángulo pipjpk conteniendo a pr
    2.2. SI pr cae en el interior del triángulo pipjpk ENTONCES añadir aristas desde pr hasta los vértices pi,pj,pk
    ● Legalizar_Aristas (pr, pipj)
    ● Legalizar_Aristas (pr, pjpk)
    ● Legalizar_Aristas (pr, pkpi)
    2.3. SINO pr cae en la arista pipj , que es incidente a los triángulos pipjpk y pipjpl
    ● Legalizar_Aristas (pr, pipl)
    ● Legalizar_Aristas (pr, plpj)
    ●Legalizar_Aristas (pr, pjpk)
    ● Legalizar_Aristas (pr, pkpi)
    3. Finalmente eliminar los tres puntos del gran triángulo inicial.

  5. EJECUTABLE
    Se desarrollo en java, se ingresan los puntos con el Mouse ya demás tener en cuenta que una ves ejecutado Delaunay ya no se pueden seguir ingresando mas puntos se debe abrir de nuevo la aplicación.

Descargar Delaunay

sábado, 20 de septiembre de 2008

Kirkpatrick-Seidel’s

Este algoritmo lo implemente en el curso de Geometria Computacional como trabajo de investigacion de la primera Unidad, la idea del algoritmo la explicare a continuacion pero lo que si se debe tener en cuenta es que la complejidad despues de implementarlo debe ser T(n, h) = O(n lg h) si esto no es asi entonces de nada servira pues para ello existen otros algoritmos mas sencillos pero con mayor complejidad que se implementaron en el laboratorio de este curso ( Graham Scam, Gift wrapping, Algoritmo Incremental, QuikHull, Algoritmo Divide y Venceras) .


  1. INTRODUCTION Figure 1: Casco alto y casco bajo
    El algoritmo de Kirkpatrick Seidel se nombra de esa manera por sus inventores, David G. Kirkpatrick y Raimund Seidel. La idea basica de este algoritmo es utilizar la tecnica de dividir y conquistarasi como una poda para hallar la cerradura convexa la cual es tratada como dos algoritmos (algoritmo para el casco alto y algoritmo para el casco bajo) en dos dimensiones vendria a ser la separacion por la vertical del x minimo y el x maximo ( g.1). En realidad los dos algoritmos son muy parecidos por ello se hablara de uno de ellos el algoritmo del casco alto, para este algoritmo se debe hallar la mediana (m) de los puntos P y dividir en dos grupos L y R y hallar un segmento pq donde p pertenece a L y q pertenece a R ( g.2) despues de esto se eliminaran de L los puntos mayores a x(p) y de R los menores a x(q) para volver a calcular el casco alto de cada uno de los grupos restantes L' y R'.
    Figure 2: Puente superior y mediana Figure 2: Puente superior y mediana

  2. ALGORITMO
    Es un algoritmo recursivo aqui se presenta el algoritmo para el Casco Alto de igual forma para hallar el Casco Bajo se seguira el mismo algoritmo solo que se utilizaran solo los puntos con menor Y.
  3. ENCONTRAR EL PUENTE SUPERIOR
    Para hallar el puente superior debemos escoger del grupo de puntos L un p y del grupo de puntos R un q tal que el y de la interseccion con la mediana sea el mayor de todos ( g.3).
    Sea: p=(x1, y1) y q=(x2, y2) dos puntos donde p 2 L y q 2 R. Entonces: la ecuacion de la
    recta pq seria:
    y-y1= (y2-y1/x2-x1)*(x-x1)
    Tambien sabemos que el punto de la ecuacion de la recta de la mediana que se intercepta
    con pq es: (xm, ym) pero sabemos que xm = m , ademas sabemos que el punto (xm, ym)
    pertenece ala recta pq por ello para hallar el maximo y se obtendria de la siguiente manera:
    y-y1= (y2-y1/x2-x1)*(x-x1)
    y-y1= (y2-y1/x2-x1)*(xm-x1)
    y= (y2-y1/x2-x1)*(xm-x1) +y1

Figure 3: Puentes superiores posibles
La idea no termina aqui pues la primera idea seria comparar punto por punto lo que seria O(n^2) pero este paso se debe hacer en O(n) y fue en O(n) que pude implementar este paso.

  • EJECUTABLE
    Se desarrollo en java, se pueden ingresar los puntos mediante eventos del mouse asi como cargando los puntos desde un archivo tambien se podra visulisar el tiempo que demora la ejecucion del algoritmo. En los archivos hay 1000 , 10 000 , 100 000, 500 000, 1 000 000 puntos respectivamente. Com 1 000 000 se daran cuenta que se optiene un buen tiempo al ejecutar el algoritmo O(n lg h) .

Descargar Kirkpatrick-Seidel’s parte1

domingo, 27 de abril de 2008

Programacion Logica : swi-prolog , Interfaces

Este articulo va destinado para las personas que tienen nociones básicas en programacion lógica o han manejado otro entorno programacion logica diferente al swi-prolog ejemplo visual prolog etc, Pero creo que no es tan dificil de entender lo que se les mencionara a continuacion. Lo ideal es que dado unas pequeñas nociones y funciones puedan utilizar la ayuda o demás herramientas para lograr un mejor entendimiento de todo lo que se mencionara a continuación Primeros pasos en swi-prolog en el blog de Jorge Valverde Revaza.



  1. Manejar Entorno de trabajo:
    Para esto abrir swi-Prolog aparecerá algo así , para tener un editor de programación lo único que debemos hacer es seleccionar de los botones de arriba Settings - User init file.. y nos aparecerá una nueva ventana cerramos la ventana y ahora si procedemos a file - New para crear un nuevo proyecto (la operación anterior algunos utilizan emacs.) de igual manera si se desea abrir un .pl doble clic sobre el .pl después Settings - User init file.. y la cerramos file - edit nombre.pl y aparecerá tu proyecto.

  2. Sintaxis de swi-Prolog:
    Bueno la sintaxis de swi-prolog es igual que cualquier otro entorno de programcion logica .
    Cualquier programa en Prolog tiene que estar escrito en un fichero de texto plano (sin formato). Lamanera mas sencilla es usar el Bloc de Notas. Dicho archivo debe poseer la extensin ”.pl” para indicar que contiene codigo fuente de Prolog.
    Un programa Prolog esta formado con un conjunto de hechos y de reglas junto con un objetivo. El archivo del codigo fuente de Prolog contendra el conjunto de hechos y de reglas y el objetivo sera lanzado desde el shell de SWI-Prolog.
    Existen ciertas consideraciones sobre la sintaxis de Prolog:
    1. Variables:
    El identificador de una variable tendra que tener su primera letra en mayusculas.
    Ej: X, Atapuerca, Cobaltina, RADgtfCdf
    2. Constantes:
    La primera letra de una constante deber´a estar escrita en min´usculas.
    Ej: a, incienso, roberto, rADgtfCdf
    Tambi´en se consideran constantes a los n´umeros,
    Ej: 1, 5.02, 0.7
    las palabras entre comillas simples
    Ej: ’a’, ’A’, ’a a’
    y la lista vacıa [ ].
    3. Funciones:
    Al igual que las constantes, su primera letra debe ser una minuscula. Debera estar seguido de un conjunto de terminos (otras funciones, variables o constantes) encerrados entre parentesis.
    Ej: f(c,X), conc arbol(Hijo Izq, Raiz, Hijo Der), rADgtfCdf(RADgtfCdf, rADgtfCdf)
    4. Predicados:
    Su sintaxis es la misma que la de las funciones aunque, por su localizacion dentro de la clausula (es decir, dentro del programa Prolog), el compilador los identificara como tal, y no como funciones.
    Ej: f(c,X), conc arbol(Hijo Izq, Raiz, Hijo Der), rADgtfCdf(RADgtfCdf, rADgtfCdf)
    Tambien existe la posibilidad de tener predicados 0-arios.
    5. Hechos:
    Son clausulas de Horn que poseen un unico predicado en la cabeza y ninguno en el cuerpo. Tienen la siguiente forma en sintaxis de logica de primer orden: P
    En Prolog no se escribe la flecha sino que se pone un punto al final: p.
    donde p es un predicado y tiene que seguir su sintaxis. Ej:
    padre(aaron, maria).
    compositor(shostakovich).
    shostakovich(compositor).
    6. Reglas:
    Son clausulas de Horn que poseen un ´unico predicado en la cabeza y uno o m´as en el cuerpo.
    Tienen la siguiente pinta:
    P← Q1,Q2,Q3 escritos en sintaxis clausular o
    P←Q1 ^ Q2 ^ Q3 escritos en sintaxis de logica de primer orden.
    En Prolog la flecha se sustituye por ”:-”, las conectivas conjuntivas se escriben como comas ”,” y la regla termina en punto:
    p :- q1, q2, q3.
    donde, al igual que los hechos, p y q1, q2 y q3 son predicados. Ej:
    cuadrado(X) :- poligono(X), numero_lados(X,4).
    7. Objetivos:
    Son clausulas de Horn que no poseen ningun predicado en su cabeza:
    &← Q1,Q2,Q3
    Los predicados se escriben separados por comas y terminados en punto. Solo pueden sen lanzados desde el shell de SWI-Prolog.
    ?- padre(X, Y),padre(Y, Z).
  3. Compilacion y ejecucion en swi-prolog:
    La codificacion en swi- prolog es la misma que todos los editores de prolog solo que aquí no declaras la variables que vas a utilizar, las funciones básicas serian:
    write, fail, nl, is ,!,:- dynamic, retract, assert, etc ;

    Algunos códigos como disktra , autómata, gramaticas, pequeño sistema experto, operaciones con listas , ordenación por mezcla selección inserción, vectores , matrices, problemas con recursion, torre de hanoi, búsquedas , etc, son los que se puedieron desarrollar en el laboratorio del curso de programacion logica dictado por Ivan sipiran.
    Para complilar un proyecto Compile-Compile buffer y para ejecutarlo en la consola de swi-prolog (figura anterior) escribir nombreReglaoHecho. y enter.



  4. Todas las soluciones a un objetivo:
    Existen predicados que no se paran cada vez que llegan a una hoja exito en el arbol de vuelta atras sino que realizan todo el arbol que esta por debajo de un objetivo dado y guardan las soluciones (unificaciones) en una lista.
    findall(+Template, +Goal, -Bag): realiza todo el arbol de backtracking del objetivo Goal. Cada vez que llega a un exito unifica las variables con la plantilla Template e introduce el resultado en la lista Bag.
    5 ?- listing.
    dios_egipcio(amon).
    dios_egipcio(anubis).
    dios_egipcio(apis).
    dios_egipcio(ra).
    Yes
    6 ?- findall(X,dios_egipcio(X), L).
    X = _G362
    L = [amon, anubis, apis, ra]
    yes
    bagof(+Template, +Goal, -Bag): identico a findall/3 excepto que si el objetivo posee variables libres entonces primero probara la unificacion con esas variables libres y despues realizara el arbol de vuelta atras para cada una de esas unificaciones, parando cada vez.
    ?- listing.
    vida(carlos_III, 1716, 1788).
    vida(carlos_IV, 1748, 1819).
    vida(fernando_VII, 1784, 1833).
    yes
    ?- bagof([A,B], vida(A, B, C),L).
    A = _G371
    B = _G374
    C = 1788
    L = [[carlos_III, 1716]] ;
    A = _G371
    B = _G374
    C = 1819
    L = [[carlos_IV, 1748]] ;
    A = _G371
    B = _G374
    C = 1833
    L = [[fernando_VII, 1784]] ;
    No
    Si no queremos que se pare cada vez que encuentre una unificacion debemos usar el sımbolo ˆ como
    en el ejemplo:
    ?- bagof([A,B], C^vida(A, B, C),L).
    A = _G383
    B = _G386
    C = _G391
    L = [[carlos_III, 1716], [carlos_IV, 1748], [fernando_VII, 1784]] ;
    No
    setof(+Template, +Goal, -Set): igual que bagof/3 pero la lista Bag es devuelta ordenada y sin duplicados.
  5. Interfaces en swi-prolog usando XPCE:
    La creacion de interfaces en swi-prolog no es tan complicada como podriamos imaginarnos por ejemplo tenemos lo siguiente :
    primerVentana:-new(D, dialog('Nombre de tu ventana')), send(D, open).

    Existen cuatro predicados basicos que te permiten interactuar con los objetos de swi-prolog :

    ?? new(?Reference, +NewTerm): Este predicado recoge dos parámetros, el primero recogería la referencia que se le asigna al nuevo objeto, ya que new se usa para crear objetos. El segundo parámetro le indicaría el objeto que se quiere crear.

    ?? send(?Receiver, +Selector(...Args...)): El primer parámetro del predicado es una referencia al objeto que deseemos enviarle un mensaje. El segundo parámetro indicará el método al que queremos invocar, lo cual indicaremos junto a los argumentos que queremos enviarle al método.

    ?? get(?Receiver, +Selector(+Argument...), -Result): Los dos primeros parámetros tienen el mismo significado que para send, sin embargo el último parámetro sirve para recoger el valor que nos devuelva el método que hallamos invocado.

    ?? free(?Reference): libera la memoria asociada al objeto que se le indica en el primer parámetro.

    Los objetos que podemos manejara en swi-prolog son:
    button
    label
    menu
    menu_bar
    menu_item
    popup
    slider
    window
    int_item
    editor
    text
    text_item
    picture
    etc.

    Cada uno de estos objetos como vimos en el ejemplo primeraVentana se alamcenan en variable por intuicion podemos concluir que para agreagar un boton a una ventana primero crearemos ambos objetos y despues agregaremos la variable de un boton a la variable de la ventana.

    Todos estos objetos tienen atributos como:
    size
    display
    margin
    colour
    style
    background
    font
    etc.

    Explicare algunos Objetos con mayor detalle:

    DIALOG
    Esta es la clase básica para crear dialogos.
    Constructor:
    dialog(label=[name], size=[size], display=[display])
    name: indica el titulo a la ventana
    size: es de tipo size y sirve para indicar el tamaño de la ventana display: indica donde queremos que se visualize (mejor no tocar este parametro si no sabemos que estamos haciendo) Podemos observar que todos los parametros son opcionales, aunque siempre es bueno ponerle un titulo a la ventana Así, como ejemplo crearemos un dialogo con titulo ‘Titulo del dialogo’ y de tamaño 440 x 320.
    new(D, dialog(‘Titulo del Dialogo’, size(440, 320)) ),
    Métodos:
    Esta clase dispone de varios métodos que pueden resultar interesantes, entre ellos tenemos:
    append(Objeto): Insertaria el objeto Objeto dentro del dialogo, visualizandolo en
    el mismo, por ejemplo sirve para insertar un boton o cualquier otra cosa, como en el siguiente ejemplo:
    send(D, append(button(‘Boton 1’)))
    open(): abre la ventana de diálogo visualizandola en pantalla:
    send(D, open),
    destroy(): cierra la ventana de diá logo visualizada en pantalla:
    send(D, destroy),

    BUTTON
    Esta es la clase básica para crear botones
    Constructor:
    button(name=name, message=[code]*, label=[name] )
    name: indica el nombre del boton (si no se especifica la etiqueta que queramos que tenga el boton, entonces adoptará una etiqueta con el mismo texto que name)
    message: indica el mensaje o acción que queremos que sea ejecutado cuando pulsemos sobre el botón con el ratón.
    label: Indica la etiqueta que queremos que se muestre en el boton.
    new(Boton, button(‘Salir’, message(Dialogo, quit)))

    LABEL
    Esta es la clase básica para crear etiquetas de texto
    Constructor:
    label(name=[name], selection=[stringimage], font=[font])
    name: indica el nombre de la etiqueta
    selection: puede ser una cadena o una imagen que queremos que sea mostrada en el lugar donde aparece la etiqueta.
    font: permite indicar la fuente en la que queremos mostrar el texto
    new(L, label(nombre, ‘texto que queramos que sea mostrado’)),

    WINDOW
    Esta clase sirve para crear ventanas donde dibujar o poner otros objetos graficos
    Constructor:
    window(label=[name], size=[size], display=[display])
    name: indica el nombre de la ventana
    size: indica el tamaño que queremos tenga la ventana
    display: indica donde queremos que aparezca (recomendamos no usar este parametro)
    Por ejemplo para crear una nueva ventana (de gráficos) de tamaño 320x200 pixels new(W, window(‘nombre ventana’, size(320, 200)),
    Métodos:
    Para esta clase nos interesarán básicamente los métodos ‘display’ y ‘flush’: display(figure, point): sirve para mostrar una figura en un lugar determinado de la ventana una determinada figura (que por ejemplo puede ser una imagen) y point que indicará las coordenadas (x,y) de la ventana donde queremos que se muestre.
    El siguiente ejemplo mostraría la figura Figure en la posicion (22, 32) de la ventana W.
    send(W, display, Figure, point(22,32))
    flush(): sirve para redibujar la venana que invoca al método, es decir, si estamos realizando una serie de llamadas y no está en el bucle principal de la ventana, entonces podemos llamar a este método para redibujar la ventana y los elementos que hayamos creado o movido.
    send(W, flush)

    Otros predicados y funciones importantes serian:
    timer: new( timer(0.2,'Aqui lo que se ejecutaro cad cierto tiempo')

    declarar variables globales: :- pce_global(@'aquinombre varglobal', new('objeto que sera global')).

    ubicacion de objetos dentro de otro objetos: right ,below ,next_row

    para cambiar forma de cursor: new(cursor('nombre del nuevo cursor')

    para retornar y esperar confirmacion de un objeto: return confirm

    para ejecutar predicados con parametros : message,?selection ejemplo-> message(@prolog, nombrepredicado, TI?selection)

    retrazar una ejecucion: sleep(10)

    etc.

    Manejo de eventos:
    Para manejar los eventos de mouse como los de teclado aqui les dejo su estructura .
    Para mouse:
    click_gesture

    Para teclado:
    key_binding

    Algunos eventos:
    handler
    handler_group
    key_binding
    click_gesture
    connect_gesture
    move_gesture
    move_outline_gesture
    resize_gesture
    resize_outline_gesture

    Manejo de imagenes :
    swi-prolog te permite manejar diferentes formatos de imagenes como por ejemplo JPEG, GIF, BMP y PNM.
    Para utilizar las imagenes primero tenemos que indicar el directorio en donde se encuentran

    :-pce_image_directory(‘direccion de la carpeta de imagenes ’)

    despues procedemos a seleccionar el nombre de la imagen:

    resource(fondo, image, image(‘nonbre de la imagen’)).

    Para poder mostrar la imagen fondo en un dialogo primero debemos primero debemos pasar la imagen a Bitmap para luego si mostrarla en el dialogo o ventana.
    Para mover imagenes tenemos los siguientes atributos:

    send(Figure, move, point(X, Y)).
    send(Figure, relative_move, point(X, Y)).

    Las imagenes se comportan igual que cualquier objeto visto anteriormente y se les puede agregar eventos de mouse como de teclado.

    Funciones para un entorno grafico:
    La principales funciones para dibujar con swiprolog serian:
    arrow
    bezier
    bitmap
    box
    circle
    ellipse
    arc
    line
    path
    text
    etc.

    Creacion de ejecutables swi-prolog:
    A continucaion un codigo para crear ejecutables :

    save(Exe):- pce_autoload_all, qsave_program(Exe,[ emulator(swi('bin/xpce-stub.exe')), stand_alone(true), goal(main) ]).

    Descargar ejecutables que desarrolle para el curso de programacion logica en swi-prolog:
    Tan solo debo hacerles recordar que los ejecutables de swi-prolog no son tan buenos como quisieramos pues su ejecucion se hase un poco pesada.
    Para ejecutar algun ejecutable primero descargar la carpeta Bin dentro de ella deberan de poner los ejecutables y posteriormente daran doble click sobre cada uno respectivamente.

    Descargar Carpeta Bin

    Descargar Tres raya swi-prolog
    Descargar Snake swi-prolog
    Descargar Sistema Experto swi-prolog
    Descargar Damas swi-prolog
    Descargar Automata-redPetri swi-prolog
    Descargar Tetris swi-prolog


  6. Archivos y Bases de datos en swi-prolog:
    Para archivos seria:
    Escritura: tell(achivo.txt'), write(primero.'), nl, write('segundo.'), nl, told.
    Lectura: see('archivo.txt'), read(P), read(S).

    Para base de datos mysql swi-prolog le dejo un pdf ojala les sea de utilidad:

    Tutorial mysql con swi-prolog

  7. Conectar Java con swi-prolog:
    Los pasos serian en si los siguientes:
    agregar alas variables de entorno del sistema operativo los siguientes direcciones talvez las direcciones no son las mismas buscar y poner la direccion indicada de cada uno si no conecta reiniciar la maquina o volver a intentar todo de nuevo.

    path=C:\Archivos de programa\Java\jdk1.5.0_09\bin;%path%
    path=C:\Archivos de programa\Java\jdk1.5.0_09\lib\tools.jar;%path%
    path=C:\Archivos de programa\Java\jdk1.5.0_09\jre\lib\rt.jar;%path% path=C:\Archivos de programa\pl\bin;%path%
    path=C:\Archivos de programa\pl\lib\jpl.jar;%path%

    Aqui les dejo un codigo de java-swiprolog que se encuentra en la ayuda de swi-prolog . Tambien lo pueden encontrar en C:\Archivos de programa \pl\doc\packages\ examples \jpl \java\Family
  8. Descagar codigo de Family

    Tambien unos ejemplos que encontre en internet para la coneccion java con swi-prolog
    ojala les sea de utilidad (son de calculadora y tictactoe).

    Descargar Ejemplos java con swi-prolog


  9. Sockets en swi-prolog:
    Para el manejo de sockets en swi-prolog ai les dejo un codigo que encontre y me sirvio , ojala les ayude a comprender un poco mas sobre este tema de sockes :

    %--------------Servidor.pl-----------------------
    server(Port):- tcp_socket(Socket), tcp_setopt(Socket, reuseaddr), tcp_bind(Socket, Port), tcp_listen(Socket, 0), tcp_open_socket(Socket, InStream, _OutStream), add_stream_to_pool(InStream,get_requests_from_clients(Socket)), stream_pool_main_loop.
    get_requests_from_clients(Socket):- trim_stacks, tcp_accept(Socket, ClientSocket, ClientIP), tcp_open_socket(ClientSocket, InStream, OutStream), add_stream_to_pool(InStream,get_request(InStream,OutStream,ClientIP)).
    get_request(InStream,OutStream,_ClientIP):- catch( read(InStream, Request), _, (writeln(error1), close(InStream), close(OutStream),delete_stream_from_pool(InStream), fail) ),
    close(InStream),
    ( Request==end_of_file -> ( writeln(error2),close(OutStream), delete_stream_from_pool(InStream),fail) ; true ),
    process(Request,Answer),
    catch( (write_canonical(OutStream, Answer), write(OutStream, '.\n')), _, (writeln(error3), close(OutStream), delete_stream_from_pool(InStream),fail) ),
    close(OutStream),
    delete_stream_from_pool(InStream).
    get_request(_InStream,_OutStream,_AgentIP).
    process(Message,test_ok(Message)).
    :-prolog_ide(thread_monitor), thread_create(server(4000),_, [alias(server),detached(true)]).


    %------ ------Clientes.pl ---------------
    create_clients:- between(1,8,N), term_to_atom(client(N),Client), thread_create(client(N), _, [alias(Client),detached(true)]), fail.create_clients.
    client(N):- Port is 4000+N, between(0,10000,F), sleep(0.0001), once( request(client(ip(127,0,0,1),Port), server(ip(127,0,0,1), 4000),hello_world(F)) ), fail.client(N):- writeln(client_finished(N)).
    request(client(_ClientIp,ClientPort), server(ServerIp,ServerPort),Message):- tcp_host_to_address(Host,ServerIp),
    repeat, tcp_socket(Socket), tcp_setopt(Socket, reuseaddr),
    catch( tcp_connect(Socket, Host:ServerPort), _, (writeln(error(ClientPort,' Client cannot tcp_connect.')),tcp_close_socket(Socket),fail) ),
    tcp_open_socket(Socket, ReadFd, WriteFd),
    catch( (write_canonical(WriteFd,Message), write(WriteFd, '.\n')), _, ( writeln(error(ClientPort,' Client cannot tcp_connect.')),tcp_close_socket(Socket),fail) ),
    close(WriteFd),
    wait_for_input([ReadFd], [ReadFd], 0),
    catch( read(ReadFd,Answer), _, ( writeln(error(ClientPort,' Client cannot tcp_connect.')), close(ReadFd),fail) ),
    close(ReadFd),
    writeln(answer(ClientPort,Answer)).
    :-create_clients.