OpenCV – Mouse Event Handler (parte 1)

Para aquellos que os estáis introduciendo un poco en temas de visión artificial, seguramente ya habréis oído hablar de OpenCV, pero para los que no, os explico someramente lo que es.

OpenCV es una librería de visión artificial desarrollada originalmente por Intel y licenciada como BSD. OpenCV está escrito en C/C++ y es multiplataforma GNU/Linux, Mac OS XWindows, IOS y Android. El proyecto proporciona un entorno de programación fácil de utilizar, altamente eficiente y sin dependencias a librerías de terceros.

Una de las herramientas esenciales cuando se trabaja en visión es la visualización e interacción con los resultados (véase imagen). OpenCV cubre perfectamente este tipo de necesidades. Para ello voy a presentar un ejemplo sencillo de manejo de ventanas con eventos de ratón.

GMM-GC-segmentation

En el siguiente código se muestra una función que renderiza una ventana:

void showWindow()
{
  	//Create an autoresize window
	namedWindow("My Window", 1);

	//Set the callback function for any mouse event
	setMouseCallback("My Window", mouseEventHandler, NULL);

	//Show the image
	frame = cv::imread("0001_.jpg");
	imshow("My Window", frame);

	//Wait until user press some key
	waitKey(0);
}

El método "namedWindow" nos permite crear una ventana con un nombre que la identifique y que además se autodimensione dependiendo el contenido que muestre. Para cargar un fichero de imagen basta con usar "imread" especificando el nombre o path del fichero para cargarlo en un objeto Mat de OpenCV. La variable "frame" es del tipo Mat mencionado, que se ha definido como global fuera de la función. Por último "waitKey" nos permite tener renderizándose la ventana hasta que se presione alguna tecla o se cierre desde el aspa de cierre de la ventana.

Habréis apreciado que me he saltado el método "setMouseCallback", pero lo he hecho para enlazar con el siguiente fragmento de código. Dicho método, nos permite asociar un callback a una ventana usando su nombre de identificación(en nuestro caso "My Windows") y pudiendo pasar parámetros adicionales (en nuestro caso no se pasa ninguno y se pasa un NULL).

void mouseEventHandler(int event, int x, int y, int flags, void* param)
{
	if  ( event == EVENT_LBUTTONDOWN )
	{
		cout << "Left button of the mouse is clicked DOWN - position (" << x << ", " << y << ")" << endl;
	}
	else if  ( event == EVENT_LBUTTONUP )
	{
		cout << "Left button of the mouse is clicked UP - position (" << x << ", " << y << ")" << endl;
	}
	else if  ( event == EVENT_LBUTTONDBLCLK )
	{
		cout << "Left button of the mouse is double clicked - position (" << x << ", " << y << ")" << endl;
	}
	else if  ( event == EVENT_RBUTTONDOWN )
	{
		cout << "Right button of the mouse is clicked DOWN - position (" << x << ", " << y << ")" << endl;
	}
	else if  ( event == EVENT_RBUTTONUP )
	{
		cout << "Right button of the mouse is clicked UP - position (" << x << ", " << y << ")" << endl;
	}
	else if  ( event == EVENT_RBUTTONDBLCLK )
	{
		cout << "Right button of the mouse is double clicked - position (" << x << ", " << y << ")" << endl;
	}
	else if  ( event == EVENT_MBUTTONDOWN )
	{
		cout << "Middle button of the mouse is clicked DOWN - position (" << x << ", " << y << ")" << endl;
	}
	else if  ( event == EVENT_MBUTTONUP )
	{
		cout << "Middle button of the mouse is clicked UP - position (" << x << ", " << y << ")" << endl;
	}
	else if  ( event == EVENT_MBUTTONDBLCLK )
	{
		cout << "Middle button of the mouse is double clicked - position (" << x << ", " << y << ")" << endl;
	}
	else if ( event == EVENT_MOUSEMOVE )
	{
		cout << "Mouse move over the window - position (" << x << ", " << y << ")" << endl;
	}
}

