Frigo Time Machine

De fablab
Aller à : navigation, rechercher

Cadre du projet

  • Nombre d'étudiants : 2 à 4
  • Lieu : le projet aura lieu en salle FabLab à l'Ensimag.
  • Prérequis : programmation Java, RoR ou LAMP


Contexte

Ce projet propose d’implémenter un prototype d’un nouveau service pour un habitat intelligent. Il s’agit d’un systeme automatique d'inventaire du contenu d’un frigo. Le but étant de permettre aux habitants de pouvoir visualiser le contenu de leur frigo à tout moment, d’avoir des alertes sur les aliments perimés, des rappels des denrées à acheter, la génération automatique des listes des courses, des recettes à partir d'aliments présents, des conseils dietetiques, etc. Ce travail exploratoire est fait en lien avec des activités des projets AppsGate et de l’EquipEx Amiqual4Home.

Aperçu de l'application WEB mise en place :


Frigo imp1.jpg Frigo historique.jpg

Frigo suggestions.jpg

Travail demandé

Nous vous proposons d’implémenter la premiere version du Frigo Time Machine en utilisant un smartphone Android en guise de camera intelligente sans fil, placé à l’interieur du frigo. A chaque ouverture de la porte, la caméra prendra une ou plusieurs photos des contenus du frigo. L’objectif de la caméra est de capturer des images avec les contraintes suivantes :

  1. meilleure prise de vue possible de l’ensemble des aliments présents,
  2. eviter les prises d’images potentiellement ocultées par la présence de l’utilisateur.

Les images serrons ensuite envoyées à une plateforme web ou elle serons filtrées et mises à disposition de l’utilisateur pour la consultation. La présentation sur la plateforme devra permettre de naviguer dans l’historique des différentes prises de vue.

Gestion du projet

Membres de l'équipe

  • Maïlys Reneaume (IF) - mailys.reneaume@ensimag.fr
  • Alexis Sciau (IF) - alexis.sciau@ensimag.fr
  • Emilie Paillous (ISI) - emilie.paillous@ensimag.fr
  • Alice Millour (ISI) - alice.millour@ensimag.fr

Périmètre du projet

Dans le cadre de ce projet sur 3 semaines, nous nous sommes fixés les objectifs de prototypage suivants :

1. Intégration capteur dans le frigo

Construire un support maintenant le smartphone à l'intérieur du frigo de manière à obtenir la meilleure prise de vue possible.

2. Application Android

Réaliser, grâce à un smartphone Android, une prise d'un unique cliché de l'intérieur du frigo, net et non obstrué par l'éventuelle présence de l'utilisateur à chaque ouverture de la porte et l'envoyer à la plateforme web.

3. Application WEB

Fournir une interface à l'utilisateur lui permettant d'accéder aux fonctionnalités suivantes :

  • Accès au contenu de son frigo à la date courante.
- Visualisation du cliché.
- Possibilité de rajouter manuellement à la liste du contenu des aliments qui sont présents dans le frigo.
  • Accès à un historique des contenus du frigo.
  • Elaboration d'une liste de courses à partir :
- Du contenu actuel du frigo.
- Du contenu à une date antérieure.
- De recettes proposées.
- D'anciennes listes de courses.
  • Réception d'alertes si la date de péremption d'un aliment approche.
La date de péremption ne peut à l'heure actuelle être connue sans être saisie manuellement.
Hors du périmètre
  • Reconnaîssance des aliments à partir du cliché.

L'analyse du cliché transmis à la plateforme web ne sera pas implémentée. Nous avons pour l'instant mis en place des listes d'aliments par défaut, sur lesquels nous testons nos fonctionnalités.


Architecture globale

Le schéma ci-dessous illustre comment s'articulent les différents modules consitutifs de notre projet :

Architecture wiki.jpg

Voici ci-dessous le diagramme de classes correspondant à l'architecture de notre base de données :

FTM UML.jpg

Détails techniques

