Universidad de Costa Rica Facultad de Ingeniería Escuela de Ingeniería Eléctrica IE – 0502 Proyecto Eléctrico Determinación de la posición de un objeto utilizando una cámara Web Por: Juan Antonio Lara Flores Julio del 2004 IE-0502 ii Determinación de la posición de un objeto utilizando una cámara Web Determinación de la posición de un objeto utilizando una cámara Web Por: Juan Antonio Lara Flores Sometido a la Escuela de Ingeniería Eléctrica de la Facultad de Ingeniería de la Universidad de Costa Rica como requisito parcial para optar por el grado de: BACHILLER EN INGENIERÍA ELÉCTRICA Aprobado por el Tribunal: ___________________ Ing. Federico Ruiz Profesor Guía ___________________ ___________________ Ing. Lucky Lochi Yu Dr. Jaime Fornaguera Profesor Lector Profesor Lector Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web iii DEDICATORIA A toda mi familia, en especial a mis padres y a mi novia, por todo el apoyo que me dieron para lograr vencer los retos impuestos y llegar a esta etapa de mi vida que gracias a Dios esta culminando satisfactoriamente, muchas gracias a todos... Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web iv RECONOCIMIENTOS Llegando a esta etapa de la vida, donde se culmina con gran esfuerzo una labor iniciada cinco años atrás, se debe reconocer a mis padres los cuales me han facilitado todo lo necesario para que obtenga los conocimientos que hoy tengo, gracias a todos los profesores que me han enseñado todo lo necesario para poder ser un profesional útil a los demás y versátil en el campo laboral. Muchas gracias a todos los profesores, en especial a Alexis Maldonado el cual me brindó su apoyo durante la elaboración de este proyecto hoy terminado exitosamente, aportando las ideas necesarias para su elaboración. Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web v ÍNDICE GENERAL ÍNDICE GENERAL.................................................................................. v ÍNDICE DE FIGURAS ........................................................................... vii ÍNDICE DE TABLAS ............................................................................ viii NOMENCLATURA................................................................................. ix RESUMEN ................................................................................................ x CAPÍTULO 1: Introducción ..................................................................... 1 1.1 1.2 1.3 1.4 Objetivos ..........................................................................................................................1 Problema a resolver .........................................................................................................2 Justificación del tema ......................................................................................................3 Metodología .....................................................................................................................5 CAPÍTULO 2: Desarrollo teórico ............................................................. 6 2.1 Imágenes digitales .....................................................................................................................6 2.1.1 Concepto de imagen digital ............................................................................6 2.1.2 Muestreo espacial y niveles de gris ................................................................6 2.1.3 Relaciones entre píxeles: Vecindad y Conectividad.......................................8 2.1.4 Color ...............................................................................................................9 2.1.5 Espacio RGB ................................................................................................10 2.1.6 Reconocimiento de objetos ...........................................................................11 2.1.7 Determinación del centroide del objeto determinado...................................12 2.2 Preprocesamiento de imágenes digitales .......................................................................13 2.2.1 Definición.....................................................................................................13 2.2.2 Eliminación de Ruido ...................................................................................13 2.2.3 Filtros pasobajos lineales espaciales.............................................................14 CAPÍTULO 3: Análisis del programa..................................................... 16 3.1 Estructuración del programa ..........................................................................................16 3.1.1 Archivo interfaz.h.........................................................................................16 3.1.2 Archivo interfaz.cpp .....................................................................................17 3.1.3 Programas para abrir las imágenes tomadas .................................................19 3.1.4 Programas makefile para la compilación de los archivos.............................20 3.2 Resultados de las pruebas realizadas al programa .........................................................22 3.2.1 Primera prueba ..............................................................................................22 3.2.2 Segunda prueba.............................................................................................25 3.2.3 Tercera prueba ..............................................................................................30 3.2.4 Tiempos de ejecución del programa .............................................................34 CAPÍTULO 4: Conclusiones y recomendaciones .................................... 37 Agosto del 2004 IE-0502 4.1 4.2 Determinación de la posición de un objeto utilizando una cámara Web vi Conclusiones ..................................................................................................................37 Recomendaciones ..........................................................................................................39 BIBLIOGRAFÍA..................................................................................... 40 ANEXOS ................................................................................................. 41 Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web vii ÍNDICE DE FIGURAS Figura 2.1 Vecinos en el plano vertical y horizontal de un píxel.......................................8 Figura 2.2 Vecinos asociados a las diagonales de un píxel................................................9 Figura 2.3 Espacio RGB ..................................................................................................11 Figura 2.4 Máscara utilizada en el filtro ..........................................................................15 Figura 3.1 Fotografía de la posición de un objeto ............................................................22 Figura 3.2 Fotografías de algunas de las posiciones del objeto durante la prueba ..........23 Figura 3.3 Fotografía de una posición del objeto ............................................................24 Figura 3.4 Fotografía de los centroides obtenidos durante la prueba ..............................24 Figura 3.5 Fotografías de algunas de las posiciones del objeto durante la prueba ..........25 Figura 3.6 Fotografía de una posición tomada durante la prueba....................................26 Figura 3.7 Fotografía en escala de grises del objeto durante la prueba ...........................27 Figura 3.8 Fotografía de los centroides del objeto durante la prueba..............................27 Figura 3.9 Fotografía de algunas posiciones del objeto durante la prueba......................31 Figura 3.10 Fotografía en escala de grises del objeto ......................................................31 Figura 3.11 Fotografía de los centroides del objeto durante la prueba............................32 Figura 3.12 Fotografía en escala de grises del fondo dividido en zonas .........................33 Figura 3.13 Fotografía de una posición del objeto ..........................................................33 Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web viii ÍNDICE DE TABLAS Tabla 2.1 Tiempos de ejecución del programa .................................................................34 Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web ix NOMENCLATURA X Distancia desde el origen a un punto en el eje de las abscisas Y Distancia desde el origen a un punto en el eje de las ordenadas F(x,y) Función que describe la imagen por posición I(x,y) Función de iluminación de la imagen por posición R(x,y) Función de reflexión de la imagen por posición N Número de píxeles en el eje de las abscisas M Número de píxeles en el eje de las ordenadas b Número de total de bits de la imagen G Número que determina el número de bits por píxel de la imagen N4(p) Representación de los vecinos verticales y horizontales de un píxel ND(p) Representación de los vecinos en las diagonales de un píxel N8(p) Representación de los ocho píxeles que rodean a un píxel Qy Distancia de un punto del objeto a el origen en el eje y Qx Distancia de un punto del objeto a el origen en el eje x A Área del objeto x Posición del centroide de un objeto en el eje x y Posición del centroide de un objeto en el eje y Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web x RESUMEN Para resolver el problema de determinar las posiciones en las cuales se movió un ratón dentro de un laberinto se buscó solucionar el problema utilizando una cámara Web, esto debido a la velocidad con la que pueden tomar fotos y a la facilidad que se tiene en el sistema operativo Linux, para poder manejarla. En la captura de imágenes se utilizó un programa escrito en el lenguaje de programación C encontrado en la red, el cual se modificó para adaptarlo a las necesidades del programa que va a determinar las posiciones. Inicialmente se debe tomar la foto del fondo, la cual se va a utilizar de base de comparación para las otras fotos tomadas con el ratón en el laberinto. Con el objetivo de facilitar el uso del programa se va a tener la opción de ejecutar el programa por un tiempo determinado, el cual lo ordena el usuario, este va a tener un rango de uno a diez minutos para escoger y con la opción de variar el tiempo de ejecución en minutos únicamente. Durante las pruebas del programa, se observó como los resultados se veían alterados luego de haber tomado fotos por un tiempo, esto cuando se ejecutaba el programa por primera vez luego de haber cargado el sistema operativo. Luego de varias pruebas se llegó a la conclusión de que el motivo es un ajuste que realiza la cámara durante este tiempo, por lo que para prevenir que esto afecte los resultados se hizo una opción que toma fotos durante dos minutos para darle el tiempo requerido a la cámara para que ajuste la iluminación. Además se hicieron pruebas de tiempo para determinar el tiempo que dura la cámara tomando una foto, donde este tiempo depende de la máquina en la cual se esté corriendo el programa, por lo que para instalar el programa en una computadora diferente se debe determinar este tiempo y cambiar los datos dentro del programa, para obtener la precisión requerida por el usuario. Debido al proceso utilizado para determinar la posición del objeto, durante la ejecución del programa se debe contar con una iluminación constante y evitar que se mueva la cámara durante la toma de fotos, ya que estas dos situaciones varian los valores de cada píxel en las fotografías del fondo y de la posición del objeto, lo cua l va a provocar Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web xi diferencias en píxeles que no forman parte del objeto, con lo que se darán errores en los resultados. Tomando en cuenta lo anterior y una vez realizadas una gran cantidad de pruebas al programa, corrigiendo las posibles fuentes de error, se concluye que si se toman en consideración las recomendaciones dadas, este programa que utiliza una cámara Web, es una solución viable para solucionar el problema planteado, ya que con él se han obtenido resultados satisfactorios siempre y cuando se ejecute correctamente. Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 1 CAPÍTULO 1: Introducción 1.1 Objetivos 1.1.1 Diseñar un programa utilizando el lenguaje C++ para que se puedan obtener las posiciones de un ratón que se mueve en un laberinto, tomando fotografías con una frecuencia adecuada, determinándose las posiciones en que se encontró el animal. 1.1.1.1 Montar una plataforma de Linux en la versión brindada por Debian para contar con los módulos necesarios para la cámara Web que se utiliza y de video for linux para su manejo. 1.1.1.2 Conocer las principales herramientas del lenguaje de programación C++, lográndose con ello la mayor eficiencia en el diseño del programa que se implemente. 1.1.1.3 Utilizar un método de programación estructurado, que permita un desarrollo del programa adecuado y fácil de comprender. 1.1.1.4 Utilizar óptimamente el programa mvc, el cual se va a aprovechar para tomar las fotografías del laberinto en el cual se esta moviendo el ratón. 1.1.1.5 Brindar al usuario la zona y la posición en coordenadas donde se encontró el ratón, mediante el cálculo de su centro de masa, para que se determine con exactitud la posición en donde se detectó. 1.1.1.6 Construir una imagen dividida en zonas donde se muestran puntos en las coordenadas donde se encontró el ratón, y además de imprimirse las fotografías de cada posición que se determinó, en el cual se brinde al usuario un medio para corroborar la validez de cada uno de los datos obtenidos. 1.1.1.7 Crear un archivo en el cual se tenga una lista de las posiciones obtenidas, mostrando la posición y la zona a la cual pertenece esa coordenada que se averiguó. 1.1.1.8 Diseñar una interfaz gráfica para el programa, que brinde al usuario herramientas visuales fáciles de manejar, donde se le indiquen los pasos a seguir y los cuidados que debe tener cuando ejecuta el programa. Agosto del 2004 IE-0502 1.2 Determinación de la posición de un objeto utilizando una cámara Web 2 Problema a resolver El presente proyecto busca resolver la necesidad de la escuela de medicina de la Universidad de Costa Rica para realizar análisis del comportamiento de un ratón moviéndose en un laberinto. Lo que se busca es un sistema para determinar las posiciones en las cuales se encontró el ratón durante la prueba en el laboratorio, esto utilizando una cámara web manejada por una computadora que procese las fotografías tomadas e imprima los resultados obtenidos. Agosto del 2004 IE-0502 1.3 Determinación de la posición de un objeto utilizando una cámara Web 3 Justificación del tema La escogencia del tema de este proyecto se dio debido a la necesidad que se tiene en la escuela de medicina de la Universidad de Costa Rica de una herramienta adecuada para realizar experimentos en los que se estudie el comportamiento de un ratón moviéndose en un laberinto, determinando las zonas en las que éste se mueve. Dado que para obtener las posiciones en las que se encuentra el ratón en cada instante del experimento se hacía una tarea muy tediosa y poco exacta, es que surge como solución a éste problema se va a ins talar una cámara Web en el sistema operativo Debian GNU/Linux, debido a que este sistema operativo brinda una mayor flexibilidad para que se manipule la cámara con un programa utilizando el lenguaje de programación C++. Éste cuenta con librerías para poder procesar adecuadamente las fotografías obtenidas y utilizar una serie de técnicas que permitan determinar la posición exacta del ratón y la zona en la que está. La solución propuesta brinda una muy buena herramienta si se cumple con una serie de requisitos para que la mayoría de los resultados tengan la posición exacta en la que se encontraba el ratón en el momento de tomar la fotografía. Es importante que se tome en cuenta que cualquier pequeña variación durante el tiempo de ejecución del programa, pueden afectar radicalmente los resultados, por lo cual es de vital importancia que se cuiden la iluminación y la posición de la cámara, para poder garantizar una alta confiabilidad en los datos del programa. Este proyecto brinda una óptima solución a un problema utilizando todas las ventajas que brinda la tecnología actual, donde se está dando un aprovechamiento de algunas herramientas que brinda actualmente el sistema operativo Linux, dado al fácil acceso que brinda hacia las partes estructurales del computador utilizado, además de la facilidad con la que se puede ejecutar en éste el programa que se va a diseñar. Además de esto, es importante mencionar que los conocimientos necesarios para que se lleve a cabo el proyecto se encuentran en libros y direcciones en la red donde se pueden adquirir todas las herramientas que puedan hacer el programa más eficiente y se aumente la confianza en los Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 4 datos que se obtengan. Para poder corroborar cuales posiciones calculadas son incorrectas se añade la fotografía del objeto en cada una de las posiciones determinadas, para que se verifique rápidamente cuales son los datos confiables y cuales sufrieron de variaciones que afectaron los resultados al instante en que se tomó la fotografía del objeto. Agosto del 2004 IE-0502 1.4 Determinación de la posición de un objeto utilizando una cámara Web 5 Metodología La metodología a seguir para solucionar el problema propuesto tiene como primer paso montar la platarforma a utilizar en Linux , inicialmente para poder utilizar la cámara Web se debe recompilar el Kernel, donde se incluyen en él los módulos necesarios para manejar los dispositivos de la computadora utilizada, el de la cámara que se tiene y el de Video for Linux, el cual es el módulo que brinda las herramientas necesarias para poder controlar los dispositivos de video. Una vez que se tenga instalado Linux, se debe de conseguir una manera para tomar las fotografías necesarias para que se pueda determinar la posición del ratón en el laberinto. Las fotos se necesitan tomar con una frecuencia mínima de una foto por segundo y se van a almacenar en la carpeta donde se encuentran los archivos del programa. Luego de que se tienen las fotos en la carpeta del programa, se procesan primero para cambiarlas de imágenes en colores a imágenes en niveles de grises. Teniendo la foto del fondo en gris, se va a comparar con las fotos en gris del objeto moviéndose. El resultado de esta comparación será una imagen de una figura en negro con la forma del objeto en la posición en que se encontraba en ese instante, después de obtenerla, ésta se almacena en la carpeta del programa junto con las demás fotografías. Las imágenes resultantes de la comparación se utilizan para calcular el centro de masa del objeto y saber el punto exacto en que se encontraba. Una vez que se tiene el centroide en los ejes horizontal y vertical se imprimen en un archivo, en el cual se encuentran las demás posiciones determinadas y el instante en el cual el objeto se encontraba en esta posición. Por último se implementa una interfaz gráfica para el programa, la cual va a brindar al usuario las herramientas para ejecutar el programa y luego poder observar fácilmente los resultados obtenidos. Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 6 CAPÍTULO 2: Desarrollo teórico 2.1 Imágenes digitales 2.1.1 Concepto de imagen digital El concepto de imagen digital esta asociado a una función de dos dimensiones f(x,y), en donde cada coordenada contiene una amplitud, la cual determina el grado de iluminación de la imagen en ese punto, esto tomando como punto de referencia un lugar específico de la imagen. Dado a que esta magnitud la determina la iluminación, es por ello que se da una dependencia de la de la cantidad de luz que incide sobre la escena vista en la imagen, así como de la parte que sea reflejada por los objetos que componen dicha imagen. Estos componentes son llamados iluminación definida como i(x,y) y reflexión definida como r(x,y) respectivamente; con lo que si se multiplican ambas cantidades en una coordenada específica, se obtiene como resultado la amplitud de la función f(x,y), teniendo entonces: f ( x, y) = i ( x, y )r ( x, y) (1) teniendo como intervalos de definición: 0 < i ( x, y ) < ∞ 0 < r ( x, y) < 1 (2) 0 < f ( x, y ) < ∞ (3) por lo que se tiene: La naturaleza de la iluminación viene determinada por la fuente de luz, mientras que la reflexión depende de las características del objeto en escena, dado a esto es que se tiene que ambas cantidades siempre son positivas, pero para la iluminación se tiene un rango infinito, mientras que para la reflexión se tiene limitado por 1. 2.1.2 M uestreo espacial y niveles de gris Las imágenes dependiendo del número de variables puede ser unidimensional o bidimensional, al igual que dependiendo de las dimensiones de la función pueden ser Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 7 escalares, como es el caso de las imágenes en blanco y negro, o vectoriales, como las imágenes en color, que cuentan con tres componentes. Las imágenes tienen un dominio y un rango discretos, dado a que se determinan como señales digitales; donde se tiene una imagen definida por la función f(x,y) y esta se puede digitalizar en la memoria del computador, dando la posición en coordenadas y la magnitud en dicha posición, obteniéndose como resultado una matriz de valores de NxM elementos, donde N determina los espacios en x y M los espacios en y, obteniendo como resultado: f(0,0) ................... f(N - 1,0) . . f ( x, y) = . . f(0, M - 1) ................ f(N - 1, M - 1) (4) esto teniendo como origen la esquina superior izquierda de la imagen. Debido a que las imágenes son originalmente señales analógicas, se debe de darse un muestreo de las dos dimensiones espaciales para convertirlas a señales digitales, por lo que como se muestra en la fórmula anterior lo que se almacena en el computador en cada una de los elementos de la matriz es una cantidad que dependiendo de su amplitud así será el nivel de gris de la imagen es dicha posición, dándose una cuantificación de la señal analógica, de donde proviene el concepto de nivel de gris o intensidad. Cada una de las posiciones que determina cada uno de los elementos de la matriz anterior reciben el nombre de pixeles. Para el caso en que se tienen 256 niveles de gris, la magnitud de cada píxel va a encontrarse dentro del rango de 0 a 255, donde 0 corresponde a negro, o sea, donde no hay iluminación o se absorbe todos los rayos que inciden sobre el objeto y 1 corresponde a blanco, o sea, donde se esta dando una iluminación máxima del objeto. Para el proceso de digitalización de una imagen se debe precisar el tamaño de la imagen, dando valores determinados a N y M, así como los niveles de gris que se le asignen a cada píxel. En la práctica, es común que los niveles vengan determinados por números potencias de 2, donde se tiene entonces que el número de bits requeridos para almacenar una imagen digitalizada es: b = NMg (5) Agosto del 2004 IE-0502 8 Determinación de la posición de un objeto utilizando una cámara Web donde los niveles de gris vienen determinados por 2g . Otro concepto importante que surge en el procesamie nto de imágenes es la resolución, el cual viene asociado al número de muestras y niveles de gris necesarios para tener una buena aproximación de la imagen. Estos conceptos definidos anteriormente se encuentran muy ligados y de ellos depende la calidad de la imagen. Una vez que se tienen definidas las resoluciones, surge el concepto de histograma, el cual es un gráfico muy conocido en la estadística. Para el caso de las imágenes, el histograma va a contener el número de píxeles que tienen el mismo nivel de gris, por lo que este puede entenderse como la probabilidad de que un valor de gris determinado se tenga en la imagen, pero éste tiene el inconveniente de que no aporta las posiciones en las que se están dando estos niveles de gris, sólo el número de veces que se dieron. Ahora bien, es importante que se profundice más en los bits; ya que ellos dan origen a un último elemento presente en la imagen, los planos de bits. Para comprenderse mejor esto, es necesario que se observe cual es la potencia de dos utilizada, ya que si por ejemplo se tiene g=3, cada píxel de la imagen va a contar con 8 bits, dando origen a un byte. Cada plano de bits, es una imagen formada por un determinado bit de cada píxel. La importancia de estos es que revelan muy bien la influencia del ruido en la imagen. 2.1.3 Relaciones entre píxeles: Vecindad y Conectividad Un píxel p con coordenadas (x,y) tiene un total de cuatro vecinos en dos dimensiones, estos en forma vertical y horizontal, como se observa en la siguiente figura: x,y-1 x-1,y x,y x+1,y x,y+1 Figura 2.1 Vecinos en el plano vertical y horizontal de un píxel Este conjunto de píxeles mostrados en la figura 2.1 se denomina vecindad de tipo 4 del píxel p, representada por N4(p). Además se puede considerar la existencia de otros cuatro vecinos asociados a las diagonales, como se ilustra en la siguiente figura: Agosto del 2004 IE-0502 9 Determinación de la posición de un objeto utilizando una cámara Web x-1,y-1 x+1,y-1 x,y x-1,y+1 x+1,y+1 Figura 2.2 Vecinos asociados a las diagonales de un píxel Y estos píxeles que se encuentran en las diagonales del pixel de la posición (x,y) se representa como ND(p) y sumandos a los vecinos que se muestran en la figura 2.1 dan origen a la representación N8(p), donde se tienen 8 vecinos para el píxel en (x,y). Otro concepto importante es el de conectividad, el cual se utiliza para expresar cuando dos píxeles vecinos pertenecen al mismo objeto, esto se determina por algún criterio de especificación, si por ejemplo ambos píxeles poseen el mismo nivel de gris y son vecinos. Para la conectividad se tienen tres tipos: 1. Conectividad-4. Dos píxeles p y q presentan una conectividad-4 si q pertenece a N4(p). 2. Conectividad-8. Dos píxeles p y q presentan una conectividad-8 si q pertenece a N8(p). 3. Conectividad-m. Dos píxeles p y q presenta conectividad mixta si: a) q pertenece a N4(p), o b) q pertenece a Nd(p) y el conjunto N4(p)∩N4(q) es el conjunto vacío. La conectividad mixta es una modificación de la conectividad-8 cuya utilidad es eliminar las conexiones múltiples que en ocasiones aparecen cuando la conectividad-8 es utilizada. La conectividad tipo 8 es utilizada para determinar cuando dos píxeles pertenecen al mismo objeto. 2.1.4 Color El color en una imagen, es un concepto hasta hace poco utilizado para las imágenes, dado a que se tiene un alto costo en cuanto a la memoria necesaria para procesar las imágenes a colores; lo cual a cambiado debido a los avances tecnológicas en la industria de la informática, donde se mejora a un paso acelerado el hardware de las computadoras. Agosto del 2004 IE-0502 10 Determinación de la posición de un objeto utilizando una cámara Web Para el color de una imagen, se deben toma r en cuenta algunas definiciones para comprender mejor los espacios de colores, teniendo entonces las siguientes definiciones: 2 Brillo: sensación que indica si un área está más o menos iluminada. 3 Tono: sensación que indica si un área parece similar al rojo, amarillo, verde o azul o a una proporción de dos de ellos. 4 Coloración: sensación por la que un área tiene un mayor o menor tono. 5 Luminosidad: brillo de una zona respecto a otra blanca en la imagen. 6 Croma: la coloridad de un área respecto al brillo de una blanco de referencia. 7 Saturación: la relación entre la coloridad y el brillo. Un espacio de color es un método por el cual se puede especificar, crear o visualizar cualquier color. Dependiendo del tipo de sensor y aplicación se han desarrollado diversos espacios de colores. Así se tienen espacios de colores que se utilizan para la adquisición, la transmisión de señales y la impresión o los espacios que tratan de imitar la percepción humana. 2.1.5 Espacio RGB El espacio RGB se basa en la combinación de tres señales de iluminancia cromática distinta: el rojo, el verde y el azul (red, green, blue). La manera más sencilla de conseguir un color concreto es determinar la cantidad de color rojo, verde y azul que se necesita para combinar, por lo que se realiza una suma de las componentes: X = R+G + B (6) Esto se puede representar gráficamente como un cubo, donde en la recta que une el valor máximo se hayan los grises, ya que las tres componentes son iguales; como se observa en la siguiente figura: Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 11 Figura 2.3 Espacio RGB Lo importante cuando se tiene una fotografía a color es tomarse en cuenta que para cada píxel en color se tienen en realidad tres, uno para cada componente; la ganancia máxima de cada uno de ellos corresponde a la longitud de onda de los tres colores básicos (rojo, verde y azul). Este espacio es el utilizado para las cámaras, dado a que es el más intuitivo, aunque presenta un inconveniente, ya que en sus tres valores mezcla la información del color (tono y saturación) y la intensidad. 2.1.6 Reconocimiento de objetos El reconocimiento de objetos es la principal herramienta del programa utilizado, ya que por medio de esta técnica es que se va ha determinar en que posición es que se encuentra el ratón dentro del laberinto. La herramienta que se va a utilizar es muy sencilla, los pasos a seguirse son muy sencillos y efectivos si se cuentan con condiciones idóneas. Primero se realiza un reconocimiento de la imagen base, en este caso el laberinto, donde se toma la fotografía sin el objeto que se quiere observar. Esta fotografía se tiene a colores y aplicando los valores Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 12 para transformar la imagen en niveles de grises, procedimiento que se repite con la imagen que se tome con el objeto dentro de la imagen base. Entonces finalmente se hace una comparación de las imágenes realizando una resta píxel por píxel, donde si no se da una diferencia en las condiciones en que se tomó la foto base y la foto con el objeto, entonces sólo se va a dar una diferencia en los píxeles donde se encuentra el objeto, donde se examina el resultado y se toma un valor límite, previniendo que se de también la presencia de ruido. De lo explicado anteriormente, es que se evidencia claramente como los cambios en la iluminación van a afectar los resultados obtenidos, así como si se da un movimiento de la cámara, ya que se va a tener una diferencia en cada píxel, al darse un desplazamiento de las magnitudes de cada posición. Si se tiene la precaución de no tener ninguna de las dos variaciones anteriores, es muy probable que los resultados del programa van a ser muy buenos. Seguidamente se va a explicar como se encuentra el punto exacto en que se encontró el objeto, esto se hace encontrando el centroide del objeto, mediante los principios físicos, aplicados a la imagen. 2.1.7 Determinación del centroide del objeto determinado Para la determinación del centroide del objeto encontrado, se utilizan las fórmulas: Qy = X ∑ A = ∑ xA (7) Qx = Y ∑ A = ∑ yA Teniendo estas fórmulas en cuenta, se realiza un barrido de los píxeles determinados donde se encuentra el objeto y se realiza una sumatoria de todos los píxeles que conforman al objeto encontrado, tomando esto como el área A del objeto. El punto donde se encuentra el centroide en las fórmulas se denomina como x y y en los ejes, por lo que se debe de realizar una sumatoria de las distancias de cada píxel del objeto con referencia a la esquina superior izquierda que es el punto (0,0), entonces aplicando las fórmulas: Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web x =∑ 13 Qy A Q y=∑ x A (8) en donde se tiene que el centroide del objeto encontrado es ( x , y ). 2.2 Preprocesamiento de imágenes digitales 2.2.1 Definición El preprocesamiento de imágenes comprende aquellos algorit mos cuya finalidad es conseguir una mejora en la apariencia de la imagen original. Dependiendo de la aplicación que se le vaya a dar a la imagen, se hace un aumento en las características que se desean resaltar de la imagen a procesar o eliminar lo que dificulta que la imagen resultante sea como se espera. Es importante tomar en cuenta que para el preprocesamiento de imágenes, el objetivo de esta etapa es hacer de la imagen más clara para el computador, por lo cual no siempre se tiene va a tener un resultado que sea visible para el usuario, ya que si se desea realizar una comparación entre dos imágenes, lo importante es eliminar lo más que se puede las variaciones que se tengan en cuanto a la iluminación principalmente, por lo que se hace necesario aplicar filtros para evitar en la mayoría de lo posible este inconveniente. 2.2.2 Eliminación de Ruido Todas las imágenes poseen ruido, este ruido se manifiesta en la imagen como píxeles aislados que toman un valor distinto al de sus vecinos. Existen varios tipos de filtros que se mencionan a continuación y se basan en esta característica. El ruido se puede clasificar en cuatro tipos: • Gausiano : Produce pequeñas variaciones en la imagen. Es debido, por ejemplo, a las diferentes ganancias en el sensor, ruido en los digitadores, perturbaciones en la transmisión, etc. En los filtros de este tipo se tiene que el valor final del píxel sería Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 14 el ideal más una cantidad correspondiente al error, que puede describirse como una variable gausiana. • Impulsional: El valor que toma el píxel no tiene relación con el valor ideal sino con el valor del ruido que toma valores altos o bajos. Se caracteriza entonces porque el píxel toma un valor máximo, causado por una saturación del sensor, o mínimo, si se ha perdido su señal. También puede encontrarse si se trabaja con objetos a altas temperaturas, ya que las cámaras tienen una ganancia en el infrarrojo de la que no dispone el ojo humano. Por ello las partes muy calientes de un objeto pueden llegar a saturar el píxel. • Frecuenc ial: La imagen obtenida es la suma entre la imagen ideal y otra señal, la interferencia, caracterizada por ser una senoide de frecuencia determinada. • Multiplicativo : La imagen obtenida es fruto de la multiplicación de dos señales, donde la iluminación no es constante, de modo que se dan zonas más oscuras que otras. 2.2.3 Filtros pasobajos lineales espaciales Al ser el ruido variaciones sobre los niveles de gris, estos entonces tienen altas frecuencias, por ello es que se aplican filtros pasobajos para la eliminación del ruido que se encuentra en su mayoría en las altas frecuencias. En el presente proyecto, ya que lo que más afecta al programa son los cambios de iluminación, se va a eliminar las altas frecuencias tomando en cuenta rangos de variación, dependiendo de la magnitud que se tenga en el píxel examinado, aplicando una máscara que modifica los píxeles vecinos horizontales y verticales, por lo que se tiene un filtro con conectividad tipo 4, y lo que se pretende con él es eliminar las variaciones que se den si se da un pico de iluminación, donde cuando se determine un píxel que pase del rango estipulado, este va a ser eliminado suavemente, modificando sus vecinos más suavemente, para no ocasionar cambios bruscos de iluminación en la imagen preprocesada. Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 15 En la figura 2.4 se observa la máscara aplicada para cada píxel en que se de un alto valor, teniendo en cuenta que la imagen tiene valores en el rango [0,1], por lo que se pretende disminuir los píxeles en los cuales se encuentren valores mayores de 0.9 principalmente, y esto se hace paulatinamente, disminuyendo también la magnitud de los píxeles vecinos. (x,y-1)(0.9) (x-1,y)(0.9) (x,y)(0.85) (x+1,y)(0.9) (x,y+1)(0.9) Figura 2.4 Máscara utilizada en el filtro Agosto del 2004 IE-0502 16 Determinación de la posición de un objeto utilizando una cámara Web CAPÍTULO 3: Análisis del programa 3.1 Estructuración del programa 3.1.1 Archivo interfaz.h Este archivo cuenta con las definiciones de clases utilizadas en el programa, en él se implementan también las funciones utilizadas para el procesamiento de las imágenes tomadas, esto se realiza así, para no mezclarlas con las funciones que se utilizan para la construcción de la interfaz gráfica, para mayor comprensión del programa. Los comentarios específicos de cada función se encuentran en el programa, el cual se incluye en los anexos del presente documento. Para el programa se tiene una clase llamada C_matriz, la cual construye una matriz de 320x240, dado a que las fotos tomadas tienen estas dimensiones de píxeles. Esta clase cuenta con dos funciones, la función get(x,y) que se utiliza para obtener los valores almacenados en la matriz y la función set(x,y,elemento) que se utiliza para insertar datos en la matriz, donde elemento es la cantidad que se quiere almacenar. Para estas funciones se crea un puntero que va a almacenar los valores, este se crea en el constructor de la clase y se elimina en el destructor. Una vez que se tiene esta clase, se implementan las funciones para procesar la imagen, para ello se tiene que incluir las herramientas presentes en la librería <magick++>, donde se utiliza una función para obtener las dimensiones de la imagen, esto implementando un objeto de tipo Image. La primera función que se implementa es la utilizada para imprimir en la carpeta la imagen que se envíe a dicha función, luego de ella se encuentra la función iluminancia, la cual recibe la foto a transformar en escala de grises, en esta se utilizan las funciones de la librería <magick++> para dividir cada píxel en sus tres elementos (rojo, verde y azul), teniendo entonces que iluminancia va a unificar estos tres valores en uno sólo, multiplicando cada uno de ellos por un valor estipulado y devolviendo por último la matriz resultante en niveles de grises. Agosto del 2004 IE-0502 17 Determinación de la posición de un objeto utilizando una cámara Web A la matriz que resulta de esta función iluminancia se le aplica un filtro para eliminar los píxeles en los cuales se encuentran picos de iluminación, esto para evitar que los cambios de iluminación puedan afectar en mayor medida los datos del programa. Luego se crea la función que finalmente va a determinar los píxeles en que se encuentra el objeto, en ésta se recibe la imagen de la fotografía base y las fotos del objeto moviéndose, en donde, lo que se hace es restar las imágenes píxel por píxel y a esa diferencia obtenerle el valor absoluto. Luego se toma un valor límite de diferencia para eliminar valores en los que se puede dar diferencia por ruido, dando una mayor precisión en la determinación de la posición del objeto. Por último, se tienen las dos funciones que se utilizan para determinar el centroide del eje x y el eje y, en ellas se aplica la fórmula explicada en el apartado 2.1.6 del capítulo dos, donde básicamente se hace una suma de los píxeles totales del objeto, determinando su área. También se realiza una suma de las distancias que se tienen desde la posición (0,0) hasta el píxel que forma parte del objeto y luego se devuelve la división de ambas cantidades para determinar con ello la posición exacta del centroide. También en este archivo se tienen las definiciones de la clase MyFrame, la cual utiliza las librerias de wxwindows para implementar la ventana del programa y los menus que se utilizan, donde en el archivo interfaz.cpp se va a observar más claramente como se implementa esta clase. 3.1.2 Archivo interfaz.cpp En el archivo interfaz.cpp se tiene la implementación del programa base, donde se escriben las funciones para la interfaz. En el constructor de la función MyFrame, se construye la ventana y el menú de funciones que realiza el programa, además de las funciones que reciben el nombre para cada opción que se tiene en el menú. Es importante tomar en cuenta que la principal función es la llamada Posiciones, esta se utiliza cuando se selecciona la opción Obtener posiciones. En esta se tiene básicamente la utilización de Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 18 todas las funciones para el procesamiento de las imágenes, las cuales se explicaron anteriormente, dado que están en el archivo interfaz.h. Las demás funciones que se tienen es para abrir las fotos que se tomaron una vez ejecutado el programa, para ello se tiene una llamada a un programa, utilizando la función system. Esto se hace así dado que lo que se quiere es abrir las fotos recién tomadas, lo cual no sucede si se implementan estas opciones como las demás, ya que se abren las fotos que se tenían en el momento de cargar el programa general, lo cual no es deseado, debido a lo anteriormente explicado. Dado a los ajustes que realiza la cámara cuando se utiliza por primera vez desde que se inicia el sistema operativo, se incluyó una variación del programa mvc que se ejecuta por 2 minutos, para que durante este tiempo la cámara realice todos los ajustes. Para dar el tiempo necesario para evitar que la cámara varíe las intensidades de iluminación durante la ejecución entonces se realizará una función de calibración que llame a la variación de mvc antes mencionada al inicio de este párrafo. Además para evitar algún inconveniente con esto, para capturar la imagen de fondo se van a tomar antes 25 fotos y para empezar a procesar las imágenes con el objeto moviéndose se van a desechar las primeras 25 fotos y se empezará a procesar a partir de la posición número 25 para así tener un programa más robusto. La función principal para correr el programa primero toma la fotografía sin el objeto y una vez obtenida la imagen base, pregunta al usuario cuantos minutos desea tomar fotografías del objeto. Con este dato toma en cuenta dado por minuto debe tomar 110 fotos, con lo que se tiene un pequeño error de ejecución de tiempo de ±0.02s aproximadamente, según las pruebas realizadas; por lo cual se tiene una buena precisión en cuanto al tiempo en que se van a tomar fotografías. Una vez que al programa se le indica el tiempo, toma las fotografías y las archiva en la carpeta del programa para luego entrar a un ciclo que se ejecuta 110 veces por el número de minutos que se pidió. Lo primero que se hace con cada foto es aplicarle el mismo filtro que a la imagen base, luego de mandar la imagen a la función iluminancia para ponerla en escala de grises. Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 19 Una vez que se tiene esto, se compara la imagen recién procesada con la imagen base para determinar los píxeles en donde se encuentra el objeto, para luego determinarle el centroide al objeto en los dos ejes y se almacenan en dos arreglos dinámicos. Además estos datos van a irse almacenando en el archivo Posiciones.txt donde evalúa en que zona esta el objeto y se imprime en el archivo la posición, la zona y el tiempo, ya que se tiene que por posición se va sumando continuamente 0.547s, brindando al usuario los datos principales para determinar la trayectoria que siguió el ratón, en este caso. Después se crea la imagen con los puntos donde se determinó que estaba el objeto, para que el usuario tenga una vista rápida de los datos que se determinaron en el tiempo en que se ejecutó el programa; finalizando con esto la ejecución principal del programa base y tomando en cuenta que una vez terminado este proceso, puede observar las fotografías que da como opción el menú Acciones, presente en la parte superior. El programa en general brinda la mayor cantidad de datos al usuario durante su ejecución, pa ra que éste no sienta dudas. Para ello se agregó una ventana de texto, la cual va diciendo al usuario el paso que se ejecutó y el que debe seguir, además de los tiempos en que se procesó cada imagen, tratando de brindar la mayor claridad posible, como se explica más claramente en el manual de uso que se encuentra en los anexos de éste trabajo. 3.1.3 Programas para abrir las imágenes tomadas Dado a que el programa cuenta con las funciones en la barra de menú para abrir las fotos que se obtuvieron luego de obtener las posiciones del objeto, se implementaron cuatro programas con un archivo .h y otro .cpp para tal objetivo. En los archivos .h se tienen definidas las clases MyFrame y MyCanvas. En lo que es el archivo .cpp la clase MyFrame se implementa para crear la ventana y la barra de menú con las funciones necesarias, aunque para el caso de las ventanas que se abren con la foto, no se necesita ninguna acción; solamente se crea una barra de menú llamada Archivo con la opción para obtener ayuda y otra para cerrar la ventana. Agosto del 2004 IE-0502 20 Determinación de la posición de un objeto utilizando una cámara Web Luego se tiene la clase MyCanvas la cual es utilizada para crear el mapa de bits para la imagen a abrir, donde se crea un puntero de tipo wxImage para tener acceso a la imagen en la clase MyFrame mediante el puntero tipo MyCanvas llamado m_canvas. Esta última clase tiene como única función a OnPaint la cual es la que convierte al mapa de bits en imagen, y en la cual se informa al programa la dirección en la cual se encuentra la foto a abrir y en que coordenadas se quiere colocar el título de la imagen y la imagen a abrir. Estos dos archivos son cortos, dado a que la única función que cumplen es abrir una imagen en especificó, por lo que los cuatro programas para abrir cada una de las fotos deseadas solamente tiene como diferencia el nombre del puntero del mapa de bits creado para la imagen y la dirección en la cual se encuentra la imagen que se quiere abrir. Dichos programas se hicieron para tener mayor manejo de las ventanas que se abren con las imágenes y para que cuando el usuario seleccione la opción en la interfaz principal del programa general para abrir una imagen específica, se muestre la última imagen creada, debido a que el objetivo de estas opciones en la barra de menú es que el usuario pueda observar rápidamente los resultados obtenidos por el programa. 3.1.4 Programas makefile para la compilación de los archivos En general para la compilación de todos los programas que se juntan para cumplir con el objetivo principal de este proyecto, existen tres tipos de makefile, uno para compilar la interface del programa principal, otro para compilar los programas para abrir las fotos y por último el makefile del programa mvc-0.8.8. Los makefile para compilar los programas que constan de interfaz gráfica, se tienen tres archivos más que cuentan con las librerías necesarias para contar con todas las funciones utilizadas por el wxwindows, pero dado a que la interfaz del programa principal utiliza además la librería <magick++> la cual, como se dijo anteriormente, cuenta con las funciones necesarias para procesar las fotos tomadas. Debido a que los makefile tienen tres archivos bases, el archivo makeprog.env, el make.env y el libmake.env los cuales se van llamando por jerarquía para ir nivel por nivel cumpliendo con los pasos de la compilación, para realizar la compilación del programa Agosto del 2004 IE-0502 21 Determinación de la posición de un objeto utilizando una cámara Web principal se necesitó modificar el makefile utilizado para compilar los programas para abrir las fotos resultantes, básicamente lo que se cambió fue las direcciones de llamado de los archivos entre sí, dado a que se necesita agregar la librería magick++ y cambiar las direcciones de llamado de cada uno de root/wxwindows/wxGTK-2.4.2/demos/proyecto_nuevo los archivos para llamar para los la carpeta archivos makeprog.env y make.env para incluir en ellos la librería magick++. En cuanto al makefile del programa mvc, no se cambió nada en él, debido a que no era necesario, ya que éste no usa ninguna librería especial, este makefile tiene una jerarquía de archivos al igual que los otros dos makefile para la interfaz gráfica, pero en este caso se llaman depend.sh y depend.inc en los cuales se encuentran el llamado a las librerías de video4linux y apertura de la carpeta /dev/video0 donde se encuentra la cámara. En sí, los makefile usados tienen una estructura parecida en su archivo makefile, donde se tiene el nombre del archivo .cpp ó .c para crear el ejecutable, y el archivo .h con el mismo nombre del archivo. Lo que cambia entre ellos son los archivos que se llaman dentro del makefile, donde se incluyen las librerías necesarias para la compilación dependiendo del tipo de programa que se tiene y además de otro archivo que es opcional, dado a que se puede escoger crear un archivo o incluirlo en el makefile, en éste archivo o en el makefile se imcluyen las banderas de compilación del archivo, dependiendo de las restricciones que se quieren antes de crear el ejecutable del programa. Agosto del 2004 IE-0502 22 Determinación de la posición de un objeto utilizando una cámara Web 3.2 Resultados de las pruebas realizadas al programa Para las siguientes pruebas se debe de tomar en cuenta que la máquina utilizada contaba con un procesador Intel Pentium IV con 384 MB de memoria RAM, una tarjeta de video Nvidia GeForce II de 32 MB y una cámara web IBM VGA. 3.2.1 Primera prueba En esta prueba se movió el mango de un desatornillador en condiciones de iluminación constantes, pe ro con superficies que reflejan luz, por lo que se nota la presencia de ruido en la posiciones determinadas, como se muestra en la siguiente foto: Figura 3.1 Fotografía de la posición de un objeto En la figura anterior realmente el objeto es el mayor grupo de píxeles negros, pero dada la reflexión de algunas superficies y el poco contraste del objeto utilizado, la determinación de la posición no es exacta, aunque aún con estos grupos de ruido, dado que el mayor grupo se encuentra donde esta el objeto, se tendrá un error pero siempre se dará una noción de la posición del objeto en el momento en que se tomó la foto. Agosto del 2004 IE-0502 23 Determinación de la posición de un objeto utilizando una cámara Web El movimiento seguido por el objeto fue horizontal, para ilustrarlo a continuación se muestran unas de las posiciones resultantes: Figura 3.2 Fotografías de algunas de las posiciones del objeto durante la prueba estas posiciones están en desorden, pero como el movimiento fue constante, se observa sin embargo, la trayectoria seguida. En esta prueba se comprueba claramente el efecto de la reflexión de luz y como afecta los resultados obtenidos, que aunque tengan concordancia con la posición del objeto, introducen un error en cuanto a la posición exacta del objeto, como se mencionó antes, más aún en la prueba realizada, ya que el objeto utilizado brillaba, por lo cual reflejaba luz, lo cual también se observa en los resultados, donde se puede ver como hay un reflejo del objeto junto a él como se muestra en la siguiente foto: Agosto del 2004 IE-0502 24 Determinación de la posición de un objeto utilizando una cámara Web Figura 3.3 Fotografía de una posición del objeto Lo importante aquí, es que se comprobó que la reflexión afecta los resultados, pero para cuando se utilice en el laberinto y con el ratón, al disminuir la reflexión el ruido producido por ésta no afectará los resultados, por lo cual esta no es una razón por la cual la solución que se plantea no funcione. A continuación se muestra la imagen de los centroides encontrados en la prueba: Figura 3.4 Fotografía de los centroides obtenidos durante la prueba Como se observa en la figura, los puntos que ilustran las posiciones determinadas tienen el comportamiento de movimiento horizontal seguido por el objeto, lo cual demuestra el correcto funcionamiento del programa, ahora para tener una idea del error se Agosto del 2004 IE-0502 25 Determinación de la posición de un objeto utilizando una cámara Web puede observar que este es pequeño al comparar los puntos con las fotos del objeto en distintas posiciones, dado a que el número de píxeles de ruido son mucho menores que los del objeto, lo cual desplaza un poco la posición calculada, pero aún así da una buena aproximación de donde se encontraba el objeto en ese momento. 3.2.2 Segunda prueba Como segunda prueba se dirigió la cámara hacia el piso, se puso una alfombra y se utilizó un zapato deportivo de tela como objeto, para evitar que se dé alguna reflexión. Además el zapato no se moverá para que se pueda verificar la correcta determinación del objeto y se pueda observar el resultado en la imagen de los centroides encontrados. Para verificar que el objeto se mantuvo en una sola posición se muestra una imagen de varias de las posiciones obtenidas del objeto: Figura 3.5 Fotografías de algunas de las posiciones del objeto durante la prueba Agosto del 2004 IE-0502 26 Determinación de la posición de un objeto utilizando una cámara Web La figura anterior muestra claramente la forma del zapato en una sola posición, ahora bien, si se analiza la imagen de la posición mostrada más claramente en la imagen que se tiene a continuación: Figura 3.6 Fotografía de una posición tomada durante la prueba se observa ruido en la parte superior, donde esta zona corresponde a la parte del piso que no estaba cubierta por la alfombra. Esto demuestra nuevamente los efectos del reflejo, mas aún si se observa como se da una zona blanca en el objeto, esto se dio debido a que el zapato utilizado tiene en la plantilla de la parte interior una cobertura de tela gr is, lo cual produce un color similar al fondo, cuando se produce la imagen en escala de grises y eso provoca que esa parte no se tome en cuenta como parte del objeto. Lo anterior resalta la importancia que tiene el contraste que debe tener el color del fondo y el del objeto, ya que de no ser así se introducirá un error en las posiciones calculadas al verse disminuido el tamaño del objeto. Para mostrarlo basta con observar la foto del objeto en escala de grises para corroborar lo que se comentó anteriormente: Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 27 Figura 3.7 Fotografía en escala de grises del objeto durante la prueba En la imagen se verifica lo dicho, ya que se observa como en las zonas donde terminó la alfombra se introdujo ruido producto de la reflexión y como en efecto la tela de la plantilla del zapato es de una magnitud de gris muy similar al color de la alfombra, provocando que esto no se tome como parte del objeto. Para verificar la determinación de la posición del objeto se muestra la figura resultante de los centroides: Figura 3.8 Fotografía de los centroides del objeto durante la prueba Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 28 Esta figura que se mostró verifica la exactitud del cálculo del centroide y como ante condiciones que varían poco durante la toma de fotos, el error introducido es menor que el introducido en la prueba #1. Ahora para que se observe numéricamente el error introducido se muestran los resultados dados en el archivo Posiciones.txt tal y como lo imprime el programa: Inicio Ejecucion Programa de Captura: Fri Jul 23 15:11:09 2004 Fin Ejecucion Programa de Captura: Fri Jul 23 15:12:25 2004 La ejecucion del programa duro: 76 segundos LOS TIEMPOS EN QUE SE TOMO CADA POSICION SE ENCUENTRAN EN LA CONSOLA Centroides (x,y) Zona Tiempo(s) Posicion #1 (130,129) 13 0 Posicion #2 (131,125) 13 0.545454 Posicion #3 (130,128) 13 1.09091 Posicion #4 (129,128) 13 1.63636 Posicion #5 (129,130) 13 2.18182 Posicion #6 (129,131) 13 2.72727 Posicion #7 (130,131) 13 3.27272 Posicion #8 (129,131) 13 3.81818 Posicion #9 (130,130) 13 4.36363 Posicion #10 (130,129) 13 4.90909 Posicion #11 (131,130) 13 5.45454 Posicion #12 (130,131) 13 5.99999 Posicion #13 (130,131) 13 6.54545 Posicion #14 (130,131) 13 7.0909 Posicion #15 (130,130) 13 7.63636 Posicion #16 (130,131) 13 8.18181 Posicion #17 (131,128) 13 8.72726 Posicion #18 (132,129) 13 9.27272 Posicion #19 (132,128) 13 9.81817 Posicion #20 (131,128) 13 10.3636 Posicion #21 (131,128) 13 10.9091 Posicion #22 (130,129) 13 11.4545 Posicion #23 (130,130) 13 12 Posicion #24 (131,128) 13 12.5454 Posicion #25 (129,132) 13 13.0909 Posicion #26 (130,131) 13 13.6364 Posicion #27 (129,130) 13 14.1818 Posicion #28 (130,129) 13 14.7273 Posicion #29 (130,127) 13 15.2727 Posicion #30 (131,126) 13 15.8182 Posicion #31 (131,128) 13 16.3636 Posicion #32 (130,129) 13 16.9091 Posicion #33 (130,127) 13 17.4545 Posicion #34 (130,127) 13 18 Posicion #35 (130,129) 13 18.5454 Posicion #36 (130,129) 13 19.0909 Posicion #37 (130,128) 13 19.6363 Posicion #38 (131,127) 13 20.1818 Posicion #39 (131,127) 13 20.7273 Posicion #40 (131,127) 13 21.2727 Posicion #41 (131,126) 13 21.8182 Posicion #42 (131,126) 13 22.3636 Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web Posicion #43 (131,127) Posicion #44 (131,128) Posicion #45 (129,132) Posicion #46 (129,131) Posicion #47 (129,131) Posicion #48 (128,132) Posicion #49 (129,132) Posicion #50 (131,127) Posicion #51 (130,127) Posicion #52 (130,130) Posicion #53 (129,132) Posicion #54 (129,131) Posicion #55 (130,132) Posicion #56 (129,130) Posicion #57 (129,130) Posicion #58 (130,130) Posicion #59 (129,131) Posicion #60 (129,131) Posicion #61 (130,129) Posicion #62 (130,130) Posicion #63 (130,129) Posicion #64 (131,128) Posicion #65 (132,127) Posicion #66 (131,127) Posicion #67 (131,127) Posicion #68 (131,127) Posicion #69 (131,128) Posicion #70 (129,129) Posicion #71 (130,128) Posicion #72 (130,128) Posicion #73 (130,128) Posicion #74 (130,128) Posicion #75 (130,127) Posicion #76 (130,128) Posicion #77 (130,128) Posicion #78 (130,128) Posicion #79 (131,129) Posicion #80 (130,129) Posicion #81 (130,129) Posicion #82 (130,129) Posicion #83 (130,129) Posicion #84 (131,129) Posicion #85 (131,128) Posicion #86 (130,128) Posicion #87 (131,129) Posicion #88 (131,129) Posicion #89 (130,130) Posicion #90 (130,128) Posicion #91 (130,129) Posicion #92 (130,130) Posicion #93 (129,130) Posicion #94 (130,129) Posicion #95 (130,129) Posicion #96 (130,130) Posicion #97 (129,130) Posicion #98 (129,129) Posicion #99 (130,129) 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 29 22.9091 23.4545 24 24.5454 25.0909 25.6363 26.1818 26.7272 27.2727 27.8182 28.3636 28.9091 29.4545 30 30.5454 31.0909 31.6363 32.1818 32.7272 33.2727 33.8181 34.3636 34.909 35.4545 36 36.5454 37.0909 37.6363 38.1818 38.7272 39.2727 39.8181 40.3636 40.909 41.4545 41.9999 42.5454 43.0908 43.6363 44.1817 44.7272 45.2726 45.8181 46.3635 46.909 47.4544 47.9999 48.5453 49.0908 49.6363 50.1817 50.7272 51.2726 51.8181 52.3635 52.909 53.4544 Agosto del 2004 IE-0502 30 Determinación de la posición de un objeto utilizando una cámara Web Posicion #100 (130,128) Posicion #101 (130,129) Posicion #102 (130,129) Posicion #103 (129,130) Posicion #104 (129,130) Posicion #105 (129,131) Posicion #106 (129,131) Posicion #107 (129,130) Posicion #108 (129,130) Posicion #109 (130,131) Posicion #110 (131,129) 13 13 13 13 13 13 13 13 13 13 13 53.9999 54.5453 55.0908 55.6362 56.1817 56.7271 57.2726 57.818 58.3635 58.9089 59.4544 La imagen de los centroides y las posiciones mostradas en el archivo Posiciones.txt indican que la solución planteada consta de precisión para obtener la posición del objeto, donde entre posición y posición la mayor diferencia que se tiene es de 5 en ambos ejes, teniendo como valores máximos 132 y mínimos 128. Esto hace preever que si se hubiera contado con una alfombra que cubriera toda la zona que captura la cámara y si el zapato no hubiera tenido en su plantilla un color similar al de la alfombra, el resultado obtenido posiblemente hubiera sido un conjunto de puntos mucho mas reducido que el obtenido. En la práctica si se lograse eliminar totalmente la reflexión y se utilizara un objeto de un color contrastante, la imagen que se obtendría probablemente contendría un solo punto, confirmando que el objeto no se movió en lo absoluto. 3.2.3 Tercera prueba Para esta prueba se ajustó la alfombra que se utilizó en la prueba #2 de forma que la cámara captara una pequeña sección del piso, evitando que se dé un reflejo por esta razón. Además se utilizó como objeto un disquete negro (para que se dé un contraste con el fondo) en un mismo lugar, tratando de corregir las fuentes de ruido que se tuvieron en la prueba anterior, obteniendo las siguientes fotos del objeto: Agosto del 2004 IE-0502 31 Determinación de la posición de un objeto utilizando una cámara Web Figura 3.9 Fotografía de algunas posiciones del objeto durante la prueba Con estas fotos se observa como efectivamente el disquete no se movió y la forma que tiene éste, aunque se contó con el inconveniente de que el disquete tiene una superficie metálica, la cual introdujo un error, dado que como se observa, esta recortó la forma del disquete. Para ilustrar lo anterior se observa a continuación la foto que capturó la cámara y procesó el programa: Figura 3.10 Fotografía en escala de grises del objeto Agosto del 2004 IE-0502 32 Determinación de la posición de un objeto utilizando una cámara Web con esta imagen se verifica como afectó el reflejo que tiene la parte metálica del disquete, donde claramente se observa como el reflejo del disquete se combina con el color de la alfombra, lo cual origina que cuando se procesa por el programa no se toma en cuenta como parte del objeto. Para el cálculo de los centroides del objeto, la imagen resultante es la siguiente: Figura 3.11 Fotografía de los centroides del objeto durante la prueba En esta imagen se nota un grupo de puntos menor al obtenido en la prueba #2 y con una mayor aproximación en cuanto al punto en el cual verdaderamente se encontraba el disquete, para ello se observa una foto de la posición del objeto y la del fondo cuadriculado para tener una mejor noción de cuan precisa fue la determinación de la posición al calcular el centroide: Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 33 Figura 3.12 Fotografía en escala de grises del fondo dividido en zonas Figura 3.13 Fotografía de una posición del objeto Comparando las posiciones, se nota como aunque se trató de ajustar la alfombra para eliminar el ruido por el reflejo del piso, se introdujo una línea delgada en el borde derecho e inferior. Esto produjo un corrimiento de la posición del disquete hacia abajo y a la derecha, pero con me jores resultados a los obtenidos en la prueba anterior, por lo que se confirma que conforme se van mejorando las condiciones en las que se toman las fotos de las posiciones del objeto, los resultados se van mejorando. Además es importante notar como aunque la resolución de la imagen no es buena, como se observa en la foto de una posición, esto no afecta a la determinación de la posición del objeto, lo único que afectó Agosto del 2004 IE-0502 34 Determinación de la posición de un objeto utilizando una cámara Web para determinar donde se encontró el disquete fueron los reflejos producidos por el piso y por las partes metálicas que tiene el disquete. 3.2.4 Tiempos de ejecución del programa A continuación se va a realizar un análisis de tiempos obtenidos del programa ejecutándose, para ello se obtuvieron posiciones por varios minutos, obteniendo los resultados vistos en la siguiente tabla: Tabla 2.1 Tiempos de ejecución del programa Tiempo Tiempo Error especificado ejecución (s) (s) (s) 600 616 16 480 473 7 360 352 8 540 572 32 60 59 1 240 239 1 300 295 5 180 178 2 420 422 2 600 601 1 Promedios 7,5 Tiempo por foto especificado(s) 0,545454545 0,545454545 0,545454545 0,545454545 0,545454545 0,545454545 0,545454545 0,545454545 0,545454545 0,545454545 Tiempo por foto en Ejecución(s) 0,56 0,5375 0,53333333 0,57777778 0,53636364 0,54318182 0,53636364 0,53939394 0,54805195 0,54636364 Error Tiempo Tiempo Número (s) procesando procesando Fotos imágenes(s) una foto(s) 0,0145 1209 1,0990909 1100 0,008 665 0,7556818 880 0,0121 559 0,8469697 660 0,0323 1208 1,220202 990 0,0091 131 1,1909091 110 0,0023 586 1,3318182 440 0,0091 648 1,1781818 550 0,0061 251 0,7606061 330 0,0026 651 0,8454545 770 0,0009 1227 1,1154545 1100 0.545454545 0,54583297 0,0097 1,0344369 En la tabla 2.1 se observa claramente como en el programa se tiene una muy buena aproximación del tiempo que se tarda en tomar cada foto, donde se estimó un tiempo de 0.5454s por foto y en la práctica en promedio se tiene un tiempo de 0.5458s, teniendo como diferencia 0.0004s, además de un error promedio de 0.0097s; teniendo como error máximo 0.0323s, con lo que a los tiempos que se tienen para la toma de fotografías es muy constante y confiable. Es importante observar que el error que se tiene para la toma de cada fotografía se va aumentando dado al alto número de fotos que se toman en poco tiempo, pero éste no llega a ser muy elevado según las pruebas realizadas ya que tiene como máximo un valor de 32s, pero como valor promedio se dieron 7.5s, esto claro esta Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 35 que se tiene un mayor error cuando el tiempo de ejecución es mayor, por lo que entre más número de fotos se tomen se va a tender a tener un mayor error en los tiempos, pero ello no afecta en gran medida a los resultados. Una situación importante que se observó cuando se estaban tomando los datos de la tabla 2.1 es que cuando la computadora se forzó ejecutando el programa por más de 60 minutos consecutivos, los tiempos tendían a aumentar, por lo que una observación importante para tomar en consideración es tener el cuidado de no ejecutar el programa por más de 40 minutos, el cual es el tiempo aproximado de duración para procesar las posiciones que se obtuvieron por 10 minutos consecutivos; teniendo entonces como recomendación no obtener las posiciones por más de 10 minutos y luego volver a ejecutar el programa, se darían mejores resultados si se le diera unos minutos a la computadora para luego volver a ejecutar los programas, ya que cuando entre prueba y prueba se hizo esto, los tiempos se mantuvieron estables. Dado a lo apuntado anteriormente, otros datos de tiempos que se tabularon en las pruebas realizadas, fue el tiempo total que dura el programa procesando las fotografías tomadas, donde se tiene en promedio que por foto se dan 1.034s con un tiempo máximo de 1.3318s, apuntando para este dato que como se dijo en el párrafo anterior, los resultados cuando se tenía la computadora trabajando por más de 40 minutos consecutivos sin dar ningún intervalo entre ejecución y ejecución, entonces los tiempos tendieron a subir, aunque teniendo en consideración la cantidad de fotografías que se están procesando para obtener los datos que se imprimen en el archivo Posiciones.txt y la fotografía Centroides.jpg donde se ilustran todas las posiciones obtenidas y los datos de importancia para el usuario. En general, la conclusión importante de la tabla 2.1 es que los datos que se obtienen del programa una vez que se procesan las fotografías del objeto moviéndose son muy buenos en cuanto a precisión y exactitud, teniendo errores pequeños tomando en cuenta que el número de fotos tomadas es alto. Otra ventaja que tiene el programa es la impresión de cada una de las posiciones del objeto con su respectivo número, ya que así se pueden revisar rápidamente para saber cuales son los datos que verdaderamente valen en los datos Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 36 del archivo Posiciones.txt, para así poder tener una mayor confianza en los datos que se tabulen una vez finalizada la obtención de las posiciones. Tomando en cuenta lo anterior, se tienen en total en la carpeta donde se ejecutó el programa un total de 2200 fotos como máximo, pero esto no es de gran preocupación en cuanto a espacio de memoria, ya que estas se van regenerando con cada corrida del programa y además según las pruebas realizadas el espacio en memoria utilizado por la carpeta con el mayor número de fotos fue de 32 a 50 MB, lo cual no es una gran cantidad de memoria, por lo cual esta no sería una dificultad para el correcto funcionamiento del computador. Una situación importante es tomar en cuenta el computador donde se procesaron las fotos utilizadas, esto va a ser un aspecto muy importante a tomar en cuenta, ya que el equipo utilizado puede variar sustancialmente los datos que se obtuvieron anteriormente, para ello es que en el apéndice A se agrega un apartado donde se especifican las características del computador donde se hicieron las pruebas, ya que esto va a tener una relevancia primordial en la eficiencia del programa. Agosto del 2004 IE-0502 37 Determinación de la posición de un objeto utilizando una cámara Web CAPÍTULO 4: Conclusiones y recomendaciones 4.1 Conclusiones Una vez finalizado el proyecto, se concluye primeramente que según los resultados de las pruebas realizadas se cumplió con el objetivo principal, dado que se brinda un programa que determina las posiciones en las cuales se encuentra un ratón durante el tiempo en el cual se toman las fotos de él moviéndose dentro de un laberinto. La cámara Web se utilizó exitosamente en la plataforma de Linux instalada en la máquina que se usó para probar el programa, donde se instalaron correctamente los módulos y librerías necesarias para que se puedan tomar las fotos del ratón moviéndose en el laberinto con una frecuencia alta de dos fotografías por segundo. El código del programa fue escrito en el lenguaje C++, aprovechándose las funciones con las cuales cuentan sus librerías, lográndose que el código del programa sea más simple y eficiente. La estructura del programa se pudo realizar de una forma estructurada, donde se tiene un archivo para las definiciones y otro en el cual se implementan las funciones. El programa mvc versión 0.8.8 se utilizó óptimamente para poder tomar las fotografías del objeto con una frecuencia aproximada de 2 fotos por segundo, con lo cual se pudo tener un mayor número de fotos del ratón y establecer claramente la trayecroria que el animal siguió. Se logró hacer que el programa calcule el centro de masa del objeto encontrado, para con ello determinarse con exactitud la posición y luego la zona en la cual se encuentra el objeto. Se construyó una imagen de la foto del fondo mostrando las divisiones entre la zonas, con lo cual se consigue brindar al usuario la posibilidad de aj ustar el laberinto al ancho de la imagen del fondo que se captura en la cámara y corroborar la validez de los resultados obtenidos. Para la creación del archivo con los resultados, se concluye que en él se pudo imprimir la hora de inicio, final y el tiempo en el cual se tomaron las fotografías del ratón Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web moviéndose. 38 También se consigue escribir el número de posición y la posición del centroide de éste en el momento que se tomó la foto, el cual se imprime al lado de la zona en la cual se encuentra la posición determinada. Para la interfaz gráfica del programa se diseñó una ventana con una barra de menú que cuenta con las opciones Archivo y Acciones, además de un cuadro de texto en el centro donde se indica al usuario los pasos a seguir y los cuidados que debe tener cuando ejecuta el programa, con lo cual se logra brindar al usuario herramientas visuales fáciles para utilizar el programa. Con los análisis de las pruebas realizadas al programa, se concluye que los resultados de las fotos fueron muy buenos, y se mejoran conforme van eliminándose las superficies que producen reflejo y teniendo un objeto de un color que contraste con el fondo. Agosto del 2004 IE-0502 4.2 Determinación de la posición de un objeto utilizando una cámara Web 39 Recomendaciones Debido a que las primeras veces que se corrió el programa se concluyó que la cámara puede tener un tiempo de calibración de la iluminación cuando se utiliza por primera vez luego de arrancar el sistema operativo, se recomienda utilizar una cámara que no realice ningún ajuste de iluminación para evitarse errores en los resultados. Una recomendación importante que se da luego de finalizar el proyecto utilizando la metodología escogida para la captura de fotos, la cual tiene una dependencia de las condiciones del medio en que se toman las fotografías, es la forma en que se procesaron éstas. Si se quiere realizar un programa más robusto, es preferible realizar una comparación entre fotos consecutivas, aunque con esto se va a tener la complicación de que se deberá de generar la forma del objeto, es probable que se eliminen los problemas tenidos con la iluminación y los reflejos. Agosto del 2004 IE-0502 40 Determinación de la posición de un objeto utilizando una cámara Web BIBLIOGRAFÍA Libros: 1. Eckel, Bruce. “Thinking in C++”, segunda edición, Prentice Hall, 2000. 2. Beer y Johnston, Ferdinand y Russell. “Estática”, sexta edición, McGraw Hill, 1997 Páginas web: 3. “Programa mvc”, www.turbolinux.com.cn/~merlin/mvc. 4. “Programa tcap”, http://toonarchive.com/tcap. 5. “V4l resources”, http://student.wsp.krakow.pl/~mummin/pliki/dolinuxa/video%20Linux%20Linux% 20resources.html. 6. “Modelo de programación con v4l”, http://oasis.dit.upm.es/~jantonio/documentos/revistas/video4linux/v4l_2.html 7. “Crear archivos en C”, www.linuxchile.cl/foros.php?op=ver&id=530 8. “Manual de Linux”, http://es.ttdp.org//Manuales-LuCAS/doc-manual- linux-procfs 9. “Install Manual”, http://www.debian.org/releases/stable/installmanual Agosto del 2004 IE-0502 41 Determinación de la posición de un objeto utilizando una cámara Web ANEXOS Anexo 1.Manual de instalación del programa Paquetes del kernel En este punto, se considera que ya se tiene correctamente instalado en la máquina donde se va a ejecutar el programa, el sistema operativo Linux de Debian, para esto se tienen muchas maneras de hacerlo, se puede realizar su instalación directamente de la red o con los discos que se encuentra en la página principal de Debian. La ventaja de instalar este sistema es que se cuenta con mucha ayuda en la red, teniendo como manual principal el que se encuentra en la página www.debian.org, donde se explica paso a paso el proceso de instalación. Los paquetes a incluir durante la recompilación del kernel son en los recursos que se tienen para video, por ello se debe agregar video4linux para poder incluir en el sistema linux de Debian las herramientas que se encuentran en las librerías de v4l. Además del paquete de video for linux se debe incluir el módulo para la instalación de la cámara, para la cámara utilizada basta con un módulo que se encuentra en el kernel, de no ser así se hace necesario buscar si la cámara que se tiene es soportada en la red para linux, para que una vez que se encontró el paquete de instalación se sigan las instrucciones para instalarlo. Una vez que se tenga compilado el kernel utilizado es importante incluir los módulos utilizando la instrucción modconfig o incluyendo el módulo en el archivo /etc/modules, en las computadores utilizadas para implementar y probar el programa se instaló el paquete de video4linux y se agregó el de la cámara web como módulo, teniendo este último el nombre ibmcam, por lo cual para probar si se instaló correctamente ambos paquetes primero para asegurar que se tiene bien el módulo de la cámara se puede dar la instrucción modprobe ibmcam y una vez que se ejecute esta instrucción sin problemas se puede instalar el programa xawtv utilizando la instrucción apt-get install xawtv y observar si este programa se ejecuta correctamente, entonces se puede asegurar que están bien instalados ambos paquetes dado a que este paquete utiliza ambos. Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 42 Instalación de librerias y programas Lo primero que se debe de instalar para correr el programa son las librerías para C++ y las del compilador g++. Estas librerías son las necesarias para poder compilar el programa, en caso de que una vez que se tengan instaladas las librerías siguientes, los archivos ejecutables incluidos no corran y den algún error. Las siguientes librerías son las que cuentan con las funcio nes necesarias para llevar a cabo los procedimientos de tratamientos de imágenes, las librerías a incluir son imagemagick y libmagick++6-dev, estas se instalan con la instrucción apt-get install <nombre del paquete> (esta función se utiliza también para instalar las anteriores), una vez que se tienen estas librerias instaladas se pueden utilizar las funciones para el procesamiento de las fotos tomadas. Luego de tener instaladas las librerías necesarias para correr el programa principal y compilarlo, se hace necesario instalar el paquete wxGTK-2.4.2 el cual sirve para instalar las librerías de wxwindows para utilizar las funciones necesarias para construir la interfaz gráfica del programa. Estas librerías son una herramienta sencilla para construir una interfaz gráfica, ya que utilizan internamente las librerias de gtk, por lo que para poder instalar correctamente wxGTK se debe instalar antes el paquete libgtk-dev. El paquete wxGTK-2.4.2 es gratuito y se puede bajar de la red fácilmente, aunque estos paquetes normalmente vienen comprimidos por lo que se hace necesario descomprimirlos en una carpeta antes de instalarlos, a esta carpeta se le llamará wxwindows y luego se abrirá el archivo de texto que trae con las instrucciones para su instalación. Es importante tomar en cuenta que los paquetes se van actualizando, por lo cual dependiendo de la versión de Linux que se tiene, los nombres de los paquetes pueden variar en comparación con los nombrados aquí, por lo cual si se tienen problemas al instalar una de estas librerías con la instrucción apt-get install se debe de observar la lista de paquetes con los que se cuenta, para ello se utiliza la instrucción apt-cache search <nombre del paquete> y poniendo los nombres de los paquetes anteriores, se despliegan los paquetes Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 43 que tengan un nombre similar al que se escribió, por lo que así se sabe con exactitud cual es el nombre del paquete en la versión de Linux que se tiene instalada en la máquina. Instalación del programa Para instalar correctamente el programa primero se debe de verificar que se cuente con los archivos necesarios. Para la instalación del programa primero se debe de tener las carpetas con los programas para abrir las ventanas con las fotos tomadas por el programa, estas carpetas tienen el nombre de FotoFondo, FotoFolder, FotoObjeto y FotoPosición, en cada una de las carpetas se tiene un archivo ejecutable, un archivo .h, un archivo.cpp y un makefile. Estas carpetas se deben guardar en la carpeta creada /root/wxwindows/wxGTK2.4.2/demos para que se compilen sin problema; una vez que se tengan las carpetas aquí, se debe abrir una consola para ejecutar la instrucción make en la carpeta para compilar el programa y crear el archivo ejecutable. También se cuenta con el programa utilizado para capturar las imágenes, dado a que este se modificó para tomar el fondo y para tomar las fotos para determinar las posiciones, entonces se tiene las carpeta mvc que contiene las carpetas 1_Foto y Pidiendo_numero. Para compilar el programa se debe estar en el archivo correspondiente y ejecutar la instrucción make, esto se realiza para ambas carpetas, luego al ejecutable llamado mvc que se crea en la carpeta 1_Foto se debe de cambiar su nombre por mvc1 y el ejecutable creado en la carpeta Pidiendo_numero se deja con el nombre mvc. Una vez que ya se compilaron estos programas, se tienen en cada una de esas carpetas un ejecutable y se sigue por último con el programa principal, el cual se va ha encuentrar en la carpeta proyecto_nuevo, esta se debe crear en la direcció n /root/wxwindows/wxGTK-2.4.2/demos/ donde se encuentran las otras carpetas. Luego se ejecuta make en una consola estando en esta carpeta y con ello ya se tiene el archivo ejecutable llamado interfaz2 del programa principal el cual dentro de su ejecución va a llamar a los demás ejecutables creados en las otras carpetas. Dado a esto es que se necesita copiar los ejecutables de las carpetas anteriores en las cuales se compilaron los demás Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 44 programas como se explicó antes y teniendo el cuidado como se dijo anteriormente de cambiar el nombre del ejecutable de la librería ../mvc/1_Foto por mvc1, para luego copiarlo a la carpeta proyecto_nuevo donde se encuentra el ejecutable. Una vez que se tienen todos los archivos ejecutables, los cuales se pueden diferenciar de los demás dado que son los únicos que no tienen tipo como los demás (solamente se llaman por su nombre), por lo cual entonces en sí dentro de la carpeta principal se deben tener los archivo ejecutables fondo, centroides, objeto, posición, interfaz2, mvc1 y mvc. Si se cumple con lo anterior, es probable que si se tiene correctamente instalada la cámara y el paquete video4linux, el programa se ejecute con éxito, esto si se tienen los cuidados mencionados en el manual de uso del programa. Configuración del tiempo de captura de una foto Este es un dato necesario para determinar los tiempos en que se toma cada foto durante el tiempo en que se capturan fotos. Para determinarlo se debe ejecutar el programa mvc, dando la instrucción ./mvc <número de fotos a tomar> y dado a que se le puede dar el número de fotos a tomar y que el programa imprime en consola el tiempo y el número de la foto tomada, entonces se puede determinar fácilmente las fotos tomadas por un minuto, y teniendo este número se puede determinar el tiempo que dura tomando una foto, donde para la máquina utilizada para las pruebas fue de 0.5454s y si se utiliza una máquina con una velocidad de procesamiento parecido, es probable que éste varíe muy poco. Entre mayores pruebas se realicen para determinar este tiempo mayor será la precisión de los tiempos de ejecución del programa y los tiempos en que se tomó cada foto. Finalmente cuando ya se tiene el tiempo que dura tomando una foto y el número de fotos por minuto que toma, se deben cambiar lo s valores en el archivo interfaz2.cpp, esto se puede realizar abriendo un programa para escribir códigos, donde se recomienda el anjuta, ya que fue el utilizado para implementar el programa. Después de abierto en el anjuta el archivo interfaz2.cpp se debe buscar al inicio las variables tiempo_captura, fotos_minuto y Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 45 modificar los valores de estas, para asegurarse que obtener resultados correctos según la máquina que se está utilizando. Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 46 Anexo 2. Manual de uso de programa Partes de la ventana del programa Para abrir el programa se debe acceder a la carpeta root/wxwindows/wxGTK2.4.2/demos/proyecto_nuevo (desde una consola o terminal) donde se encuentra el archivo interfaz2, una vez que se está en esta carpeta ejecuta la instrucción ./interfaz2 y con ello se abre la ventana para ejecutar el programa de detección del movimiento del ratón en el laberinto. A continuación se muestra la ventana del programa: Una vez que se abrió la ventana se tiene en ella un cuadro de texto central en el cual se brinda una ayuda para saber cual es el paso a seguir y las sugerencias según lo que se esté ejecutando. Además se cuenta con una barra de menú que cuenta con las opciones Archivo y Acciones, donde en la opción archivo se tiene la orden Salir para cerrar el programa y la orden Créditos para mostrar una ventana con los créditos del programa. En la otra opción de la barra se tiene Acciones en las cuales se tienen las opciones Obtener Posiciones, Abrir foto del fondo, Abrir foto dl último objeto, Abrir foto de la primera posición, Abrir foto de los posiciones y Calibración de la cámara. Estas son las opciones Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 47 que se tienen en la ventana del programa la cual muestra el título Detección de objetos debido a la finalidad del programa. Esto se observa en la siguiente imagen que muestra las opciones en el menú Acciones: Ejecución del programa La ejecución del programa para obtener las posiciones del ratón en el laberinto es muy sencilla, dado a que el programa siempre va mostrando cual es el próximo paso a seguir y abre una serie de ventanas con advertencias y sugerencias para evitar errores en la ejecución. Además es difícil perderse en los menús ya que solamente se tienen dos y el menú para ejecutar el programa es Acciones. Lo primero a tomar en cuenta es saber si se está ejecutando por primera vez el programa luego de arrancado el sistema operativo, ya que se comprobó con las pruebas realizadas que la cámara realiza un ajuste del lente respecto a la iluminación del lugar en que se encuentra y esto produce lecturas incorrectas del programa. Aquí es importante mencionar que aunque no se demostró en ninguna prueba utilizada, el cambio de posición de la cámara puede provocar que se de un ajuste del lente, por lo que si se mueve la cámara Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 48 a un lugar con una iluminación diferente. Para evitar errores por estos motivos se tiene la opción Calibración de la cámara, la cual activa la cámara por aproximadamente minuto y medio para que ésta realice el ajuste del sensor y asegurarse que no lo haga durante la ejecución del programa. Si ya se ha ejecutado el programa no es necesaria ordenar calibrar la cámara, por lo que se puede proceder a capturar las posiciones del ratón. Para ello se cuenta con la opción Obtener posiciones, luego de que se ejecutó esta acció n inmediatamente se empieza a capturar la foto del fondo, pero para evitar errores por ajustes de la cámara, la foto del fondo se captura luego de tomar un número de fotos antes, lo cual toma alrededor de 20 segundos, por lo que durante este tiempo el laberinto no puede ser movido ni tener dentro de él al ratón todavía. La fotografía del fondo se toma y luego el programa pide el número de minutos a determinar las posiciones, en esta opción se cuenta con un intervalo de 1 a 10 minutos según las especificaciones dadas. Luego de escoger el número de minutos, el programa le pide un nivel de resolución para la determinación de la posición del objeto, este varía entre 0 y 10, donde entre mayor sea este número mayor será la restricción que se le dé al programa para determinar la posición del ratón. El valor estándar según las pruebas realizadas es 3 y 4 normalmente, pero si luego de observar las fotos de los resultados se tiene ruido se recomienda aumentar éste número para eliminarlo. Después de escoger el valor para la resolución, se empieza a tomar las fotos, pero es importante tomar en cuenta que para prever nuevamente que los ajustes que realice la cámara introduzcan errores se toman 25 fotos que no se van a tomar en cuenta, en lo cual dura aproximadamente 15 segundos, por lo que es aconsejable introducir el ratón antes oprimir el botón OK en una ventana que le comunica al usuario que se van a iniciar a tomar las fotos, aunque se debe de tomar en cuenta que los movimientos que éste realice en los primeros 15 segundos no se van a tomar en cuenta en los resultados. El programa va a durar un minuto según la exactitud que se tenga en el número de fotos que se determinó que toma la cámara según la máquina en la cual se está ejecutando la captura. Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 49 El programa sugiere que se observe el proceso de tomar las fotos en la consola donde se abrió el programa con la instrucción ./interfaz2, ya que allí se van a desplazar el número de fotos que se han tomado y los tiempos en que se tomaron, con una exactitud dada en segundos. Luego se da una ventana que comunica que las fotos ya fueron tomadas y que si se abrió la ventana de consola se minimice para abrir la ventana del programa principal para observar los resultados obtenidos. Durante el tiempo en que se están procesando las fotos tomadas se pueden observar los resultados en la carpeta del programa, donde se imprimen las fotos del ratón en la posición donde se encontraba. Cuando se terminan de procesar las fotos, lo cual lleva aproximadamente el doble del tiempo que se duró tomando fotos, se imprime en el cuadro de texto la hora a la cual se procesó cada posición y se indica que ya se crearon las fotos, por lo que estas se pueden observar escogiendo cual de ellas abrir según la opción que se de en el menú Acciones. Es importante también tomar en cuenta que el programa imprime una foto para cada posición, lo cual permite al usuario observar rápidamente en la carpeta del programa cuales posiciones se determinaron con la presencia de ruido y cuales no, para tener una absoluta confianza en los resultados obtenidos. Otra ventaja del programa es que crea un archivo con el tiempo que duró tomando fotos, los tiempos en que tomó la foto para cada posición y el punto en el cual se encontraba el ratón en ese momento, además de la zona en la cual se encontraba, teniendo una división de 25 zonas del laberinto, las cuales tienen la siguiente estructura 0 6 11 16 21 1 7 12 17 22 2 8 13 18 23 3 9 14 19 24 4 10 15 20 25 Para observar claramente como se dividió el laberinto, cuando se crea la foto del fondo se incluyen las divisiones de las zonas, para comparar resultados con los puntos mostrados en la foto de las posiciones. Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 50 Este programa se puede ejecutar cuantas veces consecutivas se quiera, no hay restricción para ello, por lo que se pueden realizar varias pruebas continuas y aunque las pruebas realizadas dan una confianza en los resultados que se obtienen, debido a la sensibilidad que tiene por la iluminación y los problemas que se dan si se movió la cámara durante la ejecución, es que se debe de comprobar los resultados observando las fotos resultantes de las posiciones, para poder obtener las posiciones con un error mínimo, esto tomando en cuenta que se cumpla con todas las recomendaciones dadas en las conclusiones de este trabajo. Agosto del 2004 IE-0502 51 Determinación de la posición de un objeto utilizando una cámara Web Anexo 3. Recomendaciones de utilización Dado el procedimiento utilizado para determinar los puntos en los que se mueve el objeto, se dan a continuación una serie de recomendaciones, donde lo primordial es que deben darse igualdad de condiciones del entorno durante el tiempo en que se están tomando las fotos del objeto moviéndose. Las principales condiciones a tomar en cuenta para la correcta ejecución del programa son la iluminación y la posición de la cámara, para poder tener buenos resultados se debe de tener un fondo donde se tenga una mínima o nula reflexión, para no tener picos de iluminación en la cámara, por ello se recomienda que el color de éste sea uno que absorba luz y contraste con el color del objeto, por ejemplo para el caso del ratón que es blanco, sería bueno tener un laberinto azul pintado o forrado con un material que no refleje, como se especificó anteriormente. Otra situación es la posición de la cámara y el fondo que esta capturando la cámara, donde es de vital importancia que no se dé ningún tipo de movimiento en la imagen que se este tomando, de darse un movimiento en la cámara o el fondo todos los resultados se verían afectados, dado a que se daría una diferencia en todos los píxeles de la imagen , lo cual ocasionaría que la determinación del objeto sería imposible, ya que lo que se pretende es que lo único que varía entre la foto del fondo sin el objeto y las fotos del objeto moviéndose es tener una igualdad total en el fondo y que la única variación que se tenga sea el objeto, para así obtener únicamente al objeto y no tener ningún tipo de ruido que vaya a afectar los resultados. Una precaución que se debe tener es no tener la cámara recibiendo directamente luz, ya que el lente de la cámara realiza ajustes, con lo que se va introduciendo errores, esto se puede observar en las fotos que imprime el programa de cada posición, donde el resultado si se tienen condiciones ideales sería únicamente la forma del objeto (en este caso del ratón) lo que se debería ver, si esto no fuera así es porque alguna condición se varío, es aquí donde surge la importancia de la calidad de la iluminación que se le dé al fondo que esta capturando la cámara, ya que esta debe ser constante, para no tener variaciones que se vayan luego a tomar en cuenta como diferencia a la hora de obtener los píxeles donde está Agosto del 2004 IE-0502 52 Determinación de la posición de un objeto utilizando una cámara Web el objeto. Aunque para evitar esto se incluyó el filtro anteriormente analizado, este no va a eliminar del todo los picos de iluminación que se den, por ello es de vital importancia que la iluminación se mantenga constante durante la toma de fotografías del objeto moviéndose. Según la cámara que se utilice, puede tenerse un tiempo de calibración de la iluminación cuando se utiliza por primera vez luego de arrancar el sistema operativo, por lo que se recomienda que cuando se arranque el computador utilizado, antes de capturar el movimiento del ratón en el laberinto, se ejecute la función que se agregó en la barra de menú Acciones llamada “Calibrar la cámara” para asegurarse que no se den resultados negativos. Si se tienen en consideración las recomendaciones anteriormente dichas es posible que no haya que tener preocupaciones por los datos obtenidos, ya que la eficacia del programa es muy buena, la única consideración que queda es la del equipo utilizado, donde la computadora debe tener un mínimo de especificaciones para que el programa puede ejecutarse correctamente y con los tiempos que se tienen en la tabla 2.1 para tomar cada foto. Además es posible que el tiempo que dure procesando cada foto aumente si la computadora utilizada tiene menor memoria RAM o un procesador más lento, por lo que la diferencia entre el equipo puede ocasionar que los resultados no sean satisfactorios, lo ideal sería contar con una máquina con especificaciones parecidas a las utilizadas (las especificaciones de la máquina usada se agregan en los anexos del trabajo) para poder tener una absoluta confianza de que el programa corra exitosamente. Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 53 Anexo 4. Especificaciones del equipo utilizado • Procesador Intel Pentium 4 de 1.6 GHz • 384 MB de memoria ram • Tarjeta de video Nvidia GeforceII de 32 MB • Tarjeta madre Intel I-810 con tarjeta de sonido incorporada • CD-Writer LG de 16x-10x-40x • Monitor LG Studioworks 553V • Cámara Web: IBM VGA camera XVP610, 5.0±5%V, 350mA Máximos. FCC ID: KSX-X9902 Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 54 Anexo 5. Código del programa Programa mvc-0.8.8 modificado Archivo mvc.c /* * mvc.c * * Copyright (C) Merlin Ma. 2000-2004. * EMail: [email protected] * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <libgen.h> #include <errno.h> #include <getopt.h> #include <fcntl.h> #include <signal.h> #include <time.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/ioctl.h> #include <sys/mman.h> #include <sys/wait.h> #include <linux/videodev.h> #ifdef HAVE_JPEG #include <jpeglib.h> #endif #ifdef HAVE_PNG #include <png.h> #endif */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 55 #include <libgen.h> #include <errno.h> #include <getopt.h> #include <fcntl.h> #include <signal.h> #include <time.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/ioctl.h> #include <sys/mman.h> #include <sys/wait.h> #include <linux/videodev.h> #ifdef HAVE_JPEG #include <jpeglib.h> #endif #ifdef HAVE_PNG #include <png.h> #endif #include "font.h" #include "config.h" typedef struct myvideo { char *device; int devfd; int width; int height; int depth; int input; int maxinputs; int norm; unsigned int brightness; unsigned int contrast; char *buf; int mmaped; int mbufsize; } MyVID; /* global variable */ static int verbose = DEF_VERBOSE; static int quitflag = 0; static int daemon_flag = 0; static int usr1_flag = 0; static char *logfile = "/dev/null"; /* USER1 signal handler */ void sig_usr1(int signal) { printf("Got SIGUSR1, trigger a capture.\n"); usr1_flag = 1; } void block_sigs(void) { sigset_t masked_signals; sigemptyset(&masked_signals); sigaddset(&masked_signals, SIGUSR1); Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 56 sigaddset(&masked_signals, SIGINT); sigaddset(&masked_signals, SIGTSTP); sigprocmask(SIG_BLOCK, &masked_signals, NULL); } void unblock_sigs(void) { sigset_t masked_signals; sigemptyset(&masked_signals); sigaddset(&masked_signals, SIGUSR1); sigaddset(&masked_signals, SIGINT); sigaddset(&masked_signals, SIGTSTP); sigprocmask(SIG_UNBLOCK, &masked_signals, NULL); } void usage(void) { fprintf(stderr, "mvc version " VERSION " - motion detection video capture program \n\n" "Usage: mvc <options>\n\n" " -B picture brightness value.\n" " -C picture contrast value.\n" " -D run in daemon mode.\n" " -O Base directory for output images. default is current dir.\n" " -o Don't create sub-directories for output.\n" " -t Print t imestamp on image.\n" " -d <device> video device (default:" VIDEO_DEV ").\n" " -e <program> excute a external program while motion detected.\n" " -f {jpeg|png} set output file format. default is jpeg.\n" " -q <quality> jpeg quality setting. \n" " -h print this help.\n" " -i <channel> which input channel to use, default is 1, or 0 if only 1 input.\n" " -m use mono color (grayscale) for capture.\n" " -n {pal|ntsc|secam|auto} video norm to use, default: PAL\n" " -s XxY size of the output image, example: -s 640x480\n" " -a HxV block division number in Horizantal and Vertical. Ex: -a 16x8\n" " -b <diff_block_limit> threshold of hot block number.\n" " -c <diff_color_limit> threshold of block color difference.\n" " -w delay time for each capture(seconds), example: -w 0.5\n" " -l logfile used in daemon mode. default is null.\n" " -v increase verbose level for more details, can multiple applied.\n\n"); } /* init v4l device for image capture */ int v4l_init(MyVID * myvid) { int devfd; int i, ret = 0; int input; struct video_capability vid_caps; struct video_channel vid_chnl; struct video_picture vid_pict; struct video_window vid_win; struct video_mbuf vid_buf; /* Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 57 * open the video4linux device */ int max_try = 5; while ((devfd = open(myvid->device, O_RDWR)) == -1 && --max_try) sleep(1); if (devfd == -1) { fprintf(stderr, "Can't open device %s\n", VIDEO_DEV); ret urn -1; } myvid->devfd = devfd; /* * get capabilities of the device */ if (ioctl(devfd, VIDIOCGCAP, &vid_caps) == -1) { perror("ioctl (VIDIOCGCAP)"); return -2; } myvid->maxinputs = vid_caps.channels; /* print channel names */ if (verbose >= 2) { for (i = 0; i < myvid->maxinputs; i++) { vid_chnl.channel = i; if (ioctl(devfd, VIDIOCGCHAN, &vid_chnl) == -1) { perror("ioctl (VIDIOCGCHAN)"); } printf("The name of input channel #%d is \"%s\".\n", i, vid_chnl.name); } } input = myvid->input; if (input == -1) { // if no input channel specified, use first composite. input = (myvid->maxinputs == 1) ? 0 : 1; // tv often use channel 0, skip it. } if (myvid->input > myvid->maxinputs - 1) { input = myvid->maxinputs - 1; printf("Warning: Input channel number over range. use %d instead.\n", input); } if (verbose >= 2) { printf("Total %d input channel(s). Using channel #%d.\n", myvid->maxinputs, input); printf("Supported resolution range: %dx%d => %dx%d\n\n", vid_caps.minwidth, vid_caps.minheight, vid_caps.maxwidth, vid_caps.maxheight); } /* * get default video properties and then set new value */ if (ioctl(devfd, VIDIOCGPICT, &vid_pict) == -1) { perror("ioctl (VIDIOCGPICT)"); ret = 1; } vid_pict.brightness = myvid->brightness; Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 58 vid_pict.contrast = myvid->contrast; if (myvid->depth == 1) vid_pict.palette = VIDEO_PALETTE_GREY; else if (myvid->depth == 3) vid_pict.palette = VIDEO_PALETTE_RGB24; else { printf("Wrong color depth. only 1 or 3 is valid.\n"); return -3; } if (ioctl(devfd, VIDIOCSPICT, &vid_pict) == -1) { perror("ioctl (VIDIOCSPICT)"); ret = 1; } /* * get default and then set new channel and norm */ vid_chnl.channel = input; if (ioctl(devfd, VIDIOCGCHAN, &vid_chnl) == -1) { perror("ioctl (VIDIOCGCHAN)"); } vid_chnl.channel = input; vid_chnl.norm = myvid->norm; if (ioctl(devfd, VIDIOCSCHAN, &vid_chnl) == -1) { perror("ioctl (VIDIOCSCHAN)"); ret = 2; } /* * check if drvier support mmap mode and do init */ if (ioctl(devfd, VIDIOCGMBUF, &vid_buf) == -1) { fprintf(stderr, "No mmap support, Use read instead.\n"); myvid->mmaped = 0; if (ioctl(devfd, VIDIOCGWIN, &vid_win) != -1) { vid_win.width = myvid->width; vid_win.height = myvid->height; if (ioctl(devfd, VIDIOCSWIN, &vid_win) == -1) { perror("ioctl (VIDIOCSWIN)"); return -2; } } } else { myvid->mmaped = 1; myvid->mbufsize = vid_buf.size; } return ret; } /* * read rgb image from v4l device * return: mmap'ed buffer and size */ int get_image(MyVID * myvid) { struct video_mmap vid_mmap; Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 59 char *map; int len; int framesize = myvid->width * myvid->height * myvid->depth; if (myvid->mmaped) { map = mmap(0, myvid->mbufsize, PROT_READ | PROT_WRITE, MAP_SHARED, myvid->devfd, 0); if ((unsigned char *) -1 == (unsigned char *) map) { perror("mmap()"); return -1; } vid_mmap.format = (myvid->depth == 1) ? VIDEO_PALETTE_GREY : VIDEO_PALETTE_RGB24; vid_mmap.frame = 0; vid_mmap.width = myvid->width; vid_mmap.height = myvid->height; if (ioctl(myvid->devfd, VIDIOCMCAPTURE, &vid_mmap) == -1) { perror("VIDIOCMCAPTURE"); munmap(map, myvid->mbufsize); return -1; } if (ioctl(myvid->devfd, VIDIOCSYNC, &vid_mmap) == -1) { perror("VIDIOCSYNC"); munmap(map, myvid->mbufsize); return -1; } memcpy(myvid->buf, map, framesize); munmap(map, myvid->mbufsize); } else { len = read(myvid->devfd, myvid->buf, framesize); if (len <= 0) { return -1; } } return 0; } /* * Write image buffer to jpeg file. */ void put_image_jpeg(char *filename, IMG image, int quality) { #ifdef HAVE_JPEG char *buf = image.buf; int width = image.width; int height = image.height; int depth = image.depth; int y, x, line_width; JSAMPROW row_ptr[1]; struct jpeg_compress_struct cjpeg; struct jpeg_error_mgr jerr; char *line; FILE *fd; if ((fd = fopen(filename, "w+")) == NULL) { Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 60 perror("fopen JPG"); exit(-2); } line = malloc(width * 3); if (!line) return; cjpeg.err = jpeg_std_error(&jerr); jpeg_create_compress(&cjpeg); cjpeg.image_width = width; cjpeg.image_height = height; cjpeg.input_components = 3; cjpeg.in_color_space = JCS_RGB; if (depth == 1) { cjpeg.input_components = 1; cjpeg.in_color_space = JCS_GRAYSCALE; } jpeg_set_defaults(&cjpeg); jpeg_set_quality(&cjpeg, quality, TRUE); cjpeg.dct_method = JDCT_FASTEST; jpeg_stdio_dest(&cjpeg, fd); jpeg_start_compress(&cjpeg, TRUE); row_ptr[0] = line; if (depth == 1) { line_width = width; for (y = 0; y < height; y++) { row_ptr[0] = buf; jpeg_write_scanlines(&cjpeg, row_ptr, 1); buf += line_width; } } else { line_width = width * 3; for (y = 0; y < height; y++) { for (x = 0; x < line_width; x += 3) { line[x] = buf[x + 2]; line[x + 1] = buf[x + 1]; line[x + 2] = buf[x]; } jpeg_write_scanlines(&cjpeg, row_ptr, 1); buf += line_width; } } jpeg_finish_compress(&cjpeg); jpeg_destroy_compress(&cjpeg); free(lin e); fclose(fd); #else fprintf(stderr, "NOT Compiled with JPEG support!\n\n"); exit(2); #endif } /* Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 61 * Create direcotry recursively */ /* int pmkdir(char *path) { struct stat st; int umask_save; char *dir, *parent; dir = strdup(path); if (stat(dir, &st) < 0 && errno == ENOENT) { parent = dirname(dir); pmkdir(parent); if (verbose >= 1) printf("Making dir: %s\n", path); umask_save = umask(0); umask(umask_save); if (mkdir(path, 00777 & ~umask_save) < 0) { perror("MKDIR "); }; } free(dir); return 0; }*/ /* * Divide image into sx * sy blocks. For each splited block, * calculate its average RGB color, then store these RGB color * values into array r. */ int proc_img(RGB24 * r, IMG image, int sx, int sy) { char *buf = image.buf; int w = image.width; int h = image.height; int depth = image.depth; unsigned char *p; int x, y, m, n; int blk_wid = w / sx, blk_hgt = h / sy; int x0, y0, x1, y1; int s = blk_wid * blk_hgt; unsigned int R, G, B; int r_offset, g_offset; if (depth == 1) { r_offset = 0; g_offset = 0; } else { r_offset = 2; g_offset = 1; } for (n = 1; n <= sy; n++) { for (m = 1; m <= sx; m++) { x0 = (m - 1) * blk_wid; y0 = (n - 1) * blk_hgt; Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 62 x1 = blk_wid * m - 1; y1 = blk_hgt * n - 1; R = G = B = 0; for (y = y0; y <= y1; y++) { for (x = x0; x <= x1; x++) { p = buf + (y * w + x) * depth; R += *(p + r_offset); G += *(p + g_offset); B += *p; } } r->red = R / s; r->green = G / s; r->blue = B / s; r++; } } return s; } /* * main() */ int main(int argc, char **argv) { //int entrada_contador=0; int contador=0; /*creo un contador para tomar un numero determinado de posiciones*/ int c=0,n = 0; int ofmt = DEF_FMT; int create_dir = 1; int ptimestamp = PRINT_TIME; int prog_run = 0, ret, pstat; int blks, slow_count; int i,j,k; unsigned int buflen; char *buf; IMG image; RGB24 *colors_new, *colors_last, *colors_older, *ptr; char *basedir = BASEDIR; char *userprog = NULL; pid_t pid = -1; char lasttime[32], str_date[32], str_time[32],filename[255]; time_t now; struct tm *tm; float w = DEF_INTERVAL; unsigned int delay = w * 1000000; MyVID myvid; char *device = VIDEO_DEV; int width = DEF_WIDTH, height = DEF_HEIGHT; int input = IN_DEFAULT; int norm = NORM_DEFAULT; int brightness = DEF_BRIGHTNESS; int contrast = DEF_CONTRAST; int depth = 3; int blk_x = DEF_BLK_X; int blk_y = DEF_BLK_Y; int color_diff_ts = DEF_COLOR_TS; /* default color diff threshold */ Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web int hotblk_ts = blk_x * blk_y / 64 + 1; int jpeg_quality = QUAL_DEFAULT; 63 /* default hot block threshold */ /* default jpeg quality setting */ //ENTRADA DEL NUMERO DE VECES A EJECUTAR EL PROGRAMA i=j=k=0; while((int)argv[1][i]!=0) { k=k*10+(int)argv[1][i]-48; i++; } if(contador==25){ printf("SE VAN A INICIAR A DETERMINAR LAS POSICIONES"); } if (signal(SIGUSR1, sig_usr1) == SIG_ERR) { printf("can not setup SIGUSR1 handler.\n"); exit(1); } while ((c = getopt(argc, argv, "B:C:O:a:b:c:d:e:s:q:f:n:i:l:w:Dhmovt")) != EOF) { /* * B: brightness -B 32768 * C: contrast -C 32768 * D: run in daemon mode * O: base directory for output * o: don't create sub-directories * a: horizontal split number x vertical split number -a 16x8 * b: threshold of hot block number (0-blk_x*blk_y) * c: threshold of color diff for each block (0-255*3) * d: v4l device name * e: execute a external program while motion detected. * s: width x height -s 640x480 * q: jpeg quality -q 85 * f: output file format * t: print timestamp on image * m: grayscale mode * n: input video norm * i: input channel # * l: logfile -l /var/log/mvc.log * w: delay time for each capture(seconds), -w 0.5 * h: help */ switch (c) { case 'B': sscanf(optarg, "%d", &brightness); break; case 'C': sscanf(optarg, "%d", &contrast); break; case 'D': daemon_flag = 1; break; case 'O': basedir = optarg; break; case 'd': device = optarg; break; Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 64 case 's': sscanf(optarg, "%dx%d", &width, &height); break; case 'a': sscanf(optarg, "%dx%d", &blk_x, &blk_y); hotblk_ts = blk_x * blk_y / 64 + 1; break; case 'b': sscanf(optarg, "%d", &hotblk_ts); break; case 'c': sscanf(optarg, "%d", &color_diff_ts); break; case 'e': userprog = optarg; break; case 'f': if (strcasecmp("jpeg", optarg) == 0) { ofmt = FMTJPEG; } else if (strcasecmp("png", optarg) == 0) { ofmt = FMTPNG; } break; case 't': ptimestamp = 1; break; case 'm': depth = 1; break; case 'n': if (strcasecmp("ntsc", optarg) == 0) { norm = VIDEO_MODE_NTSC; } else if (strcasecmp("pal", optarg) == 0) { norm = VIDEO_MODE_PAL; } else if (strcasecmp("secam", optarg) == 0) { norm = VIDEO_MODE_SECAM; } else if (strcasecmp("auto", optarg) == 0) { norm = VIDEO_MODE_AUTO; } break; case 'o': create_dir = 0; break; case 'q': sscanf(optarg, "%d", &jpeg_quality); break; case 'w': sscanf(optarg, "%f", &w); delay = w * 1000000; break; case 'i': sscanf(optarg, "%d", &input); break; Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 65 case 'l': logfile = optarg; break; case 'v': verbose++; break; case 'h': default: usage(); exit(1); } } myvid.device = device; myvid.width = width; myvid.height = height; myvid.depth = depth; myvid.input = input; myvid.norm = norm; myvid.brightness = brightness; myvid.contrast = contrast; block_sigs(); /* bttv driver ioctl hates signal */ if (v4l_init(&myvid) != 0) { fprintf(stderr, "v4l init fault!\n"); exit(0); } unblock_sigs(); buflen = myvid.width * myvid.height * myvid.depth; myvid.buf = malloc(buflen); blks = blk_x * blk_y; colors_new = calloc(blks, sizeof(RGB24)); colors_last = calloc(blks, sizeof(RGB24)); colors_older = calloc(blks, sizeof(RGB24)); /* grub a init image as reference */ if (verbose >= 3) { printf("Initializing first image...\n"); } block_sigs(); image.buf = myvid.buf; image.width = width; image.height = height; image.depth = depth; if (get_image(&myvid) == 0) { unblock_sigs(); proc_img(colors_last, image, blk_x, blk_y); memcpy(colors_older, colors_last, blks * sizeof(RGB24)); } /* begin loop */ slow_count = 0; while (!quitflag) { Agosto del 2004 IE-0502 66 Determinación de la posición de un objeto utilizando una cámara Web block_sigs(); if (get_image(&myvid) == 0) { unblock_sigs(); buf = myvid.buf; image.buf = myvid.buf; proc_img(colors_new, image, blk_x, blk_y); contador++; //incremento al contador /* Write Image */ //ESCRIBE EL NUMERO DE FOTOS QUE QUIERA Y LAS LLAMA Foto# time(&now); tm = localtime(&now); strftime(str_time, 31, "%H.%M.%S", tm); strftime(str_date, 31, "%Y-%m-%d", tm); if (strcmp(str_time, lasttime) == 0) n++; else n = 0; strcpy(lasttime, str_time); sprintf(filename,"objeto%i",contador); if (ofmt == FMTJPEG) { strcat(filename, ".jpg"); put_image_jpeg(filename, image, jpeg_quality); } if (verbose >= 1) { printf("Se imprimio el %s --- %s\a\n", filename,str_time); } /* fork and execute external program if needed */ if (userprog != NULL) { if (!prog_run) { prog_run = 1; if (verbose >= 3) { printf("Start user program: %s\n", userprog); } if ((pid = fork()) == -1) { perror("Fork: "); exit(-1); } } if (pid == 0) { } else { // child ret = system(userprog); exit(ret); // parent if (waitpid(-1, &pstat, WNOHANG) != 0) { if (WIFEXITED(pstat) && verbose >= 3) { printf("User program is done. exit code %d.\n", WEXITSTATUS(pstat)); Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 67 } prog_run = 0; } } } /* update 'color_older' array */ memcpy(colors_older, colors_new, blks * sizeof(RGB24)); slow_count = 0; /************************************************************************/ EL PROGRAMA SE EJECUTA HASTA TOMAR 10 FOTOS EN QUE DETECTO MOVIMIENTO /************************************************************************/ if(contador>=k){ quitflag=1; } ptr = colors_last; colors_last = colors_new; colors_new = ptr; } else { fprintf(stderr, "Error: Can't get image \n"); } usleep(delay); } exit(0); /* end of while */ } Archivo font.h typedef struct RGB24 { unsigned char red; unsigned char green; unsigned char blue; } RGB24; typedef struct IMG { int width; int height; int depth; int format; char *buf; } IMG; typedef struct font { char *fontdata; int char_width; int char_height; } FONT; extern void fontinit(); extern int gputch(IMG image, int x0, int y0, int ch, RGB24 color, FONT font); extern int gputs(IMG image, int x0, int y0, char *str, RGB24 color, FONT font); Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 68 extern FONT font8x16; extern FONT font6x11; Archivo config.h #define VERSION "0.8.8" /* Default video device */ #define VIDEO_DEV "/dev/video0" /* Default output directory */ #define BASEDIR "." /* Default capture size */ #define DEF_WIDTH 320 #define DEF_HEIGHT 240 /* Default input port * usually, tv = 0, composite1 = 1, composite2 = 2, svideo = 3. * if specify -1 here and if only 1 channel (such as ov511 webcam) supported * by your device, then mvc will use channel 0 as input, if more than 1 channels * supported by your device (such as most bttv card), it will use channel 1 * as input, because most tv card use channel 0 as tv input, so skip it. */ #define IN_DEF AULT -1 /* Default video norm, defined in videodev.h */ #define NORM_DEFAULT VIDEO_MODE_PAL /* Default brightness and contrast value (0-65535) */ #define DEF_BRIGHTNESS 32768 #define DEF_CONTRAST 32768 /* Default screen divider */ #define DEF_BLK_X #define DEF_BLK_Y 16 8 /* Default block color diff threshold */ #define DEF_COLOR_TS 50 /* Default interval for sample rate (sec) */ #define DEF_INTERVAL 0.3 /* this multiplier used for slow motion detection. Usually, this value is good enough. To disable slow motion detect, set 0 here. */ #define SLOW_COUNT_MAX 60 /* Default output format */ #define DEF_FMT FMTJPEG #define FMTJPEG #define FMTPNG 1 2 /* Default JPEG file quality */ #define QUAL_DEFAULT 90 Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 69 /* Default verbose level for message output */ #define DEF_VERBOSE 1 /* Print timestamp on image or not. * FONTSIZE, font6x11 for smaller, font8x16 for bigger */ #define PRINT_TIME 0 #define FONTSIZEfont6x11 Archivo makefile include depend.inc prefix=/usr dist=$(prefix)/bin CC = gcc all: mvc depend.inc: @echo Generating depend.inc file for this system... @sh depend.sh OBJS=mvc.o font.o mvc: $(OBJS) $(CC) $(LIBS) -o $@ $(OBJS) .c.o: $(CC) $(CFLAGS) $(DEFS) -c $< strip: mvc strip -s mvc install: mvc mkdir -p $(dist) install -s mvc $(dist)/ clean: rm -f *.o mvc distclean: clean rm -f depend.inc *.jpg *.bak *~ rm -rf [0-9][0-9][0-9][0-9]-* Archivo depend.inc LIBS= -ljpeg -lpng12 CFLAGS=-O2 -Wall -g -I. -I/usr/include/libpng12 DEFS= -DHAVE_JPEG -DHAVE_PNG Archivo depend.sh #!/bin/sh CC=${CC-gcc} CFLAGS=${CFLAGS-'-O2 -Wall -g -I.'} Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 70 LIBS='' DEFS='' compile='rm -f conftest.o ; $CC $CFLAGS $CFLAGS2 $TESTLIBS conftest.c -o conftest &> /dev/null' #test libjpeg [ -f conftest ] && rm -f conftest cat << XEOF > conftest.c #include <stdio.h> #include <jpeglib.h> main() { struct jpeg_compress_struct cjpeg; struct jpeg_error_mgr jerr; cjpeg.err = jpeg_std_error(&jerr); jpeg_create_compress(&cjpeg); } XEOF TESTLIBS='-ljpeg' eval $compile if [ -f conftest ] ; then LIBS="$LIBS -ljpeg" DEFS="$DEFS -DHAVE_JPEG" else echo "WARNING: libjpeg NOT Found." fi #test libpng [ -f conftest ] && rm -f conftest cat << XEOF > conftest.c #include <stdio.h> #include <png.h> main() { png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); } XEOF TESTLIBS='-lpng' if which libpng-config &> /dev/null ; then CFLAGS2=`libpng-config --cflags` TESTLIBS=`libpng-config --libs` else if which pkg-config &> /dev/null ; then for libpng in libpng libpng12 libpng10 nolibpng.pc; do if pkg-config --exists $libpng ; then break; fi done if [ "$libpng" != "nolibpng.pc" ] ; then CFLAGS2=`pkg-config --cflags $libpng` TESTLIBS=`pkg-config --libs $libpng` fi fi fi eval $compile if [ -f conftest ] ; then Agosto del 2004 IE-0502 71 Determinación de la posición de un objeto utilizando una cámara Web CFLAGS="$CFLAGS $CFLAGS2" LIBS="$LIBS $TESTLIBS" DEFS="$DEFS -DHAVE_PNG" else echo "WARNING: libpng NOT Found." fi rm -f conftest.c conftest echo LIBS=$LIBS > depend.inc echo CFLAGS=$CFLAGS >> depend.inc echo DEFS=$DEFS >> depend.inc Programa Principal Archivo interfaz.h #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include "wx/image.h" #include "wx/file.h" #include "wx/mstream.h" #include "wx/wfstream.h" #include "wx/quantize.h" #include <ctime> #include <cstring> #ifndef C_matriz_H #define C_matriz_H /*************************************************************/ #include <iostream> /*************************************************************/ using namespace std; /*************************************************************/ /************************************************************************* COMIENZA LA DEFINICION DE LA CLASE C_matriz Y LAS FUNCIONES DE LA MISMA, ADEMAS DE LAS FUNCIONES PARA EL PROCESAMIENTO DE LAS FOTOGRAFIAS TOMADAS *************************************************************************/ class C_matriz { public: C_matriz(int=1, int=1); //parámetros por defecto, estos son fila, columna C_matriz(const C_matriz &); //constructor de copia ~C_matriz(); float get(int fila, int columna) const; //retorna un elemento de la C_matriz void set(int fila, int columna ,float dato); //graba un elemento en una posición de la C_matriz C_matriz &operator=(const C_matriz &); //Operador de asignación Agosto del 2004 IE-0502 72 Determinación de la posición de un objeto utilizando una cámara Web private: int filas; int columnas; float *ptr_data; }; /*************************************************************/ #endif C_matriz::C_matriz(int x, int y) { x>0 ? filas=x : filas=1; y>0 ? columnas=y : columnas=1; ptr_data=new float[filas*columnas]; //se crea un puntero, en el se va a almacenar for(int i=0;i<filas*columnas;i++) //los datos de la matriz, luego se limpia el arreglo ptr_data[i]=0; //para evitar que tenga basura }; /*************************************************************/ C_matriz::C_matriz(const C_matriz &Matriz) //este es un cosntructor de copia { filas=Matriz.filas; columnas=Matriz.columnas; ptr_data=new float[filas*columnas]; for(int i=0;i<filas*columnas;i++) ptr_data[i]=Matriz.ptr_data[i]; }; /*************************************************************/ C_matriz::~C_matriz() { delete [] ptr_data; //el destructor borra el puntero }; /*************************************************************/ /* El operador = se utiliza para hacer la igual entre una */ /* funcion y un objeto tipo C_matriz */ C_matriz &C_matriz::operator=(const C_matriz & Matriz) { if(&Matriz!=this) //this es un puntero, aqui se verifica { if((filas!=Matriz.filas)|| //que los valores adquiridos sean los mismos (columnas!=Matriz.columnas)) //que la matriz que se esta igualando { delete [] ptr_data; filas=Matriz.filas; columnas=Matriz.columnas; ptr_data=new float[filas*columnas]; } for(int i=0;i<filas*columnas;i++) ptr_data[i]=Matriz.ptr_data[i]; //aqui se realiza la igualdad de los elementos } //de la matriz return *this; //permite concatenación }; /*************************************************************/ float C_matriz::get(int i,int j) const //la funcion obtiene los valores de las posiciones { //de la matriz que se le indique if(i>=0 && i<=filas && j>=0 && j<=columnas) //se asegura que no se pase de los limites de la matriz return ptr_data[(i-1)*columnas+(j-1)]; //returna de esta manera, dado a que se tiene solo Agosto del 2004 IE-0502 73 Determinación de la posición de un objeto utilizando una cámara Web else { //un arreglo, donde se conoce las filas y las columnas //desplega un mensaje de error y terminas la funcion //en la cuál se llamó a get() cout<<"get() error: Ãndices fuera de los là mites"<<i<<","<<j<<endl; exit(0); } }; /*************************************************************/ void C_matriz::set(int i,int j,float element) //la funcion set guarda un dato tipo float en la posicion { //de la matriz que se le indique if(i>0 && i<=filas && j>0 && j<=columnas) //se asegura que no se pase de los limites de la matriz ptr_data[(i-1)*columnas+(j-1)]=element; //lo guarda de esta manera ya que la matriz se guarda else //en un arreglo { //desplega un mensaje de error y terminas la funcion //en la cuál se llamó a set() cout<<"set() error: Ãndices fuera de los lÃmites"<<endl; exit(0); } }; /********************************************************/ //Funcion para imprimir la imagen, crear un archivo de nombre archivo_modificado bool imprimir(string archivo, string archivo_modificado, const C_matriz &matriz){ Image Imagen(archivo); //utiliza la libreria magick++ para obtener el valor de cada pixel ColorRGB pixelrgb; //y sus tres elementos para RGB for (unsigned int i=1; i<=240;i++){ for (unsigned int j=1; j<=320;j++){ pixelrgb=Imagen.pixelColor(j-1,i-1); //magick++ recorre primero columns luego rows, contrario a matriz pixelrgb.green(matriz.get(i,j)); pixelrgb.red(matriz.get(i,j)); pixelrgb.blue(matriz.get(i,j)); Imagen.pixelColor(j-1,i-1,pixelrgb); //Asigna al objeto tipo Image el valor del pixel } } Imagen.write(archivo_modificado); //crea una imagen con los valores del objeto Imagen return true; } /************************************************************************* La función iluminancia se utiliza para crear la imagen en grises, utilizando los valores dados para multiplicar los elementos RGB de cada pixelColor *************************************************************************/ C_matriz iluminancia(string imagen1){ Image Imagen; Imagen.read(imagen1); ColorRGB pixelrgb; C_matriz matriz_iluminancia(Imagen.rows(),Imagen.columns()); float iluminancia1; for (unsigned int i=1; i<=240;i++){ for (unsigned int j=1;j<=320;j++){ pixelrgb=Imagen.pixelColor(j-1,i-1); Agosto del 2004 IE-0502 74 Determinación de la posición de un objeto utilizando una cámara Web iluminancia1 = pixelrgb.red()*0.299 + pixelrgb.green()*0.587 +pixelrgb.blue()*0.114; matriz_iluminancia.set(i,j,iluminancia1); } } return matriz_iluminancia; } /************************************************************************* El siguiente filtro observa el valor de cada pixel, si el valor es muy alto lo reduce en mayor medida, conforme los valores van siendo mas bajos, los va reduciendo en menor medida. Ademas reduce un poco los vecinos tipo 4 para no tener mucha variacion en la imagen *************************************************************************/ C_matriz filtro1(C_matriz &matriz){ for (unsigned int i=2; i<=239;i++){ for (unsigned int j=2;j<=319;j++){ if(matriz.get(i,j)>0.8){ matriz.set(i,j,matriz.get(i,j)*0.85); matriz.set(i,j-1,matriz.get(i,j-1)*0.9); matriz.set(i,j+1,matriz.get(i,j+1)*0.9); matriz.set(i-1,j,matriz.get(i-1,j)*0.9); matriz.set(i+1,j,matriz.get(i+1,j)*0.9); } } } return matriz; } /************************************************************************* Esta funcion es la encargada de detectar los pixeles en que se encuentra el objeto, recibe dos matrices que contienen los valores en escala de grises de dos imagenes y los compara, restandolos y sacando su valor absoluto, luego pone en negro los valores , dependiendo si la diferencia fue mayor al valor almacenado en la variable limites *************************************************************************/ C_matriz deteccion_objeto(C_matriz &matriz_fondo,C_matriz &matriz_objeto,float limite ){ float elemento; C_matriz matriz_resta(240,320); for (unsigned int i=1; i<=239;i++){ for (unsigned int j=1;j<=319;j++){ elemento=abs(matriz_fondo.get(i,j)-matriz_objeto.get(i,j)); //Saca el valor absoluto a cada resultado de la resta matriz_resta.set(i,j,elemento); //almacena el valor en matriz_resta if(matriz_resta.get(i,j)>limite){ //lo evalua a ver si es mayor al limite lo pone negro matriz_resta.set(i,j,0); //sino lo pone blanco } else{ matriz_resta.set(i,j,1); } } } return matriz_resta; } /************************************************************************* La funcion centroides_x obtiene el centroide en x del objeto almacenado en la matriz que contiene el objeto en color negro, siendo esta el resultado de la funcion deteccion_objeto, esta suma en la variable numero_pixeles los pixeles que forman el objeto que seria el area y en la variable suma_x las distancias de este pixel a el pixel en (0,0), luego aplica la formula para el centroide, dividiendo la suma de las distancias entre el total de pixeles del objeto y devuelve la posicion donde se encuentra el centroide *************************************************************************/ Agosto del 2004 IE-0502 75 Determinación de la posición de un objeto utilizando una cámara Web unsigned int centroides_x(C_matriz &matriz){ unsigned int centroide_x; unsigned int suma_x=0; unsigned int numero_pixeles=0; for (unsigned int i=1; i<=240;i++){ for (unsigned int j=1;j<=320;j++){ if(matriz.get(i,j)==0){ suma_x=suma_x+j; numero_pixeles++; } } } centroide_x=(suma_x/numero_pixeles); return (centroide_x); } /************************************************************************* Esta funcion hace el mismo procedimiento que la funcion centroides_x, pero con los valores en el eje y, para luego devolver la posicion del centroide en el eje y *************************************************************************/ unsigned int centroides_y(C_matriz &matriz){ unsigned int centroide_y; unsigned int suma_y=0; unsigned int numero_pixeles=0; for (unsigned int i=1; i<=240;i++){ for (unsigned int j=1;j<=320;j++){ if(matriz.get(i,j)==0){ suma_y=suma_y+i; numero_pixeles++; } } } centroide_y=(suma_y/numero_pixeles); return (centroide_y); } /************************************************************************* Esta funcion basicamente recibe una matriz en la que se encuentran los pixeles de una imagen y le escribe encima unas rayas negras mostrando la division de zonas que se esta haciendo para determinar la posicion del objeto *************************************************************************/ C_matriz cuadricula(C_matriz &matriz){ C_matriz matriz_cuadricula(240,320); float elemento; for (unsigned int i=1; i<=240;i++){ for (unsigned int j=1;j<=320;j++){ if((j==320)||(j==256)||(j==192)||(j==128)||(j==64)||(j==1)){ matriz_cuadricula.set(i,j,1); } else{ if((i==240)||(i==192)||(i==144)||(i==96)||(i==48)||(i==1)){ matriz_cuadricula.set(i,j,1); } else{ elemento=matriz.get(i,j); matriz_cuadricula.set(i,j,elemento); } } } Agosto del 2004 IE-0502 76 Determinación de la posición de un objeto utilizando una cámara Web } return matriz_cuadricula; } /************************************************************************* IMPLEMENTACION DE LA CLASE Time Y DE LAS FUNCIONES NECESARIAS PARA DETERMINAR EL TIEMPO EN QUE SE ESTAN DETERMINANDO LAS POSICIONES *************************************************************************/ class Time { std::time_t t; std::tm local; char asciiRep[26]; //crea un arreglo de tipo char para almacenar los caracteres unsigned char lflag,aflag; //de la hora void updatelocal(){ if(!lflag){ local= *std::localtime(&t); //se tiene un puntero t para determinar cuando se llamo la funcion } } void updateAscii(){ if(!aflag){ updatelocal(); //devuelve un string en Ascii con la hora y fecha std::strcpy(asciiRep,std::asctime(&local)); aflag++; } } public: Time() {mark();} void mark() { lflag=aflag=0; std::time(&t); } const char* ascii(){ updateAscii(); return asciiRep; } //devuelve el string con la fecha y hora int delta(Time* dt) const { return int(std::difftime(t,dt->t)); //devuelve el tiempo transcurrido desde start hasta end } //los cuales son punteros de inicio y final }; /************************************************************************* COMIENZA LA IMPLEMENTACION DE LA INTERFAZ GRAFICA *************************************************************************/ class MyApp: public wxApp { public: bool OnInit(); //esta clase contempla las caracteristicas de la ventana }; class MyFrame: public wxFrame { public: MyFrame(wxFrame *frame, const wxChar *title, int x, int y, int w, int h); virtual ~MyFrame() { delete wxLog::SetActiveTarget(m_logOld); } Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 77 void OnAbout( wxCommandEvent &event ); //son las definiciones de las funciones que se van void OnQuit( wxCommandEvent &event ); //a tener para realizar todas las funciones que void AbrirFondo( wxCommandEvent &event ); //tiene el programa en el menu void AbrirObjeto( wxCommandEvent &event ); void Posiciones( wxCommandEvent &event); void AbrirPosicion( wxCommandEvent &event); void AbrirPosiciones( wxCommandEvent &event); void Calibracion(wxCommandEvent &event); wxTextCtrl *m_log; //este puntero es el utilizado para escribir al cuadro de texto wxLog *m_logOld; //de la ventana del programa private: DECLARE_EVENT_TABLE() //se declara una tabla de eventos donde se incluyen las funciones }; /************************************************************************/ Archivo interfaz2.cpp // For compilers that support precompilation, includes "wx/wx.h". #include "wx/wxprec.h" #include <iostream> using namespace std; #include <Magick++.h> using namespace Magick; #include <string> using std::string; #include <fstream> #include <cstdio> #include <cstdlib> #ifdef __BORLANDC__ #pragma hdrstop #endif // for all others, include the necessary headers #ifndef WX_PRECOMP #include "wx/app.h" #include "wx/log.h" #include "wx/frame.h" #include "wx/panel.h" #include "wx/stattext.h" #include "wx/menu.h" #include "wx/layout.h" #include "wx/msgdlg.h" #endif #include "wx/calctrl.h" #include "interfaz2.h" /*********************************************************************** Esta instruccion se pone para que el compilador sepa que se va a implementar una ventana de clase MyApp ************************************************************************/ Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 78 IMPLEMENT_APP(MyApp) //Definiciones de las funciones que se tienen en la barra de menu de la ventana enum { ID_QUIT = 108, ID_ABOUT = 109, ID_ABRIRFONDO = 112, ID_ABRIROBJETO = 113, ID_POSICIONES = 114, ID_ABRIRPOSICION = 115, ID_ABRIRPOSICIONES = 116, ID_CALIBRAR = 117 }; bool MyApp::OnInit() { // Se crea la ventana principal del programa MyFrame *frame = new MyFrame((wxFrame *) NULL, _T("Deteccion de Objetos"), 50, 50, 700, 420); frame->SetSizeHints( 500, 400 ); wxMenu *file_menu = new wxMenu(); //Se crea un puntero file_menu el cual despliega las funciones del menu Archivo file_menu->Append( ID_ABOUT, _T("&Creditos...")); file_menu->AppendSeparator(); file_menu->Append( ID_QUIT, _T("&Salir")); //Se crea el menu Acciones, con las funciones que tiene wxMenu *acciones_menu = new wxMenu(); acciones_menu->Append(ID_POSICIONES,_T("&Obtener Posiciones")); acciones_menu->Append(ID_ABRIRFONDO,_T("&Abrir Fotografia del Fondo")); acciones_menu->Append(ID_ABRIROBJETO,_T("&Abrir Fotografia del ultimo objeto")); acciones_menu->Append(ID_ABRIRPOSICION,_T("&Abrir Fotografia de la primera posicion")); acciones_menu->Append(ID_ABRIRPOSICIONES,_T("&Abrir Fotografia de las posiciones")); acciones_menu->Append(ID_ABRIRPOSICIONES,_T("&Calibracion de la camara")); //se crea la barra de menu con las dos opciones Archivo y Acciones wxMenuBar *menu_bar = new wxMenuBar(); menu_bar->Append(file_menu, _T("&Archivo")); menu_bar->Append(acciones_menu,_T("&Acciones")); frame->SetMenuBar(menu_bar); frame->Show(TRUE); SetTopWindow(frame); return TRUE; } /************************************************************************* Se crea la tabla de eventos con todas las funciones que se tienen en la barra de menu creada *************************************************************************/ BEGIN_EVENT_TABLE(MyFrame,wxFrame) EVT_MENU (ID_ABOUT, MyFrame::OnAbout) EVT_MENU (ID_QUIT, MyFrame::OnQuit) EVT_MENU (ID_ABRIRFONDO,MyFrame::AbrirFondo) Agosto del 2004 IE-0502 79 Determinación de la posición de un objeto utilizando una cámara Web EVT_MENU (ID_ABRIROBJETO,MyFrame::AbrirObjeto) EVT_MENU (ID_ABRIRPOSICION,MyFrame::AbrirPosicion) EVT_MENU (ID_ABRIRPOSICIONES,MyFrame::AbrirPosiciones) EVT_MENU (ID_POSICIONES,MyFrame::Posiciones) EVT_MENU (ID_CALIBRAR,MyFrame::Calibracion) END_EVENT_TABLE() /************************************************************************* En el constructor de la clase MyFrame se crea el cuadro de texto en la ventana principal del programa *************************************************************************/ MyFrame::MyFrame(wxFrame *frame, const wxChar *title, int x, int y, int w, int h) : wxFrame(frame, -1, title, wxPoint(x, y), wxSize(w, h) ) { m_log = new wxTextCtrl( this, -1, _T("Esta es la ventana de control de eventos\nPara ejecutar el programa vaya a Acciones y oprima Obtener Posiciones \nSi esta ejecutando el programa por primera vez luego de inicializado Linux, debe calibrar la camara antes de Obtener posiciones"), wxPoint(5,260), wxSize(630,100), wxTE_MULTILINE | wxTE_READONLY /* | wxTE_RICH */); m_logOld = wxLog::SetActiveTarget( new wxLogTextCtrl( m_log ) ); CreateStatusBar(2); } void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event)) { // TRUE forza a cerrar la ventana, si se escoge la opcion Salir del menu Archivo Close(TRUE); } //Despliega una ventana con los creditos del programa y avisa la accion en la ventana void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event)) { wxMessageBox(_T("Programa de Deteccion de Objetos\nCreado por: Juan Lara Flores\nEscuela de Ingenieria\nUCR"), _T("Creditos del Programa"), wxOK | wxICON_INFORMATION, this); *m_log<<_T("Se abrio la ventana con los creditos del programa de Deteccion de objetos\n"); } /************************************************************************* La funciones llamadas AbrirXXXXX se utilizan para abrir una ventana con la foto que se dice en la barra del menu Acciones, estas hacen una llamada a otro programa para que la foto que se despliegue sea la ultima que se genero, ya que si no se hace de esta manera, se carga la que estaba con ese nombre antes de que se ejecute el programa principal ./interfaz2 *************************************************************************/ void MyFrame::AbrirFondo(wxCommandEvent& WXUNUSED(event)) { wxMessageBox(_T("Se va a abrir la fotografia del fondo\nPara salir vaya al menu Archivo y ejecute el comando Salir\n"), _T("Fotografia del fondo"), wxOK | wxICON_INFORMATION, this); system("./fondo"); //Se hace la llamada a otro programa para que se vea la ultima foto tomada } void MyFrame::AbrirObjeto(wxCommandEvent& WXUNUSED(event)) { Agosto del 2004 IE-0502 80 Determinación de la posición de un objeto utilizando una cámara Web wxMessageBox(_T("Se va a abrir la fotografia del objeto\nPara salir vaya al menu Archivo y ejecute el comando Salir\n"), _T("Fotografia del objeto"), wxOK | wxICON_INFORMATION, this); system("./objeto"); } void MyFrame::AbrirPosicion(wxCommandEvent& WXUNUSED(event)) { wxMessageBox(_T("Se va a abrir la fotografia de la ultima primera posicion tomada\nPara salir vaya al menu Archivo y ejecute el comando Salir\n"), _T("Fotografia de la primera posicion"), wxOK | wxICON_INFORMATION, this); system("./posicion"); } void MyFrame::AbrirPosiciones(wxCommandEvent& WXUNUSED(event)) { wxMessageBox(_T("Se va a abrir la fotografia de las posiciones determinadas\nPara salir vaya al menu Archivo y ejecute el comando Salir\n"), _T("Fotografia de las posiciones determinadas"), wxOK | wxICON_INFORMATION, this); system("./centroides"); } void MyFrame::Calibracion(wxCommandEvent& WXUNUSED(event)) { wxMessageBox(_T("La camara se dura calibrandose alrededor de minuto y medio\nRealice esta operacion cuando ejecuta por primera vez\n el programa luego de inicializado el sistema operativo"), _T("Calibracion de la camara"), wxOK | wxICON_INFORMATION, this); system("./mvc2"); } /************************************************************************* Esta funcion es la principal del programa, en ella se ordena empezar a tomar las fotos para las posiciones, para tomar las fotos llama al programa mvc creado en el lenguaje C, el cual toma las fotos y las almacena en la carpeta, para que luego de tomarlas sean procesadas, los pasos seguidos se explican seguidamente *************************************************************************/ void MyFrame::Posiciones (wxCommandEvent &) { C_matriz objeto,deteccion,objeto1,deteccion1,centroides(240,320),fondo1,fondo,fondocuadricula; int numobjetos=1; int n=0; unsigned int contador1=0; unsigned int centroide_x,centroide_y; unsigned int *array_x,*array_y; float limite=0.15; char archivo[255]; char archivo1[255]; int numeroposiciones=0; int limite1=3; float tiempo=0; fotos_minuto=110; tiempo_foto=0.545454; //Esta llamada a este puntero se hace para escribir el mensaje en el cuadro de texto wxMessageBox(_T("Si se esta ejecutando el programa por primera vez luego de haber iniciado el sistema operativo, utilice la opcion Calibrar la camara"), _T("ADVERTENCIA"), wxOK | wxICON_INFORMATION, this); *m_log << _T("Se va a iniciar a obtener las posiciones del objeto\n"); Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 81 //Se crea el archivo Posiciones.txt ofstream out("Posiciones.txt"); //se toma la foto llamando al programa mvc1 que toma 25 fotos system("./mvc1"); //a la matriz fondo se le asigna la matriz que devuelve la //funcion fondo y a esta se le aplica el filtro y se almacena //en fondo1 para luego mandarla a fondocuadricula y imprimirle //las rayas que dividen el fondo en zonas fondo=iluminancia("fondo1.jpg"); fondo1=filtro1(fondo); fondocuadricula=cuadricula(fondo1); imprimir("fondo.jpg","fondo1.jpg",fondocuadricula); *m_log << _T("Se tomo la fotografia del fondo, para verificarla abra el menu Acciones\n"); //Aqui se crea la ventana que recibe el numero de minutos que se quiere obtener posiciones numeroposiciones = wxGetNumberFromUser(_T("Por cuantos minutos desea tomar posiciones:"), _T("Minutos a ejecutar:"), _T("Posiciones a determinar"), numeroposiciones, 0, 10, this); //Dura 0.5454s por foto, por lo que en un minuto toma 110 fotos y esto se multiplica //por el numero de minutos para obtener el total de fotos tomadas numeroposiciones=(numeroposiciones*fotos_minuto); cout<<"Se escogio correr el programa por: "<<numeroposiciones<<" minutos"<<endl; array_x=new unsigned int [numeroposiciones]; array_y=new unsigned int [numeroposiciones]; *m_log << _T("Se van a iniciar a obtener las posiciones del objeto, no mueva la camara\n"); wxMessageBox(_T("Escoja la resolucion que quiere para la foto\nEntre mayor sea el valor, menor cantidad de puntos del objeto se obtendran\nSi la foto salio con ruido aumente el valor para mejorarla\nSe recomienda 3 o 4, Observe los resultados"), _T("Valor limite estipulado como diferencia"), wxOK | wxICON_INFORMATION, this); limite1 = wxGetNumberFromUser(_T("Escoja el valor de resolucion de la foto del objeto"), _T("Escoja el valor de 0-10:"), _T("Posiciones a determinar"), limite1, 0, 10, this); switch(limite1){ case 0: limite=0.13; break; case 1: limite=0.14; break; case 2: limite=0.145; break; case 3: limite=0.15; break; case 4: limite=0.155; break; Agosto del 2004 IE-0502 82 Determinación de la posición de un objeto utilizando una cámara Web case 5: limite=0.16; break; case 6: limite=0.165; break; case 7: limite=0.17; break; case 8: limite=0.175; break; case 9: limite=0.18; break; } cout<<limite<<endl; //Se crea un mensaje de advertencia, para que el usuario se devuelva a la consola donde //corrio el programa y repita los minutos y observe los tiempos en que toma cada foto wxMessageBox(_T("Repita el numero de posiciones que desea tomar\nCuando el programa lo pide en la consola\nObserve que en ella se imprimen los tiempos en los que se tomo cada posicion"), _T("ADVERTENCIA"), wxOK | wxICON_INFORMATION, this); Time start; system("./mvc"); Time end; //Se crea un mensaje para que el usuario minimice la consola y vuelva al programa //para que este procese las fotos tomadas wxMessageBox(_T("Minimice esta ventana de consola y vuelva al programa de deteccion de\nobjetos y espere mientras se procesan la fotos tomadas"), _T("ADVERTENCIA"), wxOK | wxICON_INFORMATION, this); //De esta forma se imprime en el archivo Posiciones.txt out<<"\nInicio Ejecucion Programa de Captura: "<<start.ascii()<<"\nFin Ejecucion Programa de Captura: "<<end.ascii()<<endl; out<<"La ejecucion del programa duro: "<<end.delta(&start)<<" segundos"<<endl; out<<"LOS TIEMPOS EN QUE SE TOMO CADA POSICION SE ENCUENTRAN EN LA CONSOLA\n"<<endl; out<<"Centroides\n(x,y) Zona Tiempo(s)"<<endl; //Se entra a un ciclo que va a procesar todas las fotos tomadas por el programa mvc while(numobjetos<=numeroposiciones){ n++; if(n>=50){ //Se desprecian las primeras 10 fotos para asegurar que la camara enfoque cout<<"entre al if"<<n<<"/"<<numobjetos<<endl; if(numobjetos==1){ tiempo=0; } else{ tiempo=tiempo+tiempo_foto; //Se calcula el tiempo en que se tomo cada foto, segun } //el tiempo promedio que dura por cada foto //Se crea un string objeto#(numero del objeto) sprintf(archivo,"objeto%i.jpg",n); //se manda la foto a la funcion iluminancia para que la convierta Agosto del 2004 IE-0502 83 Determinación de la posición de un objeto utilizando una cámara Web //a escala de grises y la pase por el filtro objeto=iluminancia(archivo); objeto1=filtro1(objeto); imprimir("fondo.jpg","objeto.jpg",objeto1); sprintf(archivo1,"Posicion%i",numobjetos); //Se mandan ambas matrices, una con el fondo deteccion=deteccion_objeto(fondo1,objeto1,limite); imprimir("fondo.jpg",archivo1,deteccion); //y otra con la foto recien abierta, para luego //imprimir el resultado de la funcion deteccion_objeto centroide_x=centroides_x(deteccion); array_x[contador1]=centroide_x; //guarda en el arreglo el centroide en x del objeto centroide_y=centroides_y(deteccion); array_y[contador1]=centroide_y; //guarda en el arreglo el centroide en y del objeto //Imprime el tiempo en que proceso la imagen y el numero de posicion que es wxLogStatus(this, _T("Posicion #%ld"), numobjetos); out<<"Posicion #"<<numobjetos<<endl; //se indica la posicion en Posiciones.txt /*********************************************************************** SE VAN A DETERMINAR LAS ZONAS EN LAS QUE SE ENCUENTRA EL OBJETO CON UNA SERIE DE IF QUE DIVIDEN LA IMAGEN DEVUELTA POR deteccion_objeto ***********************************************************************/ if((0<=centroide_x)&&(centroide_x<64)&&(0<=centroide_y)&&(centroide_y<48)){ out<<"("<<centroide_x<<","<<centroide_y<<")\t"<<"\t0\t \t"<<tiempo<<endl; } if((64<=centroide_x)&&(centroide_x<128)&&(0<=centroide_y)&&(centroide_y<48)){ out<<"("<<centroide_x<<","<<centroide_y<<")\t"<<"\t1\t \t"<<tiempo<<endl; } if((128<=centroide_x)&&(centroide_x<192)&&(0<=centroide_y)&&(centroide_y<48)){ out<<"("<<centroide_x<<","<<centroide_y<<")\t"<<"\t2\t \t"<<tiempo<<endl; } if((192<=centroide_x)&&(centroide_x<256)&&(0<=centroide_y)&&(centroide_y<48)){ out<<"("<<centroide_x<<","<<centroide_y<<")\t"<<"\t3\t \t"<<tiempo<<endl; } if((256<=centroide_x)&&(centroide_x<=320)&&(0<=centroide_y)&&(centroide_y<48)){ out<<"("<<centroide_x<<","<<centroide_y<<")\t"<<"\t4\t \t"<<tiempo<<endl; } if((0<=centroide_x)&&(centroide_x<64)&&(48<=centroide_y)&&(centroide_y<96)){ out<<"("<<centroide_x<<","<<centroide_y<<")\t"<<"\t5\t \t"<<tiempo<<endl; } if((64<=centroide_x)&&(centroide_x<128)&&(48<=centroide_y)&&(centroide_y<96)){ out<<"("<<centroide_x<<","<<centroide_y<<")\t"<<"\t6\t \t"<<tiempo<<endl; } if((128<=centroide_x)&&(centroide_x<192)&&(48<=centroide_y)&&(centroide_y<96)){ out<<"("<<centroide_x<<","<<centroide_y<<")\t"<<"\t7\t \t"<<tiempo<<endl; Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 84 } if((192<=centroide_x)&&(centroide_x<256)&&(48<=centroide_y)&&(centroide_y<96)){ out<<"("<<centroide_x<<","<<centroide_y<<")\t"<<"\t8\t \t"<<tiempo<<endl; } if((256<=centroide_x)&&(centroide_x<=320)&&(48<=centroide_y)&&(centroide_y<96)){ out<<"("<<centroide_x<<","<<centroide_y<<")\t"<<"\t10\t\t"<<tiempo<<endl; } if((0<=centroide_x)&&(centroide_x<64)&&(96<=centroide_y)&&(centroide_y<144)){ out<<"("<<centroide_x<<","<<centroide_y<<")\t"<<"\t11\t\t"<<tiempo<<endl; } if((64<=centroide_x)&&(centroide_x<128)&&(96<=centroide_y)&&(centroide_y<144)){ out<<"("<<centroide_x<<","<<centroide_y<<")\t"<<"\t12\t\t"<<tiempo<<endl; } if((128<=centroide_x)&&(centroide_x<192)&&(96<=centroide_y)&&(centroide_y<144)){ out<<"("<<centroide_x<<","<<centroide_y<<")\t"<<"\t13\t\t"<<tiempo<<endl; } if((192<=centroide_x)&&(centroide_x<256)&&(96<=centroide_y)&&(centroide_y<144)){ out<<"("<<centroide_x<<","<<centroide_y<<")\t"<<"\t14\t\t"<<tiempo<<endl; } if((256<=centroide_x)&&(centroide_x<=320)&&(96<=centroide_y)&&(centroide_y<144)){ out<<"("<<centroide_x<<","<<centroide_y<<")\t"<<"\t15\t\t"<<tiempo<<endl; } if((0<=centroide_x)&&(centroide_x<64)&&(144<=centroide_y)&&(centroide_y<192)){ out<<"("<<centroide_x<<","<<centroide_y<<")\t"<<"\t16\t\t"<<tiempo<<endl; } if((64<=centroide_x)&&(centroide_x<128)&&(144<=centroide_y)&&(centroide_y<192)){ out<<"("<<centroide_x<<","<<centroide_y<<")\t"<<"\t17\t\t"<<tiempo<<endl; } if((128<=centroide_x)&&(centroide_x<192)&&(144<=centroide_y)&&(centroide_y<192)){ out<<"("<<centroide_x<<","<<centroide_y<<")\t"<<"\t18\t\t"<<tiempo<<endl; } if((192<=centroide_x)&&(centroide_x<256)&&(144<=centroide_y)&&(centroide_y<192)){ out<<"("<<centroide_x<<","<<centroide_y<<")\t"<<"\t19\t\t"<<tiempo<<endl; } if((256<=centroide_x)&&(centroide_x<=320)&&(144<=centroide_y)&&(centroide_y<192)){ out<<"("<<centroide_x<<","<<centroide_y<<")\t"<<"\t20\t\t"<<tiempo<<endl; } if((0<=centroide_x)&&(centroide_x<64)&&(192<=centroide_y)&&(centroide_y<=240)){ out<<"("<<centroide_x<<","<<centroide_y<<")\t"<<"\t21\t\t"<<tiempo<<endl; } if((64<=centroide_x)&&(centroide_x<128)&&(192<=centroide_y)&&(centroide_y<=240)){ out<<"("<<centroide_x<<","<<centroide_y<<")\t"<<"\t22\t\t"<<tiempo<<endl; Agosto del 2004 IE-0502 85 Determinación de la posición de un objeto utilizando una cámara Web } if((128<=centroide_x)&&(centroide_x<192)&&(192<=centroide_y)&&(centroide_y<=240)){ out<<"("<<centroide_x<<","<<centroide_y<<")\t"<<"\t23\t\t"<<tiempo<<endl; } if((192<=centroide_x)&&(centroide_x<256)&&(192<=centroide_y)&&(centroide_y<=240)){ out<<"("<<centroide_x<<","<<centroide_y<<")\t"<<"\t24\t\t"<<tiempo<<endl; } if((192<=centroide_x)&&(centroide_x<256)&&(192<=centroide_y)&&(centroide_y<=240)){ out<<"("<<centroide_x<<","<<centroide_y<<")\t"<<"\t25\t\t"<<tiempo<<endl; } /********************************************************************/ numobjetos++; //se aumentan los contadores para comparar cuantas fotos contador1++; //se han procesado hasta este momento } } *m_log << _T("Se va a imprimir la fotografia con las posiciones del objeto\n"); /*********************************************************************** Seguidamente lo que se hace es crear la imagen Centroides.jpg, imprimiendo un punto en la posicion donde esta el centroide del objeto, esto recorriendo los arreglos creados con todos los centroides encontrados y recorriendo todas las posiciones de la imagen de 320x240 ************************************************************************/ for (unsigned int i=1; i<=240;i++){ for (unsigned int j=1;j<=320;j++){ if((j==320)||(j==256)||(j==192)||(j==128)||(j==64)||(j==1)){ centroides.set(i,j,0); } else{ if((i==240)||(i==192)||(i==144)||(i==96)||(i==48)||(i==1)){ centroides.set(i,j,0); } else{ centroides.set(i,j,1); } } for(unsigned int k=0;k<=contador1;k++){ if((array_x[k]==j)&&(array_y[k]==i)){ centroides.set(i,j,0); } } } } imprimir("fondo.jpg","centroides.jpg",centroides); //aqui se imprime Centroides.jpg *m_log << _T("Se creo la fotografia con las posiciones, para abrirla vaya al menu Acciones\n"); *m_log << _T("Observe los resultados en el archivo Posiciones.txt localizado en la carpeta del programa\n"); } Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 86 Archivo makefile # Generated automatically from Makefile.in by configure. # Purpose: makefile for calendar example (UNIX). # Created: 2000-01-03 top_srcdir = ../.. top_builddir = ../.. program_dir = demos/proyecto PROGRAM=interfaz2 OBJECTS = interfaz2.o DEPFILES=interfaz2.d include /root/wxwindows/wxGTK-2.4.2/demos/proyecto/makeprog.env -include $(DEPFILES) Archivo makelib.env # Template makefile for building wxWindows companion libraries. # # Author: Ron Lee <[email protected]> # Created: 19/3/2000 # $Id: makelib.env.in,v 1.12.2.1 2002/11/03 23:58:38 VS Exp $ # # To use, set the following vars before including it: # # top_srcdir # top_builddir # libsrc_dir # # TARGET_LIBNAME # LIBVERSION_CURRENT # LIBVERSION_REVISION # LIBVERSION_AGE # HEADER_PATH # HEADER_SUBDIR # # HEADERS # OBJECTS # # either a shared or static lib will be built according to the # option given to configure. # prefix = /usr/local exec_prefix = ${prefix} includedir = ${prefix}/include libdir = ${exec_prefix}/lib INSTALL = /usr/bin/install -c INSTALL_PROGRAM = ${INSTALL} INSTALL_DATA = ${INSTALL} -m 644 Agosto del 2004 IE-0502 87 Determinación de la posición de un objeto utilizando una cámara Web TARGETLIB_STATIC = $(TARGET_LIBNAME).a TARGETLIB_SHARED = $(TARGET_LIBNAME).so.$(LIBVERSION_CURRENT).$(LIBVERSION_REVISION).$(LIBVERSION_AGE) TARGETLIB_LINK1 = $(TARGET_LIBNAME).so.$(LIBVERSION_CURRENT) TARGETLIB_LINK2 = $(TARGET_LIBNAME).so TARGETLIB_SONAME = LDFLAGS_VER SIONING = -Wl,--version-script,$(top_builddir)/version-script # NB: see remark in Makefile.in as to why we don't use %.foo: %.bar rules .SUFFIXES: .o .c .cpp .cxx .c.o: $(CC) -c $(CFLAGS) $(PICFLAGS) -o $@ $< .cpp.o: $(CXX) -c $(CXXFLAGS) $(PICFLAGS) -o $@ $< .cxx.o: $(CXX) -c $(CXXFLAGS) $(PICFLAGS) -o $@ $< # the comment at the end of the next line is needed because otherwise autoconf # would remove this line completely - it contains a built-in hack to remove # any VPATH assignment not containing ':' VPATH = :$(top_srcdir)/$(libsrc_dir) # ':' for autoconf include $(top_builddir)/src/make.env all: libtype_so libtype_so: $(top_builddir)/lib/$(TARGETLIB_SHARED) libtype_a: $(top_builddir)/lib/$(TARGETLIB_STATIC) $(top_builddir)/lib/$(TARGETLIB_SHARED): $(OBJECTS) @$(INSTALL) -d $(top_builddir)/lib $(SHARED_LD) $@ $(TARGETLIB_SONAME) $(OBJECTS) $(LDFLAGS_VERSIONING) cd $(top_builddir)/lib \ && $(RM) $(TARGETLIB_LINK1) $(TARGETLIB_LINK2) \ && $(LN_S) $(TARGETLIB_SHARED) $(TARGETLIB_LINK1) \ && $(LN_S) $(TARGETLIB_SHARED) $(TARGETLIB_LINK2) $(top_builddir)/lib/$(TARGETLIB_STATIC): $(OBJECTS) @$(INSTALL) -d $(top_builddir)/lib @$(RM) $@ $(AR) $(AROPTIONS) $@ $(OBJECTS) $(RANLIB) $@ install: install_so install_headers install_so: $(INSTALL_PROGRAM) $(top_builddir)/lib/$(TARGETLIB_SHARED) $(libdir)/$(TARGETLIB_SHARED) @$(RM) $(libdir)/$(TARGETLIB_LINK1) $(libdir)/$(TARGETLIB_LINK2) cd $(libdir) \ && $(LN_S) $(TARGETLIB_SHARED) $(TARGETLIB_LINK1) \ Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 88 && $(LN_S) $(TARGETLIB_SHARED) $(TARGETLIB_LINK2) install_a: $(INSTALL_PROGRAM) $(top_builddir)/lib/$(TARGETLIB_STATIC) $(libdir)/$(TARGETLIB_STATIC) install_headers: $(INSTALL) -d $(includedir)/wx/$(HEADER_SUBDIR) @for h in $(HEADERS); do \ $(INSTALL_DATA) $(HEADER_PATH)/$(HEADER_SUBDIR)/$$h $(includedir)/wx/$(HEADER_SUBDIR)/$$h; \ echo "installing $(includedir)/wx/$(HEADER_SUBDIR)/$$h"; \ done uninstall: $(RM) $(libdir)/$(TARGETLIB_STATIC) $(RM) $(libdir)/$(TARGETLIB_SHARED) $(RM) $(libdir)/$(TARGETLIB_LINK1) $(RM) $(libdir)/$(TARGETLIB_LINK2) @echo "removing headers" @for h in $(HEADERS); do \ $(RM) $(includedir)/wx/$(HEADER_SUBDIR)/$$h; \ done @if test -d $(includedir)/wx/$(HEADER_SUBDIR); then \ rmdir $(includedir)/wx/$(HEADER_SUBDIR); \ fi @-rmdir $(includedir)/wx clean: $(RM) $(OBJECTS) $(top_builddir)/lib/$(TARGETLIB_SHARED) \ $(top_builddir)/lib/$(TARGETLIB_LINK1) \ $(top_builddir)/lib/$(TARGETLIB_LINK2) \ $(top_builddir)/lib/$(TARGETLIB_STATIC) core .PHONY: all libtype_so libtype_a install install_so install_a install_headers uninstall clean Archivo makeprog.env # Make environment for making samples on Unix # The binary program extension, if any, including dots (e.g. '.exe') PROGRAM_EXT = BIN_PROGRAM = $(PROGRAM)$(PROGRAM_EXT) RES_PROGRAM_OBJ = BUNDLE = $(BIN_PROGRAM).app/Contents # NB: see remark in Makefile.in as to why we don't use %.foo: %.bar rules .SUFFIXES: .o .c .cpp .cxx .rc _resources.o .c.o: $(CC) -c $(CFLAGS) $(APPEXTRADEFS) -o $@ $< .cpp.o: $(CXX) -c $(CXXFLAGS) $(APPEXTRADEFS) -o $@ $< .cxx.o: $(CXX) -c $(CXXFLAGS) $(APPEXTRADEFS) -o $@ $< Agosto del 2004 IE-0502 89 Determinación de la posición de un objeto utilizando una cámara Web .rc_resources.o: $(RESCOMP) -i $< -o $@ $(RESFLAGS) # the comment at the end of the next line is needed because otherwise autoconf # would remove this line completely - it contains a built-in hack to remove # any VPATH assignment not containing ':' VPATH = :$(top_srcdir)/$(program_dir) # ':' for autoconf # Set defaults from configure include /root/wxwindows/wxGTK-2.4.2/demos/proyecto/make.env #include $(top_builddir)/src/make.env all: $(BIN_PROGRAM) install_dirs install_data $(BIN_PROGRAM): $(OBJECTS) $(top_builddir)/lib/libwx_gtk2u-2.4.so.0.1.1 $(RES_PROGRAM_OBJ) $(CXX) $(LDFLAGS_EXE) -o $@ $(OBJECTS) $(LDLIBS) $(LIBRARIES) $(RES_PROGRAM_OBJ) # install_dirs: @list='$(DATADIRS)'; for p in $$list; do \ mkdir -p $(top_builddir)/$(program_dir)/$$p; \ done install_data: @list='$(DATAFILES)'; for p in $$list; do \ if test ! -s $(top_builddir)/$(program_dir)/$$p; then \ cp -pRf $(top_srcdir)/$(program_dir)/$$p $(top_builddir)/$(program_dir)/$$p; \ fi; \ done clean: rm -f $(OBJECTS) $(DEPFILES) $(BIN_PROGRAM) $(RES_PROGRAM_OBJ) core # # Targets to build a Mac OS X application bundle # bundle: $(BUNDLE)/MacOS/$(PROGRAM) $(BUNDLE)/Info.plist $(BUNDLE)/PkgInfo $(BUNDLE)/Resources/$(PROGRAM).rsrc $(BUNDLE)/Resources/wxmac.icns $(BUNDLE)/Info.plist: $(top_srcdir)/src/$(TOOLKITDIR)/Info.plist.in $(top_builddir)/lib/libwx_gtk2u-2.4.so.0.1.1 @$(INSTALL) -d `dirname $@` sed -e "s/IDENTIFIER/`echo $(program_dir) | sed 's,/,.,g'`/" \ -e "s/EXECUTABLE/$(PROGRAM)/" \ -e "s/VERSION/$(WX_MAJOR_VERSION_NUMBER).$(WX_MINOR_VERSION_NUMBER).$(WX_RELEASE_NUM BER)/" $< > $@ $(BUNDLE)/PkgInfo: @$(INSTALL) -d `dirname $@` echo -n "APPL????" > $@ $(BUNDLE)/MacOS/$(PROGRAM): $(OBJECTS) $(top_builddir)/lib/libwx_gtk2u-2.4.so.0.1.1 @$(INSTALL) -d `dirname $@` $(CXX) $(LDFLAGS_EXE) -o $@ $(OBJECTS) $(LDLIBS) $(LIBRARIES) $(BUNDLE)/Resources/$(PROGRAM).rsrc: $(top_builddir)/lib/ Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 90 @$(INSTALL) -d `dirname $@` cp $< $@ $(BUNDLE)/Resources/wxmac.icns: $(top_srcdir)/src/$(TOOLKITDIR)/wxmac.icns @$(INSTALL) -d `dirname $@` cp $< $@ Archivo make.env # File: make.env # Author: Julian Smart, Robert Roebling, Vadim Zeitlin, Ron Lee # Created: 1993 # Updated: 2001 # Copyright:(c) 1993, AIAI, University of Edinburgh, # Copyright:(c) 1999, Vadim Zeitlin # Copyright:(c) 1999, Robert Roebling # Copyright:(c) 2001, Ron Lee # ####################### GENERAL SETTINGS ############################ # see comment near LDFLAGS at the end of file EXTRALIBS = -pthread -Wl,--version-script,$(top_builddir)/version-script -Wl,--export-dynamic -pthread -lgtk-x11-2.0 -lgdk-x11-2.0 -latk-1.0 -lgdk_pixbuf-2.0 -lm -lpangoxft -1.0 -lpangox-1.0 -lpango-1.0 -lgobject-2.0 -lgmodule-2.0 -ldl lgthread-2.0 -lglib-2.0 -lpng -ljpeg -ltiff -lz -Wl,--export-dynamic -lpangoft2-1.0 -lpango-1.0 -lgobject -2.0 -lgmodule-2.0 ldl -lglib-2.0 -lm -lMagick++ OPENGLLIBS = LDFLAGS_GL = LDLIBS = ${APPEXTRALIBS} ${top_builddir}/lib/libwx_gtk2u-2.4.so.0.1.1 ${EXTRALIBS} TOOLKIT = GTK TOOLKITDIR = gtk WXLIB = libwx_gtk2u-2.4.a WXSHLIB = libwx_gtk2u-2.4.so.0.1.1 WXLIBBASE = wx_gtk2u ########################### VERSION ################################# WX_MAJOR_VERSION_NUMBER = 2 WX_MINOR_VERSION_NUMBER = 4 WX_RELEASE_NUMBER = 2 ########################### Programs ################################# CXX CC = c++ = gcc # Compiler for lex/yacc .c programs CCLEX = gcc LEX = lex YACC = yacc AR = ar AS = NM = LN_S = ln -s Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 91 STRIP = strip AROPTIONS = rcu RANLIB = ranlib LD = MAKEINFO = RM = rm -f SHARED_LD = c++ -shared -o RESFLAGS = RESCOMP = DEREZ DLLTOOL = = INSTALL = /usr/bin/install -c INSTALL_PROGRAM = ${INSTALL} INSTALL_DATA = ${INSTALL} -m 644 INSTALL_SCRIPT = /usr/bin/install -c ########################### Flags ################################# DEBUG = -g CPPFLAGS = ${APPEXTRACPPFLAGS} -I${top_builddir}/lib/wx/include/gtk2u-2.4 -I${top_srcdir}/include -pthread -I/usr/include/gtk-2.0 -I/usr/lib/gtk-2.0/include -I/usr/include/atk-1.0 -I/usr/include/pango-1.0 -I/usr/include/freetype2 I/usr/X11R6/include -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -D_FILE_OFFSET_BITS=64 -D_LARGE_FILES $(EXTRADEFS) $(APPEXTRADEFS) -D__WXGTK__ -DGTK_NO_CHECK_CASTS CFLAGS = ${APPEXTRACFLAGS} ${CPPFLAGS} -O2 -MMD -pthread -Wall -c $(DEBUG) --pedantic CXXFLAGS = ${APPEXTRACXXFLAGS} ${CPPFLAGS} -O2 -MMD -I/usr/include/pango -1.0 I/usr/include/freetype2 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -pthread –Wall PICFLAGS = -fPIC # taking into account how SHARED_LD is defined, appending LDFLAGS to it # doesn't work, so we put them in the end of the linker command line in # EXTRALIBS instead (see above) # LDFLAGS = -pthread # specific linker flags for when building executables since there # Mac OS X requires specific linker flags for executables linked # against dynamic shared libraries LDFLAGS_EXE = Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 92 Programas para abrir las fotografías resultantes Archivo centroides.h #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include "wx/image.h" #include "wx/file.h" #include "wx/mstream.h" #include "wx/wfstream.h" #include "wx/quantize.h" class MyFrame; class interfaz; class MyCanvas: public wxScrolledWindow //clase para crear la foto como un Bitmap { public: MyCanvas() {} MyCanvas( wxWindow *parent, wxWindowID, const wxPoint &pos, const wxSize &size ); ~MyCanvas(); void OnPaint( wxPaintEvent &event ); wxBitmap *my_posiciones_jpeg; //declaracion del puntero tipo wxBitmap para portar la imagen private: //declaraciones de la tabla de eventos y de la clase dinamica DECLARE_DYNAMIC_CLASS(MyCanvas) DECLARE_EVENT_TABLE() }; class MyFrame: public wxFrame { public: MyFrame(); void OnAbout( wxCommandEvent &event ); //funciones de la barra de menu Archivo void OnQuit( wxCommandEvent &event ); MyCanvas *m_canvas; //puntero tipo MyCanvas para crear la imagen private: //declaraciones de la clase dinamica y la tabla de eventos de la clase DECLARE_DYNAMIC_CLASS(MyFrame) DECLARE_EVENT_TABLE() }; class interfaz : public wxApp //funcion inicial para crear las aplicaciones de la ventana { public: virtual bool OnInit(); Agosto del 2004 IE-0502 93 Determinación de la posición de un objeto utilizando una cámara Web protected: private: }; DECLARE_APP(interfaz) Archivo centroides.cpp // For compilers that support precompilation, includes "wx/wx.h". #include "wx/wxp rec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif // for all others, include the necessary headers #ifndef WX_PRECOMP #include "wx/app.h" #include "wx/log.h" #include "wx/frame.h" #include "wx/panel.h" #include "wx/stattext.h" #include "wx/menu.h" #include "wx/layout.h" #include "wx/msgdlg.h" #endif #include "wx/calctrl.h" #include "centroides.h" IIMPLEMENT_DYNAMIC_CLASS(MyCanvas, wxScrolledWindow) BEGIN_EVENT_TABLE(MyCanvas, wxScrolledWindow) //Tabla de eventos de la clase MyCanvas EVT_PAINT(MyCanvas::OnPaint) END_EVENT_TABLE() MyCanvas::MyCanvas( wxWindow *parent, wxWindowID id, //Esta es la instruccion para implementar la clase const wxPoint &pos, const wxSize &size ) //dinamica para observar la foto : wxScrolledWindow( parent, id, pos, size, wxSUNKEN_BORDER ) //constructor de la clase MyCanvas { my_posiciones_jpeg = (wxBitmap*) NULL; SetBackgroundColour(* wxWHITE); //se crea el fondo de la ventana blanco wxBitmap bitmap( 100, 100 ); //tamano de la foto wxMemoryDC dc; dc.SelectObject( bitmap ); dc.SetBrush( wxBrush( wxT("orange"), wxSOLID ) ); dc.SetPen( *wxBLACK_PEN ); dc.DrawRectangle( 0, 0, 100, 100 ); dc.SetBrush( *wxWHITE_BRUSH ); dc.DrawRectangle( 20, 20, 60, 60 ); dc.SelectObject( wxNullBitmap ); wxString dir; wxImage image = bitmap.ConvertToImage(); //se convierte el bitmap a imagen Agosto del 2004 IE-0502 94 Determinación de la posición de un objeto utilizando una cámara Web #if wxUSE_LIBJPEG image.Destroy(); if ( !image.LoadFile( dir + _T("/root/wxwindows/wxGTK-2.4.2/demos/proyecto_nuevo/centroides.jpg")) ) //Aqui va la direccion de la foto wxLogError(wxT("No se puede abrir la imagen")); //ventana de error en caso de no poder abrir la foto else my_posiciones_jpeg = new wxBitmap( image ); //agrega la foto a un Bitmap #endif // wxUSE_LIBJPEG } MyCanvas::~MyCanvas() { delete my_posiciones_jpeg; //destructor borra la imagen de la memoria } void MyCanvas::OnPaint( wxPaintEvent &WXUNUSED(event) ) //funcion para abrir la imagen { wxPaintDC dc( this ); PrepareDC( dc ); dc.DrawText( _T("Posiciones del Objeto"), 30, 15 ); //titulo de la foto if (my_posiciones_jpeg && my_posiciones_jpeg->Ok()) dc.DrawBitmap( *my_posiciones_jpeg, 30, 30 ); //se pone la imagen en la ventana y se le da la posicion 30,30 } const int ID_QUIT = 108; //declaraciones de la funciones de la barra de menu Archivo const int ID_ABOUT = 109; IMPLEMENT_DYNAMIC_CLASS( MyFrame, wxFrame ) BEGIN_EVENT_TABLE(MyFrame,wxFrame) EVT_MENU (ID_ABOUT, MyFrame::OnAbout) EVT_MENU (ID_QUIT, MyFrame::OnQuit) END_EVENT_TABLE() //tabla de MyFrame MyFrame::MyFrame() //constructor de la clase MyFrame para crear la ventana : wxFrame( (wxFrame *)NULL, -1, _T("Fotografia de las Posiciones del Objeto"), wxPoint(20,20), wxSize(470,360) ) //tamano de la ventana { wxMenu *file_menu = new wxMenu(); //se crea la barra de menu file_menu->Append( ID_ABOUT, _T("&Ayuda...")); file_menu->AppendSeparator(); file_menu->Append( ID_QUIT, _T("&Salir")); wxMenuBar *menu_bar = new wxMenuBar(); menu_bar->Append(file_menu, _T("&Archivo")); SetMenuBar( menu_bar ); //se agrega la barra de menu a la ventana CreateStatusBar(2); int widths[] = { -1, 100 }; SetStatusWidths( 2, widths ); Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 95 m_canvas = new MyCanvas( this, -1, wxPoint(0,0), wxSize(10,10) ); //se le agrega a la ventana la foto m_canvas->SetScrollbars( 10, 10, 10, 15 );//tamano de la ventana } void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event)) { Close(TRUE); //verdadera para salirse del programa } void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event)) { wxMessageBox(_T("Esta es la fotografia del fondo\nPara cerrarla, oprima Archivo y luego Salir\nVolvera a la ventana de ejecucion del programa de deteccion de objeto"), _T("AYUDA"), wxOK | wxICON_INFORMATION, this); //creditos del programa } IMPLEMENT_APP(interfaz) bool interfaz::OnInit() //funcion para la iniciacion de la ventana { // Se crea las aplicaciones principales de la ventana #if wxUSE_LIBJPEG wxImage::AddHandler( new wxJPEGHandler ); #endif wxFrame *frame = new MyFrame(); frame->Show( TRUE ); return true; } Archivo fondo.h #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include "wx/image.h" #include "wx/file.h" #include "wx/mstream.h" #include "wx/wfstream.h" #include "wx/quantize.h" class MyFrame; class interfaz; class MyCanvas: public wxScrolledWindow //clase para crear la foto como un Bitmap { public: MyCanvas() {} MyCanvas( wxWindow *parent, wxWindowID, const wxPoint &pos, const wxSize &size ); ~MyCanvas(); Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 96 void OnPaint( wxPaintEvent &event ); wxBitmap *my_fondo_jpeg; //declaracion del puntero tipo wxBitmap para portar la imagen private: //declaraciones de la tabla de eventos y de la clase dinamica DECLARE_DYNAMIC_CLASS(MyCanvas) DECLARE_EVENT_TABLE() }; class MyFrame: public wxFrame { public: MyFrame(); void OnAbout( wxCommandEvent &event ); //funciones de la barra de menu Archivo void OnQuit( wxCommandEvent &event ); MyCanvas *m_canvas; //puntero tipo MyCanvas para crear la imagen private: //declaraciones de la clase dinamica y la tabla de eventos de la clase DECLARE_DYNAMIC_CLASS(MyFrame) DECLARE_EVENT_TABLE() }; class interfaz : public wxApp //funcion inicial para crear las aplicaciones de la ventana { public: virtual bool OnInit(); protected: private: }; DECLARE_APP(interfaz) Archivo fondo.cpp // For compilers that support precompilation, includes "wx/wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif // for all others, include the necessary headers #ifndef WX_PRECOMP #include "wx/app.h" #include "wx/log.h" #include "wx/frame.h" #include "wx/panel.h" #include "wx/stattext.h" #include "wx/menu.h" #include "wx/layout.h" #include "wx/msgdlg.h" #endif #include "wx/calctrl.h" #include "fondo.h" Agosto del 2004 IE-0502 97 Determinación de la posición de un objeto utilizando una cámara Web IMPLEMENT_DYNAMIC_CLASS(MyCanvas, wxScrolledWindow) //Esta es la instruccion para implementar la clase //dinamica para observar la foto BEGIN_EVENT_TABLE(MyCanvas, wxScrolledWindow) //Tabla de eventos de la clase MyCanvas EVT_PAINT(MyCanvas::OnPaint) END_EVENT_TABLE() MyCanvas::MyCanvas( wxWindow *parent, wxWindowID id, //constructor de la clase MyCanvas const wxPoint &pos, const wxSize &size ) : wxScrolledWindow( parent, id, pos, size, wxSUNKEN_BORDER ) { my_fondo_jpeg = (wxBitmap*) NULL; SetBackgroundColour(* wxWHITE); wxBitmap bitmap( 100, 100 ); //se crea el fondo de la ventana blanco //tamano de la foto wxMemoryDC dc; dc.SelectObject( bitmap ); dc.SetBrush( wxBrush( wxT("orange"), wxSOLID ) ); dc.SetPen( *wxBLACK_PEN ); dc.DrawRectangle( 0, 0, 100, 100 ); dc.SetBrush( *wxWHITE_BRUSH ); dc.DrawRectangle( 20, 20, 60, 60 ); dc.SelectObject( wxNullBitmap ); wxString dir; wxImage image = bitmap.ConvertToImage(); //se convierte el bitmap a imagen #if wxUSE_LIBJPEG image.Destroy(); if ( !image.LoadFile( dir + _T("/root/wxwindows/wxGTK-2.4.2/demos/proyecto_nuevo/fondo1.jpg")) ) //Aqui va la direccion de la foto wxLogError(wxT("No se puede abrir la imagen")); //ventana de error en caso de no poder abrir la foto else my_fondo_jpeg = new wxBitmap( image ); //agrega la foto a un Bitmap #endif // wxUSE_LIBJPEG } MyCanvas::~MyCanvas() { delete my_fondo_jpeg; //destructor borra la imagen de la memoria } void MyCanvas::OnPaint( wxPaintEvent &WXUNUSED(event) ) //funcion para abrir la imagen { wxPaintDC dc( this ); PrepareDC( dc ); dc.DrawText( _T("Fondo"), 30, 15 ); if (my_fondo_jpeg && my_fondo_jpeg->Ok()) dc.DrawBitmap( *my_fondo_jpeg, 30, 30 ); //se pone la imagen en la ventana y se le da la posicion 30,30 Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 98 } const int ID_QUIT = 108; //declaraciones de la funciones de la barra de menu Archivo const int ID_ABOUT = 109; IMPLEMENT_DYNAMIC_CLASS( MyFrame, wxFrame ) BEGIN_EVENT_TABLE(MyFrame,wxFrame) //tabla de MyFrame EVT_MENU (ID_ABOUT, MyFrame::OnAbout) EVT_MENU (ID_QUIT, MyFrame::OnQuit) END_EVENT_TABLE() MyFrame::MyFrame() //constructor de la clase MyFrame para crear la ventana : wxFrame( (wxFrame *)NULL, -1, _T("Fotografia del Fondo"), //titulo de la ventana wxPoint(20,20), wxSize(470,360) ) //tamano de la ventana { wxMenu *file_menu = new wxMenu(); //se crea la barra de menu file_menu->Append( ID_ABOUT, _T("&Ayuda...")); file_menu->AppendSeparator(); file_menu->Append( ID_QUIT, _T("&Salir")); wxMenuBar *menu_bar = new wxMenuBar(); menu_bar->Append(file_menu, _T("&Archivo")); SetMenuBar( menu_bar ); //se agrega la barra de menu a la ventana CreateStatusBar(2); int widths[] = { -1, 100 }; SetStatusWidths( 2, widths ); m_canvas = new MyCanvas( this, -1, wxPoint(0,0), wxSize(10,10) ); //se le agrega a la ventana la foto m_canvas->SetScrollbars( 10, 10, 10, 15 );//tamano de la ventana } void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event)) { Close(TRUE); //verdadera para salirse del programa } void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event)) { wxMessageBox(_T("Esta es la fotografia del fondo\nPara cerrarla, oprima Archivo y luego Salir\nVolvera a la ventana de ejecucion del programa de deteccion de objeto"), _T("AYUDA"), wxOK | wxICON_INFORMATION, this); //creditos del programa } IMPLEMENT_APP(interfaz) bool interfaz::OnInit() //funcion para la iniciacion de la ventana { // Se crea las aplicaciones principales de la ventana #if wxUSE_LIBJPEG wxImage::AddHandler( new wxJPEGHandler ); #endif wxFrame *frame = new MyFrame(); frame->Show( TRUE ); Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 99 return true; } Archivo objeto.h #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include "wx/image.h" #include "wx/file.h" #include "wx/mstream.h" #include "wx/wfstream.h" #include "wx/quantize.h" class MyFrame; class interfaz; class MyCanvas: public wxScrolledWindow //clase para crear la foto como un Bitmap { public: MyCanvas() {} MyCanvas( wxWindow *parent, wxWindowID, const wxPoint &pos, const wxSize &size ); ~MyCanvas(); void OnPaint( wxPaintEvent &event ); wxBitmap *my_objeto_jpeg; //declaracion del puntero tipo wxBitmap para portar la imagen private: //declaraciones de la tabla de eventos y de la clase dinamica DECLARE_DYNAMIC_CLASS(MyCanvas) DECLARE_EVENT_TABLE() }; class MyFrame: public wxFrame { public: MyFrame(); void OnAbout( wxCommandEvent &event ); void OnQuit( wxCommandEvent &event ); MyCanvas *m_canvas; //funciones de la barra de menu Archivo //puntero tipo MyCanvas para crear la imagen private: //declaraciones de la clase dinamica y la tabla de eventos de la clase DECLARE_DYNAMIC_CLASS(MyFrame) DECLARE_EVENT_TABLE() }; class interfaz : public wxApp //funcion inicial para crear las aplicaciones de la ventana Agosto del 2004 IE-0502 100 Determinación de la posición de un objeto utilizando una cámara Web { public: virtual bool OnInit(); protected: private: }; DECLARE_APP(interfaz) Archivo objeto.cpp // For compilers that support precompilation, includes "wx/wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif // for all others, include the necessary headers #ifndef WX_PRECOMP #include "wx/app.h" #include "wx/log.h" #include "wx/frame.h" #include "wx/panel.h" #include "wx/stattext.h" #include "wx/menu.h" #include "wx/layout.h" #include "wx/msgdlg.h" #endif #include "wx/calctrl.h" #include "objeto.h" IIMPLEMENT_DYNAMIC_CLASS(MyCanvas, wxScrolledWindow) BEGIN_EVENT_TABLE(MyCanvas, wxScrolledWindow) //Tabla de eventos de la clase MyCanvas EVT_PAINT(MyCanvas::OnPaint) END_EVENT_TABLE() MyCanvas::MyCanvas( wxWindow *parent, wxWindowID id, //Esta es la instruccion para implementar la clase const wxPoint &pos, const wxSize &size ) //dinamica para observar la foto : wxScrolledWindow( parent, id, pos, size, wxSUNKEN_BORDER ) //constructor de la clase MyCanvas { { my_objeto_jpeg = (wxBitmap*) NULL; SetBackgroundColour(* wxWHITE); wxBitmap bitmap( 100, 100 ); //se crea el fondo de la ventana blanco //tamano de la foto wxMemoryDC dc; dc.SelectObject( bitmap ); dc.SetBrush( wxBrush( wxT("orange"), wxSOLID ) ); dc.SetPen( *wxBLACK_PEN ); dc.DrawRectangle( 0, 0, 100, 100 ); dc.SetBrush( *wxWHITE_BRUSH ); dc.DrawRectangle( 20, 20, 60, 60 ); dc.SelectObject( wxNullBitmap ); Agosto del 2004 IE-0502 101 Determinación de la posición de un objeto utilizando una cámara Web wxString dir; wxImage image = bitmap.ConvertToImage(); //se convierte el bitmap a imagen #if wxUSE_LIBJPEG image.Destroy(); if ( !image.LoadFile( dir + _T("/root/wxwindows/wxGTK-2.4.2/demos/proyecto_nuevo/objeto.jpg")) ) //Aqui va la direccion de la foto wxLogError(wxT("No se puede abrir la image n")); else my_objeto_jpeg = new wxBitmap( image ); //agrega la foto a un Bitmap #endif // wxUSE_LIBJPEG } MyCanvas::~MyCanvas() { delete my_objeto_jpeg; //destructor borra la imagen de la memoria } void MyCanvas::OnPaint( wxPaintEvent &WXUNUSED(event) ) //funcion para abrir la imagen { wxPaintDC dc( this ); PrepareDC( dc ); dc.DrawText( _T("Objeto"), 30, 15 ); //titulo de la foto if (my_objeto_jpeg && my_objeto_jpeg->Ok()) dc.DrawBitmap( *my_objeto_jpeg, 30, 30 ); //se pone la imagen en la ventana y se le da la posicion 30,30 } const int ID_QUIT = 108; //declaraciones de la funciones de la barra de menu Archivo const int ID_ABOUT = 109; IMPLEMENT_DYNAMIC_CLASS( MyFrame, wxFrame ) BEGIN_EVENT_TABLE(MyFrame,wxFrame) //tabla de MyFrame EVT_MENU (ID_ABOUT, MyFrame::OnAbout) EVT_MENU (ID_QUIT, MyFrame::OnQuit) END_EVENT_TABLE() MyFrame::MyFrame() //constructor de la clase MyFrame para crear la ventana : wxFrame( (wxFrame *)NULL, -1, _T("Fotografia del Objeto"), wxPoint(20,20), wxSize(470,360) ) //tamano de la ventana { wxMenu *file_menu = new wxMenu(); //se crea la barra de menu file_menu->Append( ID_ABOUT, _T("&Ayuda...")); file_menu->AppendSeparator(); file_menu->Append( ID_QUIT, _T("&Salir")); wxMenuBar *menu_bar = new wxMenuBar(); menu_bar->Append(file_menu, _T("&Archivo")); SetMenuBar( menu_bar ); //se agrega la barra de menu a la ventana Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 102 CreateStatusBar(2); int widths[] = { -1, 100 }; SetStatusWidths( 2, widths ); m_canvas = new MyCanvas( this, -1, wxPoint(0,0), wxSize(10,10) ); //se le agrega a la ventana la foto m_canvas->SetScrollbars( 10, 10, 10, 10 );//tamano de la ventana } void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event)) { Close(TRUE); //verdadera para salirse del programa } void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event)) { wxMessageBox(_T("Esta es la fotografia del objeto\nPara cerrarla, oprima Archivo y luego Salir\nVolvera a la ventana de ejecucion del programa de deteccion de objeto"), _T("AYUDA"), wxOK | wxICON_INFORMATION, this); //creditos del programa } IMPLEMENT_APP(interfaz) bool interfaz::OnInit() //funcion para la iniciacion de la ventana { // Se crea las aplicaciones principales de la ventana #if wxUSE_LIBJPEG wxImage::AddHandler( new wxJPEGHandler ); #endif wxFrame *frame = new MyFrame(); frame->Show( TRUE ); return true; } Archivo posición.h #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include "wx/image.h" #include "wx/file.h" #include "wx/mstream.h" #include "wx/wfstream.h" #include "wx/quantize.h" class MyFrame; class interfaz; class MyCanvas: public wxScrolledWindow //clase para crear la foto como un Bitmap Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 103 { public: MyCanvas() {} MyCanvas( wxWindow *parent, wxWindowID, const wxPoint &pos, const wxSize &size ); ~MyCanvas(); void OnPaint( wxPaintEvent &event ); wxBitmap *my_posicion_jpeg; //declaracion del puntero tipo wxBitmap para portar la imagen private: //declaraciones de la tabla de eventos y de la clase dinamica DECLARE_DYNAMIC_CLASS(MyCanvas) DECLARE_EVENT_TABLE() }; class MyFrame: public wxFrame { public: MyFrame(); void OnAbout( wxCommandEvent &event ); //funciones de la barra de menu Archivo void OnQuit( wxCommandEvent &event ); MyCanvas *m_canvas; //puntero tipo MyCanvas para crear la imagen private: DECLARE_DYNAMIC_CLASS(MyFrame) DECLARE_EVENT_TABLE() }; class interfaz : public wxApp //funcion inicial para crear las aplicaciones de la ventana { public: virtual bool OnInit(); protected: private: }; DECLARE_APP(interfaz) Archivo posición.cpp // For compilers that support precompilation, includes "wx/wx.h". #include "wx/wxprec.h" #include <iostream> #include <string> using std::string; #include <cstdlib> #include <fstream> #ifdef __BORLANDC__ #pragma hdrstop #endif // for all others, include the necessary headers #ifndef WX_PRECOMP #include "wx/app.h" #include "wx/log.h" #include "wx/frame.h" #include "wx/panel.h" Agosto del 2004 IE-0502 104 Determinación de la posición de un objeto utilizando una cámara Web #include "wx/stattext.h" #include "wx/menu.h" #include "wx/layout.h" #include "wx/msgdlg.h" #endif #include "wx/calctrl.h" #include "posicion.h" IMPLEMENT_DYNAMIC_CLASS(MyCanvas, wxScrolledWindow) //Esta es la instruccion para implementar la clase //dinamica para observar la foto BEGIN_EVENT_TABLE(MyCanvas, wxScrolledWindow) EVT_PAINT(MyCanvas::OnPaint) END_EVENT_TABLE() MyCanvas::MyCanvas( wxWindow *parent, wxWindowID id, //Esta es la instruccion para implementar la clase const wxPoint &pos, const wxSize &size ) : wxScrolledWindow( parent, id, pos, size, wxSUNKEN_BORDER ) //constructor de la clase MyCanvas { my_posicion_jpeg = (wxBitmap*) NULL; SetBackgroundColour(* wxWHITE); //se crea el fondo de la ventana blanco wxBitmap bitmap( 100, 100 ); //tamano de la foto wxMemoryDC dc; dc.SelectObject( bitmap ); dc.SetBrush( wxBrush( wxT("orange"), wxSOLID ) ); dc.SetPen( *wxBLACK_PEN ); dc.DrawRectangle( 0, 0, 100, 100 ); dc.SetBrush( *wxWHITE_BRUSH ); dc.DrawRectangle( 20, 20, 60, 60 ); dc.SelectObject( wxNullBitmap ); wxString dir; wxImage image = bitmap.ConvertToImage(); //se convierte el bitmap a imagen #if wxUSE_LIBJPEG image.Destroy(); if ( !image.LoadFile( dir + _T("/root/wxwindows/wxGTK-2.4.2/demos/proyecto_nuevo/Posicion1")) ) //Aqui va la direccion de la foto wxLogError(wxT("No se puede abrir la imagen")); else my_posicion_jpeg = new wxBitmap( image ); //agrega la foto a un Bitmap #endif // wxUSE_LIBJPEG } MyCanvas::~MyCanvas() { delete my_posicion_jpeg; //destructor borra la imagen de la memoria } Agosto del 2004 IE-0502 105 Determinación de la posición de un objeto utilizando una cámara Web void MyCanvas::OnPaint( wxPaintEvent &WXUNUSED(event) ) //funcion para abrir la imagen { wxPaintDC dc( this ); PrepareDC( dc ); dc.DrawText( _T("Posicion del Objeto"), 30, 15 ); //titulo de la foto if (my_posicion_jpeg && my_posicion_jpeg->Ok()) dc.DrawBitmap( *my_posicion_jpeg, 30, 30 ); //se pone la imagen en la ventana y se le da la posicion 30,30 } const int ID_QUIT = 108; //declaraciones de la funciones de la barra de menu Archivo const int ID_ABOUT = 109; IMPLEMENT_DYNAMIC_CLASS( MyFrame, wxFrame ) BEGIN_EVENT_TABLE(MyFrame,wxFrame) //tabla de MyFrame EVT_MENU (ID_ABOUT, MyFrame::OnAbout) EVT_MENU (ID_QUIT, MyFrame::OnQuit) END_EVENT_TABLE() MyFrame::MyFrame() //constructor de la clase MyFrame para crear la ventana : wxFrame( (wxFrame *)NULL, -1, _T("Fotografia del Objeto en la Posicion"), wxPoint(20,20), wxSize(470,360) ) //tamano de la ventana { wxMenu *file_menu = new wxMenu(); //se crea la barra de menu file_menu->Append( ID_ABOUT, _T("&Ayuda...")); file_menu->AppendSeparator(); file_menu->Append( ID_QUIT, _T("&Salir")); wxMenuBar *menu_bar = new wxMenuBar(); menu_bar->Append(file_menu, _T("&Archivo")); SetMenuBar( menu_bar ); //se agr ega la barra de menu a la ventana CreateStatusBar(2); int widths[] = { -1, 100 }; SetStatusWidths( 2, widths ); m_canvas = new MyCanvas( this, -1, wxPoint(0,0), wxSize(10,10) ); //se le agrega a la ventana la foto m_canvas->SetScrollbars( 10, 10, 10, 15 );//tamano de la ventana } void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event)) { Close(TRUE); //verdadera para salirse del programa } void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event)) { wxMessageBox(_T("Esta es la fotografia del fondo\nPara cerrarla, oprima Archivo y luego Salir\nVolvera a la ventana de ejecucion del programa de deteccion de objeto"), _T("AYUDA"), wxOK | wxICON_INFORMATION, this); //creditos del programa } IMPLEMENT_APP(interfaz) Agosto del 2004 IE-0502 Determinación de la posición de un objeto utilizando una cámara Web 106 bool interfaz::OnInit() //funcion para la iniciacion de la ventana { // Se crea las aplicaciones principales de la ventana #if wxUSE_LIBJPEG wxImage::AddHandler( new wxJPEGHandler ); #endif wxFrame *frame = new MyFrame(); frame->Show( TRUE ); return true; } Agosto del 2004