Cada vez que se produzca alguno de los siguientes eventos:

  • EVENT_MOUSEMOVE
  • EVENT_LBUTTONDOWN
  • EVENT_RBUTTONDOWN
  • EVENT_MBUTTONDOWN
  • EVENT_LBUTTONUP
  • EVENT_RBUTTONUP
  • EVENT_MBUTTONUP
  • EVENT_LBUTTONDBLCLK
  • EVENT_RBUTTONDBLCLK
  • EVENT_MBUTTONDBLCLK

Se invocará a la función callback "mouseEventHandler". En el código se puede observar que la sucesión de los distintos "if" permite identificar el tipo de evento. En el caso concreto del movimiento del ratón, además se imprimen las coordenadas de la ventana a las que se ha desplazado el ratón, utilizando los parámetros "x" e "y" que recibe "mouseEventHandler".

A continuación dejo el código completo de la arquitectura básica para el manejo de eventos:

 

Medir tiempo de ejecución en C++

Habitualmente una de las cosas que nos interesa medir cuando programamos código, es el tiempo de ejecución. Identificar las secciones de código que más impactan en el tiempo de ejecución total, nos permite optimizar el código y disminuir el tiempo de ejecución general de todo nuestro código.

chronometre

En C++ hay varias formas de hacerlo, pero dependiendo de cómo lo implementemos y qué cabeceras usemos, podemos encontrarnos que al compilar nuestro código en ciertos sistemas no nos funcione. El siguiente ejemplo muestra cómo medir tiempos en una sección de código utilizando cabeceras estándar de C++:

#include <iostream>
#include <ctime> 

unsigned t0, t1;

t0=clock()
// Code to execute
t1 = clock();

double time = (double(t1-t0)/CLOCKS_PER_SEC);
cout << "Execution Time: " << time << endl;

La función "clock" retorna el tiempo consumido por el programa medido en ticks,  que junto con la macro "CLOCKS_PER_SEC" nos permite traducir los ticks a segundos.

El código también se encuentra disponible en:

execution_time.cpp

Evernote – Base de conocimiento Personal

Muchas veces apuntamos cosas, o decimos que nos tenemos que acordar de algo, y hacemos pequeñas notas mentales o escritas que resultan importantes para nosotros, ya que de alguna forma queremos que sirvan de recuerdo en un futuro lejano o no.

Llevo varios años usando sistemas combinados o ideados por mí mismo para tal cometido. Usando blogs, notas en el sistema operativo o en la nube, creando las anotaciones allí donde pienso que las necesitaré y que por alguna razón pienso que nunca se perderán y las encontraré. Pero esto no es así siempre y muchas veces necesitas hacer un gran esfuerzo  para recordar dónde dejaste la nota que contiene información que ahora necesitas, o simplemente acordarte de aquello que dijiste que te tenías que acordar para un futuro.

Por otro lado en lo que concierne al conocimiento, es bien sabido que la información con la que ya hemos trabajado y nos resultó útil, resulta una fuente muchos más conveniente a causa de ser un conocimiento asimilado, tanto en contenido como en la forma en la que se presenta. Recordar y volver a utilizar esa información que resulta un conocimiento más real por ser conocido, hace que haya una mejor y más directa aplicación del mismo.

evernote_notes

Yo creo haber dado con la solución, y se llama Evernote. Es un sistema que te permite dejar cualquier tipo de nota manuscrita, tipografiada(con el teclado), con imágenes, urls, capturas, adjuntos…. Suena como un cajón desastre, pero lo que realmente le da fuerza al sistema es su capacidad de búsqueda y de indexación y la posibilidad de integrarse con el sistema y los navegadores. También puede integrarse en móviles, tablets o sistemas similares…. Lo mejor de todo llega cuando encima tiene capacidad de sincronización en la nube y te permite tener acceso y añadir contenidos cuando quieras desde donde quieras. También tiene capacidad de uso la herramienta vía web, lo que aumenta aún más  el alcance de un sistema completo como pocos.

evernote_archive

Si sueles hacer anotaciones, bien porque andas con mil cosas, eres imaginativo, o necesitas un soporte para hacer un seguimiento y gestión de aquellas cosas que te gustaría recordar en un futuro, tu herramienta es EverNote:

https://evernote.com/intl/es/evernote/

La información no vale para nada cuando la guardas; vale cuando la necesitas.

Protocolo de exclusión robots.txt

