IMA4 2017/2018 P14
Sommaire
Présentation générale
Description
- Intitulé du projet : Proposer une solution permettant d'assembler des écrans de PC afin de créer un écran géant
Le renouvellement de matériel informatique continu entraîne un nombre grandissant d'écrans d'ordinateur qui sont difficilement réutilisables compte tenu de leur petite taille. (17")
Afin de leur donner une seconde vie, ce projet a pour but de construire une plateforme permettant d'assembler ces écrans en un écran géant d'une forme "quelconque"
Objectifs
Afin de réaliser ce projet, il faudra :
- Ajouter un Raspberry Pi sur chaque écran afin de le rentre "intelligent".
- Créer une application permettant de prendre un flux vidéo et de le diriger vers l'écran visé.
- Permettre de déplacer facilement les écrans tout en maintenant le flux, que ce soit sur des configurations pleines en 2D ou des configurations plus complexes avec des espaces vides ou en 3D.
Analyse du projet
Positionnement par rapport à l'existant
Analyse du premier concurrent
Analyse du second concurrent
Scénario d'usage du produit ou du concept envisagé
Réponse à la question difficile
- Le positionnement des écrans et la communication entre ces derniers.
Pour une application telle qu'un écran géant composé de plusieurs écran, il est difficilement envisageable d'utiliser un système de coordonnées GPS pour repérer des écrans qui sont particulièrement proches les uns des autres. En revanche il est tout à fait réaliste de penser à un système de capteurs de contact/proximité, disposés sur les bords des écrans pour leur permettre de s’emboîter puis il ne resterait qu'à exploiter les possibilités proposées par les Raspberry Pi ainsi qu'un système de coordonnées réalisé dans ce but pour déterminer où l'écran se situe par rapport aux autres.
- La gestion du flux vidéo
Le système sera potentiellement réalisé de sorte que chaque écran soit autonome dans son fonctionnement, une fois sa position relative déterminée au préalable. En effet, pour le moment le problème était surtout dans le positionnement des écrans plus que dans la gestion du flux vidéo, à priori.
- "Est-ce que le système peut continuer de fonctionner si on retire l'un des écrans ?"
Pour pallier au problème d'un retrait d'écran, ou d'un disfonctionnement éventuel localisé, une solution possible est de fournir à chaque écran la totalité du flux vidéo. Ceci permet dans un premier temps de s'affranchir d'un traitement vidéo avant distribution mais surtout que les autres écrans puissent fonctionner sans interruption due à un écran en particulier
- "Peut-il y avoir des décalages d'affichage entre les écrans ?"
Malgré l'absence de possibilités de test pour le moment, on peut néanmoins supposer qu'il n'y ait pas de décalage. Chaque écran va recevoir le flux vidéo puis en fonction du positionnement des écrans, et on pourra utiliser le système de coordonnées pour effectuer une "selection" sur la partie à afficher.
Dans le cas d'une configuration de 4 écrans en rectangle, il faudrait donc que l'écran inférieur gauche n'affiche que l'image correspondante jusqu'à la moitié, ensuite l'écran inférieur droit s'occuperait de l'affichage de la partie inférieure droite, etc
En agrandissant le procédé à plus d'écrans, on trouve facilement une méthode de calcul.
Préparation du projet
Cahier des charges
Dans le cadre de ce projet où il s'agira d'être capable de fournir une solution matérielle à la problématique, on s'orientera vers un prototype n'incluant que 4 écrans. Ceci permet à la fois d'éviter un encombrement matériel mais aussi .
Choix techniques : matériel et logiciel
- Un Commutateur (5 Ports +)
- 5 Câbles Ethernet
- 4 Câbles VGA
- 4 Adaptateur VGA-femelle vers HDMI-mâle
Liste des tâches à effectuer
- 1) Régler le problème de la gestion du flux vidéo par le réseau ainsi qu'au niveau des Raspberry-Pi
Hypothèse: pour une configuration d'écran donnée, on suppose les écrans déjà intelligent et on dispose de leur emplacement relatif.
- 2) Une fois la première version fonctionnelle, s'orienter vers la mise en place du système intelligent
Calendrier prévisionnel
Réalisation du Projet
Feuille d'heures
Tâche | Prélude | Heures S1 | Heures S2 | Heures S3 | Heures S4 | Heures S5 | Heures S6 | Heures S7 | Heures S8 | Heures S9 | Heures S10 | Total | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Analyse du projet | 0 | Lundi 15/01/18 : 3h30
Mercredi 17/01/18 : 4h |
Mercredi 24/01/18 : 4h | Mercredi 31/01/18 : 4h | Lundi 05/02/18 : 2h
Mercredi 07/02/18 : 4h |
Mercredi 14/02/18 : 4h |
Absente (malade) |
Mercredi 07/03/18 : 4h |
Lundi 12/03/18 : 2h
Mercredi 14/03/18 : 4h |
Lundi 19/03/18 : 6h
Mercredi 21/03/18 : ---- |
Prologue
Semaine 1
Lundi 15/01/18
- Première séance ayant pour but de synthétiser l'idée théorique souhaitée par le projet.
On imagine un système d'ensemble d'écrans autonomes mais qui communiquent leur emplacement entre eux, dans le sens où il n'est pas nécessaire de reconfigurer à chaque modification sur l'emplacement des écrans.
Le système est pour ainsi dire évolutif puisqu'à chaque modification, exemple: passage d'un écran géant de 2*2 à 2*3 ou 3*2 (ou plus), les affichages peuvent modifier la zone du flux vidéo à afficher afin de conserver une image sur la totalité des écrans.
De ce fait on peut imaginer des structures plus complexes, cylindriques dans le cas d'un flux d'une caméra à 360° ou plus simplement pour des simulateurs où les écrans seraient inclinés sans pour autant décrire un cercle autour de l'utilisateur.
Cependant, pour des raisons évidentes d'effectif, de temps il est nécessaire de se réduire à une solution moins ambitieuse mais néanmoins acceptable.
Mercredi 17/01/18
- Mise en place d'un cahier des charge réalisable dans le temps imparti par rapport à la réponse théorique que l'on souhaiterai apporter au problème.
Suite aux raisons évoquées précédemment, nous allons donc nous orienter vers un système à échelle réduite que nous ferons évoluer progressivement.
Comme prévu nous diffuserons le flux vidéo initial, envoyé par Ethernet par une Raspberry Pi à partir d'un fichier stocké sur une clé usb par exemple, aux 4 Raspberry intégrées aux écrans via un switch donc également par Ethernet (le port HDMI des R-Pi étant uniquement une sortie)
Schéma
Nous effectuerons ensuite grâce aux R-Pi la modification du flux en fonction des écrans servant à l'affichage avant de rediriger la partie du flux qui nous intéresse vers les écrans.
- Remarque: Dans un premier temps, pour une configuration donnée et avec les emplacement des écrans connues, il s'agit uniquement de réaliser la conversion d'affichage.
Le fait de rendre les écrans intelligents n'est cependant pas ignoré et viendra dans un second temps, le choix de la méthode à employer étant encore en suspend. Nous allons cependant effectuer des hypothèses avec des capteurs.
- Soit X et Y les dimensions du flux vidéo
- Soit U,R,D,L les états des capteurs sur un écran donné (respectivement, Up, Right, Down, Left) (1 pour actifs, 0 pour inactif)
- Soit I,J les indices des écrans (I = 0/1 et J = 0/1)
- Soit nb_X et nb_Y respectivement le nombre d'écrans en fonction des coordonnées i.e les dimensions de notre écran géant
La configuration d'écran est la suivante:
Schéma (I,J)
0,1 ; 1,1
0,0 ; 1,0
Quel que soit l'écran, le flux qu'il devra recevoir sera situé entre [X1,X2] et [Y1,Y2]. Évidemment ces valeurs de l'emplacement de l'écran
- Y2 = Y * ( D||U ) * (I+1) / nb_Y
- Y1 = Y * D * I / nb_Y
- X1 = X * L * J / nb_X
- X2 = X * ( L||R ) * (J+1) / nb_X
Semaine 2
Mercredi 24/01/18
Début de la gestion réseau du flux vidéo.
Pour la partie théorique, nous allons donc procéder de la manière suivante :
Une Raspberry s'occupera de diffuser le flux sur le réseau via un commutateur. À partir d'un fichier vidéo interne.
Les autres R-Pi disposeront d'un fichier de configuration qui contient les coordonnées à afficher en fonction de la position de l'écran, dans la première partie ce fichier sera directement implanté avec un contenu propre à chaque R-Pi mais dans la seconde il s'agira de les modifier automatiquement.
Configuration eth0 sur la Raspberry pi : iface eth0 inet static address 192.168.1.<2+numero_rpi> netmask 255.255.255.0
On commencera par créer un fichier fifo pour faire la transmission entre nc et OMXplayer
Lecture du réseau : nc -l -p <port> > /dev/shm/video.fifo
Affichage : omxplayer --crop x1,y1,x2,y2 /dev/shm/video.fifo
[3] : Documentation OMX player
Semaine 3
Mercredi 31/01/18
Tentatives de communication PC (Source flux) à Raspberry (Écran) via nc : Échec
- [PC source] : | nc
- [Raspberry Écran - Terminal 1] : nc -l -p 12345 > /dev/shm/video.fifo
- [Raspberry Écran - Terminal 2] : omxplayer --crop x1,y1,x1,y2 /dev/shm/video.fifo
Avec x1,y1,x2,y2 les coordonnées des coins de la fenêtre à afficher
Problème rencontré : la Raspberry n'arrive pas à obtenir une adresse joignable malgré une connexion directe avec le PC en ethernet
- sudo nano /etc/network/interfaces
-> iface eth0 inet dhcp
- ifdown eth0
- ifup eth0
- ifconfig
-> inet adr:169.254.68.185
Seconde tentative avec VLC en mode Streaming sur le PC source et VLC en écoute de stream avec VLC également : Échec (IP de la source = ?)
Ligne de commande pour VLC de lecture
- vlc -vvv http://IP_SOURCE:8080/PATH --crop X_RESxY_RES+LEFT_CROP+TOP_CROP -f
PATH: paramètre donné lors du lancement du stream sur la machine source
X_RES : Résolution X de l'affichage (en pixel)
Y_RES : Résolution Y de l'affichage (en pixel)
LEFT_CROP : Largeur de la zone coupée en partant de la gauche (en pixel)
TOP_CROP : Hauteur de la zone coupée en partant du haut (en pixel)
-f : Full screen
- Test avec le mode de stream (une fois le problème résolu) : le lancement de la lecture sous VLC du côté de la raspberry entraîne des pertes considérables au niveau du flux vidéo avec des coupures très fréquentes (écran noir) ainsi qu'une forte consommation des ressources
Semaine 4
Lundi 05/02/18
Omxplayer demeure plus adapté puisqu'il n'entraîne pas une sur-consommation.
Mercredi 07/02/18
Envoie avec succès d'un fichier vidéo via netcat du PC source vers la Raspberry
- $ nc -w 3 172.26.145.172 1234 < Downloads/dragons.mp4
Où 172.26.145.172 est l'adresse obtenue par ifconfig sur la Raspberry.
Réception avec :
- $ nc -l -p 1234 > Downloads/test.mp4
Commande de lecture :
- $ omxplayer --aspect-mode stretch --crop X1,Y1,X2,Y2 Downloads/test.mp4
Récupération de la résolution du flux vidéo (ou fichier dans le cas actuel) : exiftool
Nécessite un "exiftool" sur chaque Raspberry
- $ sudo apt-get install exiftool
- $ exiftool <file> | grep "Image Size" | cut -d' ' -f25 | cut -dx -f1
Observation d'événements particuliers sur des dossiers
- $ apt-get install inotify-tools
Script d'observation et d’exécution d'action sur la création d'un fichier dans un dossier
#!/bin/sh # CONFIGURATION DIR="~/Downloads" EVENTS="create" NB_X=1 NB_Y=1 X=0 Y=0 # MAIN inotifywait -m -e $EVENTS $DIR | while read file do X1=0 Y1=0 X2=exiftool /home/pifou/Downloads/hide-and-seek.mp4 | grep "Image Size" | cut -d' ' -f25 | cut -dx -f1 | awk '{print $1"*(1+X)/$NB_X"}' | bc Y2=exiftool /home/pifou/Downloads/hide-and-seek.mp4 | grep "Image Size" | cut -d' ' -f25 | cut -dx -f2 | awk '{print $1"*(1+Y)/$NB_Y"}' | bc echo "File recieved : $file"; omxplayer --aspect-mode stretch --crop X1,Y1,X2,Y2 $DIR/$file; PID=$!; wait $PID; rm -f $DIR/$file; echo "File removed $file"; done
Semaine 5
Mercredi 14/02/18
Récupération du temps de lecture (pour la commande wait)
- exiftool <video> | grep -m 1 "Track Duration" | cut -d' ' -f21 | cut -d':' -fX
X=1 -> heures ; 2 -> minutes ; 3 ; secondes
Début de la conception d'une méthode d'acquisition de la position de l'écran relative aux autres.
Un premier problème est présent pour la détection des coins dans une configuration d'écrans plus ou moins aléatoire
Dans le cas de notre prototype à 4 écrans. Qu'ils soient disposés en carré ou en ligne à l'horizontale ou à la verticale, ça ne pose pas de problème puisqu'il suffit de juger à l'état des (futurs) capteurs disposé cependant dans le cas où l'on supprime un écran, on se retrouve avec des incohérences
Semaine 6
absente pour maladie toute la semaine
Semaine 7
Jusqu'à présent nous nous sommes surtout intéressés à la partie lecture du flux vidéo (fichier jusqu'à présent) et nous alors donc nous orienter sur la partie essentielle, le streaming de la R-pi maîtresse.
Remarque : La R-pi maîtresse sera dotée d'une caméra afin de pouvoir effectuer la détection des écrans via un traitement d'image.
Le concept est simple, la R-pi envoie un signal aux autres qui doivent afficher un identifiant qui est sous la forme d'une image de 4 carrés de couleurs. Ensuite elle prend une photo des écrans puis après un traitement d'image elle peut ensuite attribuer les fichiers de configuration aux R-pi correspondantes pour les scripts de lecture
Pour le moment, seul le streaming par VLC sur la maîtresse et la lecture sous omxplayer sur la partie visualisation fonctionne mais souffre d'une latence particulièrement élevée (rappel: vlc consomme 97%+ de la raspberry).
Semaine 8
Lundi 12/03/18
- Problème avec la carte SD de la R-pi 1 théoriquement résolu en copiant via "dd if=<input_file> of=<output_file>"
- Début des recherches sur le traitement d'image par une raspberry utilisant une caméra.
OpenCV semble proposer plusieurs solution possibles qui sont à exploiter
Sources:
- Vidéo de présentation d'un projet de reconnaissance de formes colorées [4]
- Détermination de la couleur d'un objet avec OpenCV [5]
- Shape Detection avec OpenCV [6]
- Solution à examiner pour la gestion d'un stream par une R-pi puis lu par une R-pi via omxplayer [7]
Mercredi 14/03/18
- Installation d'OpenCV sur la R-pi maîtresse suivant le tutoriel [8]
Note : Lors de l'installation le nom de l'environnement du tutoriel est "cv" pour les deux exemples (python2 et python3) or nous avons déclaré "cv2" pour python2 ET "cv3" pour python3
-> actuellement bloquée au point du make -j4 la compilation plante à environ 24-25% sur une erreur (même chose avec la commande make pour n'utiliser qu'un coeur de la R-pi)
- Création d'un serveur de stream pour la R-pi maîtresse [9]
-> Le système est installé sur la R-pi maîtresse mais n'arrive pas à se lancer pour le moment -> en recherche de solution pour ce problème
Semaine 9
Lundi 19/03/18
- Compilation d'OpenCV débloquée [10]
Réinstallation effectuée proprement en raison d'un problème avec stdlib.h dans les fichiers précompilés d'où l'ajout de la commande
>>> -DENABLE_PRECOMPILED_HEADERS=OFF
à la suite du cmake qui est à présent
$ cd ~/opencv-3.1.0/ $ mkdir build $ cd build $ cmake -D CMAKE_BUILD_TYPE=RELEASE \ -D CMAKE_INSTALL_PREFIX=/usr/local \ -D INSTALL_PYTHON_EXAMPLES=ON \ -D OPENCV_EXTRA_MODULES_PATH=~/opencv_contrib-3.1.0/modules \ -D BUILD_EXAMPLES=ON .. \ -DENABLE_PRECOMPILED_HEADERS=OFF
- Réinstallation complète du serveur de stream indiqué au tutoriel : [11]
Le serveur est fonctionnel (testé en local uniquement) localhost:8081/steam.html conformément au instructions.
L'une des raisons du non fonctionnement était que /dev/video0 n'était pas disponible malgré le fait qu'une caméra était présente sur la raspberry or une webcam branchée en USB permet l'apparition de /dev/video1 qui a été utilisée pour le test.
Mercredi 21/03/18
- Serveur de streaming R-pi-M à R-pi-1 et R-pi-2 fonctionnel
Il faut cependant lancer le script en root sinon le système renvoie un échec de lancement
#./mjpg-streamer.sh start
- Le script de lecture est fonctionnel et il ne reste qu'à implanter la détection de la position des écrans dans l'ensemble du système pour rendre l'implémentation du fichier position.conf "automatique"
#!/bin/sh X=`grep -m 1 X= position.conf | cut -d'=' -f2` Y=`grep -m 1 Y= position.conf | cut -d'=' -f2` NB_X=`grep -m 1 NB_X= position.conf | cut -d'=' -f2` NB_Y=`grep -m 1 NB_Y= position.conf | cut -d'=' -f2` X1_tmp=1280 X1=`echo $X1_tmp"*"$X"/"$NB_X | bc` Y1_tmp=720 Y1=`echo $Y1_tmp"*"$Y"/"$NB_Y | bc` X2_tmp=1280 X2=`echo $X2_tmp"*(1+"$X")/"$NB_X | bc` Y2_tmp=720 Y2=`echo $Y2_tmp"*(1+"$Y")/"$NB_Y | bc` STREAM="http://169.254.171.72:8081/?action=stream" echo "Fichier de lecture = "$STREAM omxplayer --aspect-mode stretch --crop $X1,$Y1,$X2,$Y2 --live $STREAM
$sudo ./play_stream.sh