miércoles, 15 de diciembre de 2010

Mi paint

Como ya tengo los dedales calibrados, los sigue bien y esas cosas ahora hay que ponerlos en algo útil, en este caso me he hecho una aplicación que retoca las imágenes. Se pasa una imagen por parámetro y esta se muestra en una ventana, poniendo un pequeño menú en el lado derecho.


En esta captura se observa que el filtro de partículas reconoce donde está cada uno de los dedos. Y en mi aplicación a la izquierda se ve una equis donde se ha reconocido el dedo rojo, que es el puntero. El azul no aparece porque solo se activa con una opción del menú, y el amarillo tampoco se ve porque solo se muestra cuando está encima del menú.

A continuación pongo unas capturas con algunas opciones del menú:

Filtro: cvThreshold(imagen, copia ,100,255, CV_THRESH_TOZERO_INV)




Filtro: cvThreshold(imagen, igauss,100,255, CV_THRESH_TRUNC)



Filtro: cvThreshold(imagen, copia,100, 255,1)

¿Qué he estado haciendo?

Durante todo este tiempo lo que he hecho es trabajar en el mundo real, con los objetos que me interesan realmente. Los dedales que voy a usar definitivamente son estos:



Como se puede apreciar están el rojo, azul y amarillo, con estos he realizado un calibrado de cada uno de ellos.

Para realizar el calibrado primero he situado una ventana donde hay que poner el dedal, y luego se muestra un cuadrado donde se ve el tamaño que recoge el calibrado del objeto en cuestión. Y para que quede más bonito he puesto al lado el umbralizado de la imagen con ese calibrado.



miércoles, 3 de noviembre de 2010

Mis clases

Para hacer el calibrado he tenido que crear clases nuevas y retocar clases que tenía anterior mente. El esquema general ahora mismo es el siguiente:


Y las diferentes clases que tengo son:


En esta clase se almacenan los umbrales que puede coger cada color en RGB. Tengo tres variables, una para cada canal y varias funciones para escribir los valores y para recuperarlos.



Esta clase se dedica a hacer el vector de pesos acumulado, que expliqué anteriormente, y luego selecciona los candidatos que se reproducirán después.


La clase rectángulo ha quedado finalmente así:

  • setID: establece el ID de la partícula.
  • setColor: establece el color de la partícula.
  • setEsquinaIA: establece la esquina superior izquierda.
  • setEsquinaDB: establece la esquina inferior derecha.
  • setAlto: establecida la esquinaIA, calcula la Y de la otra esquina según el alto.
  • setAncho: establecida la esquinaIA, calcula la X de la otra esquina según el ancho.
  • setPeso: establece el peso.
  • 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 alto y ancho que se quiere que tenga.


Esta clase MiImagen es que la que utilizo para tratar la imagen que me pasan. Contiene a la clase umbrales, para saber los umbrales que hay que usar en el umbralizado. También contiene la imagen a la que se le resta el fondo (sinFondo) y la máscara que se obtiene de ésta imagen. A parte tiene el atributo imagen que será donde se guardará la imagen umbralizada. 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.


Los atributos de esta clase son:
  • dedo: es un vector de rectángulos, estas son las partículas que vamos a general para el filtro.
  • color: color que tendrá cada partícula.
  • ancho: ancho de las partículas.
  • alto: alto de las partículas.
  • umbralizado: según el valor se usará un umbralizado.
  • des: desplazamiento de la ventana para calibrar.
  • calib: objeto de la clase calibrado.
  • dibujado: objeto de la clase miImagen.
  • noDibujar: puntero a la imagen principal sobre la que se harán las operaciones.
A continuación explicaré cada una de las funciones:
  • setColor: establece el color que tendrán todas las partículas.
  • setUmbralizado: establece el valor de umbralizado.
  • setDesplazamiento: establece el desplazamiento de la ventana a calibrar.
  • 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.
  • nuevosCandidatos: genera los nuevos candidatos que se han elegido en la ruleta.
  • run: función principal que realiza las llamadas correspondientes para el filtro de partículas.
  • seleccionUmbralizado: en función del valor selecciona el umbralizado de un color sobre la imagen.
  • calibrarColor: realiza la calibración del color.



Y esta última clase es la que realiza el calibrado de los colores. Los atributos que tiene son:
  • Ventana: es el rectángulo donde se pondrá el objeto a calibrar.
  • imagen: puntero a objeto miImagen.
  • fondo: imagen de fondo.
  • alto: alto del objeto a seguir.
  • ancho: ancho del objeto a seguir.