Desde hace unos años se viene implantando una cultura de rendir cuentas y de la transparencia. Una de las forma más fáciles para mostrar aquellos resultados o datos que hacen considerarse transparente a una organización, es la creación de una web y publicación de datos en la misma. Pero, ¿una web realmente convierte a una organización en transparente? La respuesta inmediata es no del todo.

Por aquí no pases

En la red existe un protocolo de exclusión de robots para evitar que ciertos bots que analizan los sitios web u otros robots que investigan todo o una parte del acceso de un sitio Web, público o privado, agreguen información innecesaria a los resultados de búsqueda. A tal efecto en la raíz de cualquier sitio web, es posible especificar un archivo "robots.txt" con dichas exclusiones. El fichero robots.txt es un archivo de texto que dicta unas recomendaciones para que todos los crawlers y robots de buscadores cumplan.

robots-txt

Se dice que son recomendaciones, porque un archivo robots.txt en un sitio web, funcionará como una petición que especifica que determinados robots no hagan caso a archivos o directorios específicos en su búsqueda. Este protocolo es consultivo y se confía en la cooperación de los robots del sitio Web, de modo que marca una o más áreas de un sitio fuera de los límites de búsqueda con el uso de un archivo robots.txt, aunque éste no necesariamente garantice aislamiento completo.

Algunos administradores de sitios Web utilizan el archivo robots.txt para hacer algunas secciones privadas, invisibles al resto del mundo, pero dado que los archivos están disponibles de forma pública, su contenido podría ser visto de todas maneras por cualquier persona con un navegador Web y conocimientos medianamente avanzados. En algunos casos el incluir un directorio en este archivo, anuncia de su presencia a posibles hackers.

Esta práctica además puede conllevar la intención de no cachear e indexar ciertos contenidos en la Red a fin de no dejar huella en Internet. A día de hoy Google (con su Googlebot) cachea la información de cualquier web y es posible acceder a la información incluso aunque la web esté caída. Google actualiza y/o elimina la información cacheada de una web según evoluciona el sitio web. Además Google utiliza distintos bots rastreadores para cada tipo de contenido o actividad, los cuales hacen más óptimo la indexación y cacheo de las webs.

Para cualquier resultado web en Google, existe la posibilidad de entrar a la versión cacheada desde la flecha que apunta hacia abajo al final de la dirección.

Google_cache

Por otro lado existen servicios como Wayback Machine que cachean e indexan webs, de tal forma que es posible acceder al estado de una determinada web para una fecha concreta. Digamos que hace fotografías del estado de los sitios web y los va guardando para su consulta en un futuro, como si de un diario se tratase.

El fichero robots.txt

Estructuralmente el fichero robots.txt tiene esta pinta:

User-agent: *
Disallow: /gestion/
Disallow: /imgcache/
Disallow: /demos/
Disallow: /demoweb/
Disallow: /boletines/
Disallow: /grtp/
Disallow: /baliabideak/
Disallow: /dir_phplist/
Disallow: /adjuntos/
Disallow: /partekatzeko/
Disallow: /phplist/
Disallow: /swf/

El campo User-agent especifica los bots que deben respetar el fichero. En nuestro ejemplo, el * quiere decir que todos lo deben cumplir. A continuación se añade un linea con el campo Disallow para cada directorio o recurso que no queramos que sea indexado y cacheado. Del mimos modo existe el campo Allow si se quiere explicitar algún directorio o recurso, pero no se usa ya que por defecto la mayoría de bots rastreará todo el contenido que encuentre, a no ser que encuentre alguna exclusión (disallow). Es fácil encontrar estos archivos en muchas webs, añadiendo /robots.txt a la dirección principal.

Ejemplo: http://www.google.es/robots.txt

Podéis encontrar más información sobre el fichero robots.txt en la siguiente dirección:

http://www.emezeta.com/articulos/robots-txt-todo-lo-que-deberia-saber

Conclusión

Volviendo a la pregunta con la que habríamos el artículo, una web no quiere decir transparencia por sí misma, aunque éste sea su fin último, puesto que el uso de un fichero robots.txt para ocultar recursos y directorios  a ojos robots de indexación, propicia no dejar huella y dificultar la trazabilidad de un recurso a lo largo de su existencia en la Red.