vendredi, février 13, 2009

Human Remote concept for Elisa

Human Remote concept for Elisa

Abstract
Elisa can be control by several types of device. Keyboard, mouse,remote, with gyro, bluetooth remote and so on, only if they can be plugged to the host system. But if we consider evolution of HCI world in the past year, we will see that most of innovation try to make the most intuitive and easiest HCI for human. Without anything. No more interaction but with human. Motion detection, voice recognition, everything that is the most natural way for people. This is a technical how-to set up this in Elisa.


Le pilotage de l'interface d'Elisa peut être effectué par différents types de périphériques. Clavier, souris, télécommande IR, télécommande à gyro, etc.. pourvu que le système hote possède les connectiques adéquates. A la vue de la courbe de progression en matière d'IHM grand public et de leur périphérique de contrôle, la part belle est faite à l'interaction directe, ludique et la plus naïve possible. Abordé sous cet angle, l'utilisateur lui-même en tant qu'acteur de l'IHM devient évidente. Usage du corps, des mouvements, de la voix et de toute caractéristique naturelle de l'humain. On peut définir une façon d'utiliser une IHM sans passer par aucun périphérique de commande manipulé d'aucune sorte (ni par contact, ou par pression,etc..).

Dans le prototype mis en œuvre ici pour Elisa, il sera question d'expérimenter l'usage de la combinaison de la voix et de la détection des mouvements de mains.
A elle seule, la voix permet d'activer des fonctionnalités précises. Par exemple, lecture, pause, suivant, etc.. Mais celà ne suffit pas à couvrir l'usage complet de l'interface : il faut aussi des capacités de navigation, comme le défilement ou le feuilletage. Il faut donc adjoindre à la commande vocale, la détection de mouvements.

La plateforme visée est une distribution ubuntu de type standard sur un poste équipé d'une webcam avec micro intégré.


Principe de l'implémentation dans Elisa
Elisa pour sa gestion d'événements de périphérique propose un modèle objet ayant pour racine InputProvider.
Il faut ici implémenter une classe à partir de ce modèle, dérivé de PushInputProvider, prenant en charge la reconnaissance vocale et la gestion des mouvements. Elle injectera alors des ordres automatiquement via le modèle objet à l'IHM. Le tout prenant la forme d'un plugin pour Elisa.


La voix
La reconnaissance vocale doit permettre d'associer des mots ou des phrases à des actions. Il est nécessaire ici d'adopter des mots ou phrases courtes afin de rendre le service efficace. Bien qu'on reste tributaire de la qualité du matérielle.
En ce basant sur l'architecture d'Elisa, il est nécessaire de développer un plugin de reconnaissance vocale fonctionnant de manière asynchrone via GStreamer déclenchant des évenements.
Un corpus réduit choisi : PLAY, STOP, NEXT, BACK

