Bueeeno este fue un trabajo que presente en la universidad en Inteligencia Artificial, con respecto al tema en internet la gran parte de informacion esta en ingles, y tampoco hay la implementacion en PHP... asi que aqui publico el trabajito que hice :D

El objetivo de esto es simple, necesitamos reconocer formas a partir de
simples líneas, cuadrados, rectángulos, triángulos y hasta círculos. Esto es un  reto para los métodos de inteligencia artificial, desde hace muchos años estos  métodos ya estaban en teoría desarrollados pero por las limitaciones de los  computadores, velocidad de procesamiento, memoria entre otras cosas era  muy pesado o poco probable desarrollar exitosamente estas técnicas.

Transformada de Hough

La transformada de Hough consiste en permitir descubrir las formas en una
imagen. Se basa en transformar puntos de la imagen en un espacio de
parámetros. La idea es encontrar rectas, como se menciono en teoría se
pueden encontrar varias formas, pero el costo computacional es elevado.

La aplicación mas simple de la transforma de hough es para la detección de
rectas, lo primero es tener una imagen binarizada, resultado de la detección
de bordes. Para cada punto x, y de la imagen que estemos utilizando pasan
infinitas rectas de la forma: y=ax+b, la ecuación de la recta. Luego cada
punto x, y vota para cada pareja de puntos que satisface b=y-ax.

El algoritmo tiene que recorrer todos los puntos x, y, y para cada uno votar
en el espacio de parámetros m, b o también llamado acumulador. Luego la
pareja m, b con más votos o el máximo del acumulador da la ecuación de la
recta.

Hasta aquí hemos llegado de manera sencilla con nuestro algoritmo, pero
existe un problema, los valores de m tienden al infinito, por lo que
almacenarlos y graficarlos será un impedimento para el uso de la
transformada.

La solución planteada es la siguiente, si bien y = ax + b, se dice que toda
ecuación puede ser representada en senos y cósenos es así que la ecuación de la recta de la forma y = ax + b, puede ser representada como:

p = xcos(θ) + ysen(θ)

Esta es la llamada ecuación en la forma normal de la recta, donde p es la
distancia de la recta al origen y θ es el ángulo entre la perpendicular y el eje  x, de esta forma son menos los puntos que hay que recorrer y por lo tanto más rápido es el algoritmo.

Los límites de estos están dados por las siguientes condiciones, θ varia entre 0 y 180 ya que a partir de 180 hasta 360 grados se vuelven a cruzar las curvas y p varia en la diagonal de la imagen es decir la hipotenusa con respecto a los lados de la imagen original.

Implementación en el lenguaje PHP

Si bien PHP esta orientado para el desarrollo de páginas dinámicas para entorno Web, eso no le quita potencialidad a la hora de usarlo como lenguaje de desarrollo para algoritmos complejos, ya que la gran facilidad que nos brinda en la manipulación de los tipos de datos lo hacen flexible a estas
situaciones.

PHP usa la librería GD para manipulación de imágenes, los pasos que
seguiremos en la implementación son los siguientes:

  • Implementación de un frontend simple
  • Detección de bordes, aplicando el filtro Sobel.
  • Binarizacion de las líneas en contraste con el fondo.
  • Implementación del acumulador.
  • Graficar el acumulador en una nueva imagen.

La interfaz será sencilla, constara de un formulario base donde podamos subir una imagen y cajas de entrada para la personalización del método a emplear:

Al momento de subir la imagen, la convertiremos dinámicamente al formato PNG de acuerdo a su actual extensión

switch ($ext) {
case 'jpeg':
case 'jpg': $imEntrada = imagecreatefromjpeg($archivo['tmp_name']);
break;
case 'gif': $imEntrada = imagecreatefromgif($archivo['tmp_name']);
break;
case 'png': $imEntrada = imagecreatefromgif($archivo['tmp_name']);
break;
}
imagepng($imEntrada,$this->IMG_ENTADA);

Donde this->IMG_ENTADA es el nombre de entrada que definimos previamente junto con el nombre de salida de las imágenes

$tratamiento = new TratamientoImagen();
$tratamiento->IMG_ENTADA = "entrada.png";
$tratamiento->IMG_SALIDA = "salida.png";

Necesitamos detectar los bordes de la imagen, en este resumen no incluiré la forma como se desarrollara la misma, en el proyecto presentado se uso el Filtro Sobel

Ahora podemos aplicar la transformada de Hough:

for ($y=0; $y<$alto; $y++) {
    for ($x=0; $x<$ancho; $x++) {
        if ($matrImag[$y][$x] == 1) {
           for ($theta=0; $theta<$maximoTheta; $theta+=1) {
                $r = $x * cos(deg2rad($theta)) + $y * sin(deg2rad($theta));
                if (!isset($data[(int)$theta][(int)$r])) {
                  $data[(int)$theta][(int)$r] = 1;
                } else {
                  $data[(int)$theta][(int)$r] ++;
                }
             }
         }
      }
}

Donde la matriz $data es nuestro acumulador, finalmente graficamos los
votos recibidos en esta matriz

Descargar PDF
Descargar Codigo



  1. Franco(zentido) on Miércoles 14, 2009

    Totalmente fantastico tu pogramacion es exelente, y te adimiro mucho gran xyox.. te felicito esto me ayuda mucho para poder analizarlo y asi entenderlo mejor.

    buenisimo post

    gracias !

  2. Victor on Miércoles 14, 2009

    gracias por el source voy a mirarlo un dia de estos :D se ve interesante …

    Xcierto como se llama el widget q usas para el tweeter en el blog ?

  3. XYOX on Miércoles 14, 2009

    Gracias, es interesante como se puede utilizar la inteligencia artificial para estos casos. ..

    @Victor.. el widget es el mismo que se ofrece en tweeter http://twitter.com/goodies/widgets

    Salu2

  4. deiby moreno on Miércoles 14, 2009

    oye me parece muy importate tu aporte pero no me quiere correr en mi equipo.
    no se si sera por mi version de php, estoy utilizando wampserver 2.0 con php 5.3
    me podrias colaborar??

  5. Nico on Miércoles 14, 2009

    Hola me interesa mucho este tema y estoy estudiándolo.. Creo que voy bien. Estoy intentando detectar y marcar con un rectángulo o circulo a un objeto circular que se encuentre en una imagen (por ejemplo una pelota). Para estudiar como hacerlo, primero intente detectar una posible recta en una imagen.. algo así como tu proyecto. Pero mi gran problema es como hacer una vez que tengo todos los votos de las parejas (theta, r) para detectar la linea y encerrarla en un rectángulo, o en un circulo, o sino, remarcarla.. cualquiera de estas cosas me sirve.. obviamente que si puedo encerrar a la recta en un circulo o en un rectángulo mejor!

    Vi que en la imagen que tienes al comienzo de todo (la del edificio) logras marcar donde esta cada recta. En el código que pones como ejemplo no se encuentra esta parte y es la que mas tengo dudas..

    Estaría bueno detectar el objeto, en este caso la recta, y usar la función “imageline”, “imagerectangle” u otra de PHP para remarcar donde se encuentra la recta.

    Estaré muy agradecido por tu ayuda y seguro que mas gente que recién comienza con este tipo de problemas también lo estará..

    Desde ya muchas gracias por este aporte.

    Reitero mi correo es: nico103_20@hotmail.com