lunes, 4 de agosto de 2014

El diablo con peor vista del mundo

Qué encontrarás en esta entrada?
  • Reconocimiento (AMATEUR) de imágenes por MATLAB.
  • Integración con BASH de Linux.

Siguiendo en la línea de mis últimas entradas, estoy mejorando mi sistema de comunicación con mi ordenador a través del móvil. Los que seáis lectores habituales de la página, recordaréis la reciente entrada "Comunicación ordenada", en la que hablaba de cómo redirigir CenterIM (un programa de mensajería instantánea en línea de comandos) para que respondiera un "contestador automático", que realmente era un script en shell de Linux. De esta manera, y según lo que le mandases a tu ordenador vía Hangouts, él "te respondía" atendiendo a las directrices de dicho script.

Comentaba entonces que esto abría infinitas posibilidades. Por ejemplo, podemos colocar una webcam, instalarnos Motion para la detección del movimiento, y poder controlarlo desde nuestro móvil y que nos mande avisos si alguien entra en nuestra casa.

Una de las cosas que más me gusta de programar en shell es la facilidad que hay para integrarlo con otros programas que corran desde Linux. Se me ocurrió hacer un sistema de detección de imágenes basado en octave (la versión libre análoga a MATLAB), y eso es lo que os voy a contar hoy.

Antes de nada: no os hagáis muchas ilusiones. Esto es un juego en vías de desarrollo basado en ideas muy simples que sólo pretende ilustrar las posibilidades que se abren para la gente con interés en el tema.

En primer lugar, os muestro cómo ve mi ordenador.


De lujo, ¿verdad? Estáis viendo mi habitación con la luz apagada... bueno, dicho así suena un poco estúpido, pero desarrollaré la idea a continuación.

Maravillosa y nítida imagen de mi habitación a oscuras

Tengo una webcam situada en una posición fija de mi cuarto. El objetivo es que sepa diferenciar distintas situaciones y, para ello, no me importa si cambian sutilmente un número determinado de píxeles. Lo que quiero es que reconozca patrones de una manera fácil.

En una primera fase me he centrado en las condiciones de luz y en la apertura de mi puerta. Al cambiar las condiciones de luz, varían las sombras, y al abrir o cerrar la puerta, interfiere la luz que proviene del exterior. En teoría esto debería dejar unos patrones más o menos estándar.

¿Qué hago para crear el patrón? "Repixelado e indexado". Como he comentado antes, no me interesa la variación pixel por pixel, sino por zonas. Mi primera idea ha sido unir varios píxeles en lo que podríamos llamar "macro-píxeles", los cuales tendrían la luminosidad media de los píxeles que se encuentran en su interior. La segunda idea, ha sido normalizar el color a tres estados: negro (para las zonas con luminosidad baja), blanco (para las de luminosidad alta) y gris (para las de luminosidad media). Con esto mi intención es facilitar el análisis de coincidencias por comparación directa con una imagen modelo.

celda=32;    % Tamaño de la celda.
[I,J,K]=size(IMG);
% Valores límite:
media=mean(mean(mean(IMG)));
maxim=max(max(max(IMG)));
minim=min(min(min(IMG)));
% Indexando y repixelado:
i=1;
for ni=1:(I/celda)
    j=1;
    for nj=1:(J/celda)
        IMGrp(ni,nj)=mean(mean(mean(IMG(i:i+(celda-1),j:j+(celda-1),1:3))));
        % Indexado:
        if IMGrp(ni,nj) < mean([minim,media])
            IMGrp(ni,nj)=0;
        else
            if IMGrp(ni,nj) > mean([media,maxim])
                IMGrp(ni,nj)=255;
            else
                IMGrp(ni,nj)=127;
            end
        end
        j=j+celda;
    end
    i=i+celda;
end

La siguiente parte es la toma de imágenes modelo. Una vez tomadas, se capta la imagen "muestra" y se la somete al mismo tratamiento (monocromatizado + repixelado + indexado), comparándola a continuación, "macro-pixel" a "macro-pixel", hasta obtener unos "coeficientes de similaridad" según coincidan con las imágenes modelo.


En principio, la que mayor coeficiente de similaridad tenga, representa la respuesta correcta.

Patrón que da la puerta de mi cuarto abierta con la habitación apagada

Una vez programado en octave, desde bash sólo habría que llamarlo de la siguiente forma:

echo "comando_de_matlab" | octave

De esta manera hemos unido octave con shell. A través de CenterIM, unimos shell con nuestro móvil y... voilà! Podemos recibir en nuestro móvil información procesada con octave y, en mi caso, retransmitida por el siempre carismático Diablo Fumado.


Como en otras tantas ocasiones, las posibilidades son infinitas. ¿Cuál es la vuestra?


ACTUALIZACIÓN (05/08/2014)

Creo que en la entrada que escribí ayer me quedé un poco corto de ejemplos y me gustaría que vierais de forma más dinámica cómo funciona el programa. Los siguientes ejemplos son muestras reales del amanecer de esta mañana en mi casa. Las fotos, y su posterior análisis, se han realizado mediante una orden que he dado yo desde mi móvil mientras estaba de camino al trabajo.