Différents projets notamment de recherche universitaire se prêtent au besoin en mode SPEECH-TO-TEXT. Mais de manière générale plusieurs projets se basent sur des frameworks propriétaires ou sur des technologies présentes uniquement sur une seule plateforme. Quand il ne s'agit pas de simple wrapper de systèmes pré-installés.
Le projet The CMU Sphinx Group Open Source Speech Recognition Engines [http://cmusphinx.sourceforge.net/html/cmusphinx.php] présente les avantages suivant :
- portabilité système
- licence
- utilisable via des pipeline GStreamer
- binding python
Il propose plusieurs moteurs de reconnaissance vocale basés pour la plupart sur des algorithmes communs. Sphinx 2 qui est aujourd'hui abandonné au profit de Sphinx-3, ou Sphinx-4 qui lui fonctionne en environnement Java. PocketSphinx quant à lui est spécialement dédié aux mobile device et possède ses binding pythons.


La détection de mouvement
Il faut pouvoir détecter les mouvements de main de l'utilisateur. Plus précisément détecter une vitesse de mouvement et un sens. On passe par les techniques de détection de blob. Plusieurs implémentations existent.
L'algorithme naïf à utiliser est de détecter les bounding boxes de premier plan, étant ceux possédant la plus grande surface et de les tracker dans le temps, pour calculer une vitesse et le sens. A partir de là, et en fixant des seuils il devient possible d'envoyer des ordres de défilement à l'IHM de Elisa.

Les technologies autour de Processing.org (environnement de R&D pour IHM) permettent cela en Java. Notamment via une librairie appelée JMyron (dérivée de webcamxtra) initialement prévue pour Mac et possédant un noyau en C++ (appelé Myron).
[http://webcamxtra.sourceforge.net/index.shtml]
Myron offre les techniques suffisantes et nécessaires aux besoins. De plus Myron est largement répandu dans le domaine de l'expérimentation d'IHM ou des artistes visuels dès qu'il s'agit d'aborder la motion detection.


Etat du projet
[Au 09/02/09]
Le module de reconnaissance vocale basé sur le corpus défini est fonctionnel.
La navigation par détection de mouvement n'est pas terminée. pyMyron doit être finalisé pour celà.
pyMyron n'est pas complet, seule la fonction de detection de blob est prise en compte bien qu'une erreur dans Myron engendre des erreurs.


TODO list & note
L'efficacité de ce genre de système, surtout pour la partie motion detection, reste trop tributaire de la qualité du matériel.
Un portage win32 sera normalement facilité par le choix des librairies.
Affiner le choix de la librairie de reconnaissance vocale, utilisé sphinx-3 en lieu et place de pocketsphinx.
Finir PyMyron
Intégrer les événements de detection de blob à la classe InputProvider
Etendre le corpus pour activer les sections spécifiques de Elisa via le bus de son api (accès aux films, photos, etc...)


Implémentation de la reconnaissance vocale

Plateforme d'ensemble : ubuntu 8.10, gstreamer 0.10.21, gcc4.3.2, java 1.6.0_10, python 2.5.2, Elisa 0.5.X (from SVN 20090122)

Mise en place de PocketSphinx depuis les archives de sourceforge [http://sourceforge.net/project/platformdownload.php?group_id=1904]
pour créer la librairie, les binding python et le plugin pour gstreamer.

Puis l'utiliser dans le plugin HumanRemote.

1.Compilation de SphinxBase (v0.4.1)

cd sphinxbase-0.4.1
$./configure --enable-fixed --disable-shared
$make
$sudo make install

2.Compilation de pocketsphinx (v0.5.1)

$cd pocketsphinx-0.5.1
$./configure --prefix=`pwd`/build --with-sphinxbase=`pwd`/../sphinxbase-0.4.1 --disable-shared
$make
$make install


3.Test


$export LD_LIBRARY_PATH=`pwd`/pocketsphinx-0.5.1/build/lib
$export GST_PLUGIN_PATH=`pwd`/pocketsphinx-0.5.1/build/lib/gstreamer-0.10
$export PYTHONPATH=$PWD/pocketsphinx-0.5.1/build/lib/python2.5/site-packages:$PYTHONPATH
Test de la librairie python:
$python -c "import pocketsphinx"
Test plugin gstreamer:
$gst-inspect-0.10 pocketsphinx


4.Le corpus et le dictionnaire
A partir de là, il faut créer un modele de dictionnaire à destination du moteur de reconnaissance vocale. Et ceci à partir du corpus de mots définis. Ce dictionnaire définit le vocabulaire à reconnaitre par Elisa, et se présente sous la forme de fichier binaire compilé.
(cf documentation sphinx)


5.Integration au plugin Human Remote
En se basant sur un pipeline gstreamer captant une source sonore, il faut utiliser le plugin pocketsphinx pour lever des évenements Elisa.

Pipeline mis en place pour une webcam à micro intégré :
osssrc ! audioconvert ! vader name=vad auto-threshold=true ! pocketsphinx dict=model.dic lm=model.lm name=asr ! fakesink

On peut envisager, selon la qualité du matériel d'utiler des filtres comme audiochebband pour purger les bruits de fond ou autre parasite d'informations sonores.
Exemple :
audiochebband mode=band-pass lower-frequency=3000 upper-frequency=4000 type=2


def initialize(self):
dfr = super(HumanremoteInput, self).initialize()
...
self.pipeline = gst.parse_launch('osssrc ! audioconvert ! vader name=vad auto-threshold=true ! pocketsphinx dict=' + model_folder + 'model.dic lm=' + model_folder + 'model.lm name=asr ! fakesink')

asr = self.pipeline.get_by_name('asr')
asr.connect('partial_result', self.asr_partial_result)
asr.connect('result', self.asr_result)


Le filtre pocketsphinx va lever deux types d'événements : partial_result et result. Selon qu'une séquence de son représente un mot ou une phrase complet du corpus.

def application_message(self, bus, msg):
"""Receive application messages from the bus."""
msgtype = msg.structure.get_name()
if (msgtype == 'partial_result'):
pass
if (msgtype=='result'):
self.create_input_event(msg.structure['hyp'])
pass


Lors d'un évènement de type result, il faut ensuite via le bus lever un message applicatif qui se transformera un InputEvent et sera traité par l'InputManager d'Elisa.

def create_input_event(self, msg):
...
evt = InputEvent(EventSource.REMOTE, EventType.OTHER,
self.convert_table[data])


asr.set_property('configured', True)
self.info("HUMAN REMOTE : pipeline ok")


6.Human Remote v0.0.1a supportant la voix

Archive du plugin :
http://portail.studio-etrange.net/corailnumerique/humanremote/humanremote-0.0.1a.tar.gz
(nécessite les librairies compilées)

Test avec Elisa-SVN 0.5.24:
$../../pigment/pigment/misc/pgm-uninstalled
$export PYTHONPATH=$PWD/elisa-core:$PWD/elisa-plugins:$PYTHONPATH
$export LD_LIBRARY_PATH=`pwd`/pocketsphinx-0.5.1/build/lib
$export GST_PLUGIN_PATH=`pwd`/pocketsphinx-0.5.1/build/lib/gstreamer-0.10
$ELISA_DEBUG=3 python elisa-core/bin/elisa my_conf.conf


INFO Dummy-2 humanremote_input fév 13 09:31:26 HUMAN REMOTE : full result (elisa/plugins/humanremote/humanremote_input.py:99)
INFO Dummy-2 humanremote_input fév 13 09:31:33 HUMAN REMOTE : full result (elisa/plugins/humanremote/humanremote_input.py:99)
INFO MainThread humanremote_input fév 13 09:31:33 Callback create_input_event called (elisa/plugins/humanremote/humanremote_input.py:111)
INFO MainThread humanremote_input fév 13 09:31:33 Supported key code received: PLAY (elisa/plugins/humanremote/humanremote_input.py:
INFO MainThread humanremote_input fév 13 09:31:34 Humanremote input provider is shutting down (elisa/plugins/humanremote/humanremote_input.py:107)




Implémentation de la détection de mouvement

Plateforme d'ensemble : ubuntu 8.10, gstreamer 0.10.21, gcc4.3.2, java 1.6.0_10, python 2.5.2, Elisa 0.5.X (from SVN 20090122)

Mise en place de la librairie Myron sous ubuntu, et optionnellement à des fins de tests de JMyron pour processing dans ubuntu.
Création de pyMyron en vue d'une utilisation en python de la librairie dans le plugin HumanRemote.

1.Intégrer JMyron (v0025) avec v4l2
Il faut compiler Myron à partir de son code source C++ en librairie pour Java (appelée JMyron) tout en le modifiant pour qu'il supporte v4l2 et donc linux

$svn co https://webcamxtra.svn.sourceforge.net/svnroot/webcamxtra webcamxtra

Les modifications de Myron afin d'intégrer v4l2 ont en parti été réalisées ici
http://piratestudios.com/v4ljmyron/
copier v4l2Camera.h v4l2Camera.cpp Makefile.linux ezcam.cpp dans webcamxtra/ezcam
copier myron.cpp dans webcamxtra/source
Editer Makefile.linux
$(JAVAC)=/usr/bin/javac
$(PROCESSING)=/opt/processing-1.0.1

Pour compiler
$cd webcamxtra/ezcam
$make -f Makefile.linux


2.Intégrer JMyron pour v4l2 dans processing pour Ubuntu (optionnel)


Version : Ubuntu 8.10, sun-java-6, Processing 1.0.1, Jmyron0025

Depuis le site de processing.org
dezipper processing dans /opt/processing-1.0.1

Récupérer Jmyron for processing [http://webcamxtra.sourceforge.net/distro/JMyron0025.zip]
Installer JMyron in /opt/processing-1.0.1
Placer le répertoire JMyron dans /opt/processing-1.0.1/libraries
Placer le répertoire JMyron Examples dans /opt/processing-1.0.1/examples

Installation dans processing
$cp webcamxtra/ezcam/JMyron.jar /opt/processing-1.0.1/java/lib
$cp webcamxtra/ezcam/libJMyron.so /opt/processing-1.0.1/java/lib/i386


3.Création de pyMyron

Utilisation de SIP(v4.7.9) afin de créer des bindings python de la librairie python.

Compilation de SIP
[http://www.riverbankcomputing.co.uk/software/sip/download]
$cd sip-4.7.9
$python configure.py
$make
$sudo make install

Compilation de la lib Myron
edit webcamxtra/ezcam/Makefile.linux
all: Linux jniwrapper.o myron.o libJMyron.so JMyron.jar libMyron.so
libMyron.so: myron.o ezcam.o v4l2camera.o
g++ -shared -o libMyron.so myron.o ezcam.o v4l2Camera.o
$make

Création de pyMyron
dans pymyron copier myron.h et libMyron.so
creer myron.spi à partir de myron.h
creer configure.py comme suit


import os
import sipconfig
build_file = "myron.sbf"
config = sipconfig.Configuration()
os.system(" ".join([config.sip_bin, "-c", ".", "-b", build_file, "myron.sip"]))
makefile = sipconfig.SIPModuleMakefile(config, build_file)
makefile.extra_libs = ["Myron"]
makefile.extra_lib_dirs = ["."]
makefile.generate()


$python configure.py
$make

4.Test de pyMyron
export LD_LIBRARY_PATH=.
$python
>>import pyMyron
>>m=pyMyron.Myron()
>>m.start()
>>m.stop()
pour installer le module pyMyron: make install






Ressources
VIDEO

http://videocapture.sourceforge.net/
A Win32 Python Extension for Accessing Video Devices (e.g. a USB WebCam, a TV-Card, ...)


http://snippets.dzone.com/posts/show/4920
/ Python Motion Detection Library + Demo

http://janto.blogspot.com/2006/01/motion-capture-in-python.html

Myron
http://sourceforge.net/projects/webcamxtra

PYTHON AUDIO TOOLS
Sound toolkit
http://www.speech.kth.se/snack/

Python speech recognition with microsoft speech sdk
http://surguy.net/articles/speechrecognition.xml

speech0.5.1 is a Python module that provides a clean interface to Windows's voice recognition and text-to-speech capabilitie
http://pypi.python.org/pypi/speech/

The Festival Speech Synthesis System [TEXT TO SPEECH]
http://www.cstr.ed.ac.uk/projects/festival/
http://festvox.org/
PyFest 0.1 : ?

The CMU Sphinx Group Open Source Speech Recognition Engines
http://cmusphinx.sourceforge.net/html/cmusphinx.php

IBM Text to speech
http://www.research.ibm.com/tts/