martes, 19 de octubre de 2010

Problemas

Llegados a este punto he descubierto que tengo un problema.

He conectado una webcam y he hecho un programilla simple que lo único que hace es visualizar en una pantalla lo que captura la webcam. Como don Murphy está presente cuando menos lo requieres me ha salido el siguiente error:

HIGHGUI ERROR: V4L2: Pixel format of incoming image is unsupported by OpenCV


Así que hay que buscar una solución para ello, ¿cuál? Pues la más sencilla es volver a la versión anterior de opencv, la 2.0, que se sabe que no da problemas.

Video del filtro

Antes de poner el vídeo pongo una captura de los diferentes umbralizados que tengo. En la primera imagen se observan dónde se encuentra cada uno de los objetos. En la imagen de abajo están los diferentes umbralizados que se hace a cada objeto de cada color. Como se puede ver solo se encuentra en blanco los píxeles que nos han interesado de cada uno.





Y para ver que esto realmente funciona dejo el seguimiento de los objetos durante todo el vídeo.

Filtro conseguido

El último paso que he tenido que realizar es juntar todo.

Una de las cosas que he tenido que añadir es que si en algún momento no se encuentra ninguna partícula con peso hay que volver a lanzar de forma aleatoria las partículas. Esto en el vídeo que me he creado no es muy útil ya que no desaparecen los elementos a seguir, pero en lo que voy a necesitar si pasará que desaparezca algún elemento y por lo tanto tenga que reiniciarlo de nuevo.

Otra de las cosas que he tenido que cambiar son los umbrales para hacer la umbralización, pues antes estaba trabajando en un mundo perfecto y por lo tanto los colores estaban bien definidos. Por ejemplo tenía que para el rojo necesitaba que el canal de rojo estuviera en 255 y el verde y el azul en cero ambos, así que he tenido que darle un poco más de margen, para el rojo entre 240 y 255 y para los otros dos que sean menos de 10. Los mismos cambios he hecho para el umbralizado en verde, azul y amarillo. Y con este último cambio ya se puede ver cómo funciona el filtro.

Dejo constancia que esto funciona con unas capturas de pantalla, primero de cada uno de los colores por separado y finalmente todo junto. Como se ve en la imagen el cuadrado consigue encontrar cada elemento perfectamente.












Y como estas cosas quedan mucho más bonitas cuando se ve cómo lo va haciendo por todo el vídeo ahora voy a aprender a grabar vídeo con opencv, para poder compartir con el mundo mi gran trabajo, juas.

viernes, 15 de octubre de 2010

Creando un vídeo personal

Como tengo que trabajar en mi mundo abstracto lo siguiente que he hecho ha sido crearme un vídeo adaptado para mi caso.

Para ello hemos usado el programa videosyn, al cual hay que ponerle el tamaño de la imagen del vídeo, los frames que tiene y los objetos. Luego a cada objeto se le define la altura, anchura, color y recorrido que realiza.

Como me interesa me he creado cuatro objetos, cada uno de ellos de un color (rojo, azul, verde y amarillo), y luego les he puesto a moverse por ahí por la pantalla.

El resultado es este vídeo:



Ahora me dedicaré a toquetearlo para encontrar dónde está cada uno de los cuadrados y a seguirlo.

jueves, 14 de octubre de 2010

Abriendo vídeo

Ahora que ya está todo más o menos hecho con las imágenes quietas es hora de dar una vuelta más, o como dirían en el circo, ¡aun más difícil!

Se trata de abrir un vídeo y hacer todo lo que hecho en las imágenes estáticas, pero como hay que empezar por el principio lo primero es abrir el vídeo.

Para ello he investigado que hay un objeto llamado cvCapture, donde se puede meter el vídeo (wuajaja). Para meter el vídeo en ese objeto uso cvCreateFileCapture(dirección de mi vídeo).

Luego solo tengo que crearme una imagen como las he estado manejando hasta ahora (IplImage), y meter frame a frame el vídeo en ella con cvQueryFrame.

¡Y ya está!

A partir de ahí solo tengo que ir trabajando con cada frame e ir aplicando mis cosillas para sacar lo que yo quiero. Fácil, sencillo y para toda la familia.

miércoles, 13 de octubre de 2010

Ruleta

Llegado a este punto me toca explicar el algoritmo de la ruleta.