Caso #1: Habitación en oscuridad total (6:19am).

La imagen real y la simplificada fueron las siguientes:


Se ve que, pese a la oscuridad casi total, la cámara presenta un efecto parecido al viñeteo, pero a la inversa: los bordes son más claros que el centro. En la imagen original yo diría que es imperceptible, pero al transformarla en un patrón, tomando como referencia los máximos y mínimos de una imagen en la cuál ambos son casi iguales (e iguales a cero), se acentúa el contraste apareciendo este efecto.

Y a 30 km de distancia, en mi móvil (además de la foto), pudo leerse:


Caso #2: Habitación en penumbra (7:16am).

Las imágenes:


Ahora, la imagen simplificada no muestra una tendencia a la simetría radial como en el caso anterior. Con mayor cantidad de luz, los defectos en la captura homogénea de la cámara se hacen más irrelevantes y aparecen las primeras áreas de sombra y penumbra, definiendo zonas diferenciadas entre sí. Nótese que la caja blanca es con mucha diferencia el objeto que más luz está reflejando de la habitación a estas horas, y por tanto es también la única zona que queda clasificada como "luces altas" (color blanco).

La respuesta que recibo es la siguiente:


Caso #3: Habitación iluminada (7:35am).

Las imágenes:


Las paredes blancas, en contacto con la luz del sol entrante, empiezan a reflejar y a adquirir relevancia en la imagen. Las zonas negras se reducen y el patrón obtenido es más luminoso.

La respuesta que me llega:


Bueno, tres de tres, no ha estado mal, aunque aún necesita un poco de entrenamiento.


ACTUALIZACIÓN (07/08/2014)

Sigo entrenando al Diablo Fumado para que vea correctamente y me comunique sus conclusiones por Hangouts y correo electrónico. Para ello, he aumentado la resolución (reducido el tamaño de la celda del repixelado) y completado la paleta de colores (ahora uso un blanco, un negro, y dos grises medios). Pero sobre todo, lo que estoy aumentando es el número de imágenes (o "situaciones") con las que estoy comparando. Actualmente tengo definidos 14 escenarios posibles. Con todo ello, ya se empiezan a ver algunos resultados interesantes.


Parece que distingue correctamente entre los distintos estados de iluminación, diferenciando la luz natural de la artificial, y empieza a acertar también en lo que respecta a la situación de la puerta (cosa que desde el principio le ha costado). Seguiré trabajando en ello...

martes, 22 de julio de 2014

Monitorizando el Sistema (Linux)

Qué encontrarás en esta entrada?
  • Comandos para monitorizar el sistema en Linux.

En la última entrada hablábamos de cómo comunicarnos con nuestro ordenador a través del conocido programa de mensajería instantánea de Google, Hangouts (la evolución de gTalk). Esto nos permitía "hablar" con nuestro ordenador desde cualquier lugar del mundo utilizando, por ejemplo, un teléfono móvil con conexión a Internet.

Como ya comenté en la anterior publicación, las posibilidades que se abren ante nosotros son infinitas. A mi se me ha ocurrido (aunque he de reconocer que no ha sido una idea muy original) utilizarlo para monitorizar el sistema a distancia.


Existen muchas formas de monitorizar un sistema Linux mediante el intérprete de la línea de comandos. Yo os voy a hablar, de manera muy básica, de algunas de estas opciones.

  • Ver espacio en los discos: El comando "df" os muestra una tabla en la que os aparecen los discos y/o particiones que tengáis montados en ese momento y el espacio usado y disponible de cada uno de ellos. Con la opción "-h" os aparece en "formato humano", es decir, con las siglas de las unidades más apropiadas, para una fácil comprensión.  



  • Ver temperaturas y voltajes: Para esto hay que instalarse "sensors". Una vez hecho, sólo hay que teclear el nombre del programa para que nos muestre todos los datos que recogen estos sensores de nuestra máquina.

  • Ver la memoria en uso: La memoria está reflejada en un archivo dinámico situado en "/proc/meminfo". Haciendo un "cat" del archivo (comando que sirve para mostrar el texto que hay dentro), podemos ver toda esta información.

  • Uso de la CPU: Hay varias formas de hacer esto. El conocido comando "top", por ejemplo, nos muestra en su cabecera estos datos. Yo he preferido instalarme "sysstat". Una vez instalado, un "mpstat" nos muestra unas estadísticas globales del uso del procesador. Si tecleamos "mpstat -P ALL 1 1", por ejemplo, nos muestra una información más detallada de cada uno de los procesadores que tengas por separado (los números hacen referencia al número de iteraciones y al tiempo que hay entre ellas, en este caso, realizamos una única interacción y salimos del programa). 


  • Procesos corriendo: El comando "top", el cual ya habíamos adelantado, nos muestra una lista de procesos e información sobre ellos. Otra forma de sacarlos, es con el comando "ps". Tecleando "ps -A" nos aparece una lista con todos los procesos y sus números identificativos (PIDs). Si tecleamos "ps axu" podemos ver información más completa, incluyendo el uso de la CPU que implica cada una de las aplicaciones. Por último, el comando "ps axu --sort -%cpu", además de mostrarnos la lista anterior, ordenaría los programas por uso de CPU (como hace "top"), lo cual puede ser bastante interesante.

  • Comprobar si un proceso está corriendo: El comando "ps" se puede combinar con un "grep" (buscar) para encontrar un programa de la siguiente manera: "ps -A | grep nombre_del_programa". Abreviadamente, se puede usar el comando "pgrep nombre_del_programa", que devolverá el PID en caso de encontrarlo.

  • Sesiones: El comando "who" muestra quién tiene la sesión iniciada en el sistema en el momento de ejecutarse, mientras que el comando "last" muestra un registro histórico con los últimos inicios de sesión del sistema. El comando "uptime" nos da información sobre el último arranque del sistema (información a la que también podemos acceder por medio de "who -b").