L’application est développée en utilisant conjointement le langage Java et le langage XML.

La Plateforme Web se fera en Java également et repose sur le framework Play! version 1.2.5  : Play Framework 1.2.5

OS : Windows 7

Environnement de développement : Eclipse

Pour l'implémentation du classifieur d'Haar, on utilise Ubuntu pour la grande facilité d'installation d'OpenCV

Journal de bord

(Mis à jour le 15 juin à 12h)

Deux dépôts GIT ont été mis en place contenant pour l'un la partie Application Web et pour l'autre la partie Application Android. Ils sont disponibles ici : Application Web et Application Android. Un README a aussi été écrit pour les applications Android, il est disponible ici


Mercredi 2 mai
  • Support

Elaboration d'un support basique à l'aide de scotch et de carton.

Prise en main de Sketchup 2013 ( Sketchup 2013 ) et modélisation 3D d'un support simple adapté.

  • Application Android

Implémentation HelloWorld Android à l'aide du Tutoriel Android

  • Plateforme Web

Réalisation d'une simple galerie d'images.

* Prise en main du Play! version 1.2.5  : Play Framework 1.2.5 avec sa Documentation Play! 1.2.5
* Prise en main HTML CSS JavaScript.
* Définition des spécifications de notre IHM et élaboration des croquis des vues attendues pour notre interface.
Week-end 25-26 mai
  • Support

Finalisation du modèle 3D pour notre support.

Contraintes :

- 1 mm d'épaisseur minimum (s'est avéré finalement trop fin pour notre modèle comportant une surface en devers)
- Prendre garde à l'orientation des faces dans le modèle
Lundi 27 mai
  • Support

Impression du support à l'INRIA.

Imprimante3D.JPG ChangementFil.jpg

Imprimante 3D Replicator 2 & Changement du filament en cours d'impression.

ImpressionSupport.jpg SupportEnSituation2.jpg

Impression du Support & mise en situation

Week-end 1-2 juin
  • Application Android

Réalisation d'une application prenant une photo manuellement. Pour cela, ce tutoriel simple a été utilisé.

  • Gestion de projet

Prise en main de Pivotal Tracker.

Elaboration du document de cadrage et spécification des incréments.

Lundi 3 juin
  • Application Android

Gestion de prise de photo sur événement et simulation d'utilisation du frigo pour récupérer les valeurs prises par l'accéléromètre du smartphone lors de l'ouverture et de la stabilisation de la porte.

  • Plateforme Web

Elaboration du diagramme entité-association.

Prise en main module CRUD fourni par le framework Play! et mise en place la base de données.

  • Transfert des clichés

Réflexion sur les différentes possibilités de communication entre le smartphone Android et le server WEB JBoss Netty utilisé par le framework Play! .

  • Application Android existante type Wifi File Transfer => abandonné car nous avons fait le choix de fonctionner en local pour notre prototype.
  • Réseau local ad-hoc. L'OS Android ne prend pas en charge la connexion à un réseau sans fil ad-hoc. => tentative avortée de rooter sur le téléphone pour modifier les paramètres système (Tutoriel).
  • Utilisation du smartphone comme point d'accès WiFi Solution adoptée finalement. Utilisation d'une carte Sim personnelle pour accéder à la fonctionnalité "Point d'accès WiFi".
Mardi 4 juin
  • Application Android

Utilisation du logiciel R pour le traitement des données de l'accéléromètre recueillies au cours des expérimentations (ouverture et fermeture de la porte)

=> résultat convenable : les clichés sont nets mais ne gèrent pas l'obstruction, l'instant de prise de vue étant défini par la stabilisation de la porte.
Mercredi 5 juin
  • Application Android

Installation d'OpenCV à partir du Tegra Android Developer Pack 2.0r4.

Pour ce faire, il est nécessaire de créer un compte et de faire une demande d'inscription au Tegra Registered Developer Program (onglet MyAccount du profil). La validation de l'inscription n'a pris que quelques heures.

  • Plateforme Web