Y las funciones que tiene son las siguientes:
  • setImagen: establece el puntero a MiImagen.
  • setVentana: establece la ventana.
  • setFondo: establece el fondo.
  • setAncho: establece el ancho del objeto calibrado.
  • setAlto: establece el alto del objeto calibrado.
  • getAncho: devuelve el ancho del objeto calibrado.
  • getAlto: devuelve el alto del objeto calibrado.
  • calibrar: realiza la calibración del objeto.
  • quitarRuidoMascara: quita el ruido de la máscara.
  • valoresRojo: establece los valores umbral para el color rojo.
  • valoresAzul: establece los valores umbral para el color azul.
  • valoresVerde: establece los valores umbral para el color verde.
  • valoresAmarillo: establece los valores umbral para el color amarillo.
  • quitarFondo: resta a la imagen recogida el fondo.
  • hacerMascara: realiza la máscara de la imagen sin fondo.
  • seleccionValorColor: selecciona que color es del que se quieren coger los valores umbrales.
  • cogerLado: coge del objeto el ancho y alto.

Calibrado

Lo primero que hay que hacer es calibrar los colores que se van a usar, porque ya se sabe que puede cambiar la luz y eso hace que los valores también varíen.

Para ello tengo una clase que se encarga del calibrado de cada color, de la siguiente forma:

- Resta el fondo a la imagen actual.
- Con la nueva imagen hace una máscara, donde pone en 255 los píxeles que han cambiado, esto quiere decir que ahí estará mi objeto a reconocer. Esta máscara no distingue ningún color, sino que junta todos los colores.
- Usando la máscara miro los umbrales del color (en cada caso para el que me es útil en ese momento). Y con ello almaceno los valores máximos y mínimos que tiene mi objeto.
- Recojo el tamaño del objeto, ya que dependerá a la distancia a la que se ponga, pero ejecutando el programa estará a la misma distancia siempre. Esto sirve para ajustar el tamaño de las partículas a lanzar.

Y con todo esto recogido ya puedo usar el filtro de partículas.

lunes, 25 de octubre de 2010

Recogiendo umbrales

Como en el mundo real las cosas son variables lo que estoy haciendo ahora es recoger los umbrales entre los que está cada color.

Para ello hago varios pasos:

Paso 1:
Hago una resta de la imagen actual con el fondo (el fondo ahora es una imagen que he tomado, porque trabajo en el semi mundo, pero luego será el primer frame que se coja de la cámara). Con esta operación lo que consigo es crear una máscara donde los píxeles que han cambiado serán los que tengan mi objeto a buscar.

Paso 2:
Consultando en la máscara, miro en los píxeles que son diferentes los valores que hay en cada canal. Tengo unos umbrales muy genéricos para reconocer cada color, con esta operación lo que hago es ajustar esos umbrales al momento.

Paso 3:
Aplico el umbralizado del color que quiero con los umbrales que he obtenido previamente.


Y con esto, tan bonito y sencillo, consigo hacer la calibración para cada color. Lo siguiente que hay que hacer es juntar esta calibración con el filtro de partículas. Un trabajo de chinos, pero se hará lo que se pueda.

jueves, 21 de octubre de 2010

Acercándose a la realidad

Durante todo este tiempo he estado trabajando con "un mundo ideal", donde las cosas a seguir eran cuadratitos perfectos, con su color bien definido. Es hora de enfrentarse a la realidad, pero no mucho porque da miedito aun.

Así que me he creado un mundo semi-ideal. Ahora mismo en lo que estoy trabajando es en recoger en el vídeo los parámetros que tendrá cada color que voy a seguir. Cuando todo esté bien montado tendré un dedal de cada color, pero hasta entonces tengo que coger lo que encuentro más a mano que son mis bolis de colores (y muchos me llamaron loca cuando los compré, juas).



Como se puede observar cada la tapa de cada boli es del color que quiero que sean los dedales. Y como estoy en un cuasi mundo real voy a trabajar con un fondo fijo.

La primera parte es dividir la pantalla en cuatro zonas diferentes que será donde reconoceré cada uno de los colores.



Y una vez que tengo esas zonas en cada uno de los cuadrados tengo que poner el color que quiero buscar.







Pues con esto tengo ya preparado mi mundo para poder hacer la nueva funcionalidad, pero como ya he dicho que es un cuasi mundo ahora vuelvo trabajar con imágenes fijas para sacar cada color, porque hay que ir pasito a pasito, luego ya cuando tenga el calor suficiente (y el algoritmo funcional) aplicaré el reconocimiento de los colores sobre el vídeo.

Y ya como último paso será atreverme a quitar el fondo, pero para eso aun queda mucho código entre medias.

miércoles, 20 de octubre de 2010

Arreglado

Para solucionar el error de ayer se ha tenido que desinstalar el opencv 2.1 y poner la versión 2.0, después se han instalado los drivers de la cámara, y usado la cámara:




Porque es la única (de las que tenemos) que acepta el formato de entrada en opencv.

Y por último poner cvWaitKey(2);


Con esto ya podemos acceder a la webcam, así que ahora toca trabajar con la imagen que se recoge.