Partimos de un vector de partículas, donde cada una tiene su peso, lo que queremos conseguir ahora es que las partículas que son más óptimas puedan tener mayor descendencia, y las que no nos interesan no se reproduzcan. Para conseguir esto se usa la ruleta, cuyo funcionamiento es el siguiente.

Se hace un vector con el mismo número de elementos que las partículas que tenemos, en este vector se pondrá el peso acumulado, de tal forma que si la primera tiene peso 5 y la segunda peso 10, el vector nuevo tendrá en el primer elemento un 5 y en el segundo 15, pues se repite para todos los elementos hasta llegar al final.

Después de esto se "lanzan" números de forma aleatoria, teniendo como límite el último elemento de nuestro nuevo vector. Después se mira en cada número a qué elemento corresponde y será ese el nuevo elemento que se propague.

De esta manera lo que se consigue es que las partículas con mayor peso tengan más descendencia, y las que no tengan ningún peso no se sigan propagando.

Y como la explicación me ha quedado tan chapucera, pero yo me entiendo, dejo un dibujo de una ruleta para que al menos parezca bonito.

viernes, 8 de octubre de 2010

Clases

Llegado a este punto necesito hacer una pequeña recopilación de las clases que tengo ahora mismo y cómo funcionan cada una de ellas. Para poder ponerlo todo más bonito y ordenadito he usado el programa umbrello, de momento solo para poner en cada clase qué atributos tiene y qué funciones.



Esta clase MiImagen es que la que utilizo para tratar la imagen que me pasan. Tiene un atributo imagen que es donde se guarda el umbralizado que se realiza a la clase principal. Como se ve hay diferentes funciones de umbralizado para seleccionar cada color. Y por último hay una función para quitar ruido que se aplica sobre la imagen umbralizada.


Esta clase Rectángulo es la más bonita de todas, como se puede ver es la que tiene más funciones. Con esta clase es con la que simulo mis partículas. Cada rectángulo se define por la esquina superior izquierda (esquinaIA), esquina inferior derecha (esquinaDB), color de la partícula y peso.
A continuación explicaré cada una de las funciones:

  • setID: establece el ID de la partícula.
  • setColor: establece el color de la partícula.
  • getEsquinaIA: devuelve la esquina superior izquierda de la partícula.
  • getEsquinaDB: devuelve la esquina inferior derecha de la partícula.
  • getColor: devuelve el color de la patícula.
  • getPeso: devuelve el peso de la partícula.
  • getID: devuelve el ID de la patícula.
  • dibujar: dibuja la partícula en la imagen que se pasa por parámetro.
  • dispersar: mueve a la partícula de forma aleatoria tanto movimiento como se pasa por parámetro.
  • damePosicion: devuelve el punto central de la partícula.
  • dameAlto: devuelve el alto de la partícula.
  • dameAncho: devuelve el ancho de la partícula.
  • calcularPeso: calcula el peso de la partícula. Se le pasa por parámetro la imagen ya umbralizada, de tal forma que los píxeles importantes están en 255, lo que hace es sumar cuántos de esos píxeles están dentro de la partícula.
  • generarParticula: genera las partículas de forma aleatoria por la imagen, por eso se le pasa la imagen (para saber los bordes), el color de la partícula y el lado que se quiere que tenga.


La clase dedos es la que va a realizar nuestra búsqueda. Los atributos que tienen son un vector de partículas, que se generarán al crear el dedo, el número de partículas que se harán se pasa por parámetro al inicializar el dedo, así se reserva al principio del programa la memoria que se requiera en cada caso. Los atributos color y lado se pasarán también al inicializar.
A continuación explicaré cada una de las funciones:
  • setColor: establece el color que tendrán todas las partículas.
  • setLado: establece el lado que tendrán todas las partículas.
  • estimado: de todas las partículas que se tienen devolverá el resultado más óptimo, como solo va a haber un dedo de cada color solo puede haber un resultado más óptimo.
  • calcularPesos: calcula los pesos de todas las partículas.
  • dispersar: dispersa todas las partículas en la distancia que se indica.
  • generarAleatorios: genera todas las partículas de forma aleatoria.
  • dibujarCandidatos: una vez calculados los pesos de todas las partículas dibuja en la imagen las partículas que sean candidatas a ser el mejor estimado.

Actualmente las clases están de esta forma, aunque seguramente habrá que añadir otras más para poder seguir implementando el filtro. Ahora voy a dedicarme a implementar la clase ruleta, cuya funcionalidad explicaré en la siguiente entrada.