Insertion de la base de données dans notre application (Partie Model). Mise en place de la fonction d'upload d'images sur la plateforme (Images contenues en local). Prise en main de Bootstrap.

Jeudi 6 juin
  • Application Android

Prise en main d'OpenCV. Quelques ressources utiles pour cela :

  • Le paragraphe "How to start" sur cette page contient beaucoup d'informations utiles si on veut commencer le développement dans de bonnes conditions.
  • Les "Samples" et les "Tutorials" qui sont fournis lors du téléchargement du pack Nvidia contiennent aussi de nombreuses informations utiles. On les trouve dans le dossier "Samples" du dossier d'OpenCV.
  • Plateforme Web

Création de toutes les pages de l'interface. Nous disposons d'une maquette complète rendant compte de l'apparence de l'application. Nous avons utilisé le framework bootstrap pour l'architecture de nos pages, ainsi que certains plugin jQery.

Vendredi 7 juin
  • Application Android

Utilisation d'OpenCV pour la stabilisation de la porte. A chaque nouvelle image reçue par le capteur, on compare grâce à la fonction absDiff la différence entre l'image précédente (buffer) avec la nouvelle image (current). Le résultat est stocké dans une matrice diffBuffer dont on calcule la norme (normeDiffBuffer). Enfin, si cette norme est faible pendant un certain temps, on considère que la porte est stable.

Core.absdiff(current, buffer, diffBuffer);
Double normeDiffBuffer = new Double(Core.norm(diffBuffer));
n.add(normeDiffBuffer);
compteur++;		    
if (compteur > 11) {    		
    stable = true;    		
    int i = 0; 		
    while (stable && i<10) {    		      
        if(n.get(compteur-1-i)>4500){    		            
            stable = false;    		      
        }    		
    i++;    
    }
}


Week-end 8-9 juin
  • Application Android

On reconnaît aussi l'événement "La porte du frigo est fermée" en réalisant le même traitement qu'auparavant mais en comparant l'image courante à une image noire.

  • Plateforme Web

Etablissement du lien entre pages et base de données. Mise en place de différents comptes utilisateurs.

Mardi 11 juin
  • Application Android

Dans l’état actuel, OpenCV détecte le moment où l’image est la plus stable puis déclenche l’événement prenant la photo. Il y a donc un petit temps de latence entre le moment où l’image est stable et le moment où le cliché est pris, et on peut donc avoir des images obstruées ou un peu floues. Pour pallier à ce défaut, nous pouvons modifier l’application de telle sorte que ce soit OpenCV qui réalise le cliché ce qui élimine le temps de latence problématique. L’inconvénient que présente cette méthode est que les photos seront de bien moins bonne qualité dans l’absolu même si elles ne seront plus ni floues ni obstruées. Nous allons donc implémenter ces 2 versions afin de pouvoir comparer les résultats sur la plateforme et déterminer la meilleure version.

Mercredi 12 juin
  • Transfert des clichés
Transfert des clichés assuré entre l'android et la plateforme web.
Côté Android
  • OpenActivity.java:
void envoiPhoto(String filename){
    File pictureFile = new File(filename);
    HttpClient httpClient = new DefaultHttpClient();
    httpClient.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
    HttpPost postRequest = new HttpPost("@destination:port_utilisé_par_le_framework/upload");
 
    MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
    /* Ajout des constituants de la Multipart Entity */
    entity.addPart("picture", new FileBody(((File)pictureFile), "image/jpeg"));
    entity.addPart("email", new StringBody("utilisateur@exemple.com", "text/plain",  Charset.forName("UTF-8")));

    postRequest.setEntity(entity);
    httpClient.execute(postRequest);
}
Nous transmettons l'adresse e-mail du compte associé au device qui sera installé dans le frigo intelligent et correspondant à l'identifiant pour se connecter à l'application WEB.
Les intitulés des parties des entités sont réutilisés comme suit
Côté Server :
  • conf/routes :