Añadir que, ya que estamos mirando posibles aplicaciones para consultar información a distancia sobre lo que "se está cociendo" en nuestro ordenador, comentaros brevemente el uso de "amulecmd"

La aplicación "amulecmd" nos ayuda a monitorizar a distancia el estado del aMule que tengamos instalado en nuestro ordenador. aMule es un cliente P2P muy popular en Linux, como lo fuera el eMule para Windows. Lo primero que habría que hacer es habilitar las conexiones externas en aMule, y establecer una contraseña para ello.


Una vez hecho esto, se podrá acceder mediante una consola tecleando "amulecmd" (en cuyo caso nos pedirá los datos de acceso). Estos pasos se pueden automatizar en un único comando: "amulecmd -P CONTRASEÑA". Una vez dentro, podremos ejecutar las diferentes acciones.

Estos comandos también se pueden ejecutar desde fuera con el parámetro "-c", por ejemplo, tecleando "amulecmd -P CONTRASEÑA -c Status", nos dirá el estado de la aplicación en ese momento, y "amulecmd -P CONTRASEÑA -c "show DL"" nos mostraría las descargas.

Espero que os resulte tan útil esta información como me ha sido a mi recopilarla.

domingo, 13 de julio de 2014

Comunicación ordenada

Qué encontrarás en esta entrada?
  • Cómo enviar mensajes instantáneos a tu ordenador y que te responda.
  • Ver información a distancia.
  • Ejecutar comandos. 

En primer lugar, agradecerle a Altair·Mikoto su ayuda en este tema, así como a la fuente en la que ambos nos basamos: el excelente blog RSPPI.

Desde el principio de la humanidad, el hombre ha buscado una compañera con la que compartir su monótona existencia. Durante mucho tiempo esa búsqueda estuvo brutalmente sesgada por los requisitos de la exigente selección natural... hasta la era digital, en la cual los geeks de todas partes descubrimos que, a falta de encontrar la pareja perfecta, podíamos construírnosla nosotros mismos en un desconcertante intento de "cyber-do it yourself". Ya vimos en este mismo blog alguna bizarra propuesta. El la citada ocasión construimos un script en shell de Linux que recogía una serie de datos, principalmente del sistema, y luego producía un discurso (a través de un "text to speech" como eSpeak) adecuado a las circunstancias del momento.

Hoy mi intención no es "construirme otra novia", sino crear un programa no "humanizado" que sea capaz de darme información a distancia desde mi ordenador, en lugar de ejecutarse en modo local. Para ello vamos a basarnos en las indicaciones que nos dan desde RSPPI. Resumiendo un poco lo que dicen en su elaborada entrada, la idea consiste en utilizar centerIM, un programa por línea de comandos de mensajería instantánea, al estilo de Finch (la versión "light" de Pidgin). Este programa permite redirigir los mensajes a un "contestador automático", el cual puede ser un script en shell de Linux que tome como variables de entrada lo que se le diga por mensajería instantánea y realice una acción en consecuencia. Para más detalles os recomiendo que lo leáis con atención en RSPPI, donde podréis encontrar cómo configurarlo todo paso a paso.

Con esto habríamos conseguido establecer una profunda e íntima comunicación con lo más profundo de nuestro ordenador. Podríamos programarle un random de chistes aleatorios (como el Sr. Mañoso... "ni siquiera sabía que se pudieran comer") y contestaciones ingeniosas (que lo mismo tendría su gracia), pero yo he preferido hacerme un menú con opciones que me proporcionen distinta información sobre el estado de mi ordenador de sobremesa.

Podría preguntarle ahora mismo a mi ordenador por el espacio en mi disco duro principal a través de Hangouts, y me respondería algo como lo de abajo.


O podría decirle desde mi móvil que si me he dejado el Firefox abierto en casa, y me contestaría:


Es más, quiero saber qué programas están consumiendo más memoria en mi ordenador de casa. Se lo voy a preguntar:


Ups! Ese programa me lo he dejado encendido? No debería: voy a cerrarlo!


Cómo está ahora mismo la pantalla?


Y, combinándolo con mutt, veo en mi correo:


En RSPPI tenéis algún ejemplo de cómo programarlo, aunque en mi opinión es algo personal de cada uno (cada cuál sabe de qué quiere hablar con su ordenador). El límite, una vez más, es la imaginación de cada uno.