# Upload des photos
POST    /upload                                 Upload.upload
  • Upload.java :
public static void upload( File picture, String email) {		
       /* Création du répertoire de destination */
       File uploadDir = new File(Play.applicationPath, "/public/img/");
       /* copie du fichier contenu dans la requête sur le disque du server local */
       FileUtils.moveFile(picture, new File(uploadDir, picture.getName()));		
}
L'upload de fichier est donc très simplifié par le framework. Il faut prendre garde à utiliser les intitulés des parties de l'entité comme nom de paramètre de la fonction d'upload.
Les paramètres de la fonction d'upload ne doivent pas être considérés comme des "Variables muettes" mais comme des identifiants associés directement à l'entité transmise par la requête HTTP.
Jeudi 13 Juin
  • Application Android

Recherches sur la reconnaissance d'image

Vendredi 14 juin
  • Application Android

Implémentation d'un classifieur d'Haar. Quelques conseils pour faire cela

  • Passer sous Ubuntu pour la facilité d'utilisation. On y installe OpenCV avec cette ligne
sudo apt-get install libcv-dev libcvaux-dev libhighgui-dev
  • Pour réaliser le classifieur, il faut commencer par récupérer un certain nombre d'images de l'objet que l'on souhaite identifier (dans notre cas, une banane). Pour une reconnaissance robuste, il est conseillé d'avoir des images de l'objet sous divers angles et diverses conditions de lumière. Pour notre classifieur, nous avons utilisé 300 échantilons positifs (où l'objet est présent) et 600 négatifs.
  • Pour récupérer les échantillons, on utilise la méthode présentée par ce tutotiel. On peut compiler objectmarker.c avec ces lignes :
gcc -c objectmarker.cpp -Wall `pkg-config opencv --cflags` 
gcc objectmarker.o -o objectmarker `pkg-config opencv --libs`

Il se peut que l'exécution d'objectmarker ne fonctionne pas et que l'on ait :

Loading image xxx.bmp
Examining file xxx.bmp 
Loading image yyy.bmp
Examining file yyy.bmp

Il faut alors changer la ligne

strPrefix = dir_entry_p->d_name;

par

strPrefix = inputDirectory.append(dir_entry_p->d_name);

où inputDirectory est défini comme le chemin absolu du dossier où sont les images.

  • On peut ensuite continuer de suivre le tutoriel jusqu'à l'apprentissage du classifieur. Se référer au manuel d'opencv_haartraining pour savoir quand arrêter l'apprentissage.
  • Pour convertir les données en un fichier XML qui sera ensuite utilisable par l'application Android, on utilise l'exécutable convert_cascade dont le code est donné ici.
  • Enfin, pour réaliser concrètement le classifieur, vous pouvez reprendre le code du Banana Detector que nous avons implémenté. Il faudra placer le fichier XML que vous avez généré dans le dossier /res/raw.


  • Plateforme Web

Mise en place du coverflow pour l'historique (grâce aux JavaScripts et feuilles de styles de ContentFlow. Mise en place des alertes e-mails en cas d'aliment périmé en utilisant le serveur gmail (frigotimemachine@gmail.com). Une nouvelle classe Alerte dans le package jobs est mise en place, elle permet de faire la vérification des dates de péremption de manière régulière (toutes les 24h) et à chaque démarrage de serveur.

Dimanche 16 juin
  • Application Android

Intégration du module de détection d'objet dans l'application principale

Calcul de temps moyen entre la détection de l'ouverture de la porte du frigo et la prise de photo : 3.794 s. Sur les tests effectués ce temps se situe dans l'intervalle [2.995 s , 4.853s]

  • Plateforme Web

Nouvelle fonctionnalité : ajouter le contenu d'un frigo d'une date antérieure à la liste de courses courante. Mise à jour de toutes les fonctionnalités : supprimer un aliment de la liste courante, supprimer un aliment du frigo, ajouter un aliment à la liste courante, ajouter un aliment au contenu du frigo etc.