<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="fr">
		<id>https://projets-ima.plil.fr/mediawiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Mtrimbur</id>
		<title>Wiki de Projets IMA - Contributions de l’utilisateur [fr]</title>
		<link rel="self" type="application/atom+xml" href="https://projets-ima.plil.fr/mediawiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Mtrimbur"/>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php/Sp%C3%A9cial:Contributions/Mtrimbur"/>
		<updated>2026-05-13T18:54:18Z</updated>
		<subtitle>Contributions de l’utilisateur</subtitle>
		<generator>MediaWiki 1.29.2</generator>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=Cahier_2017_groupe_n%C2%B01&amp;diff=46372</id>
		<title>Cahier 2017 groupe n°1</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=Cahier_2017_groupe_n%C2%B01&amp;diff=46372"/>
				<updated>2017-11-22T10:21:33Z</updated>
		
		<summary type="html">&lt;p&gt;Mtrimbur : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Cahier des charges=&lt;br /&gt;
==Objectif du projet ==&lt;br /&gt;
&lt;br /&gt;
L'objectif du projet consiste à réaliser un réseau permettant de manipuler les protocoles de redondance réseau ainsi que le protocole réseau IPv6.&lt;br /&gt;
&lt;br /&gt;
==Architecture générale du projet ==&lt;br /&gt;
&lt;br /&gt;
Le réseau doit être redondant, pour réaliser cela nous avons utilisé deux routeurs, deux commutateurs et deux points d'accès WiFi. Les points d'accès sont connectés chacun à un commutateur, les routeurs sont connectés sur les deux commutateurs, entre eux, l'un des deux sur le serveur cordouan et l'autre au réseau d'interconnexion avec l'école (Local technique SR52). Voici, le schéma général de l'architecture :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Architecture_projet_IMA5_17-18_router.jpg]]&lt;br /&gt;
&lt;br /&gt;
=Machine Virtuelle=&lt;br /&gt;
&lt;br /&gt;
Dans un premier temps nous avons créé une machine virtuelle Xen Linux sur le serveur cordouan. Le nom de notre machine virtuelle est &amp;quot;IMA5-GOYAVE&amp;quot; et son adresse IP est 193.48.57.182/28 qui est sur le réseau 193.48.57.176/28. De plus, nous avons installer des paquetages nécessaires à la suite du projet que sont SSH, le serveur web apache2 et le serveur DNS bind9. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Qu'est ce qu'un routeur ?=&lt;br /&gt;
&lt;br /&gt;
Un routeur est un élément intermédiaire dans un réseau informatique assurant le routage des paquets. Son rôle est de faire transiter des paquets d'une interface réseau vers une autre selon un ensemble de règles.&lt;br /&gt;
&lt;br /&gt;
(Photo schéma routeur)&lt;br /&gt;
&lt;br /&gt;
==Le Routeur 4331==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Cisco4331.jpg]]&lt;br /&gt;
&lt;br /&gt;
Le routeur 4331 est un routeur créé par Cisco, il possède 3 interfaces de connexions :&lt;br /&gt;
	- interface GigabitEthernet0/0/0, qui peut être en connexion rj45 ou optique. Dans notre configuration il sera utilisé en connexion ethernet pour le relier avec le premier commutateur (en E304);&lt;br /&gt;
	- interface GigabitEthernet0/0/1, qui peut être uniquement connecté en ethernet sera quant à lui relier au réseau de l'école, par l'intermédiaire du local technique SR52;&lt;br /&gt;
	- interface GigabitEthernet0/0/2, qui peut être uniquement connecté en fibre optique. Il le sera avec le second routeur (le 3560, en E306).&lt;br /&gt;
&lt;br /&gt;
L'adresse de ce routeur sera 193.48.57.185/28.&lt;br /&gt;
&lt;br /&gt;
==Le Routeur 3560==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Catalyst-3560.jpg]]&lt;br /&gt;
&lt;br /&gt;
Le routeur 3560 est également un routeur créé par Cisco, il possède quant à lui de nombreux ports, reprennant ainsi le principe d'un commutateur. De plus, il possède un module optionnel de connexion pour rajouter différents types de connexion, dans notre cas, deux connexions en fibre optique.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:plug-catalyst-3560.jpg]]&lt;br /&gt;
&lt;br /&gt;
Pour notre part nous n'utiliserons seulement 4 interfaces, dont le module complémentaire :&lt;br /&gt;
	- interface TenGigabitEthernet0/1, qui sera relié par l'intermédiaire de la fibre optique avec le premier routeur (le 4331, en E304);&lt;br /&gt;
	- interface TenGigabitEthernet0/2, lui aussi en fibre optique permettra la liaison avec le serveur cordouan;&lt;br /&gt;
	- interface GigabitEthernet0/1, en liaison rj45 avec le seconde commutateur (en E306);&lt;br /&gt;
	- interface GigabitEthernet0/3, en liaison rj45 avec le premier commutateur (en E304).&lt;br /&gt;
&lt;br /&gt;
L'adresse de ce routeur sera 193.48.57.177/28.&lt;br /&gt;
&lt;br /&gt;
=Configuration du routeur 4331=&lt;br /&gt;
&lt;br /&gt;
Les deux routeurs se configurent par l'intermédiaire de l'utilitaire minicom. Toute configuration d'interface du routeur nécessite deux lignes de code :&lt;br /&gt;
 Router&amp;gt;enable&lt;br /&gt;
 Router#configure terminal (conf t)&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
==Interface routeur - commutateur==&lt;br /&gt;
&lt;br /&gt;
La première étape de configuration du routeur 4331 fut la mise en place de l'interface GigabitEthernet0/0/0, pour cela nous l'avons configuré sans adresse IP et en rj45, puisque celle-ci sera définie par chacun de ses services : &lt;br /&gt;
&lt;br /&gt;
 Router(config)#interface GigabitEthernet0/0/0&lt;br /&gt;
 Router(config-if)#no ip address&lt;br /&gt;
 Router(config-if)#media-type rj45&lt;br /&gt;
 Router(config-if)#negotiation auto&lt;br /&gt;
&lt;br /&gt;
Ensuite, nous avons mis en place les services de cette première interface en spécifiant a chaque fois le type d'encapsulation (dot1q), la &amp;quot;modification&amp;quot; des en-têtes 802.1Q, l'utilisation du spanning-tree et le numéro du bridge.&lt;br /&gt;
&lt;br /&gt;
 Router(config-if)#service instance 1 ethernet&lt;br /&gt;
 Router(config-if-srv)#encapsulation dot1q 1&lt;br /&gt;
 Router(config-if-srv)#rewrite ingress tag pop 1 symmetric&lt;br /&gt;
 Router(config-if-srv)#l2protocol peer stp&lt;br /&gt;
 Router(config-if-srv)#bridge-domain 1&lt;br /&gt;
 Router(config-if-srv)#exit&lt;br /&gt;
  &lt;br /&gt;
La &amp;quot;modification&amp;quot; des en-têtes 802.1Q, définit par la ligne &amp;quot;rewrite ingress tag pop 1 symmetric&amp;quot; est nécessaire pour la bonne redirection des paquets entre les différents VLAN. En effet, contrairement à un &amp;quot;switchport access vlan ...&amp;quot; le routeur ne va pas supprimer le tag802.1Q lors de la correspondance avec la &amp;quot;service instance&amp;quot;. Il est donc obligatoire de supprimer celle-ci quand les trames arrivent et de les ré-appliquer quand elles repartent.&lt;br /&gt;
&lt;br /&gt;
==Interface routeur - SR52==&lt;br /&gt;
&lt;br /&gt;
La seconde interface permet de connecter le routeur au local technique SR52 et donc à l'extérieur de l'école : &lt;br /&gt;
&lt;br /&gt;
 Router(config)#interface GigabitEthernet0/0/1&lt;br /&gt;
 Router(config-if)#ip address 192.168.222.2 255.255.255.248&lt;br /&gt;
 Router(config-if)#negotiation auto&lt;br /&gt;
 Router(config-if)#end&lt;br /&gt;
&lt;br /&gt;
==Interface inter-routeurs==&lt;br /&gt;
&lt;br /&gt;
La dernière interface à configurer du premier routeur qui permettra la communication entre les deux routeurs du projet : &lt;br /&gt;
&lt;br /&gt;
 Router(config)#interface GigabitEthernet0/0/2&lt;br /&gt;
 Router(config-if)#no ip address&lt;br /&gt;
 Router(config-if)#negotiation auto&lt;br /&gt;
&lt;br /&gt;
Là aussi il faut spécifier les services, de façon identique à la première interface.&lt;br /&gt;
&lt;br /&gt;
Une fois les premières configurations terminées, on peut vérifier le contenu avec la commande &amp;quot;show run&amp;quot; et enregistrer les modifications effectuées par l'intermédiaire de la commande &amp;quot;write&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Bridge-Domain==&lt;br /&gt;
&lt;br /&gt;
Enfin, on configure les bridges déclarés dans la première et troisième interfaces, en leur associant une adresse IP ainsi que leur masque : &lt;br /&gt;
&lt;br /&gt;
 Router(config)#interface BDI 1&lt;br /&gt;
 Router(config-if)#ip address 10.10.0.2 255.255.255.0&lt;br /&gt;
 Router(config-if)#exit&lt;br /&gt;
&lt;br /&gt;
Voici, les adresses associées à chaque bridge : &lt;br /&gt;
&lt;br /&gt;
 {| class=&amp;quot;wikitable alternance centre&amp;quot;&lt;br /&gt;
 |-&lt;br /&gt;
 ! scope=&amp;quot;row&amp;quot; | BDI 1&lt;br /&gt;
 | 10.10.0.2&lt;br /&gt;
 |-&lt;br /&gt;
 ! scope=&amp;quot;row&amp;quot; | BDI 2&lt;br /&gt;
 | 10.2.0.1&lt;br /&gt;
 |- &lt;br /&gt;
 ! scope=&amp;quot;row&amp;quot; | BDI 3&lt;br /&gt;
 | 10.3.0.1&lt;br /&gt;
 |-&lt;br /&gt;
 ! scope=&amp;quot;row&amp;quot; | BDI 4&lt;br /&gt;
 | 10.4.0.1&lt;br /&gt;
 |-&lt;br /&gt;
 ! scope=&amp;quot;row&amp;quot; | BDI 5&lt;br /&gt;
 | 10.5.0.1&lt;br /&gt;
 |-&lt;br /&gt;
 ! scope=&amp;quot;row&amp;quot; | BDI 6&lt;br /&gt;
 | 10.6.0.1&lt;br /&gt;
 |-&lt;br /&gt;
 ! scope=&amp;quot;row&amp;quot; | BDI 7&lt;br /&gt;
 | 10.7.0.1&lt;br /&gt;
 |-&lt;br /&gt;
 ! scope=&amp;quot;row&amp;quot; | BDI 8&lt;br /&gt;
 | 10.8.0.1&lt;br /&gt;
 |-&lt;br /&gt;
 ! scope=&amp;quot;row&amp;quot; | BDI 9&lt;br /&gt;
 | 193.48.57.185&lt;br /&gt;
 |-&lt;br /&gt;
 ! scope=&amp;quot;row&amp;quot; | BDI 10&lt;br /&gt;
 | 10.1.0.1&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
==Configuration OPSF==&lt;br /&gt;
&lt;br /&gt;
L'OSPF (Open Shortest Path First) est un protocole de routage interne IP. Le protocole OSPF a pour principal avantage de prendre en compte le type de connexion et donc la vitesse de celui-ci. En effet, l'OSPF attribue un coût à chaque liaison, et choisi le coût le plus faible (car plus intéressant). Les coûts sont calculés en fonction de la bande passante du lien, et on a par exemple :&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable alternance centre&amp;quot;&lt;br /&gt;
 |-&lt;br /&gt;
 ! scope=&amp;quot;row&amp;quot; | Type de réseau&lt;br /&gt;
 | Coût par défaut&lt;br /&gt;
 |-&lt;br /&gt;
 ! scope=&amp;quot;row&amp;quot; | FDDI, FastEthernet (10 Gbit/s,1 Gbit/s, 100 Mbits/s)&lt;br /&gt;
 | 1&lt;br /&gt;
 |-&lt;br /&gt;
 ! scope=&amp;quot;row&amp;quot; | Ethernet (10 Mbps)&lt;br /&gt;
 | 10&lt;br /&gt;
 |- &lt;br /&gt;
 ! scope=&amp;quot;row&amp;quot; | E1 (2,048 Mbps)&lt;br /&gt;
 | 48&lt;br /&gt;
 |-&lt;br /&gt;
 ! scope=&amp;quot;row&amp;quot; | T1 (1,544 Mbps)  &lt;br /&gt;
 | 65&lt;br /&gt;
 |-&lt;br /&gt;
 ! scope=&amp;quot;row&amp;quot; | 64 Kbps&lt;br /&gt;
 | 1562&lt;br /&gt;
 |-&lt;br /&gt;
 ! scope=&amp;quot;row&amp;quot; | 56 Kbps  &lt;br /&gt;
 | 1758&lt;br /&gt;
 |-&lt;br /&gt;
 ! scope=&amp;quot;row&amp;quot; | 19.2 Kbps   &lt;br /&gt;
 | 5208&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
L'OSPF est mis en place de cette façon sur le routeur : &lt;br /&gt;
&lt;br /&gt;
 Router(config)#router ospf 1&lt;br /&gt;
 Router(config-router)#router-id 10.10.0.2&lt;br /&gt;
 Router(config-router)#summary-address 193.48.57.176 255.255.255.240&lt;br /&gt;
 Router(config-router)#redistribute connected subnets&lt;br /&gt;
 Router(config-router)#network 192.168.222.0 0.0.0.7 area 70&lt;br /&gt;
 Router(config-router)#end&lt;br /&gt;
&lt;br /&gt;
=Configuration du routeur 3560=&lt;br /&gt;
&lt;br /&gt;
==Configuration des interfaces==&lt;br /&gt;
&lt;br /&gt;
La configuration des interfaces se fait plus simplement que sur le routeur 4331. En effet, il suffit de spécifier le type d'encapsulation ou son VLAN et de définir son mode (trunk ou access).  Dans notre cas, le type d'encapsulation est le dot1q pour le mode trunk. Ce mode trunk est utilisé uniquement pour la première interface car celle-ci est connectée au commutateur possédant les VLANs des machines virtuelles. Pour les trois autres interfaces, elles sont configurées en mode access. La configuration est donc la suivante : &lt;br /&gt;
&lt;br /&gt;
 Switch(config)#interface GigabitEthernet0/1&lt;br /&gt;
 Switch(config-if)#switchport trunk encapsulation dot1q&lt;br /&gt;
 Switch(config-if)#switchport mode trunk&lt;br /&gt;
 Switch(config-if)#exit&lt;br /&gt;
 Switch(config)#interface GigabitEthernet0/3&lt;br /&gt;
 Switch(config-if)#switchport access vlan 3&lt;br /&gt;
 Switch(config-if)#switchport mode access&lt;br /&gt;
 Switch(config-if)#exit&lt;br /&gt;
 Switch(config)#interface TenGigabitEthernet0/1&lt;br /&gt;
 Switch(config-if)#switchport access vlan 130&lt;br /&gt;
 Switch(config-if)#switchport mode access&lt;br /&gt;
 Switch(config-if)#exit&lt;br /&gt;
 Switch(config)#interface TenGigabitEthernet0/2&lt;br /&gt;
 Switch(config-if)#switchport access vlan 9&lt;br /&gt;
 Switch(config-if)#switchport mode access&lt;br /&gt;
 Switch(config-if)#end&lt;br /&gt;
&lt;br /&gt;
==Configuration des VLAN==&lt;br /&gt;
&lt;br /&gt;
Il faut ensuite configurer les VLAN du routeur avec leur adresse spécifique ainsi que leur masque :&lt;br /&gt;
&lt;br /&gt;
 Switch(config)#interface Vlan1&lt;br /&gt;
 Switch(config-if)#ip address 10.10.0.1 255.255.255.0&lt;br /&gt;
 Switch(config-if)#exit&lt;br /&gt;
 Switch(config)#interface Vlan3&lt;br /&gt;
 Switch(config-if)#ip address 10.2.0.2 255.255.0.0&lt;br /&gt;
 Switch(config-if)#exit&lt;br /&gt;
 Switch(config)#interface Vlan9&lt;br /&gt;
 Switch(config-if)#ip address 193.48.57.177 255.255.255.240&lt;br /&gt;
 Switch(config-if)#exit&lt;br /&gt;
 Switch(config)#interface Vlan130&lt;br /&gt;
 Switch(config-if)#ip address 192.168.222.1 255.255.255.248&lt;br /&gt;
 Switch(config-if)#exit&lt;br /&gt;
&lt;br /&gt;
==Configuration de l'OSPF==&lt;br /&gt;
&lt;br /&gt;
De la même manière que pour le routeur 4331, on configure le routeur en OSPF, en faisant attention à spécifier la bonne adresse du routeur :&lt;br /&gt;
&lt;br /&gt;
 Router(config)#router ospf 1&lt;br /&gt;
 Router(config-router)#router-id 10.10.0.1&lt;br /&gt;
 Router(config-router)#summary-address 193.48.57.176 255.255.255.240&lt;br /&gt;
 Router(config-router)#redistribute connected subnets&lt;br /&gt;
 Router(config-router)#network 192.168.222.0 0.0.0.7 area 70&lt;br /&gt;
 Router(config-router)#end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Configuration du serveur SSH sur la machine virtuelle=&lt;br /&gt;
&lt;br /&gt;
 apt install ssh&lt;br /&gt;
&lt;br /&gt;
 service ssh stop&lt;br /&gt;
&lt;br /&gt;
 vim /etc/ssh/sshd_config &lt;br /&gt;
&lt;br /&gt;
 PermitRootLogin Prohibited &lt;br /&gt;
&lt;br /&gt;
 PermitRootLogin yes&lt;br /&gt;
&lt;br /&gt;
 service ssh restart &lt;br /&gt;
&lt;br /&gt;
=Configuration DNS=&lt;br /&gt;
&lt;br /&gt;
 apt install bind9&lt;br /&gt;
&lt;br /&gt;
 service bind9 stop&lt;br /&gt;
&lt;br /&gt;
 vim /etc/default/bind9&lt;br /&gt;
&lt;br /&gt;
On modifie : &lt;br /&gt;
&lt;br /&gt;
 OPTIONS=&amp;quot;-4 -u bind&amp;quot;&lt;br /&gt;
&lt;br /&gt;
 vim /etc/bind/dns.goyave.space&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 $TTL    604800&lt;br /&gt;
 @       IN      SOA     dns.goyave.space. root.goyave.space (&lt;br /&gt;
                               2         ; Serial&lt;br /&gt;
                          604800         ; Refresh&lt;br /&gt;
                           86400         ; Retry&lt;br /&gt;
                         2419200         ; Expire&lt;br /&gt;
                          604800 )       ; Negative Cache TTL&lt;br /&gt;
 ;&lt;br /&gt;
         IN      NS      dns.goyave.space.&lt;br /&gt;
 ns      IN      A       193.48.57.182&lt;br /&gt;
 www     IN      A       193.48.57.182&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 vim /etc/bind/named.conf.local&lt;br /&gt;
&lt;br /&gt;
  zone &amp;quot;goyave.space&amp;quot; {&lt;br /&gt;
        type master;&lt;br /&gt;
        file &amp;quot;/etc/bind/dns.goyave.space&amp;quot;;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
 vim /etc/bind/named.conf.options&lt;br /&gt;
&lt;br /&gt;
 options {&lt;br /&gt;
         directory &amp;quot;var/cache/bind&amp;quot;&lt;br /&gt;
         dnssec-validation auto;&lt;br /&gt;
         auth-nxdomain no;&lt;br /&gt;
         allow-transfer {&amp;quot;allowed_to_transfer&amp;quot;;}&lt;br /&gt;
         listen-on-v6 {any;}&lt;br /&gt;
 }&lt;br /&gt;
 acl &amp;quot;allowed_to_transfer&amp;quot; {&lt;br /&gt;
         217.70.177.40/32;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 named-checkconf /etc/bind/named.conf&lt;/div&gt;</summary>
		<author><name>Mtrimbur</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=Cahier_2017_groupe_n%C2%B01&amp;diff=46207</id>
		<title>Cahier 2017 groupe n°1</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=Cahier_2017_groupe_n%C2%B01&amp;diff=46207"/>
				<updated>2017-11-13T10:50:00Z</updated>
		
		<summary type="html">&lt;p&gt;Mtrimbur : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
=Cahier des charges=&lt;br /&gt;
&lt;br /&gt;
=Séance 1 : Installation des routeurs et câblage =&lt;br /&gt;
&lt;br /&gt;
=Configuration du serveur SSH sur la machine virtuelle=&lt;br /&gt;
&lt;br /&gt;
 apt install ssh&lt;br /&gt;
&lt;br /&gt;
 service ssh stop&lt;br /&gt;
&lt;br /&gt;
 vim /etc/ssh/sshd_config &lt;br /&gt;
&lt;br /&gt;
 PermitRootLogin Prohibited &lt;br /&gt;
&lt;br /&gt;
 PermitRootLogin yes&lt;br /&gt;
&lt;br /&gt;
 service ssh restart &lt;br /&gt;
&lt;br /&gt;
=Configuration DNS=&lt;br /&gt;
&lt;br /&gt;
 apt install bind9&lt;br /&gt;
&lt;br /&gt;
 service bind9 stop&lt;br /&gt;
&lt;br /&gt;
 vim /etc/default/bind9&lt;br /&gt;
&lt;br /&gt;
On modifie : &lt;br /&gt;
&lt;br /&gt;
 OPTIONS=&amp;quot;-4 -u bind&amp;quot;&lt;br /&gt;
&lt;br /&gt;
 vim /etc/bind/dns.goyave.space&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 $TTL    604800&lt;br /&gt;
 @       IN      SOA     dns.goyave.space. root.goyave.space (&lt;br /&gt;
                               2         ; Serial&lt;br /&gt;
                          604800         ; Refresh&lt;br /&gt;
                           86400         ; Retry&lt;br /&gt;
                         2419200         ; Expire&lt;br /&gt;
                          604800 )       ; Negative Cache TTL&lt;br /&gt;
 ;&lt;br /&gt;
         IN      NS      dns.goyave.space.&lt;br /&gt;
 ns      IN      A       193.48.57.182&lt;br /&gt;
 www     IN      A       193.48.57.182&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 vim /etc/bind/named.conf.local&lt;br /&gt;
&lt;br /&gt;
  zone &amp;quot;goyave.space&amp;quot; {&lt;br /&gt;
        type master;&lt;br /&gt;
        file &amp;quot;/etc/bind/dns.goyave.space&amp;quot;;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
 vim /etc/bind/named.conf.options&lt;br /&gt;
&lt;br /&gt;
 options {&lt;br /&gt;
         directory &amp;quot;var/cache/bind&amp;quot;&lt;br /&gt;
         dnssec-validation auto;&lt;br /&gt;
         auth-nxdomain no;&lt;br /&gt;
         allow-transfer {&amp;quot;allowed_to_transfer&amp;quot;;}&lt;br /&gt;
         listen-on-v6 {any;}&lt;br /&gt;
 }&lt;br /&gt;
 acl &amp;quot;allowed_to_transfer&amp;quot; {&lt;br /&gt;
         217.70.177.40/32;&lt;br /&gt;
 }&lt;/div&gt;</summary>
		<author><name>Mtrimbur</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=Cahier_2017_groupe_n%C2%B01&amp;diff=46200</id>
		<title>Cahier 2017 groupe n°1</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=Cahier_2017_groupe_n%C2%B01&amp;diff=46200"/>
				<updated>2017-11-13T10:39:30Z</updated>
		
		<summary type="html">&lt;p&gt;Mtrimbur : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
=Cahier des charges=&lt;br /&gt;
&lt;br /&gt;
=Séance 1 : Installation des routeurs et câblage =&lt;br /&gt;
&lt;br /&gt;
=Configuration du serveur SSH sur la machine virtuelle=&lt;br /&gt;
&lt;br /&gt;
 apt install ssh&lt;br /&gt;
&lt;br /&gt;
 service ssh stop&lt;br /&gt;
&lt;br /&gt;
 vim /etc/ssh/sshd_config &lt;br /&gt;
&lt;br /&gt;
 PermitRootLogin Prohibited &lt;br /&gt;
&lt;br /&gt;
 PermitRootLogin yes&lt;br /&gt;
&lt;br /&gt;
 service ssh restart &lt;br /&gt;
&lt;br /&gt;
=Configuration DNS=&lt;br /&gt;
&lt;br /&gt;
 apt install bind9&lt;br /&gt;
&lt;br /&gt;
 service bind9 stop&lt;br /&gt;
&lt;br /&gt;
 vim /etc/default/bind9&lt;br /&gt;
&lt;br /&gt;
On modifie : &lt;br /&gt;
&lt;br /&gt;
 OPTIONS=&amp;quot;-4 -u bind&amp;quot;&lt;br /&gt;
&lt;br /&gt;
 vim /etc/bind/dns.goyave.space&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 $TTL    604800&lt;br /&gt;
 @       IN      SOA     dns.goyave.space. root.goyave.space (&lt;br /&gt;
                               2         ; Serial&lt;br /&gt;
                          604800         ; Refresh&lt;br /&gt;
                           86400         ; Retry&lt;br /&gt;
                         2419200         ; Expire&lt;br /&gt;
                          604800 )       ; Negative Cache TTL&lt;br /&gt;
 ;&lt;br /&gt;
         IN      NS      dns.goyave.space.&lt;br /&gt;
 ns      IN      A       193.48.57.182&lt;br /&gt;
 www     IN      A       193.48.57.182&lt;/div&gt;</summary>
		<author><name>Mtrimbur</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=Cahier_2017_groupe_n%C2%B01&amp;diff=46193</id>
		<title>Cahier 2017 groupe n°1</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=Cahier_2017_groupe_n%C2%B01&amp;diff=46193"/>
				<updated>2017-11-13T10:28:29Z</updated>
		
		<summary type="html">&lt;p&gt;Mtrimbur : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
=Cahier des charges=&lt;br /&gt;
&lt;br /&gt;
=Séance 1 : Installation des routeurs et câblage =&lt;br /&gt;
&lt;br /&gt;
=Configuration du serveur SSH sur la machine virtuelle=&lt;br /&gt;
&lt;br /&gt;
 apt install ssh&lt;br /&gt;
&lt;br /&gt;
 PermitRootLogin Prohibited &lt;br /&gt;
&lt;br /&gt;
 PermitRootLogin yes &lt;br /&gt;
&lt;br /&gt;
=Configuration DNS=&lt;/div&gt;</summary>
		<author><name>Mtrimbur</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=Cahier_2017_groupe_n%C2%B01&amp;diff=45365</id>
		<title>Cahier 2017 groupe n°1</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=Cahier_2017_groupe_n%C2%B01&amp;diff=45365"/>
				<updated>2017-10-02T13:39:34Z</updated>
		
		<summary type="html">&lt;p&gt;Mtrimbur : Page créée avec « =Séance 1 : Installation des routeurs et câblage = »&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Séance 1 : Installation des routeurs et câblage =&lt;/div&gt;</summary>
		<author><name>Mtrimbur</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=TP_sysres_IMA5sc_2017/2018&amp;diff=45364</id>
		<title>TP sysres IMA5sc 2017/2018</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=TP_sysres_IMA5sc_2017/2018&amp;diff=45364"/>
				<updated>2017-10-02T13:38:36Z</updated>
		
		<summary type="html">&lt;p&gt;Mtrimbur : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Répartition des binômes ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&lt;br /&gt;
  &amp;lt;th&amp;gt;Cahier&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;th&amp;gt;Elèves&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;th&amp;gt;Tâche particulière&amp;lt;/th&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&lt;br /&gt;
  &amp;lt;td&amp;gt;[[Cahier 2017 groupe n°1]]&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;td&amp;gt; Marius TRIMBUR Loïc TOMBAZZI &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;td&amp;gt; Configuration Routeurs &amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&lt;br /&gt;
  &amp;lt;td&amp;gt;[[Cahier 2017 groupe n°2]]&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;td&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;td&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&lt;br /&gt;
  &amp;lt;td&amp;gt;[[Cahier 2017 groupe n°3]]&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;td&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;td&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&lt;br /&gt;
  &amp;lt;td&amp;gt;[[Cahier 2017 groupe n°4]]&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;td&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;td&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&lt;br /&gt;
  &amp;lt;td&amp;gt;[[Cahier 2017 groupe n°5]]&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;td&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;td&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&lt;br /&gt;
  &amp;lt;td&amp;gt;[[Cahier 2017 groupe n°6]]&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;td&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;td&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&lt;br /&gt;
  &amp;lt;td&amp;gt;[[Cahier 2017 groupe n°7]]&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;td&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;td&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&lt;br /&gt;
  &amp;lt;td&amp;gt;[[Cahier 2017 groupe n°8]]&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;td&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;td&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mtrimbur</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=Fichier:Carre.jpg&amp;diff=42644</id>
		<title>Fichier:Carre.jpg</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=Fichier:Carre.jpg&amp;diff=42644"/>
				<updated>2017-05-19T15:35:22Z</updated>
		
		<summary type="html">&lt;p&gt;Mtrimbur : a téléversé une nouvelle version de « Fichier:Carre.jpg »&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Mtrimbur</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=Fichier:Carre.jpg&amp;diff=42642</id>
		<title>Fichier:Carre.jpg</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=Fichier:Carre.jpg&amp;diff=42642"/>
				<updated>2017-05-19T15:34:18Z</updated>
		
		<summary type="html">&lt;p&gt;Mtrimbur : a téléversé une nouvelle version de « Fichier:Carre.jpg »&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Mtrimbur</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=42639</id>
		<title>IMA4 2016/2017 P39</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=42639"/>
				<updated>2017-05-19T15:32:16Z</updated>
		
		<summary type="html">&lt;p&gt;Mtrimbur : /* Semaines Supplémentaires */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
===Contexte===&lt;br /&gt;
&lt;br /&gt;
Le laser est une technologie largement utilisé de nos jours dans de diverses applications. En effet, on retrouve cette technologie dans le domaine médical notamment pour la chirurgie oculaire ou encore dans industrie avec la découpe laser ou la soudure au laser.&lt;br /&gt;
&lt;br /&gt;
Le laser est une émission de photons produit par excitation d'un milieu amplificateur (ex : CO2), le rayonnement produit est unidirectionnel et monochromatique. Ce sont ces propriétés que nous allons exploiter afin réaliser un projecteur laser qui mis en mouvement est capable de dessiner des formes sur une surface à l'instar de systèmes existants utilisés pour des effets lumineux lors de festivités.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
L'objectif du projet est de créer un système de projection laser à plusieurs couleurs (au minimum deux) avec une application web pour programmer les formes à dessiner afin d'agrémenter des compétitions de gymnastique rythmique.&lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
Le projet consiste à réaliser avec des lasers des figures géométriques par l'intermédiaire d'un système galvanométrique. &lt;br /&gt;
&lt;br /&gt;
Notre premier travail sera de concevoir la partie projection. Pour cela, nous devrons aligner les lasers et les galvanomètres. En effet, ces derniers posséderont des miroirs à l'extrémité, ainsi les miroirs changeront d'inclinaison suivant le courant traversant les galvanomètres (similaire à l'image ci-contre). Il nous faudra également créer un système d'alimentation qui à partir d'une même source (réseau 230 V) sera capable d'alimenter les lasers et les galvanomètres ainsi qu'une Arduino et une Raspberry Pi.&lt;br /&gt;
[[File:Scanhead.jpeg|thumb]]&lt;br /&gt;
&lt;br /&gt;
Ensuite nous nous intéresserons à l'utilisation d'un système embarqué pour contrôler les galvanomètres et donc dessiner avec les lasers sur un plan 2D. En effet, le laser restera toujours fixe, seuls les galvanomètres, et donc les miroirs bougeront. Les galvanomètres étant contrôlés en courant il faudra réaliser une interface électronique pour convertir une commande en tension en commande de courant. La commande en tension sera assuré par une carte Arduino. Nous n'utiliserons qu'une seule paire de galvanomètres pour les deux laser. Il faudra donc multiplexer les deux faisceaux. La programmation des formes à effectuer, se fera par l'intermédiaire d'une application web PHP hébergée sur une RaspberryPi qui permettra de récupérer une image, d'y appliquer divers traitements et filtres afin d'en extraire les contours, et de calculer les commandes pour positionner les galvanomètres. Un serveur WebSocket également hébergé sur la RaspberryPi servira d'interface entre l'application web et L'arduino qui sera connecté via une liaison série sur la raspberryPI.&lt;br /&gt;
&lt;br /&gt;
Comme animation de test, nous dessinerons le contour d'une gymnaste avec une couleur et son ballon d'une autre couleur. La gymnaste devra lancer son ballon, réaliser quelques difficultés et récupérer son ballon.&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
Nous utiliserons comme matériels :&lt;br /&gt;
*Deux lasers de différentes couleurs&lt;br /&gt;
*Une paire de galvanomètres à miroir&lt;br /&gt;
*Arduino&lt;br /&gt;
*Raspberry Pi3&lt;br /&gt;
*Alimentation 230V/5V 1A [http://www.miniinthebox.com/fr/dual-usb-eu-prise-murale-5v-2a-voyage-adaptateur-chargeur-d-alimentation-pour-iphone7-6-xiaomi-samsung-et-autre-telephone-portable_p5410410.html?currency=EUR&amp;amp;litb_from=paid_adwords_shopping&amp;amp;sku=429_6917%7C752_20648&amp;amp;utm_source=google_shopping&amp;amp;utm_medium=cpc&amp;amp;adword_mt=&amp;amp;adword_ct=138705676724&amp;amp;adword_kw=&amp;amp;adword_pos=1o5&amp;amp;adword_pl=&amp;amp;adword_net=g&amp;amp;adword_tar=&amp;amp;adw_src_id=9653316068_661261352_33588296076_aud-79897721311:pla-256966386459&amp;amp;gclid=Cj0KEQiA_KvEBRCtzNil4-KR-LIBEiQAmgekFxxKjJJWBYCJlDZEa3Ke_2_WR0DzGVbz-jaCZHVIBoMaAvld8P8HAQ]&lt;br /&gt;
*Drivers galvanomètres x2&lt;br /&gt;
*Alimentation laser&lt;br /&gt;
*Lunette de sécurité x2 [https://www.amazon.fr/Uvex-S1933X-Eyewear-SCTOrange-Anti-Fog/dp/B000USRG90/ref=sr_1_1?ie=UTF8&amp;amp;qid=1485441383&amp;amp;sr=8-1&amp;amp;keywords=uvex+s1933x]&lt;br /&gt;
*Boitier ABS [http://fr.farnell.com/multicomp/g3118/boitier-abs-240x120x60mm-ip65/dp/1526656]&lt;br /&gt;
*DAC 4 canaux, avec interface I²C [https://www.adafruit.com/products/1083]&lt;br /&gt;
*Connecteur C14 [http://www.conrad.fr/ce/fr/product/715001/Connecteur-secteur-C14-Embase-male-verticale-715001-Nombre-de-poles-2-PE-10-A-noir-1-pcs/?ref=detview1&amp;amp;rt=detview1&amp;amp;rb=1]&lt;br /&gt;
*Câble secteur&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Logiciel :&lt;br /&gt;
&lt;br /&gt;
*Serveur web : Apache2, HTML5, PHP5, CSS&lt;br /&gt;
*Base de donnée : MySQL&lt;br /&gt;
*Serveur WebSocket : JQuerry, websocket&lt;br /&gt;
*Arduino : IDE Arduino&lt;br /&gt;
&lt;br /&gt;
===Calendrier prévisionnel===&lt;br /&gt;
&lt;br /&gt;
====Liste des tâches à effectuer====&lt;br /&gt;
Les différentes tâches à effectuer sont :&lt;br /&gt;
*Partie préliminaire : étude de fonctionnement des galvanomètres&lt;br /&gt;
**Déterminer comment est effectuée la commande des galvanomètres (protocole, tension...)&lt;br /&gt;
**Effectuer des tests avec l'Arduino ou la Raspberry Pi&lt;br /&gt;
**Effectuer des tests avec une LED à la place du laser &lt;br /&gt;
*Partie projection&lt;br /&gt;
**Fixer les lasers&lt;br /&gt;
**Aligner les lasers et les galvanomètres&lt;br /&gt;
**Créer le système d'alimentation&lt;br /&gt;
**Création d'un boitier&lt;br /&gt;
*Partie système embarqué&lt;br /&gt;
**Asservissement des galvanomètres avec l'Arduino&lt;br /&gt;
**Système électronique de commande en courant pour les galvanomètres&lt;br /&gt;
*Interface Web&lt;br /&gt;
**Installation et configuration Apache2&lt;br /&gt;
**Création d'une interface graphique simple&lt;br /&gt;
**Implémentation d'algorithmes de traitement d'image&lt;br /&gt;
**Mise en forme avec des CSS&lt;br /&gt;
**Sytème d'authentification avec mot de passe&lt;br /&gt;
**Utilisation d'une base de données pour enregistrer toutes les images déjà utilisés afin de les réutiliser&lt;br /&gt;
*Serveur Web Socket&lt;br /&gt;
**Récupération des données de l'interface web&lt;br /&gt;
**Mise en place de la liaison série avec l'Arduino&lt;br /&gt;
&lt;br /&gt;
====Calendrier====&lt;br /&gt;
Répartition du temps consacré au projet (240h) :&lt;br /&gt;
*Partie projection : 80h&lt;br /&gt;
*Partie système embarqué : 40h&lt;br /&gt;
*Partie interface web et websocket: 120h&lt;br /&gt;
&lt;br /&gt;
==Feuille d'heures==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!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&lt;br /&gt;
|-&lt;br /&gt;
| Définition cahier des charges &lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 14&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|38&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Finalisation du cahier des charges avec les responsables&lt;br /&gt;
&lt;br /&gt;
*Acquisition de matériels :&lt;br /&gt;
**Projecteur Laser&lt;br /&gt;
**Galvanomètres&lt;br /&gt;
**Alimentation des galvanomètres&lt;br /&gt;
&lt;br /&gt;
*Listage du matériels à acquérir :&lt;br /&gt;
**Lunettes de sécurité&lt;br /&gt;
**DAC&lt;br /&gt;
**Alimentation 230V/5V 1A&lt;br /&gt;
** Boitier ABS &lt;br /&gt;
**...&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
*Obtention de l'arduino et de la raspberryPI&lt;br /&gt;
&lt;br /&gt;
*Démontage du projecteur laser&lt;br /&gt;
**Deux lasers de classe 3b (vert et rouge)&lt;br /&gt;
**Circuit d'alimentation des deux lasers&lt;br /&gt;
&lt;br /&gt;
*Initialisation du port série de la raspberryPI&lt;br /&gt;
**Modification du fichier ''config.txt'' dans la partition boot&lt;br /&gt;
**Ajout d'une ligne autorisant la communication série ('''enable_uart=1''')&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
*Installation du serveur apache sur la raspberryPI&lt;br /&gt;
**Modification du fichier ''/etc/network/interfaces'' (Static, Address, Netmask, Gateway)&lt;br /&gt;
**Modification du fichier ''/etc/resolv.conf'' (Adresse du serveur)&lt;br /&gt;
**Utilisation d'un proxy pour la récupération outils de programmation (Apache2, Php5)&lt;br /&gt;
&lt;br /&gt;
*Mise en place du point d’accès wifi de la raspberryPI&lt;br /&gt;
**Récupération des logiciels nécessaires (dnsmasq, hostapd)&lt;br /&gt;
**Mise en place d'une adresse IP statique pour le point d'accès par l'intermédiaire du fichier ''/etc/dhcpcd.conf''&lt;br /&gt;
**Désactivation de la négociation automatique de bail dans le fichier ''/etc/network/interfaces''&lt;br /&gt;
**Configuration du logiciel hostapd ''/etc/hostapd/hostapd.conf''&lt;br /&gt;
**Activation du démarrage automatique du point d'accès ''/etc/default/hostapd''&lt;br /&gt;
**Configuration du serveur DNS par ''/etc/dnsmasq.conf''&lt;br /&gt;
&lt;br /&gt;
*Instauration de la page d'accueil de l'interface web à l'adresse ''192.168.3.1''&lt;br /&gt;
**Téléversement de fichiers images sur la page web et affichage de celle-ci&lt;br /&gt;
**Voyant de confirmation du bon fonctionnement du serveur web&lt;br /&gt;
&lt;br /&gt;
*Développement du serveur websocket&lt;br /&gt;
&lt;br /&gt;
Le développement du serveur websocket, initialement prévu en C (il était prévu de reprendre les sources utilisées l'année précédente dans le cadre des projet IMA3 SC), a finalement été réalisé en JAVA pour plusieurs raisons.&lt;br /&gt;
Premièrement, un seul programme met en œuvre le serveur websocket, les divers traitements d'image, ainsi que les contrôles des galvanomètres (par l'intermédiaire des DAC) via la liaison I²C de la Raspberry Pi. Le langage JAVA fournit nativement des bibliothèques d'objets pour manipuler assez simplement des images, il existe également des librairies pour contrôler le port GPIO de la Raspberry et il était également intéressant de travailler avec un langage de plus haut niveau que le C.&lt;br /&gt;
En outre, la totale portabilité de ce langage nous permet de travailler sur n'importe quelle machine et ensuite transférer notre programme sur la Raspberry Pi et l’exécuter sans même repasser par une phase de compilation. Et finalement, c'est le langage que nous étudions actuellement en cours de programmation orientée objet, ce qui permet de nous perfectionner.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Serveur WebSocket====&lt;br /&gt;
&lt;br /&gt;
N'ayant pas trouvé d'API WebSocket en Java satisfaisante (qui ne nécessitent pas l'installation et la configuration de nombreux outils additionnels), j'ai estimé plus commode et plus formateur de développer notre propre serveur WebSocket en se basant sur les librairies sockets de Java avec l'aide d'une documentation assez exhaustive [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers].&lt;br /&gt;
&lt;br /&gt;
Les WebSockets désignent à la fois un protocole réseau qui étend le protocole TCP ainsi qu'une API du World Wide Web. Nous nous en servons afin d'établir une communication asynchrone et bidirectionnelle entre un navigateur web et le serveur, notamment pour envoyer l'image à projeter. L’implémentation du serveur repose sur plusieurs étapes.&lt;br /&gt;
&lt;br /&gt;
1) Connexion d'un client &lt;br /&gt;
&lt;br /&gt;
2) Handshake : permet de faire le lien entre le protocole HTTP et WS. Le client envoie une requête HTTP demandant un upgrade de la connexion en protocole WS et le serveur répond en configurant la connexion (détail dans la documentation [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers]).&lt;br /&gt;
&lt;br /&gt;
3) Réception et décodage des messages : le serveurs reçoit des trames brutes, on extrait donc la taille du message ainsi que le message. De plus, les données son encodées (cryptage XOR) par un masque qui doit également être extrait.&lt;br /&gt;
&lt;br /&gt;
4) Fermeture de la communication.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le serveur supporte le multi-client il est donc nécessaire qu'il effectue ces étapes en &amp;quot;parallèle&amp;quot;. Nous utilisons donc les threads ou fils d’exécution. Un thread est donc responsable d'attendre qu'un nouveau client se connecte et effectue le &amp;quot;handshake&amp;quot;, il crée ensuite un thread associé à ce client afin d'établir un canal de communication. Il y a donc au moins un thread par client. Par la suite il faudra également implémenter une déconnexion automatique d'un client notamment après un timeout.&lt;br /&gt;
&lt;br /&gt;
Exemple d’exécution du serveur avec deux clients qui se connectent et envoient un message : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testServeur.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Les clients sont des navigateurs web. Pour les tests nous avons repris les exemples utilisés dans le cadre das projets IMA3 SC avec le titre de la page HTML qui se colore en vert lorsque le client est connecté, et un champ de saisie pour envoyer des messages au serveur : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testClient.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 4===&lt;br /&gt;
&lt;br /&gt;
*Mise en place d’algorithmes de traitement d'image&lt;br /&gt;
&lt;br /&gt;
====Détection de contour====&lt;br /&gt;
&lt;br /&gt;
L'objectif de notre projet est de pouvoir projeter n'importe quelle image envoyé grâce à l'application web. Pour cela nous allons tracer à une vitesse élevée les contours de l'image sur par exemple un mur grâce au laser. Il est donc nécessaire de détecter les contours de l'image grâce à plusieurs traitements.&lt;br /&gt;
&lt;br /&gt;
=====Conversion en niveau de gris=====&lt;br /&gt;
&lt;br /&gt;
Une des étapes préliminaires pour effectuer la détection de contour est de convertir l'image couleur en niveau de gris. Pour cela l'algorithme est simple : il suffit pour chaque pixel de l'image d'effectuer la moyenne des composantes rouge, verte, bleu de chaque pixel. En effet, si l'on considère une image matricielle (l'image est considérée comme un tableau à deux dimensions avec chaque case qui contient la couleur du pixel), chaque pixel contient les composantes RGB codées sur un octet. La couleur gris correspond aux composantes RGB égales. Le niveau de gris est donc codé de 0 à 255, avec 0 donnant du noir et 255 du blanc. &lt;br /&gt;
&lt;br /&gt;
Voici le résultat obtenu : [[Fichier:testGrayScale.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Filtre de Prewit et Sobel=====&lt;br /&gt;
&lt;br /&gt;
Un contour est défini par un changement brutal d'intensité lumineuse, il s'agit donc de détecter selon plusieurs directions (au moins 2) ces changements. Il existe de nombreuses techniques afin de détecter les contours d'une image (gradient, Laplacien). L'une des techniques avec un rapport efficacité/temps d'exécution correct repose sur les algorithmes de Prewit ou Sobel. L'algorithme repose sur la convolution de matrices.&lt;br /&gt;
Cela consiste à appliquer sur chaque pixel de l'image la matrice de Prewit définie comme &lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L_x = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; ainsi que sa transposée : &amp;lt;math&amp;gt;&lt;br /&gt;
L_y = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; -1 &amp;amp; -1 \\&lt;br /&gt;
 0 &amp;amp; 0 &amp;amp; 0 \\&lt;br /&gt;
+1 &amp;amp; +1 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Convoluer ces deux filtres sur l'image permet de détecter respectivement les contours verticaux et horizontaux.&lt;br /&gt;
&lt;br /&gt;
D'après wikipedia [https://fr.wikipedia.org/wiki/D%C3%A9tection_de_contours], on obtient de meilleurs résultats en appliquant un filtre triangulaire, on introduit donc la matrice de Sobel :&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-2 &amp;amp; 0 &amp;amp; +2 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
On obtient le résultat suivant : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testOutline1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Pré-traitement : Flou Gaussien=====&lt;br /&gt;
&lt;br /&gt;
Afin de réduire significativement le nombre de contours, il est nécessaire d'effectuer un pré-traitement avant la détection de contours. On utilise généralement un flou gaussien afin de réduire les transitions lumineuses et ainsi réduire le nombre de contours. L’algorithme de flou gaussien repose également sur la convolution de matrices sauf qu'ici la matrice filtre est générée grâce à une fonction gaussienne paramétrée par '''Sigma''' qui va directement impacter le niveau de flou. Plus la matrice de filtrage est grande plus la qualité du résultat est meilleure, mais le temps d’exécution devient également plus grand.&lt;br /&gt;
&lt;br /&gt;
Voici la fonction de génération du filtre : &amp;lt;math&amp;gt;G(x,y) = \frac{1}{{2\pi \sigma^2}} e^{-\frac{x^2 + y^2}{2 \sigma^2}}&amp;lt;/math&amp;gt; où x et y correspondent aux indices de la cellule de la matrice.&lt;br /&gt;
&lt;br /&gt;
On obtient ce résultat :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testGaussianBlur.png]]&lt;br /&gt;
&lt;br /&gt;
On note un bien meilleur résultat. Cependant on remarque que les composantes horizontales ne sont pas correctement détectées il subsiste un problème avec le filtrage vertical que je n'ai pas réussi à identifier. De plus, il s'agit par sa suite d'éliminer les contours parasites ainsi que d'affiner le trait pour n'avoir plus qu'un pixel d'épaisseur.&lt;br /&gt;
&lt;br /&gt;
=====Post-traitement : Algorithme de Canny=====&lt;br /&gt;
&lt;br /&gt;
Afin d'obtenir un résultat exploitable il est nécessaire d'appliquer encore quelques traitements. Pour cela nous utilisons l’algorithme de Canny qui repose que celui de Sobel mais qui ajoute un algorithme de seuillage par hysteresis qui permet de retirer les contours secondaires et de ne garder que les contours connexes dans une seuil haut et un seuil bas définis. En outre, cette algorithme affine également le trait obtenu. Pour cet algorithme nous avons directement trouvé des sources libres de droits [http://www.tomgibara.com/computer-vision/canny-edge-detector] qui donne des résultats très corrects.&lt;br /&gt;
&lt;br /&gt;
Par exemple :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ou encore : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny2.png|1500px]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 5===&lt;br /&gt;
&lt;br /&gt;
*Établissement d'un protocole de transfert d'image basé sur les WebSockets&lt;br /&gt;
**Envoie d'un requête &amp;quot;send&amp;quot; par le client dans une trame websocket texte&lt;br /&gt;
**Réponse serveur 'Y' si aucun autre client tente d'envoyer une image simultanément, 'N' sinon&lt;br /&gt;
**Si et seulement si le client reçoit 'Y' il débute le transfert en envoyant la largeur et la longueur de l'image sur 4 octets, puis les données de l'image soit 4 valeurs pour chaque pixels (r,g,b,alpha)&lt;br /&gt;
**Le serveur renvoie 'D' une fois le transfert achevé (à l'avenir, le serveur renverra l'image après filtrage).&lt;br /&gt;
**A tout moment, le serveur peut renvoyer 'E' si une erreur est survenue (ex : paquets perdus, nombre incorrects de données)&lt;br /&gt;
*Ajout du support des logs au niveau serveur&lt;br /&gt;
**Impression sur la sortie standard des messages&lt;br /&gt;
**Formatage en fonction de la sévérité du log (info, warning, error...)&lt;br /&gt;
**Incrustation de la date et heure&lt;br /&gt;
**Possibilité de redirection dans une fichier, avec configuration (écriture à la suite d'un fichier existant, écrasement...)&lt;br /&gt;
**Le tout dans une classe Java flexible et réutilisable pour d'autres projets&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 6===&lt;br /&gt;
&lt;br /&gt;
*Installation de la librairie Java Pi4j sur la raspberry pi qui permet le contrôle des GPIO de celle-ci et notamment le port I²C (basé sur WiringPi)&lt;br /&gt;
*Amélioration coté serveur websocket&lt;br /&gt;
**Gestion de message plus longs (maximum des trames websockets soit 2^63 octets)&lt;br /&gt;
**Différenciation, à la réception de messages, des trames textes ou binaires des trames de contrôle comme les requête ping, pong ou de fermeture de connexion &lt;br /&gt;
**Ajout d'un mode de debug de trames&lt;br /&gt;
*Interface web&lt;br /&gt;
**Mise en place du code css pour améliorer le rendu visuel de la page&lt;br /&gt;
**Amélioration de l'envoie des données vers le serveur&lt;br /&gt;
&lt;br /&gt;
===Semaine 7===&lt;br /&gt;
&lt;br /&gt;
*Améliorations du serveur WebSocket&lt;br /&gt;
**Gestion de la fragmentation TCP&lt;br /&gt;
**Gestion de la fragmentation WebSocket&lt;br /&gt;
**Gestion des requêtes ping envoyés par le client en renvoyant une trames de contrôle pong afin de maintenir la connexion&lt;br /&gt;
**Gestion des déconnexion de clients afin d'optimiser le serveur&lt;br /&gt;
**Amélioration de l'émission de messages en augmentant la taille maximale pouvant être émise (2^63 octets)&lt;br /&gt;
&lt;br /&gt;
*Amélioration du code css&lt;br /&gt;
*Mise en place d'une partie 'Home' et 'About'&lt;br /&gt;
**Home : Communication avec le serveur web&lt;br /&gt;
**About : Information complémentaire sur la page web&lt;br /&gt;
&lt;br /&gt;
A ce stade du développement, le client et le serveur sont opérationnels et peuvent s'échanger des messages ainsi que des images que le serveur traite pour extraire les contours.&lt;br /&gt;
&lt;br /&gt;
===Semaine 8===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Montage projecteur&lt;br /&gt;
**Intégralité des composants fixés par vis dans le boîtier ABS&lt;br /&gt;
**Fusion des alimentations&lt;br /&gt;
**Présence d'une led témoin de mise en tension&lt;br /&gt;
**Position laser réglable grâce à une vis&lt;br /&gt;
**Présence d'un switch à bascule pour allumer et éteindre le laser&lt;br /&gt;
**Isolation et vérification des composants&lt;br /&gt;
**Tests empiriques de température et de fonctionnement des lasers et galvanomètres&lt;br /&gt;
&lt;br /&gt;
Le montage boîtier est donc terminé et s’alimente en 230V par intermédiaire d'un câble secteur avec connecteur C14. Le résultat s'avère plutôt compact. Les quelques tests de température ont montrés que malgré le manque d'espace la température globale du boîtier ne dépasse pas les 50°C pendant plus d'une heure de fonctionnement. L'intégralité des connexions sont isolées avec de la gaine thermodynamique et les zones &amp;quot;sensibles&amp;quot; sont correctement vérifiés ainsi que protégées avec de la matière isolante.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:proj1.jpg|550px|Boîtier après perçage]] [[Fichier:proj2.jpg|550px|Boîtier finalisé]] [[Fichier:proj3.jpg|550px|Projecteur en fonctionnement]]&lt;br /&gt;
&lt;br /&gt;
*Page web et serveur WebSocket&lt;br /&gt;
**Ajout d'un bouton &amp;quot;reboot&amp;quot; et &amp;quot;shutdown&amp;quot; sur la page web&lt;br /&gt;
***Reboot : Permet le redémarrage de la Raspberry&lt;br /&gt;
***Shutdown : Permet l'extinction de la Raspberry&lt;br /&gt;
**Ajout d'un slider pour le flou gaussien (échelle 1 à 100)&lt;br /&gt;
&lt;br /&gt;
===Semaine 9===&lt;br /&gt;
*Installation du programme 'bind9' permettant de mettre en place un serveur DNS qui permet de remplacer les adresses IP par un nom&lt;br /&gt;
**Problème de configuration (à corriger)&lt;br /&gt;
*Prise en compte du message de retour du serveur&lt;br /&gt;
**Récupération d'un tableau de points représentants les contours de l'image envoyé par le client&lt;br /&gt;
*Mise à jour du slider du flou gaussien&lt;br /&gt;
**Double spider permettant de sélectionner un segment de valeur&lt;br /&gt;
**Echelle comprise entre 0 et 1, pour faciliter la lecture les valeurs sont écrites en pourcent&lt;br /&gt;
*Etude du pololu md08a en remplacement du DAC initialement prévu et dessin de la carte&lt;br /&gt;
&lt;br /&gt;
===Semaine 10===&lt;br /&gt;
[[Fichier:Capture_du_2017-04-12_15-53-15.png|200px|thumb|right|Image envoyée -&amp;gt; Image laser]]&lt;br /&gt;
&lt;br /&gt;
*Récupération d'un ensemble de points envoyés par le serveur permettant de tracer l'image telle que sera projetée par le laser&lt;br /&gt;
**Mise en place du canvas&lt;br /&gt;
**Traçage de l'image par l'intermédiaire de &amp;quot;lineto&amp;quot; puisqu'il s'agit d'un contour&lt;br /&gt;
*Ajout d'une sécurité sur les boutons &amp;quot;reset&amp;quot; et &amp;quot;shutdown&amp;quot;&lt;br /&gt;
**Pop-up de confirmation pour les deux actions&lt;br /&gt;
*Mise à jour du Double slider&lt;br /&gt;
**Redimensionnement&lt;br /&gt;
**Récupération des valeurs&lt;br /&gt;
**Envois des valeurs vers le serveur par un tableau de binaires&lt;br /&gt;
&lt;br /&gt;
===Semaines Supplémentaires===&lt;br /&gt;
&lt;br /&gt;
*Finalisation du code css de la page web&lt;br /&gt;
**Amélioration visuelle&lt;br /&gt;
**Rendu dynamique de la page&lt;br /&gt;
[[Fichier:Page_accueil.png|396px|Page d’accueil]]&lt;br /&gt;
[[Fichier:Page2.png|396px|Image chargée]]&lt;br /&gt;
[[Fichier:Page3.png|396px|Contours récupérés]]&lt;br /&gt;
*Finalisation de la carte Pololu md08a + Arduino Pro Mini&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Mise en place d'une liaison série Raspberry-Arduino&lt;br /&gt;
**Tests effectués avec I2C, SPI, UART. Solution retenue : I2C&lt;br /&gt;
*Contrôle des galvanomètres via PWM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:carre.jpg|550px|Exemple de projection]]&lt;br /&gt;
&lt;br /&gt;
A terme, nous arrivons à projeter une image qui manque quelque peu de précision mais qui est tout de même reconnaissable. Néanmoins les données de positions arrivant par flux &lt;br /&gt;
l'Arduino, nous sommes limité par la vitesse de transmition de l'I2C et cela provoque un clignotement de l'image.&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;br /&gt;
&lt;br /&gt;
[[Media:CptProjetIMA4.pdf‎ |Compte-rendu Projet]]&lt;br /&gt;
&lt;br /&gt;
==Bibliographie==&lt;br /&gt;
&lt;br /&gt;
*Galvanomètres et laser&lt;br /&gt;
http://www.ebay.com/itm/20KPPS-30KPPS-laser-scanning-galvo-scanner-ILDA-Closed-Loop-max-30kpps-for-laser-/261517002270?hash=item3ce3a0c61e&lt;br /&gt;
&lt;br /&gt;
http://sciences.ulb.ac.be/printemps/download/2016/dossier_pedagogique/02.pdf&lt;br /&gt;
&lt;br /&gt;
*Websocket&lt;br /&gt;
http://stackoverflow.com/questions/8125507/how-can-i-send-and-receive-websocket-messages-on-the-server-side&lt;br /&gt;
&lt;br /&gt;
https://tools.ietf.org/html/rfc6455&lt;br /&gt;
&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_a_WebSocket_server_in_Java&lt;br /&gt;
&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers&lt;br /&gt;
&lt;br /&gt;
*Traitement d'image&lt;br /&gt;
https://en.wikipedia.org/wiki/Gaussian_blur&lt;br /&gt;
&lt;br /&gt;
http://www.zebulon.fr/questions-reponses/traitement-d-image-detection-de-contours-55.html&lt;br /&gt;
&lt;br /&gt;
http://patrick-bonnin.developpez.com/cours/vision/apprendre-bases-traitement-image/partie-5-segmentation-contour/&lt;br /&gt;
&lt;br /&gt;
http://www.isir.upmc.fr/UserFiles/File/clady_homepage/EPU/2-Contour&lt;br /&gt;
&lt;br /&gt;
*Autre&lt;br /&gt;
https://icn.fenelonlille.org/mediawiki/index.php/Projet_ICN_commun_2016/2017&lt;br /&gt;
&lt;br /&gt;
https://www.g33k-zone.org/post/2016/05/11/Configurer-le-Raspberry-Pi-en-point-d-acc%C3%A8s-Wifi&lt;br /&gt;
&lt;br /&gt;
https://blogs.oracle.com/acaicedo/resource/Parallax-I2C/Sensors.java&lt;br /&gt;
&lt;br /&gt;
http://stackoverflow.com/questions/22087076/how-to-make-a-simple-image-upload-using-javascript-html&lt;/div&gt;</summary>
		<author><name>Mtrimbur</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=Fichier:Carre.jpg&amp;diff=42637</id>
		<title>Fichier:Carre.jpg</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=Fichier:Carre.jpg&amp;diff=42637"/>
				<updated>2017-05-19T15:31:02Z</updated>
		
		<summary type="html">&lt;p&gt;Mtrimbur : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Mtrimbur</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=42635</id>
		<title>IMA4 2016/2017 P39</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=42635"/>
				<updated>2017-05-19T15:29:06Z</updated>
		
		<summary type="html">&lt;p&gt;Mtrimbur : /* Semaines Supplémentaires */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
===Contexte===&lt;br /&gt;
&lt;br /&gt;
Le laser est une technologie largement utilisé de nos jours dans de diverses applications. En effet, on retrouve cette technologie dans le domaine médical notamment pour la chirurgie oculaire ou encore dans industrie avec la découpe laser ou la soudure au laser.&lt;br /&gt;
&lt;br /&gt;
Le laser est une émission de photons produit par excitation d'un milieu amplificateur (ex : CO2), le rayonnement produit est unidirectionnel et monochromatique. Ce sont ces propriétés que nous allons exploiter afin réaliser un projecteur laser qui mis en mouvement est capable de dessiner des formes sur une surface à l'instar de systèmes existants utilisés pour des effets lumineux lors de festivités.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
L'objectif du projet est de créer un système de projection laser à plusieurs couleurs (au minimum deux) avec une application web pour programmer les formes à dessiner afin d'agrémenter des compétitions de gymnastique rythmique.&lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
Le projet consiste à réaliser avec des lasers des figures géométriques par l'intermédiaire d'un système galvanométrique. &lt;br /&gt;
&lt;br /&gt;
Notre premier travail sera de concevoir la partie projection. Pour cela, nous devrons aligner les lasers et les galvanomètres. En effet, ces derniers posséderont des miroirs à l'extrémité, ainsi les miroirs changeront d'inclinaison suivant le courant traversant les galvanomètres (similaire à l'image ci-contre). Il nous faudra également créer un système d'alimentation qui à partir d'une même source (réseau 230 V) sera capable d'alimenter les lasers et les galvanomètres ainsi qu'une Arduino et une Raspberry Pi.&lt;br /&gt;
[[File:Scanhead.jpeg|thumb]]&lt;br /&gt;
&lt;br /&gt;
Ensuite nous nous intéresserons à l'utilisation d'un système embarqué pour contrôler les galvanomètres et donc dessiner avec les lasers sur un plan 2D. En effet, le laser restera toujours fixe, seuls les galvanomètres, et donc les miroirs bougeront. Les galvanomètres étant contrôlés en courant il faudra réaliser une interface électronique pour convertir une commande en tension en commande de courant. La commande en tension sera assuré par une carte Arduino. Nous n'utiliserons qu'une seule paire de galvanomètres pour les deux laser. Il faudra donc multiplexer les deux faisceaux. La programmation des formes à effectuer, se fera par l'intermédiaire d'une application web PHP hébergée sur une RaspberryPi qui permettra de récupérer une image, d'y appliquer divers traitements et filtres afin d'en extraire les contours, et de calculer les commandes pour positionner les galvanomètres. Un serveur WebSocket également hébergé sur la RaspberryPi servira d'interface entre l'application web et L'arduino qui sera connecté via une liaison série sur la raspberryPI.&lt;br /&gt;
&lt;br /&gt;
Comme animation de test, nous dessinerons le contour d'une gymnaste avec une couleur et son ballon d'une autre couleur. La gymnaste devra lancer son ballon, réaliser quelques difficultés et récupérer son ballon.&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
Nous utiliserons comme matériels :&lt;br /&gt;
*Deux lasers de différentes couleurs&lt;br /&gt;
*Une paire de galvanomètres à miroir&lt;br /&gt;
*Arduino&lt;br /&gt;
*Raspberry Pi3&lt;br /&gt;
*Alimentation 230V/5V 1A [http://www.miniinthebox.com/fr/dual-usb-eu-prise-murale-5v-2a-voyage-adaptateur-chargeur-d-alimentation-pour-iphone7-6-xiaomi-samsung-et-autre-telephone-portable_p5410410.html?currency=EUR&amp;amp;litb_from=paid_adwords_shopping&amp;amp;sku=429_6917%7C752_20648&amp;amp;utm_source=google_shopping&amp;amp;utm_medium=cpc&amp;amp;adword_mt=&amp;amp;adword_ct=138705676724&amp;amp;adword_kw=&amp;amp;adword_pos=1o5&amp;amp;adword_pl=&amp;amp;adword_net=g&amp;amp;adword_tar=&amp;amp;adw_src_id=9653316068_661261352_33588296076_aud-79897721311:pla-256966386459&amp;amp;gclid=Cj0KEQiA_KvEBRCtzNil4-KR-LIBEiQAmgekFxxKjJJWBYCJlDZEa3Ke_2_WR0DzGVbz-jaCZHVIBoMaAvld8P8HAQ]&lt;br /&gt;
*Drivers galvanomètres x2&lt;br /&gt;
*Alimentation laser&lt;br /&gt;
*Lunette de sécurité x2 [https://www.amazon.fr/Uvex-S1933X-Eyewear-SCTOrange-Anti-Fog/dp/B000USRG90/ref=sr_1_1?ie=UTF8&amp;amp;qid=1485441383&amp;amp;sr=8-1&amp;amp;keywords=uvex+s1933x]&lt;br /&gt;
*Boitier ABS [http://fr.farnell.com/multicomp/g3118/boitier-abs-240x120x60mm-ip65/dp/1526656]&lt;br /&gt;
*DAC 4 canaux, avec interface I²C [https://www.adafruit.com/products/1083]&lt;br /&gt;
*Connecteur C14 [http://www.conrad.fr/ce/fr/product/715001/Connecteur-secteur-C14-Embase-male-verticale-715001-Nombre-de-poles-2-PE-10-A-noir-1-pcs/?ref=detview1&amp;amp;rt=detview1&amp;amp;rb=1]&lt;br /&gt;
*Câble secteur&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Logiciel :&lt;br /&gt;
&lt;br /&gt;
*Serveur web : Apache2, HTML5, PHP5, CSS&lt;br /&gt;
*Base de donnée : MySQL&lt;br /&gt;
*Serveur WebSocket : JQuerry, websocket&lt;br /&gt;
*Arduino : IDE Arduino&lt;br /&gt;
&lt;br /&gt;
===Calendrier prévisionnel===&lt;br /&gt;
&lt;br /&gt;
====Liste des tâches à effectuer====&lt;br /&gt;
Les différentes tâches à effectuer sont :&lt;br /&gt;
*Partie préliminaire : étude de fonctionnement des galvanomètres&lt;br /&gt;
**Déterminer comment est effectuée la commande des galvanomètres (protocole, tension...)&lt;br /&gt;
**Effectuer des tests avec l'Arduino ou la Raspberry Pi&lt;br /&gt;
**Effectuer des tests avec une LED à la place du laser &lt;br /&gt;
*Partie projection&lt;br /&gt;
**Fixer les lasers&lt;br /&gt;
**Aligner les lasers et les galvanomètres&lt;br /&gt;
**Créer le système d'alimentation&lt;br /&gt;
**Création d'un boitier&lt;br /&gt;
*Partie système embarqué&lt;br /&gt;
**Asservissement des galvanomètres avec l'Arduino&lt;br /&gt;
**Système électronique de commande en courant pour les galvanomètres&lt;br /&gt;
*Interface Web&lt;br /&gt;
**Installation et configuration Apache2&lt;br /&gt;
**Création d'une interface graphique simple&lt;br /&gt;
**Implémentation d'algorithmes de traitement d'image&lt;br /&gt;
**Mise en forme avec des CSS&lt;br /&gt;
**Sytème d'authentification avec mot de passe&lt;br /&gt;
**Utilisation d'une base de données pour enregistrer toutes les images déjà utilisés afin de les réutiliser&lt;br /&gt;
*Serveur Web Socket&lt;br /&gt;
**Récupération des données de l'interface web&lt;br /&gt;
**Mise en place de la liaison série avec l'Arduino&lt;br /&gt;
&lt;br /&gt;
====Calendrier====&lt;br /&gt;
Répartition du temps consacré au projet (240h) :&lt;br /&gt;
*Partie projection : 80h&lt;br /&gt;
*Partie système embarqué : 40h&lt;br /&gt;
*Partie interface web et websocket: 120h&lt;br /&gt;
&lt;br /&gt;
==Feuille d'heures==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!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&lt;br /&gt;
|-&lt;br /&gt;
| Définition cahier des charges &lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 14&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|38&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Finalisation du cahier des charges avec les responsables&lt;br /&gt;
&lt;br /&gt;
*Acquisition de matériels :&lt;br /&gt;
**Projecteur Laser&lt;br /&gt;
**Galvanomètres&lt;br /&gt;
**Alimentation des galvanomètres&lt;br /&gt;
&lt;br /&gt;
*Listage du matériels à acquérir :&lt;br /&gt;
**Lunettes de sécurité&lt;br /&gt;
**DAC&lt;br /&gt;
**Alimentation 230V/5V 1A&lt;br /&gt;
** Boitier ABS &lt;br /&gt;
**...&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
*Obtention de l'arduino et de la raspberryPI&lt;br /&gt;
&lt;br /&gt;
*Démontage du projecteur laser&lt;br /&gt;
**Deux lasers de classe 3b (vert et rouge)&lt;br /&gt;
**Circuit d'alimentation des deux lasers&lt;br /&gt;
&lt;br /&gt;
*Initialisation du port série de la raspberryPI&lt;br /&gt;
**Modification du fichier ''config.txt'' dans la partition boot&lt;br /&gt;
**Ajout d'une ligne autorisant la communication série ('''enable_uart=1''')&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
*Installation du serveur apache sur la raspberryPI&lt;br /&gt;
**Modification du fichier ''/etc/network/interfaces'' (Static, Address, Netmask, Gateway)&lt;br /&gt;
**Modification du fichier ''/etc/resolv.conf'' (Adresse du serveur)&lt;br /&gt;
**Utilisation d'un proxy pour la récupération outils de programmation (Apache2, Php5)&lt;br /&gt;
&lt;br /&gt;
*Mise en place du point d’accès wifi de la raspberryPI&lt;br /&gt;
**Récupération des logiciels nécessaires (dnsmasq, hostapd)&lt;br /&gt;
**Mise en place d'une adresse IP statique pour le point d'accès par l'intermédiaire du fichier ''/etc/dhcpcd.conf''&lt;br /&gt;
**Désactivation de la négociation automatique de bail dans le fichier ''/etc/network/interfaces''&lt;br /&gt;
**Configuration du logiciel hostapd ''/etc/hostapd/hostapd.conf''&lt;br /&gt;
**Activation du démarrage automatique du point d'accès ''/etc/default/hostapd''&lt;br /&gt;
**Configuration du serveur DNS par ''/etc/dnsmasq.conf''&lt;br /&gt;
&lt;br /&gt;
*Instauration de la page d'accueil de l'interface web à l'adresse ''192.168.3.1''&lt;br /&gt;
**Téléversement de fichiers images sur la page web et affichage de celle-ci&lt;br /&gt;
**Voyant de confirmation du bon fonctionnement du serveur web&lt;br /&gt;
&lt;br /&gt;
*Développement du serveur websocket&lt;br /&gt;
&lt;br /&gt;
Le développement du serveur websocket, initialement prévu en C (il était prévu de reprendre les sources utilisées l'année précédente dans le cadre des projet IMA3 SC), a finalement été réalisé en JAVA pour plusieurs raisons.&lt;br /&gt;
Premièrement, un seul programme met en œuvre le serveur websocket, les divers traitements d'image, ainsi que les contrôles des galvanomètres (par l'intermédiaire des DAC) via la liaison I²C de la Raspberry Pi. Le langage JAVA fournit nativement des bibliothèques d'objets pour manipuler assez simplement des images, il existe également des librairies pour contrôler le port GPIO de la Raspberry et il était également intéressant de travailler avec un langage de plus haut niveau que le C.&lt;br /&gt;
En outre, la totale portabilité de ce langage nous permet de travailler sur n'importe quelle machine et ensuite transférer notre programme sur la Raspberry Pi et l’exécuter sans même repasser par une phase de compilation. Et finalement, c'est le langage que nous étudions actuellement en cours de programmation orientée objet, ce qui permet de nous perfectionner.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Serveur WebSocket====&lt;br /&gt;
&lt;br /&gt;
N'ayant pas trouvé d'API WebSocket en Java satisfaisante (qui ne nécessitent pas l'installation et la configuration de nombreux outils additionnels), j'ai estimé plus commode et plus formateur de développer notre propre serveur WebSocket en se basant sur les librairies sockets de Java avec l'aide d'une documentation assez exhaustive [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers].&lt;br /&gt;
&lt;br /&gt;
Les WebSockets désignent à la fois un protocole réseau qui étend le protocole TCP ainsi qu'une API du World Wide Web. Nous nous en servons afin d'établir une communication asynchrone et bidirectionnelle entre un navigateur web et le serveur, notamment pour envoyer l'image à projeter. L’implémentation du serveur repose sur plusieurs étapes.&lt;br /&gt;
&lt;br /&gt;
1) Connexion d'un client &lt;br /&gt;
&lt;br /&gt;
2) Handshake : permet de faire le lien entre le protocole HTTP et WS. Le client envoie une requête HTTP demandant un upgrade de la connexion en protocole WS et le serveur répond en configurant la connexion (détail dans la documentation [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers]).&lt;br /&gt;
&lt;br /&gt;
3) Réception et décodage des messages : le serveurs reçoit des trames brutes, on extrait donc la taille du message ainsi que le message. De plus, les données son encodées (cryptage XOR) par un masque qui doit également être extrait.&lt;br /&gt;
&lt;br /&gt;
4) Fermeture de la communication.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le serveur supporte le multi-client il est donc nécessaire qu'il effectue ces étapes en &amp;quot;parallèle&amp;quot;. Nous utilisons donc les threads ou fils d’exécution. Un thread est donc responsable d'attendre qu'un nouveau client se connecte et effectue le &amp;quot;handshake&amp;quot;, il crée ensuite un thread associé à ce client afin d'établir un canal de communication. Il y a donc au moins un thread par client. Par la suite il faudra également implémenter une déconnexion automatique d'un client notamment après un timeout.&lt;br /&gt;
&lt;br /&gt;
Exemple d’exécution du serveur avec deux clients qui se connectent et envoient un message : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testServeur.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Les clients sont des navigateurs web. Pour les tests nous avons repris les exemples utilisés dans le cadre das projets IMA3 SC avec le titre de la page HTML qui se colore en vert lorsque le client est connecté, et un champ de saisie pour envoyer des messages au serveur : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testClient.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 4===&lt;br /&gt;
&lt;br /&gt;
*Mise en place d’algorithmes de traitement d'image&lt;br /&gt;
&lt;br /&gt;
====Détection de contour====&lt;br /&gt;
&lt;br /&gt;
L'objectif de notre projet est de pouvoir projeter n'importe quelle image envoyé grâce à l'application web. Pour cela nous allons tracer à une vitesse élevée les contours de l'image sur par exemple un mur grâce au laser. Il est donc nécessaire de détecter les contours de l'image grâce à plusieurs traitements.&lt;br /&gt;
&lt;br /&gt;
=====Conversion en niveau de gris=====&lt;br /&gt;
&lt;br /&gt;
Une des étapes préliminaires pour effectuer la détection de contour est de convertir l'image couleur en niveau de gris. Pour cela l'algorithme est simple : il suffit pour chaque pixel de l'image d'effectuer la moyenne des composantes rouge, verte, bleu de chaque pixel. En effet, si l'on considère une image matricielle (l'image est considérée comme un tableau à deux dimensions avec chaque case qui contient la couleur du pixel), chaque pixel contient les composantes RGB codées sur un octet. La couleur gris correspond aux composantes RGB égales. Le niveau de gris est donc codé de 0 à 255, avec 0 donnant du noir et 255 du blanc. &lt;br /&gt;
&lt;br /&gt;
Voici le résultat obtenu : [[Fichier:testGrayScale.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Filtre de Prewit et Sobel=====&lt;br /&gt;
&lt;br /&gt;
Un contour est défini par un changement brutal d'intensité lumineuse, il s'agit donc de détecter selon plusieurs directions (au moins 2) ces changements. Il existe de nombreuses techniques afin de détecter les contours d'une image (gradient, Laplacien). L'une des techniques avec un rapport efficacité/temps d'exécution correct repose sur les algorithmes de Prewit ou Sobel. L'algorithme repose sur la convolution de matrices.&lt;br /&gt;
Cela consiste à appliquer sur chaque pixel de l'image la matrice de Prewit définie comme &lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L_x = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; ainsi que sa transposée : &amp;lt;math&amp;gt;&lt;br /&gt;
L_y = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; -1 &amp;amp; -1 \\&lt;br /&gt;
 0 &amp;amp; 0 &amp;amp; 0 \\&lt;br /&gt;
+1 &amp;amp; +1 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Convoluer ces deux filtres sur l'image permet de détecter respectivement les contours verticaux et horizontaux.&lt;br /&gt;
&lt;br /&gt;
D'après wikipedia [https://fr.wikipedia.org/wiki/D%C3%A9tection_de_contours], on obtient de meilleurs résultats en appliquant un filtre triangulaire, on introduit donc la matrice de Sobel :&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-2 &amp;amp; 0 &amp;amp; +2 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
On obtient le résultat suivant : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testOutline1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Pré-traitement : Flou Gaussien=====&lt;br /&gt;
&lt;br /&gt;
Afin de réduire significativement le nombre de contours, il est nécessaire d'effectuer un pré-traitement avant la détection de contours. On utilise généralement un flou gaussien afin de réduire les transitions lumineuses et ainsi réduire le nombre de contours. L’algorithme de flou gaussien repose également sur la convolution de matrices sauf qu'ici la matrice filtre est générée grâce à une fonction gaussienne paramétrée par '''Sigma''' qui va directement impacter le niveau de flou. Plus la matrice de filtrage est grande plus la qualité du résultat est meilleure, mais le temps d’exécution devient également plus grand.&lt;br /&gt;
&lt;br /&gt;
Voici la fonction de génération du filtre : &amp;lt;math&amp;gt;G(x,y) = \frac{1}{{2\pi \sigma^2}} e^{-\frac{x^2 + y^2}{2 \sigma^2}}&amp;lt;/math&amp;gt; où x et y correspondent aux indices de la cellule de la matrice.&lt;br /&gt;
&lt;br /&gt;
On obtient ce résultat :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testGaussianBlur.png]]&lt;br /&gt;
&lt;br /&gt;
On note un bien meilleur résultat. Cependant on remarque que les composantes horizontales ne sont pas correctement détectées il subsiste un problème avec le filtrage vertical que je n'ai pas réussi à identifier. De plus, il s'agit par sa suite d'éliminer les contours parasites ainsi que d'affiner le trait pour n'avoir plus qu'un pixel d'épaisseur.&lt;br /&gt;
&lt;br /&gt;
=====Post-traitement : Algorithme de Canny=====&lt;br /&gt;
&lt;br /&gt;
Afin d'obtenir un résultat exploitable il est nécessaire d'appliquer encore quelques traitements. Pour cela nous utilisons l’algorithme de Canny qui repose que celui de Sobel mais qui ajoute un algorithme de seuillage par hysteresis qui permet de retirer les contours secondaires et de ne garder que les contours connexes dans une seuil haut et un seuil bas définis. En outre, cette algorithme affine également le trait obtenu. Pour cet algorithme nous avons directement trouvé des sources libres de droits [http://www.tomgibara.com/computer-vision/canny-edge-detector] qui donne des résultats très corrects.&lt;br /&gt;
&lt;br /&gt;
Par exemple :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ou encore : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny2.png|1500px]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 5===&lt;br /&gt;
&lt;br /&gt;
*Établissement d'un protocole de transfert d'image basé sur les WebSockets&lt;br /&gt;
**Envoie d'un requête &amp;quot;send&amp;quot; par le client dans une trame websocket texte&lt;br /&gt;
**Réponse serveur 'Y' si aucun autre client tente d'envoyer une image simultanément, 'N' sinon&lt;br /&gt;
**Si et seulement si le client reçoit 'Y' il débute le transfert en envoyant la largeur et la longueur de l'image sur 4 octets, puis les données de l'image soit 4 valeurs pour chaque pixels (r,g,b,alpha)&lt;br /&gt;
**Le serveur renvoie 'D' une fois le transfert achevé (à l'avenir, le serveur renverra l'image après filtrage).&lt;br /&gt;
**A tout moment, le serveur peut renvoyer 'E' si une erreur est survenue (ex : paquets perdus, nombre incorrects de données)&lt;br /&gt;
*Ajout du support des logs au niveau serveur&lt;br /&gt;
**Impression sur la sortie standard des messages&lt;br /&gt;
**Formatage en fonction de la sévérité du log (info, warning, error...)&lt;br /&gt;
**Incrustation de la date et heure&lt;br /&gt;
**Possibilité de redirection dans une fichier, avec configuration (écriture à la suite d'un fichier existant, écrasement...)&lt;br /&gt;
**Le tout dans une classe Java flexible et réutilisable pour d'autres projets&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 6===&lt;br /&gt;
&lt;br /&gt;
*Installation de la librairie Java Pi4j sur la raspberry pi qui permet le contrôle des GPIO de celle-ci et notamment le port I²C (basé sur WiringPi)&lt;br /&gt;
*Amélioration coté serveur websocket&lt;br /&gt;
**Gestion de message plus longs (maximum des trames websockets soit 2^63 octets)&lt;br /&gt;
**Différenciation, à la réception de messages, des trames textes ou binaires des trames de contrôle comme les requête ping, pong ou de fermeture de connexion &lt;br /&gt;
**Ajout d'un mode de debug de trames&lt;br /&gt;
*Interface web&lt;br /&gt;
**Mise en place du code css pour améliorer le rendu visuel de la page&lt;br /&gt;
**Amélioration de l'envoie des données vers le serveur&lt;br /&gt;
&lt;br /&gt;
===Semaine 7===&lt;br /&gt;
&lt;br /&gt;
*Améliorations du serveur WebSocket&lt;br /&gt;
**Gestion de la fragmentation TCP&lt;br /&gt;
**Gestion de la fragmentation WebSocket&lt;br /&gt;
**Gestion des requêtes ping envoyés par le client en renvoyant une trames de contrôle pong afin de maintenir la connexion&lt;br /&gt;
**Gestion des déconnexion de clients afin d'optimiser le serveur&lt;br /&gt;
**Amélioration de l'émission de messages en augmentant la taille maximale pouvant être émise (2^63 octets)&lt;br /&gt;
&lt;br /&gt;
*Amélioration du code css&lt;br /&gt;
*Mise en place d'une partie 'Home' et 'About'&lt;br /&gt;
**Home : Communication avec le serveur web&lt;br /&gt;
**About : Information complémentaire sur la page web&lt;br /&gt;
&lt;br /&gt;
A ce stade du développement, le client et le serveur sont opérationnels et peuvent s'échanger des messages ainsi que des images que le serveur traite pour extraire les contours.&lt;br /&gt;
&lt;br /&gt;
===Semaine 8===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Montage projecteur&lt;br /&gt;
**Intégralité des composants fixés par vis dans le boîtier ABS&lt;br /&gt;
**Fusion des alimentations&lt;br /&gt;
**Présence d'une led témoin de mise en tension&lt;br /&gt;
**Position laser réglable grâce à une vis&lt;br /&gt;
**Présence d'un switch à bascule pour allumer et éteindre le laser&lt;br /&gt;
**Isolation et vérification des composants&lt;br /&gt;
**Tests empiriques de température et de fonctionnement des lasers et galvanomètres&lt;br /&gt;
&lt;br /&gt;
Le montage boîtier est donc terminé et s’alimente en 230V par intermédiaire d'un câble secteur avec connecteur C14. Le résultat s'avère plutôt compact. Les quelques tests de température ont montrés que malgré le manque d'espace la température globale du boîtier ne dépasse pas les 50°C pendant plus d'une heure de fonctionnement. L'intégralité des connexions sont isolées avec de la gaine thermodynamique et les zones &amp;quot;sensibles&amp;quot; sont correctement vérifiés ainsi que protégées avec de la matière isolante.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:proj1.jpg|550px|Boîtier après perçage]] [[Fichier:proj2.jpg|550px|Boîtier finalisé]] [[Fichier:proj3.jpg|550px|Projecteur en fonctionnement]]&lt;br /&gt;
&lt;br /&gt;
*Page web et serveur WebSocket&lt;br /&gt;
**Ajout d'un bouton &amp;quot;reboot&amp;quot; et &amp;quot;shutdown&amp;quot; sur la page web&lt;br /&gt;
***Reboot : Permet le redémarrage de la Raspberry&lt;br /&gt;
***Shutdown : Permet l'extinction de la Raspberry&lt;br /&gt;
**Ajout d'un slider pour le flou gaussien (échelle 1 à 100)&lt;br /&gt;
&lt;br /&gt;
===Semaine 9===&lt;br /&gt;
*Installation du programme 'bind9' permettant de mettre en place un serveur DNS qui permet de remplacer les adresses IP par un nom&lt;br /&gt;
**Problème de configuration (à corriger)&lt;br /&gt;
*Prise en compte du message de retour du serveur&lt;br /&gt;
**Récupération d'un tableau de points représentants les contours de l'image envoyé par le client&lt;br /&gt;
*Mise à jour du slider du flou gaussien&lt;br /&gt;
**Double spider permettant de sélectionner un segment de valeur&lt;br /&gt;
**Echelle comprise entre 0 et 1, pour faciliter la lecture les valeurs sont écrites en pourcent&lt;br /&gt;
*Etude du pololu md08a en remplacement du DAC initialement prévu et dessin de la carte&lt;br /&gt;
&lt;br /&gt;
===Semaine 10===&lt;br /&gt;
[[Fichier:Capture_du_2017-04-12_15-53-15.png|200px|thumb|right|Image envoyée -&amp;gt; Image laser]]&lt;br /&gt;
&lt;br /&gt;
*Récupération d'un ensemble de points envoyés par le serveur permettant de tracer l'image telle que sera projetée par le laser&lt;br /&gt;
**Mise en place du canvas&lt;br /&gt;
**Traçage de l'image par l'intermédiaire de &amp;quot;lineto&amp;quot; puisqu'il s'agit d'un contour&lt;br /&gt;
*Ajout d'une sécurité sur les boutons &amp;quot;reset&amp;quot; et &amp;quot;shutdown&amp;quot;&lt;br /&gt;
**Pop-up de confirmation pour les deux actions&lt;br /&gt;
*Mise à jour du Double slider&lt;br /&gt;
**Redimensionnement&lt;br /&gt;
**Récupération des valeurs&lt;br /&gt;
**Envois des valeurs vers le serveur par un tableau de binaires&lt;br /&gt;
&lt;br /&gt;
===Semaines Supplémentaires===&lt;br /&gt;
&lt;br /&gt;
*Finalisation du code css de la page web&lt;br /&gt;
**Amélioration visuelle&lt;br /&gt;
**Rendu dynamique de la page&lt;br /&gt;
[[Fichier:Page_accueil.png|396px|Page d’accueil]]&lt;br /&gt;
[[Fichier:Page2.png|396px|Image chargée]]&lt;br /&gt;
[[Fichier:Page3.png|396px|Contours récupérés]]&lt;br /&gt;
*Finalisation de la carte Pololu md08a + Arduino Pro Mini&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Mise en place d'une liaison série Raspberry-Arduino&lt;br /&gt;
**Tests effectués avec I2C, SPI, UART. Solution retenue : I2C&lt;br /&gt;
*Contrôle des galvanomètres via PWM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:carre.jpg]]&lt;br /&gt;
&lt;br /&gt;
A terme, nous arrivons à projeter une image qui manque quelque peu de précision mais qui est tout de même reconnaissable. Néanmoins les données de positions arrivant par flux &lt;br /&gt;
l'Arduino, nous sommes limité par la vitesse de transmition de l'I2C et cela provoque un clignotement de l'image.&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;br /&gt;
&lt;br /&gt;
[[Media:CptProjetIMA4.pdf‎ |Compte-rendu Projet]]&lt;br /&gt;
&lt;br /&gt;
==Bibliographie==&lt;br /&gt;
&lt;br /&gt;
*Galvanomètres et laser&lt;br /&gt;
http://www.ebay.com/itm/20KPPS-30KPPS-laser-scanning-galvo-scanner-ILDA-Closed-Loop-max-30kpps-for-laser-/261517002270?hash=item3ce3a0c61e&lt;br /&gt;
&lt;br /&gt;
http://sciences.ulb.ac.be/printemps/download/2016/dossier_pedagogique/02.pdf&lt;br /&gt;
&lt;br /&gt;
*Websocket&lt;br /&gt;
http://stackoverflow.com/questions/8125507/how-can-i-send-and-receive-websocket-messages-on-the-server-side&lt;br /&gt;
&lt;br /&gt;
https://tools.ietf.org/html/rfc6455&lt;br /&gt;
&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_a_WebSocket_server_in_Java&lt;br /&gt;
&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers&lt;br /&gt;
&lt;br /&gt;
*Traitement d'image&lt;br /&gt;
https://en.wikipedia.org/wiki/Gaussian_blur&lt;br /&gt;
&lt;br /&gt;
http://www.zebulon.fr/questions-reponses/traitement-d-image-detection-de-contours-55.html&lt;br /&gt;
&lt;br /&gt;
http://patrick-bonnin.developpez.com/cours/vision/apprendre-bases-traitement-image/partie-5-segmentation-contour/&lt;br /&gt;
&lt;br /&gt;
http://www.isir.upmc.fr/UserFiles/File/clady_homepage/EPU/2-Contour&lt;br /&gt;
&lt;br /&gt;
*Autre&lt;br /&gt;
https://icn.fenelonlille.org/mediawiki/index.php/Projet_ICN_commun_2016/2017&lt;br /&gt;
&lt;br /&gt;
https://www.g33k-zone.org/post/2016/05/11/Configurer-le-Raspberry-Pi-en-point-d-acc%C3%A8s-Wifi&lt;br /&gt;
&lt;br /&gt;
https://blogs.oracle.com/acaicedo/resource/Parallax-I2C/Sensors.java&lt;br /&gt;
&lt;br /&gt;
http://stackoverflow.com/questions/22087076/how-to-make-a-simple-image-upload-using-javascript-html&lt;/div&gt;</summary>
		<author><name>Mtrimbur</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=42632</id>
		<title>IMA4 2016/2017 P39</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=42632"/>
				<updated>2017-05-19T15:27:27Z</updated>
		
		<summary type="html">&lt;p&gt;Mtrimbur : /* Semaines Supplémentaires */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
===Contexte===&lt;br /&gt;
&lt;br /&gt;
Le laser est une technologie largement utilisé de nos jours dans de diverses applications. En effet, on retrouve cette technologie dans le domaine médical notamment pour la chirurgie oculaire ou encore dans industrie avec la découpe laser ou la soudure au laser.&lt;br /&gt;
&lt;br /&gt;
Le laser est une émission de photons produit par excitation d'un milieu amplificateur (ex : CO2), le rayonnement produit est unidirectionnel et monochromatique. Ce sont ces propriétés que nous allons exploiter afin réaliser un projecteur laser qui mis en mouvement est capable de dessiner des formes sur une surface à l'instar de systèmes existants utilisés pour des effets lumineux lors de festivités.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
L'objectif du projet est de créer un système de projection laser à plusieurs couleurs (au minimum deux) avec une application web pour programmer les formes à dessiner afin d'agrémenter des compétitions de gymnastique rythmique.&lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
Le projet consiste à réaliser avec des lasers des figures géométriques par l'intermédiaire d'un système galvanométrique. &lt;br /&gt;
&lt;br /&gt;
Notre premier travail sera de concevoir la partie projection. Pour cela, nous devrons aligner les lasers et les galvanomètres. En effet, ces derniers posséderont des miroirs à l'extrémité, ainsi les miroirs changeront d'inclinaison suivant le courant traversant les galvanomètres (similaire à l'image ci-contre). Il nous faudra également créer un système d'alimentation qui à partir d'une même source (réseau 230 V) sera capable d'alimenter les lasers et les galvanomètres ainsi qu'une Arduino et une Raspberry Pi.&lt;br /&gt;
[[File:Scanhead.jpeg|thumb]]&lt;br /&gt;
&lt;br /&gt;
Ensuite nous nous intéresserons à l'utilisation d'un système embarqué pour contrôler les galvanomètres et donc dessiner avec les lasers sur un plan 2D. En effet, le laser restera toujours fixe, seuls les galvanomètres, et donc les miroirs bougeront. Les galvanomètres étant contrôlés en courant il faudra réaliser une interface électronique pour convertir une commande en tension en commande de courant. La commande en tension sera assuré par une carte Arduino. Nous n'utiliserons qu'une seule paire de galvanomètres pour les deux laser. Il faudra donc multiplexer les deux faisceaux. La programmation des formes à effectuer, se fera par l'intermédiaire d'une application web PHP hébergée sur une RaspberryPi qui permettra de récupérer une image, d'y appliquer divers traitements et filtres afin d'en extraire les contours, et de calculer les commandes pour positionner les galvanomètres. Un serveur WebSocket également hébergé sur la RaspberryPi servira d'interface entre l'application web et L'arduino qui sera connecté via une liaison série sur la raspberryPI.&lt;br /&gt;
&lt;br /&gt;
Comme animation de test, nous dessinerons le contour d'une gymnaste avec une couleur et son ballon d'une autre couleur. La gymnaste devra lancer son ballon, réaliser quelques difficultés et récupérer son ballon.&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
Nous utiliserons comme matériels :&lt;br /&gt;
*Deux lasers de différentes couleurs&lt;br /&gt;
*Une paire de galvanomètres à miroir&lt;br /&gt;
*Arduino&lt;br /&gt;
*Raspberry Pi3&lt;br /&gt;
*Alimentation 230V/5V 1A [http://www.miniinthebox.com/fr/dual-usb-eu-prise-murale-5v-2a-voyage-adaptateur-chargeur-d-alimentation-pour-iphone7-6-xiaomi-samsung-et-autre-telephone-portable_p5410410.html?currency=EUR&amp;amp;litb_from=paid_adwords_shopping&amp;amp;sku=429_6917%7C752_20648&amp;amp;utm_source=google_shopping&amp;amp;utm_medium=cpc&amp;amp;adword_mt=&amp;amp;adword_ct=138705676724&amp;amp;adword_kw=&amp;amp;adword_pos=1o5&amp;amp;adword_pl=&amp;amp;adword_net=g&amp;amp;adword_tar=&amp;amp;adw_src_id=9653316068_661261352_33588296076_aud-79897721311:pla-256966386459&amp;amp;gclid=Cj0KEQiA_KvEBRCtzNil4-KR-LIBEiQAmgekFxxKjJJWBYCJlDZEa3Ke_2_WR0DzGVbz-jaCZHVIBoMaAvld8P8HAQ]&lt;br /&gt;
*Drivers galvanomètres x2&lt;br /&gt;
*Alimentation laser&lt;br /&gt;
*Lunette de sécurité x2 [https://www.amazon.fr/Uvex-S1933X-Eyewear-SCTOrange-Anti-Fog/dp/B000USRG90/ref=sr_1_1?ie=UTF8&amp;amp;qid=1485441383&amp;amp;sr=8-1&amp;amp;keywords=uvex+s1933x]&lt;br /&gt;
*Boitier ABS [http://fr.farnell.com/multicomp/g3118/boitier-abs-240x120x60mm-ip65/dp/1526656]&lt;br /&gt;
*DAC 4 canaux, avec interface I²C [https://www.adafruit.com/products/1083]&lt;br /&gt;
*Connecteur C14 [http://www.conrad.fr/ce/fr/product/715001/Connecteur-secteur-C14-Embase-male-verticale-715001-Nombre-de-poles-2-PE-10-A-noir-1-pcs/?ref=detview1&amp;amp;rt=detview1&amp;amp;rb=1]&lt;br /&gt;
*Câble secteur&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Logiciel :&lt;br /&gt;
&lt;br /&gt;
*Serveur web : Apache2, HTML5, PHP5, CSS&lt;br /&gt;
*Base de donnée : MySQL&lt;br /&gt;
*Serveur WebSocket : JQuerry, websocket&lt;br /&gt;
*Arduino : IDE Arduino&lt;br /&gt;
&lt;br /&gt;
===Calendrier prévisionnel===&lt;br /&gt;
&lt;br /&gt;
====Liste des tâches à effectuer====&lt;br /&gt;
Les différentes tâches à effectuer sont :&lt;br /&gt;
*Partie préliminaire : étude de fonctionnement des galvanomètres&lt;br /&gt;
**Déterminer comment est effectuée la commande des galvanomètres (protocole, tension...)&lt;br /&gt;
**Effectuer des tests avec l'Arduino ou la Raspberry Pi&lt;br /&gt;
**Effectuer des tests avec une LED à la place du laser &lt;br /&gt;
*Partie projection&lt;br /&gt;
**Fixer les lasers&lt;br /&gt;
**Aligner les lasers et les galvanomètres&lt;br /&gt;
**Créer le système d'alimentation&lt;br /&gt;
**Création d'un boitier&lt;br /&gt;
*Partie système embarqué&lt;br /&gt;
**Asservissement des galvanomètres avec l'Arduino&lt;br /&gt;
**Système électronique de commande en courant pour les galvanomètres&lt;br /&gt;
*Interface Web&lt;br /&gt;
**Installation et configuration Apache2&lt;br /&gt;
**Création d'une interface graphique simple&lt;br /&gt;
**Implémentation d'algorithmes de traitement d'image&lt;br /&gt;
**Mise en forme avec des CSS&lt;br /&gt;
**Sytème d'authentification avec mot de passe&lt;br /&gt;
**Utilisation d'une base de données pour enregistrer toutes les images déjà utilisés afin de les réutiliser&lt;br /&gt;
*Serveur Web Socket&lt;br /&gt;
**Récupération des données de l'interface web&lt;br /&gt;
**Mise en place de la liaison série avec l'Arduino&lt;br /&gt;
&lt;br /&gt;
====Calendrier====&lt;br /&gt;
Répartition du temps consacré au projet (240h) :&lt;br /&gt;
*Partie projection : 80h&lt;br /&gt;
*Partie système embarqué : 40h&lt;br /&gt;
*Partie interface web et websocket: 120h&lt;br /&gt;
&lt;br /&gt;
==Feuille d'heures==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!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&lt;br /&gt;
|-&lt;br /&gt;
| Définition cahier des charges &lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 14&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|38&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Finalisation du cahier des charges avec les responsables&lt;br /&gt;
&lt;br /&gt;
*Acquisition de matériels :&lt;br /&gt;
**Projecteur Laser&lt;br /&gt;
**Galvanomètres&lt;br /&gt;
**Alimentation des galvanomètres&lt;br /&gt;
&lt;br /&gt;
*Listage du matériels à acquérir :&lt;br /&gt;
**Lunettes de sécurité&lt;br /&gt;
**DAC&lt;br /&gt;
**Alimentation 230V/5V 1A&lt;br /&gt;
** Boitier ABS &lt;br /&gt;
**...&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
*Obtention de l'arduino et de la raspberryPI&lt;br /&gt;
&lt;br /&gt;
*Démontage du projecteur laser&lt;br /&gt;
**Deux lasers de classe 3b (vert et rouge)&lt;br /&gt;
**Circuit d'alimentation des deux lasers&lt;br /&gt;
&lt;br /&gt;
*Initialisation du port série de la raspberryPI&lt;br /&gt;
**Modification du fichier ''config.txt'' dans la partition boot&lt;br /&gt;
**Ajout d'une ligne autorisant la communication série ('''enable_uart=1''')&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
*Installation du serveur apache sur la raspberryPI&lt;br /&gt;
**Modification du fichier ''/etc/network/interfaces'' (Static, Address, Netmask, Gateway)&lt;br /&gt;
**Modification du fichier ''/etc/resolv.conf'' (Adresse du serveur)&lt;br /&gt;
**Utilisation d'un proxy pour la récupération outils de programmation (Apache2, Php5)&lt;br /&gt;
&lt;br /&gt;
*Mise en place du point d’accès wifi de la raspberryPI&lt;br /&gt;
**Récupération des logiciels nécessaires (dnsmasq, hostapd)&lt;br /&gt;
**Mise en place d'une adresse IP statique pour le point d'accès par l'intermédiaire du fichier ''/etc/dhcpcd.conf''&lt;br /&gt;
**Désactivation de la négociation automatique de bail dans le fichier ''/etc/network/interfaces''&lt;br /&gt;
**Configuration du logiciel hostapd ''/etc/hostapd/hostapd.conf''&lt;br /&gt;
**Activation du démarrage automatique du point d'accès ''/etc/default/hostapd''&lt;br /&gt;
**Configuration du serveur DNS par ''/etc/dnsmasq.conf''&lt;br /&gt;
&lt;br /&gt;
*Instauration de la page d'accueil de l'interface web à l'adresse ''192.168.3.1''&lt;br /&gt;
**Téléversement de fichiers images sur la page web et affichage de celle-ci&lt;br /&gt;
**Voyant de confirmation du bon fonctionnement du serveur web&lt;br /&gt;
&lt;br /&gt;
*Développement du serveur websocket&lt;br /&gt;
&lt;br /&gt;
Le développement du serveur websocket, initialement prévu en C (il était prévu de reprendre les sources utilisées l'année précédente dans le cadre des projet IMA3 SC), a finalement été réalisé en JAVA pour plusieurs raisons.&lt;br /&gt;
Premièrement, un seul programme met en œuvre le serveur websocket, les divers traitements d'image, ainsi que les contrôles des galvanomètres (par l'intermédiaire des DAC) via la liaison I²C de la Raspberry Pi. Le langage JAVA fournit nativement des bibliothèques d'objets pour manipuler assez simplement des images, il existe également des librairies pour contrôler le port GPIO de la Raspberry et il était également intéressant de travailler avec un langage de plus haut niveau que le C.&lt;br /&gt;
En outre, la totale portabilité de ce langage nous permet de travailler sur n'importe quelle machine et ensuite transférer notre programme sur la Raspberry Pi et l’exécuter sans même repasser par une phase de compilation. Et finalement, c'est le langage que nous étudions actuellement en cours de programmation orientée objet, ce qui permet de nous perfectionner.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Serveur WebSocket====&lt;br /&gt;
&lt;br /&gt;
N'ayant pas trouvé d'API WebSocket en Java satisfaisante (qui ne nécessitent pas l'installation et la configuration de nombreux outils additionnels), j'ai estimé plus commode et plus formateur de développer notre propre serveur WebSocket en se basant sur les librairies sockets de Java avec l'aide d'une documentation assez exhaustive [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers].&lt;br /&gt;
&lt;br /&gt;
Les WebSockets désignent à la fois un protocole réseau qui étend le protocole TCP ainsi qu'une API du World Wide Web. Nous nous en servons afin d'établir une communication asynchrone et bidirectionnelle entre un navigateur web et le serveur, notamment pour envoyer l'image à projeter. L’implémentation du serveur repose sur plusieurs étapes.&lt;br /&gt;
&lt;br /&gt;
1) Connexion d'un client &lt;br /&gt;
&lt;br /&gt;
2) Handshake : permet de faire le lien entre le protocole HTTP et WS. Le client envoie une requête HTTP demandant un upgrade de la connexion en protocole WS et le serveur répond en configurant la connexion (détail dans la documentation [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers]).&lt;br /&gt;
&lt;br /&gt;
3) Réception et décodage des messages : le serveurs reçoit des trames brutes, on extrait donc la taille du message ainsi que le message. De plus, les données son encodées (cryptage XOR) par un masque qui doit également être extrait.&lt;br /&gt;
&lt;br /&gt;
4) Fermeture de la communication.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le serveur supporte le multi-client il est donc nécessaire qu'il effectue ces étapes en &amp;quot;parallèle&amp;quot;. Nous utilisons donc les threads ou fils d’exécution. Un thread est donc responsable d'attendre qu'un nouveau client se connecte et effectue le &amp;quot;handshake&amp;quot;, il crée ensuite un thread associé à ce client afin d'établir un canal de communication. Il y a donc au moins un thread par client. Par la suite il faudra également implémenter une déconnexion automatique d'un client notamment après un timeout.&lt;br /&gt;
&lt;br /&gt;
Exemple d’exécution du serveur avec deux clients qui se connectent et envoient un message : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testServeur.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Les clients sont des navigateurs web. Pour les tests nous avons repris les exemples utilisés dans le cadre das projets IMA3 SC avec le titre de la page HTML qui se colore en vert lorsque le client est connecté, et un champ de saisie pour envoyer des messages au serveur : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testClient.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 4===&lt;br /&gt;
&lt;br /&gt;
*Mise en place d’algorithmes de traitement d'image&lt;br /&gt;
&lt;br /&gt;
====Détection de contour====&lt;br /&gt;
&lt;br /&gt;
L'objectif de notre projet est de pouvoir projeter n'importe quelle image envoyé grâce à l'application web. Pour cela nous allons tracer à une vitesse élevée les contours de l'image sur par exemple un mur grâce au laser. Il est donc nécessaire de détecter les contours de l'image grâce à plusieurs traitements.&lt;br /&gt;
&lt;br /&gt;
=====Conversion en niveau de gris=====&lt;br /&gt;
&lt;br /&gt;
Une des étapes préliminaires pour effectuer la détection de contour est de convertir l'image couleur en niveau de gris. Pour cela l'algorithme est simple : il suffit pour chaque pixel de l'image d'effectuer la moyenne des composantes rouge, verte, bleu de chaque pixel. En effet, si l'on considère une image matricielle (l'image est considérée comme un tableau à deux dimensions avec chaque case qui contient la couleur du pixel), chaque pixel contient les composantes RGB codées sur un octet. La couleur gris correspond aux composantes RGB égales. Le niveau de gris est donc codé de 0 à 255, avec 0 donnant du noir et 255 du blanc. &lt;br /&gt;
&lt;br /&gt;
Voici le résultat obtenu : [[Fichier:testGrayScale.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Filtre de Prewit et Sobel=====&lt;br /&gt;
&lt;br /&gt;
Un contour est défini par un changement brutal d'intensité lumineuse, il s'agit donc de détecter selon plusieurs directions (au moins 2) ces changements. Il existe de nombreuses techniques afin de détecter les contours d'une image (gradient, Laplacien). L'une des techniques avec un rapport efficacité/temps d'exécution correct repose sur les algorithmes de Prewit ou Sobel. L'algorithme repose sur la convolution de matrices.&lt;br /&gt;
Cela consiste à appliquer sur chaque pixel de l'image la matrice de Prewit définie comme &lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L_x = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; ainsi que sa transposée : &amp;lt;math&amp;gt;&lt;br /&gt;
L_y = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; -1 &amp;amp; -1 \\&lt;br /&gt;
 0 &amp;amp; 0 &amp;amp; 0 \\&lt;br /&gt;
+1 &amp;amp; +1 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Convoluer ces deux filtres sur l'image permet de détecter respectivement les contours verticaux et horizontaux.&lt;br /&gt;
&lt;br /&gt;
D'après wikipedia [https://fr.wikipedia.org/wiki/D%C3%A9tection_de_contours], on obtient de meilleurs résultats en appliquant un filtre triangulaire, on introduit donc la matrice de Sobel :&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-2 &amp;amp; 0 &amp;amp; +2 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
On obtient le résultat suivant : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testOutline1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Pré-traitement : Flou Gaussien=====&lt;br /&gt;
&lt;br /&gt;
Afin de réduire significativement le nombre de contours, il est nécessaire d'effectuer un pré-traitement avant la détection de contours. On utilise généralement un flou gaussien afin de réduire les transitions lumineuses et ainsi réduire le nombre de contours. L’algorithme de flou gaussien repose également sur la convolution de matrices sauf qu'ici la matrice filtre est générée grâce à une fonction gaussienne paramétrée par '''Sigma''' qui va directement impacter le niveau de flou. Plus la matrice de filtrage est grande plus la qualité du résultat est meilleure, mais le temps d’exécution devient également plus grand.&lt;br /&gt;
&lt;br /&gt;
Voici la fonction de génération du filtre : &amp;lt;math&amp;gt;G(x,y) = \frac{1}{{2\pi \sigma^2}} e^{-\frac{x^2 + y^2}{2 \sigma^2}}&amp;lt;/math&amp;gt; où x et y correspondent aux indices de la cellule de la matrice.&lt;br /&gt;
&lt;br /&gt;
On obtient ce résultat :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testGaussianBlur.png]]&lt;br /&gt;
&lt;br /&gt;
On note un bien meilleur résultat. Cependant on remarque que les composantes horizontales ne sont pas correctement détectées il subsiste un problème avec le filtrage vertical que je n'ai pas réussi à identifier. De plus, il s'agit par sa suite d'éliminer les contours parasites ainsi que d'affiner le trait pour n'avoir plus qu'un pixel d'épaisseur.&lt;br /&gt;
&lt;br /&gt;
=====Post-traitement : Algorithme de Canny=====&lt;br /&gt;
&lt;br /&gt;
Afin d'obtenir un résultat exploitable il est nécessaire d'appliquer encore quelques traitements. Pour cela nous utilisons l’algorithme de Canny qui repose que celui de Sobel mais qui ajoute un algorithme de seuillage par hysteresis qui permet de retirer les contours secondaires et de ne garder que les contours connexes dans une seuil haut et un seuil bas définis. En outre, cette algorithme affine également le trait obtenu. Pour cet algorithme nous avons directement trouvé des sources libres de droits [http://www.tomgibara.com/computer-vision/canny-edge-detector] qui donne des résultats très corrects.&lt;br /&gt;
&lt;br /&gt;
Par exemple :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ou encore : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny2.png|1500px]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 5===&lt;br /&gt;
&lt;br /&gt;
*Établissement d'un protocole de transfert d'image basé sur les WebSockets&lt;br /&gt;
**Envoie d'un requête &amp;quot;send&amp;quot; par le client dans une trame websocket texte&lt;br /&gt;
**Réponse serveur 'Y' si aucun autre client tente d'envoyer une image simultanément, 'N' sinon&lt;br /&gt;
**Si et seulement si le client reçoit 'Y' il débute le transfert en envoyant la largeur et la longueur de l'image sur 4 octets, puis les données de l'image soit 4 valeurs pour chaque pixels (r,g,b,alpha)&lt;br /&gt;
**Le serveur renvoie 'D' une fois le transfert achevé (à l'avenir, le serveur renverra l'image après filtrage).&lt;br /&gt;
**A tout moment, le serveur peut renvoyer 'E' si une erreur est survenue (ex : paquets perdus, nombre incorrects de données)&lt;br /&gt;
*Ajout du support des logs au niveau serveur&lt;br /&gt;
**Impression sur la sortie standard des messages&lt;br /&gt;
**Formatage en fonction de la sévérité du log (info, warning, error...)&lt;br /&gt;
**Incrustation de la date et heure&lt;br /&gt;
**Possibilité de redirection dans une fichier, avec configuration (écriture à la suite d'un fichier existant, écrasement...)&lt;br /&gt;
**Le tout dans une classe Java flexible et réutilisable pour d'autres projets&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 6===&lt;br /&gt;
&lt;br /&gt;
*Installation de la librairie Java Pi4j sur la raspberry pi qui permet le contrôle des GPIO de celle-ci et notamment le port I²C (basé sur WiringPi)&lt;br /&gt;
*Amélioration coté serveur websocket&lt;br /&gt;
**Gestion de message plus longs (maximum des trames websockets soit 2^63 octets)&lt;br /&gt;
**Différenciation, à la réception de messages, des trames textes ou binaires des trames de contrôle comme les requête ping, pong ou de fermeture de connexion &lt;br /&gt;
**Ajout d'un mode de debug de trames&lt;br /&gt;
*Interface web&lt;br /&gt;
**Mise en place du code css pour améliorer le rendu visuel de la page&lt;br /&gt;
**Amélioration de l'envoie des données vers le serveur&lt;br /&gt;
&lt;br /&gt;
===Semaine 7===&lt;br /&gt;
&lt;br /&gt;
*Améliorations du serveur WebSocket&lt;br /&gt;
**Gestion de la fragmentation TCP&lt;br /&gt;
**Gestion de la fragmentation WebSocket&lt;br /&gt;
**Gestion des requêtes ping envoyés par le client en renvoyant une trames de contrôle pong afin de maintenir la connexion&lt;br /&gt;
**Gestion des déconnexion de clients afin d'optimiser le serveur&lt;br /&gt;
**Amélioration de l'émission de messages en augmentant la taille maximale pouvant être émise (2^63 octets)&lt;br /&gt;
&lt;br /&gt;
*Amélioration du code css&lt;br /&gt;
*Mise en place d'une partie 'Home' et 'About'&lt;br /&gt;
**Home : Communication avec le serveur web&lt;br /&gt;
**About : Information complémentaire sur la page web&lt;br /&gt;
&lt;br /&gt;
A ce stade du développement, le client et le serveur sont opérationnels et peuvent s'échanger des messages ainsi que des images que le serveur traite pour extraire les contours.&lt;br /&gt;
&lt;br /&gt;
===Semaine 8===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Montage projecteur&lt;br /&gt;
**Intégralité des composants fixés par vis dans le boîtier ABS&lt;br /&gt;
**Fusion des alimentations&lt;br /&gt;
**Présence d'une led témoin de mise en tension&lt;br /&gt;
**Position laser réglable grâce à une vis&lt;br /&gt;
**Présence d'un switch à bascule pour allumer et éteindre le laser&lt;br /&gt;
**Isolation et vérification des composants&lt;br /&gt;
**Tests empiriques de température et de fonctionnement des lasers et galvanomètres&lt;br /&gt;
&lt;br /&gt;
Le montage boîtier est donc terminé et s’alimente en 230V par intermédiaire d'un câble secteur avec connecteur C14. Le résultat s'avère plutôt compact. Les quelques tests de température ont montrés que malgré le manque d'espace la température globale du boîtier ne dépasse pas les 50°C pendant plus d'une heure de fonctionnement. L'intégralité des connexions sont isolées avec de la gaine thermodynamique et les zones &amp;quot;sensibles&amp;quot; sont correctement vérifiés ainsi que protégées avec de la matière isolante.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:proj1.jpg|550px|Boîtier après perçage]] [[Fichier:proj2.jpg|550px|Boîtier finalisé]] [[Fichier:proj3.jpg|550px|Projecteur en fonctionnement]]&lt;br /&gt;
&lt;br /&gt;
*Page web et serveur WebSocket&lt;br /&gt;
**Ajout d'un bouton &amp;quot;reboot&amp;quot; et &amp;quot;shutdown&amp;quot; sur la page web&lt;br /&gt;
***Reboot : Permet le redémarrage de la Raspberry&lt;br /&gt;
***Shutdown : Permet l'extinction de la Raspberry&lt;br /&gt;
**Ajout d'un slider pour le flou gaussien (échelle 1 à 100)&lt;br /&gt;
&lt;br /&gt;
===Semaine 9===&lt;br /&gt;
*Installation du programme 'bind9' permettant de mettre en place un serveur DNS qui permet de remplacer les adresses IP par un nom&lt;br /&gt;
**Problème de configuration (à corriger)&lt;br /&gt;
*Prise en compte du message de retour du serveur&lt;br /&gt;
**Récupération d'un tableau de points représentants les contours de l'image envoyé par le client&lt;br /&gt;
*Mise à jour du slider du flou gaussien&lt;br /&gt;
**Double spider permettant de sélectionner un segment de valeur&lt;br /&gt;
**Echelle comprise entre 0 et 1, pour faciliter la lecture les valeurs sont écrites en pourcent&lt;br /&gt;
*Etude du pololu md08a en remplacement du DAC initialement prévu et dessin de la carte&lt;br /&gt;
&lt;br /&gt;
===Semaine 10===&lt;br /&gt;
[[Fichier:Capture_du_2017-04-12_15-53-15.png|200px|thumb|right|Image envoyée -&amp;gt; Image laser]]&lt;br /&gt;
&lt;br /&gt;
*Récupération d'un ensemble de points envoyés par le serveur permettant de tracer l'image telle que sera projetée par le laser&lt;br /&gt;
**Mise en place du canvas&lt;br /&gt;
**Traçage de l'image par l'intermédiaire de &amp;quot;lineto&amp;quot; puisqu'il s'agit d'un contour&lt;br /&gt;
*Ajout d'une sécurité sur les boutons &amp;quot;reset&amp;quot; et &amp;quot;shutdown&amp;quot;&lt;br /&gt;
**Pop-up de confirmation pour les deux actions&lt;br /&gt;
*Mise à jour du Double slider&lt;br /&gt;
**Redimensionnement&lt;br /&gt;
**Récupération des valeurs&lt;br /&gt;
**Envois des valeurs vers le serveur par un tableau de binaires&lt;br /&gt;
&lt;br /&gt;
===Semaines Supplémentaires===&lt;br /&gt;
&lt;br /&gt;
*Finalisation du code css de la page web&lt;br /&gt;
**Amélioration visuelle&lt;br /&gt;
**Rendu dynamique de la page&lt;br /&gt;
[[Fichier:Page_accueil.png|396px|Page d’accueil]]&lt;br /&gt;
[[Fichier:Page2.png|396px|Image chargée]]&lt;br /&gt;
[[Fichier:Page3.png|396px|Contours récupérés]]&lt;br /&gt;
*Finalisation de la carte Pololu md08a + Arduino Pro Mini&lt;br /&gt;
&lt;br /&gt;
[[Fichier:cartePololu.jpg]]&lt;br /&gt;
&lt;br /&gt;
*Mise en place d'une liaison série Raspberry-Arduino&lt;br /&gt;
**Tests effectués avec I2C, SPI, UART. Solution retenue : I2C&lt;br /&gt;
*Contrôle des galvanomètres via PWM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:carre.jpg]]&lt;br /&gt;
&lt;br /&gt;
A terme, nous arrivons à projeter une image qui manque quelque peu de précision mais qui est tout de même reconnaissable. Néanmoins les données de positions arrivant par flux &lt;br /&gt;
l'Arduino, nous sommes limité par la vitesse de transmition de l'I2C et cela provoque un clignotement de l'image.&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;br /&gt;
&lt;br /&gt;
[[Media:CptProjetIMA4.pdf‎ |Compte-rendu Projet]]&lt;br /&gt;
&lt;br /&gt;
==Bibliographie==&lt;br /&gt;
&lt;br /&gt;
*Galvanomètres et laser&lt;br /&gt;
http://www.ebay.com/itm/20KPPS-30KPPS-laser-scanning-galvo-scanner-ILDA-Closed-Loop-max-30kpps-for-laser-/261517002270?hash=item3ce3a0c61e&lt;br /&gt;
&lt;br /&gt;
http://sciences.ulb.ac.be/printemps/download/2016/dossier_pedagogique/02.pdf&lt;br /&gt;
&lt;br /&gt;
*Websocket&lt;br /&gt;
http://stackoverflow.com/questions/8125507/how-can-i-send-and-receive-websocket-messages-on-the-server-side&lt;br /&gt;
&lt;br /&gt;
https://tools.ietf.org/html/rfc6455&lt;br /&gt;
&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_a_WebSocket_server_in_Java&lt;br /&gt;
&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers&lt;br /&gt;
&lt;br /&gt;
*Traitement d'image&lt;br /&gt;
https://en.wikipedia.org/wiki/Gaussian_blur&lt;br /&gt;
&lt;br /&gt;
http://www.zebulon.fr/questions-reponses/traitement-d-image-detection-de-contours-55.html&lt;br /&gt;
&lt;br /&gt;
http://patrick-bonnin.developpez.com/cours/vision/apprendre-bases-traitement-image/partie-5-segmentation-contour/&lt;br /&gt;
&lt;br /&gt;
http://www.isir.upmc.fr/UserFiles/File/clady_homepage/EPU/2-Contour&lt;br /&gt;
&lt;br /&gt;
*Autre&lt;br /&gt;
https://icn.fenelonlille.org/mediawiki/index.php/Projet_ICN_commun_2016/2017&lt;br /&gt;
&lt;br /&gt;
https://www.g33k-zone.org/post/2016/05/11/Configurer-le-Raspberry-Pi-en-point-d-acc%C3%A8s-Wifi&lt;br /&gt;
&lt;br /&gt;
https://blogs.oracle.com/acaicedo/resource/Parallax-I2C/Sensors.java&lt;br /&gt;
&lt;br /&gt;
http://stackoverflow.com/questions/22087076/how-to-make-a-simple-image-upload-using-javascript-html&lt;/div&gt;</summary>
		<author><name>Mtrimbur</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=42631</id>
		<title>IMA4 2016/2017 P39</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=42631"/>
				<updated>2017-05-19T15:26:40Z</updated>
		
		<summary type="html">&lt;p&gt;Mtrimbur : /* Semaines Supplémentaires */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
===Contexte===&lt;br /&gt;
&lt;br /&gt;
Le laser est une technologie largement utilisé de nos jours dans de diverses applications. En effet, on retrouve cette technologie dans le domaine médical notamment pour la chirurgie oculaire ou encore dans industrie avec la découpe laser ou la soudure au laser.&lt;br /&gt;
&lt;br /&gt;
Le laser est une émission de photons produit par excitation d'un milieu amplificateur (ex : CO2), le rayonnement produit est unidirectionnel et monochromatique. Ce sont ces propriétés que nous allons exploiter afin réaliser un projecteur laser qui mis en mouvement est capable de dessiner des formes sur une surface à l'instar de systèmes existants utilisés pour des effets lumineux lors de festivités.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
L'objectif du projet est de créer un système de projection laser à plusieurs couleurs (au minimum deux) avec une application web pour programmer les formes à dessiner afin d'agrémenter des compétitions de gymnastique rythmique.&lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
Le projet consiste à réaliser avec des lasers des figures géométriques par l'intermédiaire d'un système galvanométrique. &lt;br /&gt;
&lt;br /&gt;
Notre premier travail sera de concevoir la partie projection. Pour cela, nous devrons aligner les lasers et les galvanomètres. En effet, ces derniers posséderont des miroirs à l'extrémité, ainsi les miroirs changeront d'inclinaison suivant le courant traversant les galvanomètres (similaire à l'image ci-contre). Il nous faudra également créer un système d'alimentation qui à partir d'une même source (réseau 230 V) sera capable d'alimenter les lasers et les galvanomètres ainsi qu'une Arduino et une Raspberry Pi.&lt;br /&gt;
[[File:Scanhead.jpeg|thumb]]&lt;br /&gt;
&lt;br /&gt;
Ensuite nous nous intéresserons à l'utilisation d'un système embarqué pour contrôler les galvanomètres et donc dessiner avec les lasers sur un plan 2D. En effet, le laser restera toujours fixe, seuls les galvanomètres, et donc les miroirs bougeront. Les galvanomètres étant contrôlés en courant il faudra réaliser une interface électronique pour convertir une commande en tension en commande de courant. La commande en tension sera assuré par une carte Arduino. Nous n'utiliserons qu'une seule paire de galvanomètres pour les deux laser. Il faudra donc multiplexer les deux faisceaux. La programmation des formes à effectuer, se fera par l'intermédiaire d'une application web PHP hébergée sur une RaspberryPi qui permettra de récupérer une image, d'y appliquer divers traitements et filtres afin d'en extraire les contours, et de calculer les commandes pour positionner les galvanomètres. Un serveur WebSocket également hébergé sur la RaspberryPi servira d'interface entre l'application web et L'arduino qui sera connecté via une liaison série sur la raspberryPI.&lt;br /&gt;
&lt;br /&gt;
Comme animation de test, nous dessinerons le contour d'une gymnaste avec une couleur et son ballon d'une autre couleur. La gymnaste devra lancer son ballon, réaliser quelques difficultés et récupérer son ballon.&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
Nous utiliserons comme matériels :&lt;br /&gt;
*Deux lasers de différentes couleurs&lt;br /&gt;
*Une paire de galvanomètres à miroir&lt;br /&gt;
*Arduino&lt;br /&gt;
*Raspberry Pi3&lt;br /&gt;
*Alimentation 230V/5V 1A [http://www.miniinthebox.com/fr/dual-usb-eu-prise-murale-5v-2a-voyage-adaptateur-chargeur-d-alimentation-pour-iphone7-6-xiaomi-samsung-et-autre-telephone-portable_p5410410.html?currency=EUR&amp;amp;litb_from=paid_adwords_shopping&amp;amp;sku=429_6917%7C752_20648&amp;amp;utm_source=google_shopping&amp;amp;utm_medium=cpc&amp;amp;adword_mt=&amp;amp;adword_ct=138705676724&amp;amp;adword_kw=&amp;amp;adword_pos=1o5&amp;amp;adword_pl=&amp;amp;adword_net=g&amp;amp;adword_tar=&amp;amp;adw_src_id=9653316068_661261352_33588296076_aud-79897721311:pla-256966386459&amp;amp;gclid=Cj0KEQiA_KvEBRCtzNil4-KR-LIBEiQAmgekFxxKjJJWBYCJlDZEa3Ke_2_WR0DzGVbz-jaCZHVIBoMaAvld8P8HAQ]&lt;br /&gt;
*Drivers galvanomètres x2&lt;br /&gt;
*Alimentation laser&lt;br /&gt;
*Lunette de sécurité x2 [https://www.amazon.fr/Uvex-S1933X-Eyewear-SCTOrange-Anti-Fog/dp/B000USRG90/ref=sr_1_1?ie=UTF8&amp;amp;qid=1485441383&amp;amp;sr=8-1&amp;amp;keywords=uvex+s1933x]&lt;br /&gt;
*Boitier ABS [http://fr.farnell.com/multicomp/g3118/boitier-abs-240x120x60mm-ip65/dp/1526656]&lt;br /&gt;
*DAC 4 canaux, avec interface I²C [https://www.adafruit.com/products/1083]&lt;br /&gt;
*Connecteur C14 [http://www.conrad.fr/ce/fr/product/715001/Connecteur-secteur-C14-Embase-male-verticale-715001-Nombre-de-poles-2-PE-10-A-noir-1-pcs/?ref=detview1&amp;amp;rt=detview1&amp;amp;rb=1]&lt;br /&gt;
*Câble secteur&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Logiciel :&lt;br /&gt;
&lt;br /&gt;
*Serveur web : Apache2, HTML5, PHP5, CSS&lt;br /&gt;
*Base de donnée : MySQL&lt;br /&gt;
*Serveur WebSocket : JQuerry, websocket&lt;br /&gt;
*Arduino : IDE Arduino&lt;br /&gt;
&lt;br /&gt;
===Calendrier prévisionnel===&lt;br /&gt;
&lt;br /&gt;
====Liste des tâches à effectuer====&lt;br /&gt;
Les différentes tâches à effectuer sont :&lt;br /&gt;
*Partie préliminaire : étude de fonctionnement des galvanomètres&lt;br /&gt;
**Déterminer comment est effectuée la commande des galvanomètres (protocole, tension...)&lt;br /&gt;
**Effectuer des tests avec l'Arduino ou la Raspberry Pi&lt;br /&gt;
**Effectuer des tests avec une LED à la place du laser &lt;br /&gt;
*Partie projection&lt;br /&gt;
**Fixer les lasers&lt;br /&gt;
**Aligner les lasers et les galvanomètres&lt;br /&gt;
**Créer le système d'alimentation&lt;br /&gt;
**Création d'un boitier&lt;br /&gt;
*Partie système embarqué&lt;br /&gt;
**Asservissement des galvanomètres avec l'Arduino&lt;br /&gt;
**Système électronique de commande en courant pour les galvanomètres&lt;br /&gt;
*Interface Web&lt;br /&gt;
**Installation et configuration Apache2&lt;br /&gt;
**Création d'une interface graphique simple&lt;br /&gt;
**Implémentation d'algorithmes de traitement d'image&lt;br /&gt;
**Mise en forme avec des CSS&lt;br /&gt;
**Sytème d'authentification avec mot de passe&lt;br /&gt;
**Utilisation d'une base de données pour enregistrer toutes les images déjà utilisés afin de les réutiliser&lt;br /&gt;
*Serveur Web Socket&lt;br /&gt;
**Récupération des données de l'interface web&lt;br /&gt;
**Mise en place de la liaison série avec l'Arduino&lt;br /&gt;
&lt;br /&gt;
====Calendrier====&lt;br /&gt;
Répartition du temps consacré au projet (240h) :&lt;br /&gt;
*Partie projection : 80h&lt;br /&gt;
*Partie système embarqué : 40h&lt;br /&gt;
*Partie interface web et websocket: 120h&lt;br /&gt;
&lt;br /&gt;
==Feuille d'heures==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!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&lt;br /&gt;
|-&lt;br /&gt;
| Définition cahier des charges &lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 14&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|38&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Finalisation du cahier des charges avec les responsables&lt;br /&gt;
&lt;br /&gt;
*Acquisition de matériels :&lt;br /&gt;
**Projecteur Laser&lt;br /&gt;
**Galvanomètres&lt;br /&gt;
**Alimentation des galvanomètres&lt;br /&gt;
&lt;br /&gt;
*Listage du matériels à acquérir :&lt;br /&gt;
**Lunettes de sécurité&lt;br /&gt;
**DAC&lt;br /&gt;
**Alimentation 230V/5V 1A&lt;br /&gt;
** Boitier ABS &lt;br /&gt;
**...&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
*Obtention de l'arduino et de la raspberryPI&lt;br /&gt;
&lt;br /&gt;
*Démontage du projecteur laser&lt;br /&gt;
**Deux lasers de classe 3b (vert et rouge)&lt;br /&gt;
**Circuit d'alimentation des deux lasers&lt;br /&gt;
&lt;br /&gt;
*Initialisation du port série de la raspberryPI&lt;br /&gt;
**Modification du fichier ''config.txt'' dans la partition boot&lt;br /&gt;
**Ajout d'une ligne autorisant la communication série ('''enable_uart=1''')&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
*Installation du serveur apache sur la raspberryPI&lt;br /&gt;
**Modification du fichier ''/etc/network/interfaces'' (Static, Address, Netmask, Gateway)&lt;br /&gt;
**Modification du fichier ''/etc/resolv.conf'' (Adresse du serveur)&lt;br /&gt;
**Utilisation d'un proxy pour la récupération outils de programmation (Apache2, Php5)&lt;br /&gt;
&lt;br /&gt;
*Mise en place du point d’accès wifi de la raspberryPI&lt;br /&gt;
**Récupération des logiciels nécessaires (dnsmasq, hostapd)&lt;br /&gt;
**Mise en place d'une adresse IP statique pour le point d'accès par l'intermédiaire du fichier ''/etc/dhcpcd.conf''&lt;br /&gt;
**Désactivation de la négociation automatique de bail dans le fichier ''/etc/network/interfaces''&lt;br /&gt;
**Configuration du logiciel hostapd ''/etc/hostapd/hostapd.conf''&lt;br /&gt;
**Activation du démarrage automatique du point d'accès ''/etc/default/hostapd''&lt;br /&gt;
**Configuration du serveur DNS par ''/etc/dnsmasq.conf''&lt;br /&gt;
&lt;br /&gt;
*Instauration de la page d'accueil de l'interface web à l'adresse ''192.168.3.1''&lt;br /&gt;
**Téléversement de fichiers images sur la page web et affichage de celle-ci&lt;br /&gt;
**Voyant de confirmation du bon fonctionnement du serveur web&lt;br /&gt;
&lt;br /&gt;
*Développement du serveur websocket&lt;br /&gt;
&lt;br /&gt;
Le développement du serveur websocket, initialement prévu en C (il était prévu de reprendre les sources utilisées l'année précédente dans le cadre des projet IMA3 SC), a finalement été réalisé en JAVA pour plusieurs raisons.&lt;br /&gt;
Premièrement, un seul programme met en œuvre le serveur websocket, les divers traitements d'image, ainsi que les contrôles des galvanomètres (par l'intermédiaire des DAC) via la liaison I²C de la Raspberry Pi. Le langage JAVA fournit nativement des bibliothèques d'objets pour manipuler assez simplement des images, il existe également des librairies pour contrôler le port GPIO de la Raspberry et il était également intéressant de travailler avec un langage de plus haut niveau que le C.&lt;br /&gt;
En outre, la totale portabilité de ce langage nous permet de travailler sur n'importe quelle machine et ensuite transférer notre programme sur la Raspberry Pi et l’exécuter sans même repasser par une phase de compilation. Et finalement, c'est le langage que nous étudions actuellement en cours de programmation orientée objet, ce qui permet de nous perfectionner.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Serveur WebSocket====&lt;br /&gt;
&lt;br /&gt;
N'ayant pas trouvé d'API WebSocket en Java satisfaisante (qui ne nécessitent pas l'installation et la configuration de nombreux outils additionnels), j'ai estimé plus commode et plus formateur de développer notre propre serveur WebSocket en se basant sur les librairies sockets de Java avec l'aide d'une documentation assez exhaustive [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers].&lt;br /&gt;
&lt;br /&gt;
Les WebSockets désignent à la fois un protocole réseau qui étend le protocole TCP ainsi qu'une API du World Wide Web. Nous nous en servons afin d'établir une communication asynchrone et bidirectionnelle entre un navigateur web et le serveur, notamment pour envoyer l'image à projeter. L’implémentation du serveur repose sur plusieurs étapes.&lt;br /&gt;
&lt;br /&gt;
1) Connexion d'un client &lt;br /&gt;
&lt;br /&gt;
2) Handshake : permet de faire le lien entre le protocole HTTP et WS. Le client envoie une requête HTTP demandant un upgrade de la connexion en protocole WS et le serveur répond en configurant la connexion (détail dans la documentation [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers]).&lt;br /&gt;
&lt;br /&gt;
3) Réception et décodage des messages : le serveurs reçoit des trames brutes, on extrait donc la taille du message ainsi que le message. De plus, les données son encodées (cryptage XOR) par un masque qui doit également être extrait.&lt;br /&gt;
&lt;br /&gt;
4) Fermeture de la communication.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le serveur supporte le multi-client il est donc nécessaire qu'il effectue ces étapes en &amp;quot;parallèle&amp;quot;. Nous utilisons donc les threads ou fils d’exécution. Un thread est donc responsable d'attendre qu'un nouveau client se connecte et effectue le &amp;quot;handshake&amp;quot;, il crée ensuite un thread associé à ce client afin d'établir un canal de communication. Il y a donc au moins un thread par client. Par la suite il faudra également implémenter une déconnexion automatique d'un client notamment après un timeout.&lt;br /&gt;
&lt;br /&gt;
Exemple d’exécution du serveur avec deux clients qui se connectent et envoient un message : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testServeur.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Les clients sont des navigateurs web. Pour les tests nous avons repris les exemples utilisés dans le cadre das projets IMA3 SC avec le titre de la page HTML qui se colore en vert lorsque le client est connecté, et un champ de saisie pour envoyer des messages au serveur : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testClient.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 4===&lt;br /&gt;
&lt;br /&gt;
*Mise en place d’algorithmes de traitement d'image&lt;br /&gt;
&lt;br /&gt;
====Détection de contour====&lt;br /&gt;
&lt;br /&gt;
L'objectif de notre projet est de pouvoir projeter n'importe quelle image envoyé grâce à l'application web. Pour cela nous allons tracer à une vitesse élevée les contours de l'image sur par exemple un mur grâce au laser. Il est donc nécessaire de détecter les contours de l'image grâce à plusieurs traitements.&lt;br /&gt;
&lt;br /&gt;
=====Conversion en niveau de gris=====&lt;br /&gt;
&lt;br /&gt;
Une des étapes préliminaires pour effectuer la détection de contour est de convertir l'image couleur en niveau de gris. Pour cela l'algorithme est simple : il suffit pour chaque pixel de l'image d'effectuer la moyenne des composantes rouge, verte, bleu de chaque pixel. En effet, si l'on considère une image matricielle (l'image est considérée comme un tableau à deux dimensions avec chaque case qui contient la couleur du pixel), chaque pixel contient les composantes RGB codées sur un octet. La couleur gris correspond aux composantes RGB égales. Le niveau de gris est donc codé de 0 à 255, avec 0 donnant du noir et 255 du blanc. &lt;br /&gt;
&lt;br /&gt;
Voici le résultat obtenu : [[Fichier:testGrayScale.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Filtre de Prewit et Sobel=====&lt;br /&gt;
&lt;br /&gt;
Un contour est défini par un changement brutal d'intensité lumineuse, il s'agit donc de détecter selon plusieurs directions (au moins 2) ces changements. Il existe de nombreuses techniques afin de détecter les contours d'une image (gradient, Laplacien). L'une des techniques avec un rapport efficacité/temps d'exécution correct repose sur les algorithmes de Prewit ou Sobel. L'algorithme repose sur la convolution de matrices.&lt;br /&gt;
Cela consiste à appliquer sur chaque pixel de l'image la matrice de Prewit définie comme &lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L_x = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; ainsi que sa transposée : &amp;lt;math&amp;gt;&lt;br /&gt;
L_y = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; -1 &amp;amp; -1 \\&lt;br /&gt;
 0 &amp;amp; 0 &amp;amp; 0 \\&lt;br /&gt;
+1 &amp;amp; +1 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Convoluer ces deux filtres sur l'image permet de détecter respectivement les contours verticaux et horizontaux.&lt;br /&gt;
&lt;br /&gt;
D'après wikipedia [https://fr.wikipedia.org/wiki/D%C3%A9tection_de_contours], on obtient de meilleurs résultats en appliquant un filtre triangulaire, on introduit donc la matrice de Sobel :&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-2 &amp;amp; 0 &amp;amp; +2 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
On obtient le résultat suivant : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testOutline1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Pré-traitement : Flou Gaussien=====&lt;br /&gt;
&lt;br /&gt;
Afin de réduire significativement le nombre de contours, il est nécessaire d'effectuer un pré-traitement avant la détection de contours. On utilise généralement un flou gaussien afin de réduire les transitions lumineuses et ainsi réduire le nombre de contours. L’algorithme de flou gaussien repose également sur la convolution de matrices sauf qu'ici la matrice filtre est générée grâce à une fonction gaussienne paramétrée par '''Sigma''' qui va directement impacter le niveau de flou. Plus la matrice de filtrage est grande plus la qualité du résultat est meilleure, mais le temps d’exécution devient également plus grand.&lt;br /&gt;
&lt;br /&gt;
Voici la fonction de génération du filtre : &amp;lt;math&amp;gt;G(x,y) = \frac{1}{{2\pi \sigma^2}} e^{-\frac{x^2 + y^2}{2 \sigma^2}}&amp;lt;/math&amp;gt; où x et y correspondent aux indices de la cellule de la matrice.&lt;br /&gt;
&lt;br /&gt;
On obtient ce résultat :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testGaussianBlur.png]]&lt;br /&gt;
&lt;br /&gt;
On note un bien meilleur résultat. Cependant on remarque que les composantes horizontales ne sont pas correctement détectées il subsiste un problème avec le filtrage vertical que je n'ai pas réussi à identifier. De plus, il s'agit par sa suite d'éliminer les contours parasites ainsi que d'affiner le trait pour n'avoir plus qu'un pixel d'épaisseur.&lt;br /&gt;
&lt;br /&gt;
=====Post-traitement : Algorithme de Canny=====&lt;br /&gt;
&lt;br /&gt;
Afin d'obtenir un résultat exploitable il est nécessaire d'appliquer encore quelques traitements. Pour cela nous utilisons l’algorithme de Canny qui repose que celui de Sobel mais qui ajoute un algorithme de seuillage par hysteresis qui permet de retirer les contours secondaires et de ne garder que les contours connexes dans une seuil haut et un seuil bas définis. En outre, cette algorithme affine également le trait obtenu. Pour cet algorithme nous avons directement trouvé des sources libres de droits [http://www.tomgibara.com/computer-vision/canny-edge-detector] qui donne des résultats très corrects.&lt;br /&gt;
&lt;br /&gt;
Par exemple :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ou encore : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny2.png|1500px]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 5===&lt;br /&gt;
&lt;br /&gt;
*Établissement d'un protocole de transfert d'image basé sur les WebSockets&lt;br /&gt;
**Envoie d'un requête &amp;quot;send&amp;quot; par le client dans une trame websocket texte&lt;br /&gt;
**Réponse serveur 'Y' si aucun autre client tente d'envoyer une image simultanément, 'N' sinon&lt;br /&gt;
**Si et seulement si le client reçoit 'Y' il débute le transfert en envoyant la largeur et la longueur de l'image sur 4 octets, puis les données de l'image soit 4 valeurs pour chaque pixels (r,g,b,alpha)&lt;br /&gt;
**Le serveur renvoie 'D' une fois le transfert achevé (à l'avenir, le serveur renverra l'image après filtrage).&lt;br /&gt;
**A tout moment, le serveur peut renvoyer 'E' si une erreur est survenue (ex : paquets perdus, nombre incorrects de données)&lt;br /&gt;
*Ajout du support des logs au niveau serveur&lt;br /&gt;
**Impression sur la sortie standard des messages&lt;br /&gt;
**Formatage en fonction de la sévérité du log (info, warning, error...)&lt;br /&gt;
**Incrustation de la date et heure&lt;br /&gt;
**Possibilité de redirection dans une fichier, avec configuration (écriture à la suite d'un fichier existant, écrasement...)&lt;br /&gt;
**Le tout dans une classe Java flexible et réutilisable pour d'autres projets&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 6===&lt;br /&gt;
&lt;br /&gt;
*Installation de la librairie Java Pi4j sur la raspberry pi qui permet le contrôle des GPIO de celle-ci et notamment le port I²C (basé sur WiringPi)&lt;br /&gt;
*Amélioration coté serveur websocket&lt;br /&gt;
**Gestion de message plus longs (maximum des trames websockets soit 2^63 octets)&lt;br /&gt;
**Différenciation, à la réception de messages, des trames textes ou binaires des trames de contrôle comme les requête ping, pong ou de fermeture de connexion &lt;br /&gt;
**Ajout d'un mode de debug de trames&lt;br /&gt;
*Interface web&lt;br /&gt;
**Mise en place du code css pour améliorer le rendu visuel de la page&lt;br /&gt;
**Amélioration de l'envoie des données vers le serveur&lt;br /&gt;
&lt;br /&gt;
===Semaine 7===&lt;br /&gt;
&lt;br /&gt;
*Améliorations du serveur WebSocket&lt;br /&gt;
**Gestion de la fragmentation TCP&lt;br /&gt;
**Gestion de la fragmentation WebSocket&lt;br /&gt;
**Gestion des requêtes ping envoyés par le client en renvoyant une trames de contrôle pong afin de maintenir la connexion&lt;br /&gt;
**Gestion des déconnexion de clients afin d'optimiser le serveur&lt;br /&gt;
**Amélioration de l'émission de messages en augmentant la taille maximale pouvant être émise (2^63 octets)&lt;br /&gt;
&lt;br /&gt;
*Amélioration du code css&lt;br /&gt;
*Mise en place d'une partie 'Home' et 'About'&lt;br /&gt;
**Home : Communication avec le serveur web&lt;br /&gt;
**About : Information complémentaire sur la page web&lt;br /&gt;
&lt;br /&gt;
A ce stade du développement, le client et le serveur sont opérationnels et peuvent s'échanger des messages ainsi que des images que le serveur traite pour extraire les contours.&lt;br /&gt;
&lt;br /&gt;
===Semaine 8===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Montage projecteur&lt;br /&gt;
**Intégralité des composants fixés par vis dans le boîtier ABS&lt;br /&gt;
**Fusion des alimentations&lt;br /&gt;
**Présence d'une led témoin de mise en tension&lt;br /&gt;
**Position laser réglable grâce à une vis&lt;br /&gt;
**Présence d'un switch à bascule pour allumer et éteindre le laser&lt;br /&gt;
**Isolation et vérification des composants&lt;br /&gt;
**Tests empiriques de température et de fonctionnement des lasers et galvanomètres&lt;br /&gt;
&lt;br /&gt;
Le montage boîtier est donc terminé et s’alimente en 230V par intermédiaire d'un câble secteur avec connecteur C14. Le résultat s'avère plutôt compact. Les quelques tests de température ont montrés que malgré le manque d'espace la température globale du boîtier ne dépasse pas les 50°C pendant plus d'une heure de fonctionnement. L'intégralité des connexions sont isolées avec de la gaine thermodynamique et les zones &amp;quot;sensibles&amp;quot; sont correctement vérifiés ainsi que protégées avec de la matière isolante.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:proj1.jpg|550px|Boîtier après perçage]] [[Fichier:proj2.jpg|550px|Boîtier finalisé]] [[Fichier:proj3.jpg|550px|Projecteur en fonctionnement]]&lt;br /&gt;
&lt;br /&gt;
*Page web et serveur WebSocket&lt;br /&gt;
**Ajout d'un bouton &amp;quot;reboot&amp;quot; et &amp;quot;shutdown&amp;quot; sur la page web&lt;br /&gt;
***Reboot : Permet le redémarrage de la Raspberry&lt;br /&gt;
***Shutdown : Permet l'extinction de la Raspberry&lt;br /&gt;
**Ajout d'un slider pour le flou gaussien (échelle 1 à 100)&lt;br /&gt;
&lt;br /&gt;
===Semaine 9===&lt;br /&gt;
*Installation du programme 'bind9' permettant de mettre en place un serveur DNS qui permet de remplacer les adresses IP par un nom&lt;br /&gt;
**Problème de configuration (à corriger)&lt;br /&gt;
*Prise en compte du message de retour du serveur&lt;br /&gt;
**Récupération d'un tableau de points représentants les contours de l'image envoyé par le client&lt;br /&gt;
*Mise à jour du slider du flou gaussien&lt;br /&gt;
**Double spider permettant de sélectionner un segment de valeur&lt;br /&gt;
**Echelle comprise entre 0 et 1, pour faciliter la lecture les valeurs sont écrites en pourcent&lt;br /&gt;
*Etude du pololu md08a en remplacement du DAC initialement prévu et dessin de la carte&lt;br /&gt;
&lt;br /&gt;
===Semaine 10===&lt;br /&gt;
[[Fichier:Capture_du_2017-04-12_15-53-15.png|200px|thumb|right|Image envoyée -&amp;gt; Image laser]]&lt;br /&gt;
&lt;br /&gt;
*Récupération d'un ensemble de points envoyés par le serveur permettant de tracer l'image telle que sera projetée par le laser&lt;br /&gt;
**Mise en place du canvas&lt;br /&gt;
**Traçage de l'image par l'intermédiaire de &amp;quot;lineto&amp;quot; puisqu'il s'agit d'un contour&lt;br /&gt;
*Ajout d'une sécurité sur les boutons &amp;quot;reset&amp;quot; et &amp;quot;shutdown&amp;quot;&lt;br /&gt;
**Pop-up de confirmation pour les deux actions&lt;br /&gt;
*Mise à jour du Double slider&lt;br /&gt;
**Redimensionnement&lt;br /&gt;
**Récupération des valeurs&lt;br /&gt;
**Envois des valeurs vers le serveur par un tableau de binaires&lt;br /&gt;
&lt;br /&gt;
===Semaines Supplémentaires===&lt;br /&gt;
&lt;br /&gt;
*Finalisation du code css de la page web&lt;br /&gt;
**Amélioration visuelle&lt;br /&gt;
**Rendu dynamique de la page&lt;br /&gt;
[[Fichier:Page_accueil.png|396px|Page d’accueil]]&lt;br /&gt;
[[Fichier:Page2.png|396px|Image chargée]]&lt;br /&gt;
[[Fichier:Page3.png|396px|Contours récupérés]]&lt;br /&gt;
*Finalisation de la carte Pololu md08a + Arduino Pro Mini&lt;br /&gt;
&lt;br /&gt;
[[Fichier:carte.jpg]]&lt;br /&gt;
&lt;br /&gt;
*Mise en place d'une liaison série Raspberry-Arduino&lt;br /&gt;
**Tests effectués avec I2C, SPI, UART. Solution retenue : I2C&lt;br /&gt;
*Contrôle des galvanomètres via PWM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:carre.jpg]]&lt;br /&gt;
&lt;br /&gt;
A terme, nous arrivons à projeter une image qui manque quelque peu de précision mais qui est tout de même reconnaissable. Néanmoins les données de positions arrivant par flux &lt;br /&gt;
l'Arduino, nous sommes limité par la vitesse de transmition de l'I2C et cela provoque un clignotement de l'image.&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;br /&gt;
&lt;br /&gt;
[[Media:CptProjetIMA4.pdf‎ |Compte-rendu Projet]]&lt;br /&gt;
&lt;br /&gt;
==Bibliographie==&lt;br /&gt;
&lt;br /&gt;
*Galvanomètres et laser&lt;br /&gt;
http://www.ebay.com/itm/20KPPS-30KPPS-laser-scanning-galvo-scanner-ILDA-Closed-Loop-max-30kpps-for-laser-/261517002270?hash=item3ce3a0c61e&lt;br /&gt;
&lt;br /&gt;
http://sciences.ulb.ac.be/printemps/download/2016/dossier_pedagogique/02.pdf&lt;br /&gt;
&lt;br /&gt;
*Websocket&lt;br /&gt;
http://stackoverflow.com/questions/8125507/how-can-i-send-and-receive-websocket-messages-on-the-server-side&lt;br /&gt;
&lt;br /&gt;
https://tools.ietf.org/html/rfc6455&lt;br /&gt;
&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_a_WebSocket_server_in_Java&lt;br /&gt;
&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers&lt;br /&gt;
&lt;br /&gt;
*Traitement d'image&lt;br /&gt;
https://en.wikipedia.org/wiki/Gaussian_blur&lt;br /&gt;
&lt;br /&gt;
http://www.zebulon.fr/questions-reponses/traitement-d-image-detection-de-contours-55.html&lt;br /&gt;
&lt;br /&gt;
http://patrick-bonnin.developpez.com/cours/vision/apprendre-bases-traitement-image/partie-5-segmentation-contour/&lt;br /&gt;
&lt;br /&gt;
http://www.isir.upmc.fr/UserFiles/File/clady_homepage/EPU/2-Contour&lt;br /&gt;
&lt;br /&gt;
*Autre&lt;br /&gt;
https://icn.fenelonlille.org/mediawiki/index.php/Projet_ICN_commun_2016/2017&lt;br /&gt;
&lt;br /&gt;
https://www.g33k-zone.org/post/2016/05/11/Configurer-le-Raspberry-Pi-en-point-d-acc%C3%A8s-Wifi&lt;br /&gt;
&lt;br /&gt;
https://blogs.oracle.com/acaicedo/resource/Parallax-I2C/Sensors.java&lt;br /&gt;
&lt;br /&gt;
http://stackoverflow.com/questions/22087076/how-to-make-a-simple-image-upload-using-javascript-html&lt;/div&gt;</summary>
		<author><name>Mtrimbur</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=42628</id>
		<title>IMA4 2016/2017 P39</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=42628"/>
				<updated>2017-05-19T15:14:51Z</updated>
		
		<summary type="html">&lt;p&gt;Mtrimbur : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
===Contexte===&lt;br /&gt;
&lt;br /&gt;
Le laser est une technologie largement utilisé de nos jours dans de diverses applications. En effet, on retrouve cette technologie dans le domaine médical notamment pour la chirurgie oculaire ou encore dans industrie avec la découpe laser ou la soudure au laser.&lt;br /&gt;
&lt;br /&gt;
Le laser est une émission de photons produit par excitation d'un milieu amplificateur (ex : CO2), le rayonnement produit est unidirectionnel et monochromatique. Ce sont ces propriétés que nous allons exploiter afin réaliser un projecteur laser qui mis en mouvement est capable de dessiner des formes sur une surface à l'instar de systèmes existants utilisés pour des effets lumineux lors de festivités.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
L'objectif du projet est de créer un système de projection laser à plusieurs couleurs (au minimum deux) avec une application web pour programmer les formes à dessiner afin d'agrémenter des compétitions de gymnastique rythmique.&lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
Le projet consiste à réaliser avec des lasers des figures géométriques par l'intermédiaire d'un système galvanométrique. &lt;br /&gt;
&lt;br /&gt;
Notre premier travail sera de concevoir la partie projection. Pour cela, nous devrons aligner les lasers et les galvanomètres. En effet, ces derniers posséderont des miroirs à l'extrémité, ainsi les miroirs changeront d'inclinaison suivant le courant traversant les galvanomètres (similaire à l'image ci-contre). Il nous faudra également créer un système d'alimentation qui à partir d'une même source (réseau 230 V) sera capable d'alimenter les lasers et les galvanomètres ainsi qu'une Arduino et une Raspberry Pi.&lt;br /&gt;
[[File:Scanhead.jpeg|thumb]]&lt;br /&gt;
&lt;br /&gt;
Ensuite nous nous intéresserons à l'utilisation d'un système embarqué pour contrôler les galvanomètres et donc dessiner avec les lasers sur un plan 2D. En effet, le laser restera toujours fixe, seuls les galvanomètres, et donc les miroirs bougeront. Les galvanomètres étant contrôlés en courant il faudra réaliser une interface électronique pour convertir une commande en tension en commande de courant. La commande en tension sera assuré par une carte Arduino. Nous n'utiliserons qu'une seule paire de galvanomètres pour les deux laser. Il faudra donc multiplexer les deux faisceaux. La programmation des formes à effectuer, se fera par l'intermédiaire d'une application web PHP hébergée sur une RaspberryPi qui permettra de récupérer une image, d'y appliquer divers traitements et filtres afin d'en extraire les contours, et de calculer les commandes pour positionner les galvanomètres. Un serveur WebSocket également hébergé sur la RaspberryPi servira d'interface entre l'application web et L'arduino qui sera connecté via une liaison série sur la raspberryPI.&lt;br /&gt;
&lt;br /&gt;
Comme animation de test, nous dessinerons le contour d'une gymnaste avec une couleur et son ballon d'une autre couleur. La gymnaste devra lancer son ballon, réaliser quelques difficultés et récupérer son ballon.&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
Nous utiliserons comme matériels :&lt;br /&gt;
*Deux lasers de différentes couleurs&lt;br /&gt;
*Une paire de galvanomètres à miroir&lt;br /&gt;
*Arduino&lt;br /&gt;
*Raspberry Pi3&lt;br /&gt;
*Alimentation 230V/5V 1A [http://www.miniinthebox.com/fr/dual-usb-eu-prise-murale-5v-2a-voyage-adaptateur-chargeur-d-alimentation-pour-iphone7-6-xiaomi-samsung-et-autre-telephone-portable_p5410410.html?currency=EUR&amp;amp;litb_from=paid_adwords_shopping&amp;amp;sku=429_6917%7C752_20648&amp;amp;utm_source=google_shopping&amp;amp;utm_medium=cpc&amp;amp;adword_mt=&amp;amp;adword_ct=138705676724&amp;amp;adword_kw=&amp;amp;adword_pos=1o5&amp;amp;adword_pl=&amp;amp;adword_net=g&amp;amp;adword_tar=&amp;amp;adw_src_id=9653316068_661261352_33588296076_aud-79897721311:pla-256966386459&amp;amp;gclid=Cj0KEQiA_KvEBRCtzNil4-KR-LIBEiQAmgekFxxKjJJWBYCJlDZEa3Ke_2_WR0DzGVbz-jaCZHVIBoMaAvld8P8HAQ]&lt;br /&gt;
*Drivers galvanomètres x2&lt;br /&gt;
*Alimentation laser&lt;br /&gt;
*Lunette de sécurité x2 [https://www.amazon.fr/Uvex-S1933X-Eyewear-SCTOrange-Anti-Fog/dp/B000USRG90/ref=sr_1_1?ie=UTF8&amp;amp;qid=1485441383&amp;amp;sr=8-1&amp;amp;keywords=uvex+s1933x]&lt;br /&gt;
*Boitier ABS [http://fr.farnell.com/multicomp/g3118/boitier-abs-240x120x60mm-ip65/dp/1526656]&lt;br /&gt;
*DAC 4 canaux, avec interface I²C [https://www.adafruit.com/products/1083]&lt;br /&gt;
*Connecteur C14 [http://www.conrad.fr/ce/fr/product/715001/Connecteur-secteur-C14-Embase-male-verticale-715001-Nombre-de-poles-2-PE-10-A-noir-1-pcs/?ref=detview1&amp;amp;rt=detview1&amp;amp;rb=1]&lt;br /&gt;
*Câble secteur&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Logiciel :&lt;br /&gt;
&lt;br /&gt;
*Serveur web : Apache2, HTML5, PHP5, CSS&lt;br /&gt;
*Base de donnée : MySQL&lt;br /&gt;
*Serveur WebSocket : JQuerry, websocket&lt;br /&gt;
*Arduino : IDE Arduino&lt;br /&gt;
&lt;br /&gt;
===Calendrier prévisionnel===&lt;br /&gt;
&lt;br /&gt;
====Liste des tâches à effectuer====&lt;br /&gt;
Les différentes tâches à effectuer sont :&lt;br /&gt;
*Partie préliminaire : étude de fonctionnement des galvanomètres&lt;br /&gt;
**Déterminer comment est effectuée la commande des galvanomètres (protocole, tension...)&lt;br /&gt;
**Effectuer des tests avec l'Arduino ou la Raspberry Pi&lt;br /&gt;
**Effectuer des tests avec une LED à la place du laser &lt;br /&gt;
*Partie projection&lt;br /&gt;
**Fixer les lasers&lt;br /&gt;
**Aligner les lasers et les galvanomètres&lt;br /&gt;
**Créer le système d'alimentation&lt;br /&gt;
**Création d'un boitier&lt;br /&gt;
*Partie système embarqué&lt;br /&gt;
**Asservissement des galvanomètres avec l'Arduino&lt;br /&gt;
**Système électronique de commande en courant pour les galvanomètres&lt;br /&gt;
*Interface Web&lt;br /&gt;
**Installation et configuration Apache2&lt;br /&gt;
**Création d'une interface graphique simple&lt;br /&gt;
**Implémentation d'algorithmes de traitement d'image&lt;br /&gt;
**Mise en forme avec des CSS&lt;br /&gt;
**Sytème d'authentification avec mot de passe&lt;br /&gt;
**Utilisation d'une base de données pour enregistrer toutes les images déjà utilisés afin de les réutiliser&lt;br /&gt;
*Serveur Web Socket&lt;br /&gt;
**Récupération des données de l'interface web&lt;br /&gt;
**Mise en place de la liaison série avec l'Arduino&lt;br /&gt;
&lt;br /&gt;
====Calendrier====&lt;br /&gt;
Répartition du temps consacré au projet (240h) :&lt;br /&gt;
*Partie projection : 80h&lt;br /&gt;
*Partie système embarqué : 40h&lt;br /&gt;
*Partie interface web et websocket: 120h&lt;br /&gt;
&lt;br /&gt;
==Feuille d'heures==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!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&lt;br /&gt;
|-&lt;br /&gt;
| Définition cahier des charges &lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 14&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|38&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Finalisation du cahier des charges avec les responsables&lt;br /&gt;
&lt;br /&gt;
*Acquisition de matériels :&lt;br /&gt;
**Projecteur Laser&lt;br /&gt;
**Galvanomètres&lt;br /&gt;
**Alimentation des galvanomètres&lt;br /&gt;
&lt;br /&gt;
*Listage du matériels à acquérir :&lt;br /&gt;
**Lunettes de sécurité&lt;br /&gt;
**DAC&lt;br /&gt;
**Alimentation 230V/5V 1A&lt;br /&gt;
** Boitier ABS &lt;br /&gt;
**...&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
*Obtention de l'arduino et de la raspberryPI&lt;br /&gt;
&lt;br /&gt;
*Démontage du projecteur laser&lt;br /&gt;
**Deux lasers de classe 3b (vert et rouge)&lt;br /&gt;
**Circuit d'alimentation des deux lasers&lt;br /&gt;
&lt;br /&gt;
*Initialisation du port série de la raspberryPI&lt;br /&gt;
**Modification du fichier ''config.txt'' dans la partition boot&lt;br /&gt;
**Ajout d'une ligne autorisant la communication série ('''enable_uart=1''')&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
*Installation du serveur apache sur la raspberryPI&lt;br /&gt;
**Modification du fichier ''/etc/network/interfaces'' (Static, Address, Netmask, Gateway)&lt;br /&gt;
**Modification du fichier ''/etc/resolv.conf'' (Adresse du serveur)&lt;br /&gt;
**Utilisation d'un proxy pour la récupération outils de programmation (Apache2, Php5)&lt;br /&gt;
&lt;br /&gt;
*Mise en place du point d’accès wifi de la raspberryPI&lt;br /&gt;
**Récupération des logiciels nécessaires (dnsmasq, hostapd)&lt;br /&gt;
**Mise en place d'une adresse IP statique pour le point d'accès par l'intermédiaire du fichier ''/etc/dhcpcd.conf''&lt;br /&gt;
**Désactivation de la négociation automatique de bail dans le fichier ''/etc/network/interfaces''&lt;br /&gt;
**Configuration du logiciel hostapd ''/etc/hostapd/hostapd.conf''&lt;br /&gt;
**Activation du démarrage automatique du point d'accès ''/etc/default/hostapd''&lt;br /&gt;
**Configuration du serveur DNS par ''/etc/dnsmasq.conf''&lt;br /&gt;
&lt;br /&gt;
*Instauration de la page d'accueil de l'interface web à l'adresse ''192.168.3.1''&lt;br /&gt;
**Téléversement de fichiers images sur la page web et affichage de celle-ci&lt;br /&gt;
**Voyant de confirmation du bon fonctionnement du serveur web&lt;br /&gt;
&lt;br /&gt;
*Développement du serveur websocket&lt;br /&gt;
&lt;br /&gt;
Le développement du serveur websocket, initialement prévu en C (il était prévu de reprendre les sources utilisées l'année précédente dans le cadre des projet IMA3 SC), a finalement été réalisé en JAVA pour plusieurs raisons.&lt;br /&gt;
Premièrement, un seul programme met en œuvre le serveur websocket, les divers traitements d'image, ainsi que les contrôles des galvanomètres (par l'intermédiaire des DAC) via la liaison I²C de la Raspberry Pi. Le langage JAVA fournit nativement des bibliothèques d'objets pour manipuler assez simplement des images, il existe également des librairies pour contrôler le port GPIO de la Raspberry et il était également intéressant de travailler avec un langage de plus haut niveau que le C.&lt;br /&gt;
En outre, la totale portabilité de ce langage nous permet de travailler sur n'importe quelle machine et ensuite transférer notre programme sur la Raspberry Pi et l’exécuter sans même repasser par une phase de compilation. Et finalement, c'est le langage que nous étudions actuellement en cours de programmation orientée objet, ce qui permet de nous perfectionner.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Serveur WebSocket====&lt;br /&gt;
&lt;br /&gt;
N'ayant pas trouvé d'API WebSocket en Java satisfaisante (qui ne nécessitent pas l'installation et la configuration de nombreux outils additionnels), j'ai estimé plus commode et plus formateur de développer notre propre serveur WebSocket en se basant sur les librairies sockets de Java avec l'aide d'une documentation assez exhaustive [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers].&lt;br /&gt;
&lt;br /&gt;
Les WebSockets désignent à la fois un protocole réseau qui étend le protocole TCP ainsi qu'une API du World Wide Web. Nous nous en servons afin d'établir une communication asynchrone et bidirectionnelle entre un navigateur web et le serveur, notamment pour envoyer l'image à projeter. L’implémentation du serveur repose sur plusieurs étapes.&lt;br /&gt;
&lt;br /&gt;
1) Connexion d'un client &lt;br /&gt;
&lt;br /&gt;
2) Handshake : permet de faire le lien entre le protocole HTTP et WS. Le client envoie une requête HTTP demandant un upgrade de la connexion en protocole WS et le serveur répond en configurant la connexion (détail dans la documentation [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers]).&lt;br /&gt;
&lt;br /&gt;
3) Réception et décodage des messages : le serveurs reçoit des trames brutes, on extrait donc la taille du message ainsi que le message. De plus, les données son encodées (cryptage XOR) par un masque qui doit également être extrait.&lt;br /&gt;
&lt;br /&gt;
4) Fermeture de la communication.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le serveur supporte le multi-client il est donc nécessaire qu'il effectue ces étapes en &amp;quot;parallèle&amp;quot;. Nous utilisons donc les threads ou fils d’exécution. Un thread est donc responsable d'attendre qu'un nouveau client se connecte et effectue le &amp;quot;handshake&amp;quot;, il crée ensuite un thread associé à ce client afin d'établir un canal de communication. Il y a donc au moins un thread par client. Par la suite il faudra également implémenter une déconnexion automatique d'un client notamment après un timeout.&lt;br /&gt;
&lt;br /&gt;
Exemple d’exécution du serveur avec deux clients qui se connectent et envoient un message : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testServeur.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Les clients sont des navigateurs web. Pour les tests nous avons repris les exemples utilisés dans le cadre das projets IMA3 SC avec le titre de la page HTML qui se colore en vert lorsque le client est connecté, et un champ de saisie pour envoyer des messages au serveur : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testClient.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 4===&lt;br /&gt;
&lt;br /&gt;
*Mise en place d’algorithmes de traitement d'image&lt;br /&gt;
&lt;br /&gt;
====Détection de contour====&lt;br /&gt;
&lt;br /&gt;
L'objectif de notre projet est de pouvoir projeter n'importe quelle image envoyé grâce à l'application web. Pour cela nous allons tracer à une vitesse élevée les contours de l'image sur par exemple un mur grâce au laser. Il est donc nécessaire de détecter les contours de l'image grâce à plusieurs traitements.&lt;br /&gt;
&lt;br /&gt;
=====Conversion en niveau de gris=====&lt;br /&gt;
&lt;br /&gt;
Une des étapes préliminaires pour effectuer la détection de contour est de convertir l'image couleur en niveau de gris. Pour cela l'algorithme est simple : il suffit pour chaque pixel de l'image d'effectuer la moyenne des composantes rouge, verte, bleu de chaque pixel. En effet, si l'on considère une image matricielle (l'image est considérée comme un tableau à deux dimensions avec chaque case qui contient la couleur du pixel), chaque pixel contient les composantes RGB codées sur un octet. La couleur gris correspond aux composantes RGB égales. Le niveau de gris est donc codé de 0 à 255, avec 0 donnant du noir et 255 du blanc. &lt;br /&gt;
&lt;br /&gt;
Voici le résultat obtenu : [[Fichier:testGrayScale.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Filtre de Prewit et Sobel=====&lt;br /&gt;
&lt;br /&gt;
Un contour est défini par un changement brutal d'intensité lumineuse, il s'agit donc de détecter selon plusieurs directions (au moins 2) ces changements. Il existe de nombreuses techniques afin de détecter les contours d'une image (gradient, Laplacien). L'une des techniques avec un rapport efficacité/temps d'exécution correct repose sur les algorithmes de Prewit ou Sobel. L'algorithme repose sur la convolution de matrices.&lt;br /&gt;
Cela consiste à appliquer sur chaque pixel de l'image la matrice de Prewit définie comme &lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L_x = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; ainsi que sa transposée : &amp;lt;math&amp;gt;&lt;br /&gt;
L_y = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; -1 &amp;amp; -1 \\&lt;br /&gt;
 0 &amp;amp; 0 &amp;amp; 0 \\&lt;br /&gt;
+1 &amp;amp; +1 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Convoluer ces deux filtres sur l'image permet de détecter respectivement les contours verticaux et horizontaux.&lt;br /&gt;
&lt;br /&gt;
D'après wikipedia [https://fr.wikipedia.org/wiki/D%C3%A9tection_de_contours], on obtient de meilleurs résultats en appliquant un filtre triangulaire, on introduit donc la matrice de Sobel :&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-2 &amp;amp; 0 &amp;amp; +2 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
On obtient le résultat suivant : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testOutline1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Pré-traitement : Flou Gaussien=====&lt;br /&gt;
&lt;br /&gt;
Afin de réduire significativement le nombre de contours, il est nécessaire d'effectuer un pré-traitement avant la détection de contours. On utilise généralement un flou gaussien afin de réduire les transitions lumineuses et ainsi réduire le nombre de contours. L’algorithme de flou gaussien repose également sur la convolution de matrices sauf qu'ici la matrice filtre est générée grâce à une fonction gaussienne paramétrée par '''Sigma''' qui va directement impacter le niveau de flou. Plus la matrice de filtrage est grande plus la qualité du résultat est meilleure, mais le temps d’exécution devient également plus grand.&lt;br /&gt;
&lt;br /&gt;
Voici la fonction de génération du filtre : &amp;lt;math&amp;gt;G(x,y) = \frac{1}{{2\pi \sigma^2}} e^{-\frac{x^2 + y^2}{2 \sigma^2}}&amp;lt;/math&amp;gt; où x et y correspondent aux indices de la cellule de la matrice.&lt;br /&gt;
&lt;br /&gt;
On obtient ce résultat :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testGaussianBlur.png]]&lt;br /&gt;
&lt;br /&gt;
On note un bien meilleur résultat. Cependant on remarque que les composantes horizontales ne sont pas correctement détectées il subsiste un problème avec le filtrage vertical que je n'ai pas réussi à identifier. De plus, il s'agit par sa suite d'éliminer les contours parasites ainsi que d'affiner le trait pour n'avoir plus qu'un pixel d'épaisseur.&lt;br /&gt;
&lt;br /&gt;
=====Post-traitement : Algorithme de Canny=====&lt;br /&gt;
&lt;br /&gt;
Afin d'obtenir un résultat exploitable il est nécessaire d'appliquer encore quelques traitements. Pour cela nous utilisons l’algorithme de Canny qui repose que celui de Sobel mais qui ajoute un algorithme de seuillage par hysteresis qui permet de retirer les contours secondaires et de ne garder que les contours connexes dans une seuil haut et un seuil bas définis. En outre, cette algorithme affine également le trait obtenu. Pour cet algorithme nous avons directement trouvé des sources libres de droits [http://www.tomgibara.com/computer-vision/canny-edge-detector] qui donne des résultats très corrects.&lt;br /&gt;
&lt;br /&gt;
Par exemple :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ou encore : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny2.png|1500px]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 5===&lt;br /&gt;
&lt;br /&gt;
*Établissement d'un protocole de transfert d'image basé sur les WebSockets&lt;br /&gt;
**Envoie d'un requête &amp;quot;send&amp;quot; par le client dans une trame websocket texte&lt;br /&gt;
**Réponse serveur 'Y' si aucun autre client tente d'envoyer une image simultanément, 'N' sinon&lt;br /&gt;
**Si et seulement si le client reçoit 'Y' il débute le transfert en envoyant la largeur et la longueur de l'image sur 4 octets, puis les données de l'image soit 4 valeurs pour chaque pixels (r,g,b,alpha)&lt;br /&gt;
**Le serveur renvoie 'D' une fois le transfert achevé (à l'avenir, le serveur renverra l'image après filtrage).&lt;br /&gt;
**A tout moment, le serveur peut renvoyer 'E' si une erreur est survenue (ex : paquets perdus, nombre incorrects de données)&lt;br /&gt;
*Ajout du support des logs au niveau serveur&lt;br /&gt;
**Impression sur la sortie standard des messages&lt;br /&gt;
**Formatage en fonction de la sévérité du log (info, warning, error...)&lt;br /&gt;
**Incrustation de la date et heure&lt;br /&gt;
**Possibilité de redirection dans une fichier, avec configuration (écriture à la suite d'un fichier existant, écrasement...)&lt;br /&gt;
**Le tout dans une classe Java flexible et réutilisable pour d'autres projets&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 6===&lt;br /&gt;
&lt;br /&gt;
*Installation de la librairie Java Pi4j sur la raspberry pi qui permet le contrôle des GPIO de celle-ci et notamment le port I²C (basé sur WiringPi)&lt;br /&gt;
*Amélioration coté serveur websocket&lt;br /&gt;
**Gestion de message plus longs (maximum des trames websockets soit 2^63 octets)&lt;br /&gt;
**Différenciation, à la réception de messages, des trames textes ou binaires des trames de contrôle comme les requête ping, pong ou de fermeture de connexion &lt;br /&gt;
**Ajout d'un mode de debug de trames&lt;br /&gt;
*Interface web&lt;br /&gt;
**Mise en place du code css pour améliorer le rendu visuel de la page&lt;br /&gt;
**Amélioration de l'envoie des données vers le serveur&lt;br /&gt;
&lt;br /&gt;
===Semaine 7===&lt;br /&gt;
&lt;br /&gt;
*Améliorations du serveur WebSocket&lt;br /&gt;
**Gestion de la fragmentation TCP&lt;br /&gt;
**Gestion de la fragmentation WebSocket&lt;br /&gt;
**Gestion des requêtes ping envoyés par le client en renvoyant une trames de contrôle pong afin de maintenir la connexion&lt;br /&gt;
**Gestion des déconnexion de clients afin d'optimiser le serveur&lt;br /&gt;
**Amélioration de l'émission de messages en augmentant la taille maximale pouvant être émise (2^63 octets)&lt;br /&gt;
&lt;br /&gt;
*Amélioration du code css&lt;br /&gt;
*Mise en place d'une partie 'Home' et 'About'&lt;br /&gt;
**Home : Communication avec le serveur web&lt;br /&gt;
**About : Information complémentaire sur la page web&lt;br /&gt;
&lt;br /&gt;
A ce stade du développement, le client et le serveur sont opérationnels et peuvent s'échanger des messages ainsi que des images que le serveur traite pour extraire les contours.&lt;br /&gt;
&lt;br /&gt;
===Semaine 8===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Montage projecteur&lt;br /&gt;
**Intégralité des composants fixés par vis dans le boîtier ABS&lt;br /&gt;
**Fusion des alimentations&lt;br /&gt;
**Présence d'une led témoin de mise en tension&lt;br /&gt;
**Position laser réglable grâce à une vis&lt;br /&gt;
**Présence d'un switch à bascule pour allumer et éteindre le laser&lt;br /&gt;
**Isolation et vérification des composants&lt;br /&gt;
**Tests empiriques de température et de fonctionnement des lasers et galvanomètres&lt;br /&gt;
&lt;br /&gt;
Le montage boîtier est donc terminé et s’alimente en 230V par intermédiaire d'un câble secteur avec connecteur C14. Le résultat s'avère plutôt compact. Les quelques tests de température ont montrés que malgré le manque d'espace la température globale du boîtier ne dépasse pas les 50°C pendant plus d'une heure de fonctionnement. L'intégralité des connexions sont isolées avec de la gaine thermodynamique et les zones &amp;quot;sensibles&amp;quot; sont correctement vérifiés ainsi que protégées avec de la matière isolante.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:proj1.jpg|550px|Boîtier après perçage]] [[Fichier:proj2.jpg|550px|Boîtier finalisé]] [[Fichier:proj3.jpg|550px|Projecteur en fonctionnement]]&lt;br /&gt;
&lt;br /&gt;
*Page web et serveur WebSocket&lt;br /&gt;
**Ajout d'un bouton &amp;quot;reboot&amp;quot; et &amp;quot;shutdown&amp;quot; sur la page web&lt;br /&gt;
***Reboot : Permet le redémarrage de la Raspberry&lt;br /&gt;
***Shutdown : Permet l'extinction de la Raspberry&lt;br /&gt;
**Ajout d'un slider pour le flou gaussien (échelle 1 à 100)&lt;br /&gt;
&lt;br /&gt;
===Semaine 9===&lt;br /&gt;
*Installation du programme 'bind9' permettant de mettre en place un serveur DNS qui permet de remplacer les adresses IP par un nom&lt;br /&gt;
**Problème de configuration (à corriger)&lt;br /&gt;
*Prise en compte du message de retour du serveur&lt;br /&gt;
**Récupération d'un tableau de points représentants les contours de l'image envoyé par le client&lt;br /&gt;
*Mise à jour du slider du flou gaussien&lt;br /&gt;
**Double spider permettant de sélectionner un segment de valeur&lt;br /&gt;
**Echelle comprise entre 0 et 1, pour faciliter la lecture les valeurs sont écrites en pourcent&lt;br /&gt;
*Etude du pololu md08a en remplacement du DAC initialement prévu et dessin de la carte&lt;br /&gt;
&lt;br /&gt;
===Semaine 10===&lt;br /&gt;
[[Fichier:Capture_du_2017-04-12_15-53-15.png|200px|thumb|right|Image envoyée -&amp;gt; Image laser]]&lt;br /&gt;
&lt;br /&gt;
*Récupération d'un ensemble de points envoyés par le serveur permettant de tracer l'image telle que sera projetée par le laser&lt;br /&gt;
**Mise en place du canvas&lt;br /&gt;
**Traçage de l'image par l'intermédiaire de &amp;quot;lineto&amp;quot; puisqu'il s'agit d'un contour&lt;br /&gt;
*Ajout d'une sécurité sur les boutons &amp;quot;reset&amp;quot; et &amp;quot;shutdown&amp;quot;&lt;br /&gt;
**Pop-up de confirmation pour les deux actions&lt;br /&gt;
*Mise à jour du Double slider&lt;br /&gt;
**Redimensionnement&lt;br /&gt;
**Récupération des valeurs&lt;br /&gt;
**Envois des valeurs vers le serveur par un tableau de binaires&lt;br /&gt;
&lt;br /&gt;
===Semaines Supplémentaires===&lt;br /&gt;
&lt;br /&gt;
*Finalisation du code css de la page web&lt;br /&gt;
**Amélioration visuelle&lt;br /&gt;
**Rendu dynamique de la page&lt;br /&gt;
[[Fichier:Page_accueil.png|396px|Page d’accueil]]&lt;br /&gt;
[[Fichier:Page2.png|396px|Image chargée]]&lt;br /&gt;
[[Fichier:Page3.png|396px|Contours récupérés]]&lt;br /&gt;
*Finalisation de la carte Pololu md08a + Arduino Pro Mini&lt;br /&gt;
*Mise en place d'une liaison série Raspberry-Arduino&lt;br /&gt;
**Tests effectués avec I2C, SPI, UART. Solution retenue : I2C&lt;br /&gt;
*Contrôle des galvanomètres via PWM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;br /&gt;
&lt;br /&gt;
[[Media:CptProjetIMA4.pdf‎ |Compte-rendu Projet]]&lt;br /&gt;
&lt;br /&gt;
==Bibliographie==&lt;br /&gt;
&lt;br /&gt;
*Galvanomètres et laser&lt;br /&gt;
http://www.ebay.com/itm/20KPPS-30KPPS-laser-scanning-galvo-scanner-ILDA-Closed-Loop-max-30kpps-for-laser-/261517002270?hash=item3ce3a0c61e&lt;br /&gt;
&lt;br /&gt;
http://sciences.ulb.ac.be/printemps/download/2016/dossier_pedagogique/02.pdf&lt;br /&gt;
&lt;br /&gt;
*Websocket&lt;br /&gt;
http://stackoverflow.com/questions/8125507/how-can-i-send-and-receive-websocket-messages-on-the-server-side&lt;br /&gt;
&lt;br /&gt;
https://tools.ietf.org/html/rfc6455&lt;br /&gt;
&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_a_WebSocket_server_in_Java&lt;br /&gt;
&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers&lt;br /&gt;
&lt;br /&gt;
*Traitement d'image&lt;br /&gt;
https://en.wikipedia.org/wiki/Gaussian_blur&lt;br /&gt;
&lt;br /&gt;
http://www.zebulon.fr/questions-reponses/traitement-d-image-detection-de-contours-55.html&lt;br /&gt;
&lt;br /&gt;
http://patrick-bonnin.developpez.com/cours/vision/apprendre-bases-traitement-image/partie-5-segmentation-contour/&lt;br /&gt;
&lt;br /&gt;
http://www.isir.upmc.fr/UserFiles/File/clady_homepage/EPU/2-Contour&lt;br /&gt;
&lt;br /&gt;
*Autre&lt;br /&gt;
https://icn.fenelonlille.org/mediawiki/index.php/Projet_ICN_commun_2016/2017&lt;br /&gt;
&lt;br /&gt;
https://www.g33k-zone.org/post/2016/05/11/Configurer-le-Raspberry-Pi-en-point-d-acc%C3%A8s-Wifi&lt;br /&gt;
&lt;br /&gt;
https://blogs.oracle.com/acaicedo/resource/Parallax-I2C/Sensors.java&lt;br /&gt;
&lt;br /&gt;
http://stackoverflow.com/questions/22087076/how-to-make-a-simple-image-upload-using-javascript-html&lt;/div&gt;</summary>
		<author><name>Mtrimbur</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=42627</id>
		<title>IMA4 2016/2017 P39</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=42627"/>
				<updated>2017-05-19T15:14:01Z</updated>
		
		<summary type="html">&lt;p&gt;Mtrimbur : /* Semaines Supplémentaires */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
===Contexte===&lt;br /&gt;
&lt;br /&gt;
Le laser est une technologie largement utilisé de nos jours dans de diverses applications. En effet, on retrouve cette technologie dans le domaine médical notamment pour la chirurgie oculaire ou encore dans industrie avec la découpe laser ou la soudure au laser.&lt;br /&gt;
&lt;br /&gt;
Le laser est une émission de photons produit par excitation d'un milieu amplificateur (ex : CO2), le rayonnement produit est unidirectionnel et monochromatique. Ce sont ces propriétés que nous allons exploiter afin réaliser un projecteur laser qui mis en mouvement est capable de dessiner des formes sur une surface à l'instar de systèmes existants utilisés pour des effets lumineux lors de festivités.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
L'objectif du projet est de créer un système de projection laser à plusieurs couleurs (au minimum deux) avec une application web pour programmer les formes à dessiner afin d'agrémenter des compétitions de gymnastique rythmique.&lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
Le projet consiste à réaliser avec des lasers des figures géométriques par l'intermédiaire d'un système galvanométrique. &lt;br /&gt;
&lt;br /&gt;
Notre premier travail sera de concevoir la partie projection. Pour cela, nous devrons aligner les lasers et les galvanomètres. En effet, ces derniers posséderont des miroirs à l'extrémité, ainsi les miroirs changeront d'inclinaison suivant le courant traversant les galvanomètres (similaire à l'image ci-contre). Il nous faudra également créer un système d'alimentation qui à partir d'une même source (réseau 230 V) sera capable d'alimenter les lasers et les galvanomètres ainsi qu'une Arduino et une Raspberry Pi.&lt;br /&gt;
[[File:Scanhead.jpeg|thumb]]&lt;br /&gt;
&lt;br /&gt;
Ensuite nous nous intéresserons à l'utilisation d'un système embarqué pour contrôler les galvanomètres et donc dessiner avec les lasers sur un plan 2D. En effet, le laser restera toujours fixe, seuls les galvanomètres, et donc les miroirs bougeront. Les galvanomètres étant contrôlés en courant il faudra réaliser une interface électronique pour convertir une commande en tension en commande de courant. La commande en tension sera assuré par une carte Arduino. Nous n'utiliserons qu'une seule paire de galvanomètres pour les deux laser. Il faudra donc multiplexer les deux faisceaux. La programmation des formes à effectuer, se fera par l'intermédiaire d'une application web PHP hébergée sur une RaspberryPi qui permettra de récupérer une image, d'y appliquer divers traitements et filtres afin d'en extraire les contours, et de calculer les commandes pour positionner les galvanomètres. Un serveur WebSocket également hébergé sur la RaspberryPi servira d'interface entre l'application web et L'arduino qui sera connecté via une liaison série sur la raspberryPI.&lt;br /&gt;
&lt;br /&gt;
Comme animation de test, nous dessinerons le contour d'une gymnaste avec une couleur et son ballon d'une autre couleur. La gymnaste devra lancer son ballon, réaliser quelques difficultés et récupérer son ballon.&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
Nous utiliserons comme matériels :&lt;br /&gt;
*Deux lasers de différentes couleurs&lt;br /&gt;
*Une paire de galvanomètres à miroir&lt;br /&gt;
*Arduino&lt;br /&gt;
*Raspberry Pi3&lt;br /&gt;
*Alimentation 230V/5V 1A [http://www.miniinthebox.com/fr/dual-usb-eu-prise-murale-5v-2a-voyage-adaptateur-chargeur-d-alimentation-pour-iphone7-6-xiaomi-samsung-et-autre-telephone-portable_p5410410.html?currency=EUR&amp;amp;litb_from=paid_adwords_shopping&amp;amp;sku=429_6917%7C752_20648&amp;amp;utm_source=google_shopping&amp;amp;utm_medium=cpc&amp;amp;adword_mt=&amp;amp;adword_ct=138705676724&amp;amp;adword_kw=&amp;amp;adword_pos=1o5&amp;amp;adword_pl=&amp;amp;adword_net=g&amp;amp;adword_tar=&amp;amp;adw_src_id=9653316068_661261352_33588296076_aud-79897721311:pla-256966386459&amp;amp;gclid=Cj0KEQiA_KvEBRCtzNil4-KR-LIBEiQAmgekFxxKjJJWBYCJlDZEa3Ke_2_WR0DzGVbz-jaCZHVIBoMaAvld8P8HAQ]&lt;br /&gt;
*Drivers galvanomètres x2&lt;br /&gt;
*Alimentation laser&lt;br /&gt;
*Lunette de sécurité x2 [https://www.amazon.fr/Uvex-S1933X-Eyewear-SCTOrange-Anti-Fog/dp/B000USRG90/ref=sr_1_1?ie=UTF8&amp;amp;qid=1485441383&amp;amp;sr=8-1&amp;amp;keywords=uvex+s1933x]&lt;br /&gt;
*Boitier ABS [http://fr.farnell.com/multicomp/g3118/boitier-abs-240x120x60mm-ip65/dp/1526656]&lt;br /&gt;
*DAC 4 canaux, avec interface I²C [https://www.adafruit.com/products/1083]&lt;br /&gt;
*Connecteur C14 [http://www.conrad.fr/ce/fr/product/715001/Connecteur-secteur-C14-Embase-male-verticale-715001-Nombre-de-poles-2-PE-10-A-noir-1-pcs/?ref=detview1&amp;amp;rt=detview1&amp;amp;rb=1]&lt;br /&gt;
*Câble secteur&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Logiciel :&lt;br /&gt;
&lt;br /&gt;
*Serveur web : Apache2, HTML5, PHP5, CSS&lt;br /&gt;
*Base de donnée : MySQL&lt;br /&gt;
*Serveur WebSocket : JQuerry, websocket&lt;br /&gt;
*Arduino : IDE Arduino&lt;br /&gt;
&lt;br /&gt;
===Calendrier prévisionnel===&lt;br /&gt;
&lt;br /&gt;
====Liste des tâches à effectuer====&lt;br /&gt;
Les différentes tâches à effectuer sont :&lt;br /&gt;
*Partie préliminaire : étude de fonctionnement des galvanomètres&lt;br /&gt;
**Déterminer comment est effectuée la commande des galvanomètres (protocole, tension...)&lt;br /&gt;
**Effectuer des tests avec l'Arduino ou la Raspberry Pi&lt;br /&gt;
**Effectuer des tests avec une LED à la place du laser &lt;br /&gt;
*Partie projection&lt;br /&gt;
**Fixer les lasers&lt;br /&gt;
**Aligner les lasers et les galvanomètres&lt;br /&gt;
**Créer le système d'alimentation&lt;br /&gt;
**Création d'un boitier&lt;br /&gt;
*Partie système embarqué&lt;br /&gt;
**Asservissement des galvanomètres avec l'Arduino&lt;br /&gt;
**Système électronique de commande en courant pour les galvanomètres&lt;br /&gt;
*Interface Web&lt;br /&gt;
**Installation et configuration Apache2&lt;br /&gt;
**Création d'une interface graphique simple&lt;br /&gt;
**Implémentation d'algorithmes de traitement d'image&lt;br /&gt;
**Mise en forme avec des CSS&lt;br /&gt;
**Sytème d'authentification avec mot de passe&lt;br /&gt;
**Utilisation d'une base de données pour enregistrer toutes les images déjà utilisés afin de les réutiliser&lt;br /&gt;
*Serveur Web Socket&lt;br /&gt;
**Récupération des données de l'interface web&lt;br /&gt;
**Mise en place de la liaison série avec l'Arduino&lt;br /&gt;
&lt;br /&gt;
====Calendrier====&lt;br /&gt;
Répartition du temps consacré au projet (240h) :&lt;br /&gt;
*Partie projection : 80h&lt;br /&gt;
*Partie système embarqué : 40h&lt;br /&gt;
*Partie interface web et websocket: 120h&lt;br /&gt;
&lt;br /&gt;
==Feuille d'heures==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!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&lt;br /&gt;
|-&lt;br /&gt;
| Définition cahier des charges &lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 14&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|38&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Finalisation du cahier des charges avec les responsables&lt;br /&gt;
&lt;br /&gt;
*Acquisition de matériels :&lt;br /&gt;
**Projecteur Laser&lt;br /&gt;
**Galvanomètres&lt;br /&gt;
**Alimentation des galvanomètres&lt;br /&gt;
&lt;br /&gt;
*Listage du matériels à acquérir :&lt;br /&gt;
**Lunettes de sécurité&lt;br /&gt;
**DAC&lt;br /&gt;
**Alimentation 230V/5V 1A&lt;br /&gt;
** Boitier ABS &lt;br /&gt;
**...&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
*Obtention de l'arduino et de la raspberryPI&lt;br /&gt;
&lt;br /&gt;
*Démontage du projecteur laser&lt;br /&gt;
**Deux lasers de classe 3b (vert et rouge)&lt;br /&gt;
**Circuit d'alimentation des deux lasers&lt;br /&gt;
&lt;br /&gt;
*Initialisation du port série de la raspberryPI&lt;br /&gt;
**Modification du fichier ''config.txt'' dans la partition boot&lt;br /&gt;
**Ajout d'une ligne autorisant la communication série ('''enable_uart=1''')&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
*Installation du serveur apache sur la raspberryPI&lt;br /&gt;
**Modification du fichier ''/etc/network/interfaces'' (Static, Address, Netmask, Gateway)&lt;br /&gt;
**Modification du fichier ''/etc/resolv.conf'' (Adresse du serveur)&lt;br /&gt;
**Utilisation d'un proxy pour la récupération outils de programmation (Apache2, Php5)&lt;br /&gt;
&lt;br /&gt;
*Mise en place du point d’accès wifi de la raspberryPI&lt;br /&gt;
**Récupération des logiciels nécessaires (dnsmasq, hostapd)&lt;br /&gt;
**Mise en place d'une adresse IP statique pour le point d'accès par l'intermédiaire du fichier ''/etc/dhcpcd.conf''&lt;br /&gt;
**Désactivation de la négociation automatique de bail dans le fichier ''/etc/network/interfaces''&lt;br /&gt;
**Configuration du logiciel hostapd ''/etc/hostapd/hostapd.conf''&lt;br /&gt;
**Activation du démarrage automatique du point d'accès ''/etc/default/hostapd''&lt;br /&gt;
**Configuration du serveur DNS par ''/etc/dnsmasq.conf''&lt;br /&gt;
&lt;br /&gt;
*Instauration de la page d'accueil de l'interface web à l'adresse ''192.168.3.1''&lt;br /&gt;
**Téléversement de fichiers images sur la page web et affichage de celle-ci&lt;br /&gt;
**Voyant de confirmation du bon fonctionnement du serveur web&lt;br /&gt;
&lt;br /&gt;
*Développement du serveur websocket&lt;br /&gt;
&lt;br /&gt;
Le développement du serveur websocket, initialement prévu en C (il était prévu de reprendre les sources utilisées l'année précédente dans le cadre des projet IMA3 SC), a finalement été réalisé en JAVA pour plusieurs raisons.&lt;br /&gt;
Premièrement, un seul programme met en œuvre le serveur websocket, les divers traitements d'image, ainsi que les contrôles des galvanomètres (par l'intermédiaire des DAC) via la liaison I²C de la Raspberry Pi. Le langage JAVA fournit nativement des bibliothèques d'objets pour manipuler assez simplement des images, il existe également des librairies pour contrôler le port GPIO de la Raspberry et il était également intéressant de travailler avec un langage de plus haut niveau que le C.&lt;br /&gt;
En outre, la totale portabilité de ce langage nous permet de travailler sur n'importe quelle machine et ensuite transférer notre programme sur la Raspberry Pi et l’exécuter sans même repasser par une phase de compilation. Et finalement, c'est le langage que nous étudions actuellement en cours de programmation orientée objet, ce qui permet de nous perfectionner.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Serveur WebSocket====&lt;br /&gt;
&lt;br /&gt;
N'ayant pas trouvé d'API WebSocket en Java satisfaisante (qui ne nécessitent pas l'installation et la configuration de nombreux outils additionnels), j'ai estimé plus commode et plus formateur de développer notre propre serveur WebSocket en se basant sur les librairies sockets de Java avec l'aide d'une documentation assez exhaustive [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers].&lt;br /&gt;
&lt;br /&gt;
Les WebSockets désignent à la fois un protocole réseau qui étend le protocole TCP ainsi qu'une API du World Wide Web. Nous nous en servons afin d'établir une communication asynchrone et bidirectionnelle entre un navigateur web et le serveur, notamment pour envoyer l'image à projeter. L’implémentation du serveur repose sur plusieurs étapes.&lt;br /&gt;
&lt;br /&gt;
1) Connexion d'un client &lt;br /&gt;
&lt;br /&gt;
2) Handshake : permet de faire le lien entre le protocole HTTP et WS. Le client envoie une requête HTTP demandant un upgrade de la connexion en protocole WS et le serveur répond en configurant la connexion (détail dans la documentation [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers]).&lt;br /&gt;
&lt;br /&gt;
3) Réception et décodage des messages : le serveurs reçoit des trames brutes, on extrait donc la taille du message ainsi que le message. De plus, les données son encodées (cryptage XOR) par un masque qui doit également être extrait.&lt;br /&gt;
&lt;br /&gt;
4) Fermeture de la communication.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le serveur supporte le multi-client il est donc nécessaire qu'il effectue ces étapes en &amp;quot;parallèle&amp;quot;. Nous utilisons donc les threads ou fils d’exécution. Un thread est donc responsable d'attendre qu'un nouveau client se connecte et effectue le &amp;quot;handshake&amp;quot;, il crée ensuite un thread associé à ce client afin d'établir un canal de communication. Il y a donc au moins un thread par client. Par la suite il faudra également implémenter une déconnexion automatique d'un client notamment après un timeout.&lt;br /&gt;
&lt;br /&gt;
Exemple d’exécution du serveur avec deux clients qui se connectent et envoient un message : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testServeur.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Les clients sont des navigateurs web. Pour les tests nous avons repris les exemples utilisés dans le cadre das projets IMA3 SC avec le titre de la page HTML qui se colore en vert lorsque le client est connecté, et un champ de saisie pour envoyer des messages au serveur : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testClient.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 4===&lt;br /&gt;
&lt;br /&gt;
*Mise en place d’algorithmes de traitement d'image&lt;br /&gt;
&lt;br /&gt;
====Détection de contour====&lt;br /&gt;
&lt;br /&gt;
L'objectif de notre projet est de pouvoir projeter n'importe quelle image envoyé grâce à l'application web. Pour cela nous allons tracer à une vitesse élevée les contours de l'image sur par exemple un mur grâce au laser. Il est donc nécessaire de détecter les contours de l'image grâce à plusieurs traitements.&lt;br /&gt;
&lt;br /&gt;
=====Conversion en niveau de gris=====&lt;br /&gt;
&lt;br /&gt;
Une des étapes préliminaires pour effectuer la détection de contour est de convertir l'image couleur en niveau de gris. Pour cela l'algorithme est simple : il suffit pour chaque pixel de l'image d'effectuer la moyenne des composantes rouge, verte, bleu de chaque pixel. En effet, si l'on considère une image matricielle (l'image est considérée comme un tableau à deux dimensions avec chaque case qui contient la couleur du pixel), chaque pixel contient les composantes RGB codées sur un octet. La couleur gris correspond aux composantes RGB égales. Le niveau de gris est donc codé de 0 à 255, avec 0 donnant du noir et 255 du blanc. &lt;br /&gt;
&lt;br /&gt;
Voici le résultat obtenu : [[Fichier:testGrayScale.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Filtre de Prewit et Sobel=====&lt;br /&gt;
&lt;br /&gt;
Un contour est défini par un changement brutal d'intensité lumineuse, il s'agit donc de détecter selon plusieurs directions (au moins 2) ces changements. Il existe de nombreuses techniques afin de détecter les contours d'une image (gradient, Laplacien). L'une des techniques avec un rapport efficacité/temps d'exécution correct repose sur les algorithmes de Prewit ou Sobel. L'algorithme repose sur la convolution de matrices.&lt;br /&gt;
Cela consiste à appliquer sur chaque pixel de l'image la matrice de Prewit définie comme &lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L_x = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; ainsi que sa transposée : &amp;lt;math&amp;gt;&lt;br /&gt;
L_y = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; -1 &amp;amp; -1 \\&lt;br /&gt;
 0 &amp;amp; 0 &amp;amp; 0 \\&lt;br /&gt;
+1 &amp;amp; +1 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Convoluer ces deux filtres sur l'image permet de détecter respectivement les contours verticaux et horizontaux.&lt;br /&gt;
&lt;br /&gt;
D'après wikipedia [https://fr.wikipedia.org/wiki/D%C3%A9tection_de_contours], on obtient de meilleurs résultats en appliquant un filtre triangulaire, on introduit donc la matrice de Sobel :&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-2 &amp;amp; 0 &amp;amp; +2 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
On obtient le résultat suivant : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testOutline1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Pré-traitement : Flou Gaussien=====&lt;br /&gt;
&lt;br /&gt;
Afin de réduire significativement le nombre de contours, il est nécessaire d'effectuer un pré-traitement avant la détection de contours. On utilise généralement un flou gaussien afin de réduire les transitions lumineuses et ainsi réduire le nombre de contours. L’algorithme de flou gaussien repose également sur la convolution de matrices sauf qu'ici la matrice filtre est générée grâce à une fonction gaussienne paramétrée par '''Sigma''' qui va directement impacter le niveau de flou. Plus la matrice de filtrage est grande plus la qualité du résultat est meilleure, mais le temps d’exécution devient également plus grand.&lt;br /&gt;
&lt;br /&gt;
Voici la fonction de génération du filtre : &amp;lt;math&amp;gt;G(x,y) = \frac{1}{{2\pi \sigma^2}} e^{-\frac{x^2 + y^2}{2 \sigma^2}}&amp;lt;/math&amp;gt; où x et y correspondent aux indices de la cellule de la matrice.&lt;br /&gt;
&lt;br /&gt;
On obtient ce résultat :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testGaussianBlur.png]]&lt;br /&gt;
&lt;br /&gt;
On note un bien meilleur résultat. Cependant on remarque que les composantes horizontales ne sont pas correctement détectées il subsiste un problème avec le filtrage vertical que je n'ai pas réussi à identifier. De plus, il s'agit par sa suite d'éliminer les contours parasites ainsi que d'affiner le trait pour n'avoir plus qu'un pixel d'épaisseur.&lt;br /&gt;
&lt;br /&gt;
=====Post-traitement : Algorithme de Canny=====&lt;br /&gt;
&lt;br /&gt;
Afin d'obtenir un résultat exploitable il est nécessaire d'appliquer encore quelques traitements. Pour cela nous utilisons l’algorithme de Canny qui repose que celui de Sobel mais qui ajoute un algorithme de seuillage par hysteresis qui permet de retirer les contours secondaires et de ne garder que les contours connexes dans une seuil haut et un seuil bas définis. En outre, cette algorithme affine également le trait obtenu. Pour cet algorithme nous avons directement trouvé des sources libres de droits [http://www.tomgibara.com/computer-vision/canny-edge-detector] qui donne des résultats très corrects.&lt;br /&gt;
&lt;br /&gt;
Par exemple :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ou encore : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny2.png|1500px]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 5===&lt;br /&gt;
&lt;br /&gt;
*Établissement d'un protocole de transfert d'image basé sur les WebSockets&lt;br /&gt;
**Envoie d'un requête &amp;quot;send&amp;quot; par le client dans une trame websocket texte&lt;br /&gt;
**Réponse serveur 'Y' si aucun autre client tente d'envoyer une image simultanément, 'N' sinon&lt;br /&gt;
**Si et seulement si le client reçoit 'Y' il débute le transfert en envoyant la largeur et la longueur de l'image sur 4 octets, puis les données de l'image soit 4 valeurs pour chaque pixels (r,g,b,alpha)&lt;br /&gt;
**Le serveur renvoie 'D' une fois le transfert achevé (à l'avenir, le serveur renverra l'image après filtrage).&lt;br /&gt;
**A tout moment, le serveur peut renvoyer 'E' si une erreur est survenue (ex : paquets perdus, nombre incorrects de données)&lt;br /&gt;
*Ajout du support des logs au niveau serveur&lt;br /&gt;
**Impression sur la sortie standard des messages&lt;br /&gt;
**Formatage en fonction de la sévérité du log (info, warning, error...)&lt;br /&gt;
**Incrustation de la date et heure&lt;br /&gt;
**Possibilité de redirection dans une fichier, avec configuration (écriture à la suite d'un fichier existant, écrasement...)&lt;br /&gt;
**Le tout dans une classe Java flexible et réutilisable pour d'autres projets&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 6===&lt;br /&gt;
&lt;br /&gt;
*Installation de la librairie Java Pi4j sur la raspberry pi qui permet le contrôle des GPIO de celle-ci et notamment le port I²C (basé sur WiringPi)&lt;br /&gt;
*Amélioration coté serveur websocket&lt;br /&gt;
**Gestion de message plus longs (maximum des trames websockets soit 2^63 octets)&lt;br /&gt;
**Différenciation, à la réception de messages, des trames textes ou binaires des trames de contrôle comme les requête ping, pong ou de fermeture de connexion &lt;br /&gt;
**Ajout d'un mode de debug de trames&lt;br /&gt;
*Interface web&lt;br /&gt;
**Mise en place du code css pour améliorer le rendu visuel de la page&lt;br /&gt;
**Amélioration de l'envoie des données vers le serveur&lt;br /&gt;
&lt;br /&gt;
===Semaine 7===&lt;br /&gt;
&lt;br /&gt;
*Améliorations du serveur WebSocket&lt;br /&gt;
**Gestion de la fragmentation TCP&lt;br /&gt;
**Gestion de la fragmentation WebSocket&lt;br /&gt;
**Gestion des requêtes ping envoyés par le client en renvoyant une trames de contrôle pong afin de maintenir la connexion&lt;br /&gt;
**Gestion des déconnexion de clients afin d'optimiser le serveur&lt;br /&gt;
**Amélioration de l'émission de messages en augmentant la taille maximale pouvant être émise (2^63 octets)&lt;br /&gt;
&lt;br /&gt;
*Amélioration du code css&lt;br /&gt;
*Mise en place d'une partie 'Home' et 'About'&lt;br /&gt;
**Home : Communication avec le serveur web&lt;br /&gt;
**About : Information complémentaire sur la page web&lt;br /&gt;
&lt;br /&gt;
A ce stade du développement, le client et le serveur sont opérationnels et peuvent s'échanger des messages ainsi que des images que le serveur traite pour extraire les contours.&lt;br /&gt;
&lt;br /&gt;
===Semaine 8===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Montage projecteur&lt;br /&gt;
**Intégralité des composants fixés par vis dans le boîtier ABS&lt;br /&gt;
**Fusion des alimentations&lt;br /&gt;
**Présence d'une led témoin de mise en tension&lt;br /&gt;
**Position laser réglable grâce à une vis&lt;br /&gt;
**Présence d'un switch à bascule pour allumer et éteindre le laser&lt;br /&gt;
**Isolation et vérification des composants&lt;br /&gt;
**Tests empiriques de température et de fonctionnement des lasers et galvanomètres&lt;br /&gt;
&lt;br /&gt;
Le montage boîtier est donc terminé et s’alimente en 230V par intermédiaire d'un câble secteur avec connecteur C14. Le résultat s'avère plutôt compact. Les quelques tests de température ont montrés que malgré le manque d'espace la température globale du boîtier ne dépasse pas les 50°C pendant plus d'une heure de fonctionnement. L'intégralité des connexions sont isolées avec de la gaine thermodynamique et les zones &amp;quot;sensibles&amp;quot; sont correctement vérifiés ainsi que protégées avec de la matière isolante.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:proj1.jpg|550px|Boîtier après perçage]] [[Fichier:proj2.jpg|550px|Boîtier finalisé]] [[Fichier:proj3.jpg|550px|Projecteur en fonctionnement]]&lt;br /&gt;
&lt;br /&gt;
*Page web et serveur WebSocket&lt;br /&gt;
**Ajout d'un bouton &amp;quot;reboot&amp;quot; et &amp;quot;shutdown&amp;quot; sur la page web&lt;br /&gt;
***Reboot : Permet le redémarrage de la Raspberry&lt;br /&gt;
***Shutdown : Permet l'extinction de la Raspberry&lt;br /&gt;
**Ajout d'un slider pour le flou gaussien (échelle 1 à 100)&lt;br /&gt;
&lt;br /&gt;
===Semaine 9===&lt;br /&gt;
*Installation du programme 'bind9' permettant de mettre en place un serveur DNS qui permet de remplacer les adresses IP par un nom&lt;br /&gt;
**Problème de configuration (à corriger)&lt;br /&gt;
*Prise en compte du message de retour du serveur&lt;br /&gt;
**Récupération d'un tableau de points représentants les contours de l'image envoyé par le client&lt;br /&gt;
*Mise à jour du slider du flou gaussien&lt;br /&gt;
**Double spider permettant de sélectionner un segment de valeur&lt;br /&gt;
**Echelle comprise entre 0 et 1, pour faciliter la lecture les valeurs sont écrites en pourcent&lt;br /&gt;
*Etude du pololu md08a en remplacement du DAC initialement prévu et dessin de la carte&lt;br /&gt;
&lt;br /&gt;
===Semaine 10===&lt;br /&gt;
[[Fichier:Capture_du_2017-04-12_15-53-15.png|200px|thumb|right|Image envoyée -&amp;gt; Image laser]]&lt;br /&gt;
&lt;br /&gt;
*Récupération d'un ensemble de points envoyés par le serveur permettant de tracer l'image telle que sera projetée par le laser&lt;br /&gt;
**Mise en place du canvas&lt;br /&gt;
**Traçage de l'image par l'intermédiaire de &amp;quot;lineto&amp;quot; puisqu'il s'agit d'un contour&lt;br /&gt;
*Ajout d'une sécurité sur les boutons &amp;quot;reset&amp;quot; et &amp;quot;shutdown&amp;quot;&lt;br /&gt;
**Pop-up de confirmation pour les deux actions&lt;br /&gt;
*Mise à jour du Double slider&lt;br /&gt;
**Redimensionnement&lt;br /&gt;
**Récupération des valeurs&lt;br /&gt;
**Envois des valeurs vers le serveur par un tableau de binaires&lt;br /&gt;
&lt;br /&gt;
===Semaines Supplémentaires===&lt;br /&gt;
&lt;br /&gt;
*Finalisation du code css de la page web&lt;br /&gt;
**Amélioration visuelle&lt;br /&gt;
**Rendu dynamique de la page&lt;br /&gt;
[[Fichier:Page_accueil.png|396px|Page d’accueil]]&lt;br /&gt;
[[Fichier:Page2.png|396px|Image chargée]]&lt;br /&gt;
[[Fichier:Page3.png|396px|Contours récupérés]]&lt;br /&gt;
*Finalisation de la carte Pololu md08a + Arduino Pro Mini&lt;br /&gt;
*Mise en place d'une liaison série Raspberry-Arduino&lt;br /&gt;
**Tests effectués avec I2C, SPI, UART. Solution retenue : I2C&lt;br /&gt;
*Contrôle des galvanomètres via PWM&lt;br /&gt;
&lt;br /&gt;
==A faire==&lt;br /&gt;
&lt;br /&gt;
MAJ 19 Avril&lt;br /&gt;
&lt;br /&gt;
*Client websocket et page web&lt;br /&gt;
**Ajout slider pour de finir amplitude de la projection&lt;br /&gt;
**Ajout message de confirmation quand le serveur quitte ou relance&lt;br /&gt;
**Ajout boutons &amp;quot;projeter&amp;quot; &amp;quot;centrer&amp;quot; &amp;quot;etendre&amp;quot;&lt;br /&gt;
**Redimensionnement automatique de l'image !!&lt;br /&gt;
**Gestion de plusieurs images avec délai&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Serveur WebSocket&lt;br /&gt;
**Ajout fonctionnalité envoi image de prévisualisation&lt;br /&gt;
&lt;br /&gt;
*RaspberryPi&lt;br /&gt;
**Utilisation d'un serveur bind9 pour éviter de taper IP&lt;br /&gt;
&lt;br /&gt;
*Détection de contours&lt;br /&gt;
**Implémentation algorithme de tri de la plus courte disance&lt;br /&gt;
&lt;br /&gt;
*Commande galvanomêtre&lt;br /&gt;
**Utilisation API I²C&lt;br /&gt;
**Fonction de transfert position-&amp;gt;angle-&amp;gt;tension&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;br /&gt;
&lt;br /&gt;
[[Media:CptProjetIMA4.pdf‎ |Compte-rendu Projet]]&lt;br /&gt;
&lt;br /&gt;
==Bibliographie==&lt;br /&gt;
&lt;br /&gt;
*Galvanomètres et laser&lt;br /&gt;
http://www.ebay.com/itm/20KPPS-30KPPS-laser-scanning-galvo-scanner-ILDA-Closed-Loop-max-30kpps-for-laser-/261517002270?hash=item3ce3a0c61e&lt;br /&gt;
&lt;br /&gt;
http://sciences.ulb.ac.be/printemps/download/2016/dossier_pedagogique/02.pdf&lt;br /&gt;
&lt;br /&gt;
*Websocket&lt;br /&gt;
http://stackoverflow.com/questions/8125507/how-can-i-send-and-receive-websocket-messages-on-the-server-side&lt;br /&gt;
&lt;br /&gt;
https://tools.ietf.org/html/rfc6455&lt;br /&gt;
&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_a_WebSocket_server_in_Java&lt;br /&gt;
&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers&lt;br /&gt;
&lt;br /&gt;
*Traitement d'image&lt;br /&gt;
https://en.wikipedia.org/wiki/Gaussian_blur&lt;br /&gt;
&lt;br /&gt;
http://www.zebulon.fr/questions-reponses/traitement-d-image-detection-de-contours-55.html&lt;br /&gt;
&lt;br /&gt;
http://patrick-bonnin.developpez.com/cours/vision/apprendre-bases-traitement-image/partie-5-segmentation-contour/&lt;br /&gt;
&lt;br /&gt;
http://www.isir.upmc.fr/UserFiles/File/clady_homepage/EPU/2-Contour&lt;br /&gt;
&lt;br /&gt;
*Autre&lt;br /&gt;
https://icn.fenelonlille.org/mediawiki/index.php/Projet_ICN_commun_2016/2017&lt;br /&gt;
&lt;br /&gt;
https://www.g33k-zone.org/post/2016/05/11/Configurer-le-Raspberry-Pi-en-point-d-acc%C3%A8s-Wifi&lt;br /&gt;
&lt;br /&gt;
https://blogs.oracle.com/acaicedo/resource/Parallax-I2C/Sensors.java&lt;br /&gt;
&lt;br /&gt;
http://stackoverflow.com/questions/22087076/how-to-make-a-simple-image-upload-using-javascript-html&lt;/div&gt;</summary>
		<author><name>Mtrimbur</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=42625</id>
		<title>IMA4 2016/2017 P39</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=42625"/>
				<updated>2017-05-19T15:09:42Z</updated>
		
		<summary type="html">&lt;p&gt;Mtrimbur : /* Semaine 9 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
===Contexte===&lt;br /&gt;
&lt;br /&gt;
Le laser est une technologie largement utilisé de nos jours dans de diverses applications. En effet, on retrouve cette technologie dans le domaine médical notamment pour la chirurgie oculaire ou encore dans industrie avec la découpe laser ou la soudure au laser.&lt;br /&gt;
&lt;br /&gt;
Le laser est une émission de photons produit par excitation d'un milieu amplificateur (ex : CO2), le rayonnement produit est unidirectionnel et monochromatique. Ce sont ces propriétés que nous allons exploiter afin réaliser un projecteur laser qui mis en mouvement est capable de dessiner des formes sur une surface à l'instar de systèmes existants utilisés pour des effets lumineux lors de festivités.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
L'objectif du projet est de créer un système de projection laser à plusieurs couleurs (au minimum deux) avec une application web pour programmer les formes à dessiner afin d'agrémenter des compétitions de gymnastique rythmique.&lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
Le projet consiste à réaliser avec des lasers des figures géométriques par l'intermédiaire d'un système galvanométrique. &lt;br /&gt;
&lt;br /&gt;
Notre premier travail sera de concevoir la partie projection. Pour cela, nous devrons aligner les lasers et les galvanomètres. En effet, ces derniers posséderont des miroirs à l'extrémité, ainsi les miroirs changeront d'inclinaison suivant le courant traversant les galvanomètres (similaire à l'image ci-contre). Il nous faudra également créer un système d'alimentation qui à partir d'une même source (réseau 230 V) sera capable d'alimenter les lasers et les galvanomètres ainsi qu'une Arduino et une Raspberry Pi.&lt;br /&gt;
[[File:Scanhead.jpeg|thumb]]&lt;br /&gt;
&lt;br /&gt;
Ensuite nous nous intéresserons à l'utilisation d'un système embarqué pour contrôler les galvanomètres et donc dessiner avec les lasers sur un plan 2D. En effet, le laser restera toujours fixe, seuls les galvanomètres, et donc les miroirs bougeront. Les galvanomètres étant contrôlés en courant il faudra réaliser une interface électronique pour convertir une commande en tension en commande de courant. La commande en tension sera assuré par une carte Arduino. Nous n'utiliserons qu'une seule paire de galvanomètres pour les deux laser. Il faudra donc multiplexer les deux faisceaux. La programmation des formes à effectuer, se fera par l'intermédiaire d'une application web PHP hébergée sur une RaspberryPi qui permettra de récupérer une image, d'y appliquer divers traitements et filtres afin d'en extraire les contours, et de calculer les commandes pour positionner les galvanomètres. Un serveur WebSocket également hébergé sur la RaspberryPi servira d'interface entre l'application web et L'arduino qui sera connecté via une liaison série sur la raspberryPI.&lt;br /&gt;
&lt;br /&gt;
Comme animation de test, nous dessinerons le contour d'une gymnaste avec une couleur et son ballon d'une autre couleur. La gymnaste devra lancer son ballon, réaliser quelques difficultés et récupérer son ballon.&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
Nous utiliserons comme matériels :&lt;br /&gt;
*Deux lasers de différentes couleurs&lt;br /&gt;
*Une paire de galvanomètres à miroir&lt;br /&gt;
*Arduino&lt;br /&gt;
*Raspberry Pi3&lt;br /&gt;
*Alimentation 230V/5V 1A [http://www.miniinthebox.com/fr/dual-usb-eu-prise-murale-5v-2a-voyage-adaptateur-chargeur-d-alimentation-pour-iphone7-6-xiaomi-samsung-et-autre-telephone-portable_p5410410.html?currency=EUR&amp;amp;litb_from=paid_adwords_shopping&amp;amp;sku=429_6917%7C752_20648&amp;amp;utm_source=google_shopping&amp;amp;utm_medium=cpc&amp;amp;adword_mt=&amp;amp;adword_ct=138705676724&amp;amp;adword_kw=&amp;amp;adword_pos=1o5&amp;amp;adword_pl=&amp;amp;adword_net=g&amp;amp;adword_tar=&amp;amp;adw_src_id=9653316068_661261352_33588296076_aud-79897721311:pla-256966386459&amp;amp;gclid=Cj0KEQiA_KvEBRCtzNil4-KR-LIBEiQAmgekFxxKjJJWBYCJlDZEa3Ke_2_WR0DzGVbz-jaCZHVIBoMaAvld8P8HAQ]&lt;br /&gt;
*Drivers galvanomètres x2&lt;br /&gt;
*Alimentation laser&lt;br /&gt;
*Lunette de sécurité x2 [https://www.amazon.fr/Uvex-S1933X-Eyewear-SCTOrange-Anti-Fog/dp/B000USRG90/ref=sr_1_1?ie=UTF8&amp;amp;qid=1485441383&amp;amp;sr=8-1&amp;amp;keywords=uvex+s1933x]&lt;br /&gt;
*Boitier ABS [http://fr.farnell.com/multicomp/g3118/boitier-abs-240x120x60mm-ip65/dp/1526656]&lt;br /&gt;
*DAC 4 canaux, avec interface I²C [https://www.adafruit.com/products/1083]&lt;br /&gt;
*Connecteur C14 [http://www.conrad.fr/ce/fr/product/715001/Connecteur-secteur-C14-Embase-male-verticale-715001-Nombre-de-poles-2-PE-10-A-noir-1-pcs/?ref=detview1&amp;amp;rt=detview1&amp;amp;rb=1]&lt;br /&gt;
*Câble secteur&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Logiciel :&lt;br /&gt;
&lt;br /&gt;
*Serveur web : Apache2, HTML5, PHP5, CSS&lt;br /&gt;
*Base de donnée : MySQL&lt;br /&gt;
*Serveur WebSocket : JQuerry, websocket&lt;br /&gt;
*Arduino : IDE Arduino&lt;br /&gt;
&lt;br /&gt;
===Calendrier prévisionnel===&lt;br /&gt;
&lt;br /&gt;
====Liste des tâches à effectuer====&lt;br /&gt;
Les différentes tâches à effectuer sont :&lt;br /&gt;
*Partie préliminaire : étude de fonctionnement des galvanomètres&lt;br /&gt;
**Déterminer comment est effectuée la commande des galvanomètres (protocole, tension...)&lt;br /&gt;
**Effectuer des tests avec l'Arduino ou la Raspberry Pi&lt;br /&gt;
**Effectuer des tests avec une LED à la place du laser &lt;br /&gt;
*Partie projection&lt;br /&gt;
**Fixer les lasers&lt;br /&gt;
**Aligner les lasers et les galvanomètres&lt;br /&gt;
**Créer le système d'alimentation&lt;br /&gt;
**Création d'un boitier&lt;br /&gt;
*Partie système embarqué&lt;br /&gt;
**Asservissement des galvanomètres avec l'Arduino&lt;br /&gt;
**Système électronique de commande en courant pour les galvanomètres&lt;br /&gt;
*Interface Web&lt;br /&gt;
**Installation et configuration Apache2&lt;br /&gt;
**Création d'une interface graphique simple&lt;br /&gt;
**Implémentation d'algorithmes de traitement d'image&lt;br /&gt;
**Mise en forme avec des CSS&lt;br /&gt;
**Sytème d'authentification avec mot de passe&lt;br /&gt;
**Utilisation d'une base de données pour enregistrer toutes les images déjà utilisés afin de les réutiliser&lt;br /&gt;
*Serveur Web Socket&lt;br /&gt;
**Récupération des données de l'interface web&lt;br /&gt;
**Mise en place de la liaison série avec l'Arduino&lt;br /&gt;
&lt;br /&gt;
====Calendrier====&lt;br /&gt;
Répartition du temps consacré au projet (240h) :&lt;br /&gt;
*Partie projection : 80h&lt;br /&gt;
*Partie système embarqué : 40h&lt;br /&gt;
*Partie interface web et websocket: 120h&lt;br /&gt;
&lt;br /&gt;
==Feuille d'heures==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!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&lt;br /&gt;
|-&lt;br /&gt;
| Définition cahier des charges &lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 14&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|38&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Finalisation du cahier des charges avec les responsables&lt;br /&gt;
&lt;br /&gt;
*Acquisition de matériels :&lt;br /&gt;
**Projecteur Laser&lt;br /&gt;
**Galvanomètres&lt;br /&gt;
**Alimentation des galvanomètres&lt;br /&gt;
&lt;br /&gt;
*Listage du matériels à acquérir :&lt;br /&gt;
**Lunettes de sécurité&lt;br /&gt;
**DAC&lt;br /&gt;
**Alimentation 230V/5V 1A&lt;br /&gt;
** Boitier ABS &lt;br /&gt;
**...&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
*Obtention de l'arduino et de la raspberryPI&lt;br /&gt;
&lt;br /&gt;
*Démontage du projecteur laser&lt;br /&gt;
**Deux lasers de classe 3b (vert et rouge)&lt;br /&gt;
**Circuit d'alimentation des deux lasers&lt;br /&gt;
&lt;br /&gt;
*Initialisation du port série de la raspberryPI&lt;br /&gt;
**Modification du fichier ''config.txt'' dans la partition boot&lt;br /&gt;
**Ajout d'une ligne autorisant la communication série ('''enable_uart=1''')&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
*Installation du serveur apache sur la raspberryPI&lt;br /&gt;
**Modification du fichier ''/etc/network/interfaces'' (Static, Address, Netmask, Gateway)&lt;br /&gt;
**Modification du fichier ''/etc/resolv.conf'' (Adresse du serveur)&lt;br /&gt;
**Utilisation d'un proxy pour la récupération outils de programmation (Apache2, Php5)&lt;br /&gt;
&lt;br /&gt;
*Mise en place du point d’accès wifi de la raspberryPI&lt;br /&gt;
**Récupération des logiciels nécessaires (dnsmasq, hostapd)&lt;br /&gt;
**Mise en place d'une adresse IP statique pour le point d'accès par l'intermédiaire du fichier ''/etc/dhcpcd.conf''&lt;br /&gt;
**Désactivation de la négociation automatique de bail dans le fichier ''/etc/network/interfaces''&lt;br /&gt;
**Configuration du logiciel hostapd ''/etc/hostapd/hostapd.conf''&lt;br /&gt;
**Activation du démarrage automatique du point d'accès ''/etc/default/hostapd''&lt;br /&gt;
**Configuration du serveur DNS par ''/etc/dnsmasq.conf''&lt;br /&gt;
&lt;br /&gt;
*Instauration de la page d'accueil de l'interface web à l'adresse ''192.168.3.1''&lt;br /&gt;
**Téléversement de fichiers images sur la page web et affichage de celle-ci&lt;br /&gt;
**Voyant de confirmation du bon fonctionnement du serveur web&lt;br /&gt;
&lt;br /&gt;
*Développement du serveur websocket&lt;br /&gt;
&lt;br /&gt;
Le développement du serveur websocket, initialement prévu en C (il était prévu de reprendre les sources utilisées l'année précédente dans le cadre des projet IMA3 SC), a finalement été réalisé en JAVA pour plusieurs raisons.&lt;br /&gt;
Premièrement, un seul programme met en œuvre le serveur websocket, les divers traitements d'image, ainsi que les contrôles des galvanomètres (par l'intermédiaire des DAC) via la liaison I²C de la Raspberry Pi. Le langage JAVA fournit nativement des bibliothèques d'objets pour manipuler assez simplement des images, il existe également des librairies pour contrôler le port GPIO de la Raspberry et il était également intéressant de travailler avec un langage de plus haut niveau que le C.&lt;br /&gt;
En outre, la totale portabilité de ce langage nous permet de travailler sur n'importe quelle machine et ensuite transférer notre programme sur la Raspberry Pi et l’exécuter sans même repasser par une phase de compilation. Et finalement, c'est le langage que nous étudions actuellement en cours de programmation orientée objet, ce qui permet de nous perfectionner.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Serveur WebSocket====&lt;br /&gt;
&lt;br /&gt;
N'ayant pas trouvé d'API WebSocket en Java satisfaisante (qui ne nécessitent pas l'installation et la configuration de nombreux outils additionnels), j'ai estimé plus commode et plus formateur de développer notre propre serveur WebSocket en se basant sur les librairies sockets de Java avec l'aide d'une documentation assez exhaustive [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers].&lt;br /&gt;
&lt;br /&gt;
Les WebSockets désignent à la fois un protocole réseau qui étend le protocole TCP ainsi qu'une API du World Wide Web. Nous nous en servons afin d'établir une communication asynchrone et bidirectionnelle entre un navigateur web et le serveur, notamment pour envoyer l'image à projeter. L’implémentation du serveur repose sur plusieurs étapes.&lt;br /&gt;
&lt;br /&gt;
1) Connexion d'un client &lt;br /&gt;
&lt;br /&gt;
2) Handshake : permet de faire le lien entre le protocole HTTP et WS. Le client envoie une requête HTTP demandant un upgrade de la connexion en protocole WS et le serveur répond en configurant la connexion (détail dans la documentation [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers]).&lt;br /&gt;
&lt;br /&gt;
3) Réception et décodage des messages : le serveurs reçoit des trames brutes, on extrait donc la taille du message ainsi que le message. De plus, les données son encodées (cryptage XOR) par un masque qui doit également être extrait.&lt;br /&gt;
&lt;br /&gt;
4) Fermeture de la communication.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le serveur supporte le multi-client il est donc nécessaire qu'il effectue ces étapes en &amp;quot;parallèle&amp;quot;. Nous utilisons donc les threads ou fils d’exécution. Un thread est donc responsable d'attendre qu'un nouveau client se connecte et effectue le &amp;quot;handshake&amp;quot;, il crée ensuite un thread associé à ce client afin d'établir un canal de communication. Il y a donc au moins un thread par client. Par la suite il faudra également implémenter une déconnexion automatique d'un client notamment après un timeout.&lt;br /&gt;
&lt;br /&gt;
Exemple d’exécution du serveur avec deux clients qui se connectent et envoient un message : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testServeur.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Les clients sont des navigateurs web. Pour les tests nous avons repris les exemples utilisés dans le cadre das projets IMA3 SC avec le titre de la page HTML qui se colore en vert lorsque le client est connecté, et un champ de saisie pour envoyer des messages au serveur : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testClient.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 4===&lt;br /&gt;
&lt;br /&gt;
*Mise en place d’algorithmes de traitement d'image&lt;br /&gt;
&lt;br /&gt;
====Détection de contour====&lt;br /&gt;
&lt;br /&gt;
L'objectif de notre projet est de pouvoir projeter n'importe quelle image envoyé grâce à l'application web. Pour cela nous allons tracer à une vitesse élevée les contours de l'image sur par exemple un mur grâce au laser. Il est donc nécessaire de détecter les contours de l'image grâce à plusieurs traitements.&lt;br /&gt;
&lt;br /&gt;
=====Conversion en niveau de gris=====&lt;br /&gt;
&lt;br /&gt;
Une des étapes préliminaires pour effectuer la détection de contour est de convertir l'image couleur en niveau de gris. Pour cela l'algorithme est simple : il suffit pour chaque pixel de l'image d'effectuer la moyenne des composantes rouge, verte, bleu de chaque pixel. En effet, si l'on considère une image matricielle (l'image est considérée comme un tableau à deux dimensions avec chaque case qui contient la couleur du pixel), chaque pixel contient les composantes RGB codées sur un octet. La couleur gris correspond aux composantes RGB égales. Le niveau de gris est donc codé de 0 à 255, avec 0 donnant du noir et 255 du blanc. &lt;br /&gt;
&lt;br /&gt;
Voici le résultat obtenu : [[Fichier:testGrayScale.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Filtre de Prewit et Sobel=====&lt;br /&gt;
&lt;br /&gt;
Un contour est défini par un changement brutal d'intensité lumineuse, il s'agit donc de détecter selon plusieurs directions (au moins 2) ces changements. Il existe de nombreuses techniques afin de détecter les contours d'une image (gradient, Laplacien). L'une des techniques avec un rapport efficacité/temps d'exécution correct repose sur les algorithmes de Prewit ou Sobel. L'algorithme repose sur la convolution de matrices.&lt;br /&gt;
Cela consiste à appliquer sur chaque pixel de l'image la matrice de Prewit définie comme &lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L_x = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; ainsi que sa transposée : &amp;lt;math&amp;gt;&lt;br /&gt;
L_y = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; -1 &amp;amp; -1 \\&lt;br /&gt;
 0 &amp;amp; 0 &amp;amp; 0 \\&lt;br /&gt;
+1 &amp;amp; +1 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Convoluer ces deux filtres sur l'image permet de détecter respectivement les contours verticaux et horizontaux.&lt;br /&gt;
&lt;br /&gt;
D'après wikipedia [https://fr.wikipedia.org/wiki/D%C3%A9tection_de_contours], on obtient de meilleurs résultats en appliquant un filtre triangulaire, on introduit donc la matrice de Sobel :&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-2 &amp;amp; 0 &amp;amp; +2 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
On obtient le résultat suivant : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testOutline1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Pré-traitement : Flou Gaussien=====&lt;br /&gt;
&lt;br /&gt;
Afin de réduire significativement le nombre de contours, il est nécessaire d'effectuer un pré-traitement avant la détection de contours. On utilise généralement un flou gaussien afin de réduire les transitions lumineuses et ainsi réduire le nombre de contours. L’algorithme de flou gaussien repose également sur la convolution de matrices sauf qu'ici la matrice filtre est générée grâce à une fonction gaussienne paramétrée par '''Sigma''' qui va directement impacter le niveau de flou. Plus la matrice de filtrage est grande plus la qualité du résultat est meilleure, mais le temps d’exécution devient également plus grand.&lt;br /&gt;
&lt;br /&gt;
Voici la fonction de génération du filtre : &amp;lt;math&amp;gt;G(x,y) = \frac{1}{{2\pi \sigma^2}} e^{-\frac{x^2 + y^2}{2 \sigma^2}}&amp;lt;/math&amp;gt; où x et y correspondent aux indices de la cellule de la matrice.&lt;br /&gt;
&lt;br /&gt;
On obtient ce résultat :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testGaussianBlur.png]]&lt;br /&gt;
&lt;br /&gt;
On note un bien meilleur résultat. Cependant on remarque que les composantes horizontales ne sont pas correctement détectées il subsiste un problème avec le filtrage vertical que je n'ai pas réussi à identifier. De plus, il s'agit par sa suite d'éliminer les contours parasites ainsi que d'affiner le trait pour n'avoir plus qu'un pixel d'épaisseur.&lt;br /&gt;
&lt;br /&gt;
=====Post-traitement : Algorithme de Canny=====&lt;br /&gt;
&lt;br /&gt;
Afin d'obtenir un résultat exploitable il est nécessaire d'appliquer encore quelques traitements. Pour cela nous utilisons l’algorithme de Canny qui repose que celui de Sobel mais qui ajoute un algorithme de seuillage par hysteresis qui permet de retirer les contours secondaires et de ne garder que les contours connexes dans une seuil haut et un seuil bas définis. En outre, cette algorithme affine également le trait obtenu. Pour cet algorithme nous avons directement trouvé des sources libres de droits [http://www.tomgibara.com/computer-vision/canny-edge-detector] qui donne des résultats très corrects.&lt;br /&gt;
&lt;br /&gt;
Par exemple :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ou encore : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny2.png|1500px]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 5===&lt;br /&gt;
&lt;br /&gt;
*Établissement d'un protocole de transfert d'image basé sur les WebSockets&lt;br /&gt;
**Envoie d'un requête &amp;quot;send&amp;quot; par le client dans une trame websocket texte&lt;br /&gt;
**Réponse serveur 'Y' si aucun autre client tente d'envoyer une image simultanément, 'N' sinon&lt;br /&gt;
**Si et seulement si le client reçoit 'Y' il débute le transfert en envoyant la largeur et la longueur de l'image sur 4 octets, puis les données de l'image soit 4 valeurs pour chaque pixels (r,g,b,alpha)&lt;br /&gt;
**Le serveur renvoie 'D' une fois le transfert achevé (à l'avenir, le serveur renverra l'image après filtrage).&lt;br /&gt;
**A tout moment, le serveur peut renvoyer 'E' si une erreur est survenue (ex : paquets perdus, nombre incorrects de données)&lt;br /&gt;
*Ajout du support des logs au niveau serveur&lt;br /&gt;
**Impression sur la sortie standard des messages&lt;br /&gt;
**Formatage en fonction de la sévérité du log (info, warning, error...)&lt;br /&gt;
**Incrustation de la date et heure&lt;br /&gt;
**Possibilité de redirection dans une fichier, avec configuration (écriture à la suite d'un fichier existant, écrasement...)&lt;br /&gt;
**Le tout dans une classe Java flexible et réutilisable pour d'autres projets&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 6===&lt;br /&gt;
&lt;br /&gt;
*Installation de la librairie Java Pi4j sur la raspberry pi qui permet le contrôle des GPIO de celle-ci et notamment le port I²C (basé sur WiringPi)&lt;br /&gt;
*Amélioration coté serveur websocket&lt;br /&gt;
**Gestion de message plus longs (maximum des trames websockets soit 2^63 octets)&lt;br /&gt;
**Différenciation, à la réception de messages, des trames textes ou binaires des trames de contrôle comme les requête ping, pong ou de fermeture de connexion &lt;br /&gt;
**Ajout d'un mode de debug de trames&lt;br /&gt;
*Interface web&lt;br /&gt;
**Mise en place du code css pour améliorer le rendu visuel de la page&lt;br /&gt;
**Amélioration de l'envoie des données vers le serveur&lt;br /&gt;
&lt;br /&gt;
===Semaine 7===&lt;br /&gt;
&lt;br /&gt;
*Améliorations du serveur WebSocket&lt;br /&gt;
**Gestion de la fragmentation TCP&lt;br /&gt;
**Gestion de la fragmentation WebSocket&lt;br /&gt;
**Gestion des requêtes ping envoyés par le client en renvoyant une trames de contrôle pong afin de maintenir la connexion&lt;br /&gt;
**Gestion des déconnexion de clients afin d'optimiser le serveur&lt;br /&gt;
**Amélioration de l'émission de messages en augmentant la taille maximale pouvant être émise (2^63 octets)&lt;br /&gt;
&lt;br /&gt;
*Amélioration du code css&lt;br /&gt;
*Mise en place d'une partie 'Home' et 'About'&lt;br /&gt;
**Home : Communication avec le serveur web&lt;br /&gt;
**About : Information complémentaire sur la page web&lt;br /&gt;
&lt;br /&gt;
A ce stade du développement, le client et le serveur sont opérationnels et peuvent s'échanger des messages ainsi que des images que le serveur traite pour extraire les contours.&lt;br /&gt;
&lt;br /&gt;
===Semaine 8===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Montage projecteur&lt;br /&gt;
**Intégralité des composants fixés par vis dans le boîtier ABS&lt;br /&gt;
**Fusion des alimentations&lt;br /&gt;
**Présence d'une led témoin de mise en tension&lt;br /&gt;
**Position laser réglable grâce à une vis&lt;br /&gt;
**Présence d'un switch à bascule pour allumer et éteindre le laser&lt;br /&gt;
**Isolation et vérification des composants&lt;br /&gt;
**Tests empiriques de température et de fonctionnement des lasers et galvanomètres&lt;br /&gt;
&lt;br /&gt;
Le montage boîtier est donc terminé et s’alimente en 230V par intermédiaire d'un câble secteur avec connecteur C14. Le résultat s'avère plutôt compact. Les quelques tests de température ont montrés que malgré le manque d'espace la température globale du boîtier ne dépasse pas les 50°C pendant plus d'une heure de fonctionnement. L'intégralité des connexions sont isolées avec de la gaine thermodynamique et les zones &amp;quot;sensibles&amp;quot; sont correctement vérifiés ainsi que protégées avec de la matière isolante.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:proj1.jpg|550px|Boîtier après perçage]] [[Fichier:proj2.jpg|550px|Boîtier finalisé]] [[Fichier:proj3.jpg|550px|Projecteur en fonctionnement]]&lt;br /&gt;
&lt;br /&gt;
*Page web et serveur WebSocket&lt;br /&gt;
**Ajout d'un bouton &amp;quot;reboot&amp;quot; et &amp;quot;shutdown&amp;quot; sur la page web&lt;br /&gt;
***Reboot : Permet le redémarrage de la Raspberry&lt;br /&gt;
***Shutdown : Permet l'extinction de la Raspberry&lt;br /&gt;
**Ajout d'un slider pour le flou gaussien (échelle 1 à 100)&lt;br /&gt;
&lt;br /&gt;
===Semaine 9===&lt;br /&gt;
*Installation du programme 'bind9' permettant de mettre en place un serveur DNS qui permet de remplacer les adresses IP par un nom&lt;br /&gt;
**Problème de configuration (à corriger)&lt;br /&gt;
*Prise en compte du message de retour du serveur&lt;br /&gt;
**Récupération d'un tableau de points représentants les contours de l'image envoyé par le client&lt;br /&gt;
*Mise à jour du slider du flou gaussien&lt;br /&gt;
**Double spider permettant de sélectionner un segment de valeur&lt;br /&gt;
**Echelle comprise entre 0 et 1, pour faciliter la lecture les valeurs sont écrites en pourcent&lt;br /&gt;
*Etude du pololu md08a en remplacement du DAC initialement prévu et dessin de la carte&lt;br /&gt;
&lt;br /&gt;
===Semaine 10===&lt;br /&gt;
[[Fichier:Capture_du_2017-04-12_15-53-15.png|200px|thumb|right|Image envoyée -&amp;gt; Image laser]]&lt;br /&gt;
&lt;br /&gt;
*Récupération d'un ensemble de points envoyés par le serveur permettant de tracer l'image telle que sera projetée par le laser&lt;br /&gt;
**Mise en place du canvas&lt;br /&gt;
**Traçage de l'image par l'intermédiaire de &amp;quot;lineto&amp;quot; puisqu'il s'agit d'un contour&lt;br /&gt;
*Ajout d'une sécurité sur les boutons &amp;quot;reset&amp;quot; et &amp;quot;shutdown&amp;quot;&lt;br /&gt;
**Pop-up de confirmation pour les deux actions&lt;br /&gt;
*Mise à jour du Double slider&lt;br /&gt;
**Redimensionnement&lt;br /&gt;
**Récupération des valeurs&lt;br /&gt;
**Envois des valeurs vers le serveur par un tableau de binaires&lt;br /&gt;
&lt;br /&gt;
===Semaines Supplémentaires===&lt;br /&gt;
&lt;br /&gt;
*Finalisation du code css de la page web&lt;br /&gt;
**Amélioration visuelle&lt;br /&gt;
**Rendu dynamique de la page&lt;br /&gt;
[[Fichier:Page_accueil.png|396px|Page d’accueil]]&lt;br /&gt;
[[Fichier:Page2.png|396px|Image chargée]]&lt;br /&gt;
[[Fichier:Page3.png|396px|Contours récupérés]]&lt;br /&gt;
&lt;br /&gt;
==A faire==&lt;br /&gt;
&lt;br /&gt;
MAJ 19 Avril&lt;br /&gt;
&lt;br /&gt;
*Client websocket et page web&lt;br /&gt;
**Ajout slider pour de finir amplitude de la projection&lt;br /&gt;
**Ajout message de confirmation quand le serveur quitte ou relance&lt;br /&gt;
**Ajout boutons &amp;quot;projeter&amp;quot; &amp;quot;centrer&amp;quot; &amp;quot;etendre&amp;quot;&lt;br /&gt;
**Redimensionnement automatique de l'image !!&lt;br /&gt;
**Gestion de plusieurs images avec délai&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Serveur WebSocket&lt;br /&gt;
**Ajout fonctionnalité envoi image de prévisualisation&lt;br /&gt;
&lt;br /&gt;
*RaspberryPi&lt;br /&gt;
**Utilisation d'un serveur bind9 pour éviter de taper IP&lt;br /&gt;
&lt;br /&gt;
*Détection de contours&lt;br /&gt;
**Implémentation algorithme de tri de la plus courte disance&lt;br /&gt;
&lt;br /&gt;
*Commande galvanomêtre&lt;br /&gt;
**Utilisation API I²C&lt;br /&gt;
**Fonction de transfert position-&amp;gt;angle-&amp;gt;tension&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;br /&gt;
&lt;br /&gt;
[[Media:CptProjetIMA4.pdf‎ |Compte-rendu Projet]]&lt;br /&gt;
&lt;br /&gt;
==Bibliographie==&lt;br /&gt;
&lt;br /&gt;
*Galvanomètres et laser&lt;br /&gt;
http://www.ebay.com/itm/20KPPS-30KPPS-laser-scanning-galvo-scanner-ILDA-Closed-Loop-max-30kpps-for-laser-/261517002270?hash=item3ce3a0c61e&lt;br /&gt;
&lt;br /&gt;
http://sciences.ulb.ac.be/printemps/download/2016/dossier_pedagogique/02.pdf&lt;br /&gt;
&lt;br /&gt;
*Websocket&lt;br /&gt;
http://stackoverflow.com/questions/8125507/how-can-i-send-and-receive-websocket-messages-on-the-server-side&lt;br /&gt;
&lt;br /&gt;
https://tools.ietf.org/html/rfc6455&lt;br /&gt;
&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_a_WebSocket_server_in_Java&lt;br /&gt;
&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers&lt;br /&gt;
&lt;br /&gt;
*Traitement d'image&lt;br /&gt;
https://en.wikipedia.org/wiki/Gaussian_blur&lt;br /&gt;
&lt;br /&gt;
http://www.zebulon.fr/questions-reponses/traitement-d-image-detection-de-contours-55.html&lt;br /&gt;
&lt;br /&gt;
http://patrick-bonnin.developpez.com/cours/vision/apprendre-bases-traitement-image/partie-5-segmentation-contour/&lt;br /&gt;
&lt;br /&gt;
http://www.isir.upmc.fr/UserFiles/File/clady_homepage/EPU/2-Contour&lt;br /&gt;
&lt;br /&gt;
*Autre&lt;br /&gt;
https://icn.fenelonlille.org/mediawiki/index.php/Projet_ICN_commun_2016/2017&lt;br /&gt;
&lt;br /&gt;
https://www.g33k-zone.org/post/2016/05/11/Configurer-le-Raspberry-Pi-en-point-d-acc%C3%A8s-Wifi&lt;br /&gt;
&lt;br /&gt;
https://blogs.oracle.com/acaicedo/resource/Parallax-I2C/Sensors.java&lt;br /&gt;
&lt;br /&gt;
http://stackoverflow.com/questions/22087076/how-to-make-a-simple-image-upload-using-javascript-html&lt;/div&gt;</summary>
		<author><name>Mtrimbur</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=42622</id>
		<title>IMA4 2016/2017 P39</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=42622"/>
				<updated>2017-05-19T15:07:00Z</updated>
		
		<summary type="html">&lt;p&gt;Mtrimbur : /* Bibliographie */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
===Contexte===&lt;br /&gt;
&lt;br /&gt;
Le laser est une technologie largement utilisé de nos jours dans de diverses applications. En effet, on retrouve cette technologie dans le domaine médical notamment pour la chirurgie oculaire ou encore dans industrie avec la découpe laser ou la soudure au laser.&lt;br /&gt;
&lt;br /&gt;
Le laser est une émission de photons produit par excitation d'un milieu amplificateur (ex : CO2), le rayonnement produit est unidirectionnel et monochromatique. Ce sont ces propriétés que nous allons exploiter afin réaliser un projecteur laser qui mis en mouvement est capable de dessiner des formes sur une surface à l'instar de systèmes existants utilisés pour des effets lumineux lors de festivités.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
L'objectif du projet est de créer un système de projection laser à plusieurs couleurs (au minimum deux) avec une application web pour programmer les formes à dessiner afin d'agrémenter des compétitions de gymnastique rythmique.&lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
Le projet consiste à réaliser avec des lasers des figures géométriques par l'intermédiaire d'un système galvanométrique. &lt;br /&gt;
&lt;br /&gt;
Notre premier travail sera de concevoir la partie projection. Pour cela, nous devrons aligner les lasers et les galvanomètres. En effet, ces derniers posséderont des miroirs à l'extrémité, ainsi les miroirs changeront d'inclinaison suivant le courant traversant les galvanomètres (similaire à l'image ci-contre). Il nous faudra également créer un système d'alimentation qui à partir d'une même source (réseau 230 V) sera capable d'alimenter les lasers et les galvanomètres ainsi qu'une Arduino et une Raspberry Pi.&lt;br /&gt;
[[File:Scanhead.jpeg|thumb]]&lt;br /&gt;
&lt;br /&gt;
Ensuite nous nous intéresserons à l'utilisation d'un système embarqué pour contrôler les galvanomètres et donc dessiner avec les lasers sur un plan 2D. En effet, le laser restera toujours fixe, seuls les galvanomètres, et donc les miroirs bougeront. Les galvanomètres étant contrôlés en courant il faudra réaliser une interface électronique pour convertir une commande en tension en commande de courant. La commande en tension sera assuré par une carte Arduino. Nous n'utiliserons qu'une seule paire de galvanomètres pour les deux laser. Il faudra donc multiplexer les deux faisceaux. La programmation des formes à effectuer, se fera par l'intermédiaire d'une application web PHP hébergée sur une RaspberryPi qui permettra de récupérer une image, d'y appliquer divers traitements et filtres afin d'en extraire les contours, et de calculer les commandes pour positionner les galvanomètres. Un serveur WebSocket également hébergé sur la RaspberryPi servira d'interface entre l'application web et L'arduino qui sera connecté via une liaison série sur la raspberryPI.&lt;br /&gt;
&lt;br /&gt;
Comme animation de test, nous dessinerons le contour d'une gymnaste avec une couleur et son ballon d'une autre couleur. La gymnaste devra lancer son ballon, réaliser quelques difficultés et récupérer son ballon.&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
Nous utiliserons comme matériels :&lt;br /&gt;
*Deux lasers de différentes couleurs&lt;br /&gt;
*Une paire de galvanomètres à miroir&lt;br /&gt;
*Arduino&lt;br /&gt;
*Raspberry Pi3&lt;br /&gt;
*Alimentation 230V/5V 1A [http://www.miniinthebox.com/fr/dual-usb-eu-prise-murale-5v-2a-voyage-adaptateur-chargeur-d-alimentation-pour-iphone7-6-xiaomi-samsung-et-autre-telephone-portable_p5410410.html?currency=EUR&amp;amp;litb_from=paid_adwords_shopping&amp;amp;sku=429_6917%7C752_20648&amp;amp;utm_source=google_shopping&amp;amp;utm_medium=cpc&amp;amp;adword_mt=&amp;amp;adword_ct=138705676724&amp;amp;adword_kw=&amp;amp;adword_pos=1o5&amp;amp;adword_pl=&amp;amp;adword_net=g&amp;amp;adword_tar=&amp;amp;adw_src_id=9653316068_661261352_33588296076_aud-79897721311:pla-256966386459&amp;amp;gclid=Cj0KEQiA_KvEBRCtzNil4-KR-LIBEiQAmgekFxxKjJJWBYCJlDZEa3Ke_2_WR0DzGVbz-jaCZHVIBoMaAvld8P8HAQ]&lt;br /&gt;
*Drivers galvanomètres x2&lt;br /&gt;
*Alimentation laser&lt;br /&gt;
*Lunette de sécurité x2 [https://www.amazon.fr/Uvex-S1933X-Eyewear-SCTOrange-Anti-Fog/dp/B000USRG90/ref=sr_1_1?ie=UTF8&amp;amp;qid=1485441383&amp;amp;sr=8-1&amp;amp;keywords=uvex+s1933x]&lt;br /&gt;
*Boitier ABS [http://fr.farnell.com/multicomp/g3118/boitier-abs-240x120x60mm-ip65/dp/1526656]&lt;br /&gt;
*DAC 4 canaux, avec interface I²C [https://www.adafruit.com/products/1083]&lt;br /&gt;
*Connecteur C14 [http://www.conrad.fr/ce/fr/product/715001/Connecteur-secteur-C14-Embase-male-verticale-715001-Nombre-de-poles-2-PE-10-A-noir-1-pcs/?ref=detview1&amp;amp;rt=detview1&amp;amp;rb=1]&lt;br /&gt;
*Câble secteur&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Logiciel :&lt;br /&gt;
&lt;br /&gt;
*Serveur web : Apache2, HTML5, PHP5, CSS&lt;br /&gt;
*Base de donnée : MySQL&lt;br /&gt;
*Serveur WebSocket : JQuerry, websocket&lt;br /&gt;
*Arduino : IDE Arduino&lt;br /&gt;
&lt;br /&gt;
===Calendrier prévisionnel===&lt;br /&gt;
&lt;br /&gt;
====Liste des tâches à effectuer====&lt;br /&gt;
Les différentes tâches à effectuer sont :&lt;br /&gt;
*Partie préliminaire : étude de fonctionnement des galvanomètres&lt;br /&gt;
**Déterminer comment est effectuée la commande des galvanomètres (protocole, tension...)&lt;br /&gt;
**Effectuer des tests avec l'Arduino ou la Raspberry Pi&lt;br /&gt;
**Effectuer des tests avec une LED à la place du laser &lt;br /&gt;
*Partie projection&lt;br /&gt;
**Fixer les lasers&lt;br /&gt;
**Aligner les lasers et les galvanomètres&lt;br /&gt;
**Créer le système d'alimentation&lt;br /&gt;
**Création d'un boitier&lt;br /&gt;
*Partie système embarqué&lt;br /&gt;
**Asservissement des galvanomètres avec l'Arduino&lt;br /&gt;
**Système électronique de commande en courant pour les galvanomètres&lt;br /&gt;
*Interface Web&lt;br /&gt;
**Installation et configuration Apache2&lt;br /&gt;
**Création d'une interface graphique simple&lt;br /&gt;
**Implémentation d'algorithmes de traitement d'image&lt;br /&gt;
**Mise en forme avec des CSS&lt;br /&gt;
**Sytème d'authentification avec mot de passe&lt;br /&gt;
**Utilisation d'une base de données pour enregistrer toutes les images déjà utilisés afin de les réutiliser&lt;br /&gt;
*Serveur Web Socket&lt;br /&gt;
**Récupération des données de l'interface web&lt;br /&gt;
**Mise en place de la liaison série avec l'Arduino&lt;br /&gt;
&lt;br /&gt;
====Calendrier====&lt;br /&gt;
Répartition du temps consacré au projet (240h) :&lt;br /&gt;
*Partie projection : 80h&lt;br /&gt;
*Partie système embarqué : 40h&lt;br /&gt;
*Partie interface web et websocket: 120h&lt;br /&gt;
&lt;br /&gt;
==Feuille d'heures==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!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&lt;br /&gt;
|-&lt;br /&gt;
| Définition cahier des charges &lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 14&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|38&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Finalisation du cahier des charges avec les responsables&lt;br /&gt;
&lt;br /&gt;
*Acquisition de matériels :&lt;br /&gt;
**Projecteur Laser&lt;br /&gt;
**Galvanomètres&lt;br /&gt;
**Alimentation des galvanomètres&lt;br /&gt;
&lt;br /&gt;
*Listage du matériels à acquérir :&lt;br /&gt;
**Lunettes de sécurité&lt;br /&gt;
**DAC&lt;br /&gt;
**Alimentation 230V/5V 1A&lt;br /&gt;
** Boitier ABS &lt;br /&gt;
**...&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
*Obtention de l'arduino et de la raspberryPI&lt;br /&gt;
&lt;br /&gt;
*Démontage du projecteur laser&lt;br /&gt;
**Deux lasers de classe 3b (vert et rouge)&lt;br /&gt;
**Circuit d'alimentation des deux lasers&lt;br /&gt;
&lt;br /&gt;
*Initialisation du port série de la raspberryPI&lt;br /&gt;
**Modification du fichier ''config.txt'' dans la partition boot&lt;br /&gt;
**Ajout d'une ligne autorisant la communication série ('''enable_uart=1''')&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
*Installation du serveur apache sur la raspberryPI&lt;br /&gt;
**Modification du fichier ''/etc/network/interfaces'' (Static, Address, Netmask, Gateway)&lt;br /&gt;
**Modification du fichier ''/etc/resolv.conf'' (Adresse du serveur)&lt;br /&gt;
**Utilisation d'un proxy pour la récupération outils de programmation (Apache2, Php5)&lt;br /&gt;
&lt;br /&gt;
*Mise en place du point d’accès wifi de la raspberryPI&lt;br /&gt;
**Récupération des logiciels nécessaires (dnsmasq, hostapd)&lt;br /&gt;
**Mise en place d'une adresse IP statique pour le point d'accès par l'intermédiaire du fichier ''/etc/dhcpcd.conf''&lt;br /&gt;
**Désactivation de la négociation automatique de bail dans le fichier ''/etc/network/interfaces''&lt;br /&gt;
**Configuration du logiciel hostapd ''/etc/hostapd/hostapd.conf''&lt;br /&gt;
**Activation du démarrage automatique du point d'accès ''/etc/default/hostapd''&lt;br /&gt;
**Configuration du serveur DNS par ''/etc/dnsmasq.conf''&lt;br /&gt;
&lt;br /&gt;
*Instauration de la page d'accueil de l'interface web à l'adresse ''192.168.3.1''&lt;br /&gt;
**Téléversement de fichiers images sur la page web et affichage de celle-ci&lt;br /&gt;
**Voyant de confirmation du bon fonctionnement du serveur web&lt;br /&gt;
&lt;br /&gt;
*Développement du serveur websocket&lt;br /&gt;
&lt;br /&gt;
Le développement du serveur websocket, initialement prévu en C (il était prévu de reprendre les sources utilisées l'année précédente dans le cadre des projet IMA3 SC), a finalement été réalisé en JAVA pour plusieurs raisons.&lt;br /&gt;
Premièrement, un seul programme met en œuvre le serveur websocket, les divers traitements d'image, ainsi que les contrôles des galvanomètres (par l'intermédiaire des DAC) via la liaison I²C de la Raspberry Pi. Le langage JAVA fournit nativement des bibliothèques d'objets pour manipuler assez simplement des images, il existe également des librairies pour contrôler le port GPIO de la Raspberry et il était également intéressant de travailler avec un langage de plus haut niveau que le C.&lt;br /&gt;
En outre, la totale portabilité de ce langage nous permet de travailler sur n'importe quelle machine et ensuite transférer notre programme sur la Raspberry Pi et l’exécuter sans même repasser par une phase de compilation. Et finalement, c'est le langage que nous étudions actuellement en cours de programmation orientée objet, ce qui permet de nous perfectionner.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Serveur WebSocket====&lt;br /&gt;
&lt;br /&gt;
N'ayant pas trouvé d'API WebSocket en Java satisfaisante (qui ne nécessitent pas l'installation et la configuration de nombreux outils additionnels), j'ai estimé plus commode et plus formateur de développer notre propre serveur WebSocket en se basant sur les librairies sockets de Java avec l'aide d'une documentation assez exhaustive [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers].&lt;br /&gt;
&lt;br /&gt;
Les WebSockets désignent à la fois un protocole réseau qui étend le protocole TCP ainsi qu'une API du World Wide Web. Nous nous en servons afin d'établir une communication asynchrone et bidirectionnelle entre un navigateur web et le serveur, notamment pour envoyer l'image à projeter. L’implémentation du serveur repose sur plusieurs étapes.&lt;br /&gt;
&lt;br /&gt;
1) Connexion d'un client &lt;br /&gt;
&lt;br /&gt;
2) Handshake : permet de faire le lien entre le protocole HTTP et WS. Le client envoie une requête HTTP demandant un upgrade de la connexion en protocole WS et le serveur répond en configurant la connexion (détail dans la documentation [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers]).&lt;br /&gt;
&lt;br /&gt;
3) Réception et décodage des messages : le serveurs reçoit des trames brutes, on extrait donc la taille du message ainsi que le message. De plus, les données son encodées (cryptage XOR) par un masque qui doit également être extrait.&lt;br /&gt;
&lt;br /&gt;
4) Fermeture de la communication.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le serveur supporte le multi-client il est donc nécessaire qu'il effectue ces étapes en &amp;quot;parallèle&amp;quot;. Nous utilisons donc les threads ou fils d’exécution. Un thread est donc responsable d'attendre qu'un nouveau client se connecte et effectue le &amp;quot;handshake&amp;quot;, il crée ensuite un thread associé à ce client afin d'établir un canal de communication. Il y a donc au moins un thread par client. Par la suite il faudra également implémenter une déconnexion automatique d'un client notamment après un timeout.&lt;br /&gt;
&lt;br /&gt;
Exemple d’exécution du serveur avec deux clients qui se connectent et envoient un message : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testServeur.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Les clients sont des navigateurs web. Pour les tests nous avons repris les exemples utilisés dans le cadre das projets IMA3 SC avec le titre de la page HTML qui se colore en vert lorsque le client est connecté, et un champ de saisie pour envoyer des messages au serveur : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testClient.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 4===&lt;br /&gt;
&lt;br /&gt;
*Mise en place d’algorithmes de traitement d'image&lt;br /&gt;
&lt;br /&gt;
====Détection de contour====&lt;br /&gt;
&lt;br /&gt;
L'objectif de notre projet est de pouvoir projeter n'importe quelle image envoyé grâce à l'application web. Pour cela nous allons tracer à une vitesse élevée les contours de l'image sur par exemple un mur grâce au laser. Il est donc nécessaire de détecter les contours de l'image grâce à plusieurs traitements.&lt;br /&gt;
&lt;br /&gt;
=====Conversion en niveau de gris=====&lt;br /&gt;
&lt;br /&gt;
Une des étapes préliminaires pour effectuer la détection de contour est de convertir l'image couleur en niveau de gris. Pour cela l'algorithme est simple : il suffit pour chaque pixel de l'image d'effectuer la moyenne des composantes rouge, verte, bleu de chaque pixel. En effet, si l'on considère une image matricielle (l'image est considérée comme un tableau à deux dimensions avec chaque case qui contient la couleur du pixel), chaque pixel contient les composantes RGB codées sur un octet. La couleur gris correspond aux composantes RGB égales. Le niveau de gris est donc codé de 0 à 255, avec 0 donnant du noir et 255 du blanc. &lt;br /&gt;
&lt;br /&gt;
Voici le résultat obtenu : [[Fichier:testGrayScale.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Filtre de Prewit et Sobel=====&lt;br /&gt;
&lt;br /&gt;
Un contour est défini par un changement brutal d'intensité lumineuse, il s'agit donc de détecter selon plusieurs directions (au moins 2) ces changements. Il existe de nombreuses techniques afin de détecter les contours d'une image (gradient, Laplacien). L'une des techniques avec un rapport efficacité/temps d'exécution correct repose sur les algorithmes de Prewit ou Sobel. L'algorithme repose sur la convolution de matrices.&lt;br /&gt;
Cela consiste à appliquer sur chaque pixel de l'image la matrice de Prewit définie comme &lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L_x = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; ainsi que sa transposée : &amp;lt;math&amp;gt;&lt;br /&gt;
L_y = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; -1 &amp;amp; -1 \\&lt;br /&gt;
 0 &amp;amp; 0 &amp;amp; 0 \\&lt;br /&gt;
+1 &amp;amp; +1 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Convoluer ces deux filtres sur l'image permet de détecter respectivement les contours verticaux et horizontaux.&lt;br /&gt;
&lt;br /&gt;
D'après wikipedia [https://fr.wikipedia.org/wiki/D%C3%A9tection_de_contours], on obtient de meilleurs résultats en appliquant un filtre triangulaire, on introduit donc la matrice de Sobel :&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-2 &amp;amp; 0 &amp;amp; +2 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
On obtient le résultat suivant : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testOutline1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Pré-traitement : Flou Gaussien=====&lt;br /&gt;
&lt;br /&gt;
Afin de réduire significativement le nombre de contours, il est nécessaire d'effectuer un pré-traitement avant la détection de contours. On utilise généralement un flou gaussien afin de réduire les transitions lumineuses et ainsi réduire le nombre de contours. L’algorithme de flou gaussien repose également sur la convolution de matrices sauf qu'ici la matrice filtre est générée grâce à une fonction gaussienne paramétrée par '''Sigma''' qui va directement impacter le niveau de flou. Plus la matrice de filtrage est grande plus la qualité du résultat est meilleure, mais le temps d’exécution devient également plus grand.&lt;br /&gt;
&lt;br /&gt;
Voici la fonction de génération du filtre : &amp;lt;math&amp;gt;G(x,y) = \frac{1}{{2\pi \sigma^2}} e^{-\frac{x^2 + y^2}{2 \sigma^2}}&amp;lt;/math&amp;gt; où x et y correspondent aux indices de la cellule de la matrice.&lt;br /&gt;
&lt;br /&gt;
On obtient ce résultat :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testGaussianBlur.png]]&lt;br /&gt;
&lt;br /&gt;
On note un bien meilleur résultat. Cependant on remarque que les composantes horizontales ne sont pas correctement détectées il subsiste un problème avec le filtrage vertical que je n'ai pas réussi à identifier. De plus, il s'agit par sa suite d'éliminer les contours parasites ainsi que d'affiner le trait pour n'avoir plus qu'un pixel d'épaisseur.&lt;br /&gt;
&lt;br /&gt;
=====Post-traitement : Algorithme de Canny=====&lt;br /&gt;
&lt;br /&gt;
Afin d'obtenir un résultat exploitable il est nécessaire d'appliquer encore quelques traitements. Pour cela nous utilisons l’algorithme de Canny qui repose que celui de Sobel mais qui ajoute un algorithme de seuillage par hysteresis qui permet de retirer les contours secondaires et de ne garder que les contours connexes dans une seuil haut et un seuil bas définis. En outre, cette algorithme affine également le trait obtenu. Pour cet algorithme nous avons directement trouvé des sources libres de droits [http://www.tomgibara.com/computer-vision/canny-edge-detector] qui donne des résultats très corrects.&lt;br /&gt;
&lt;br /&gt;
Par exemple :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ou encore : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny2.png|1500px]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 5===&lt;br /&gt;
&lt;br /&gt;
*Établissement d'un protocole de transfert d'image basé sur les WebSockets&lt;br /&gt;
**Envoie d'un requête &amp;quot;send&amp;quot; par le client dans une trame websocket texte&lt;br /&gt;
**Réponse serveur 'Y' si aucun autre client tente d'envoyer une image simultanément, 'N' sinon&lt;br /&gt;
**Si et seulement si le client reçoit 'Y' il débute le transfert en envoyant la largeur et la longueur de l'image sur 4 octets, puis les données de l'image soit 4 valeurs pour chaque pixels (r,g,b,alpha)&lt;br /&gt;
**Le serveur renvoie 'D' une fois le transfert achevé (à l'avenir, le serveur renverra l'image après filtrage).&lt;br /&gt;
**A tout moment, le serveur peut renvoyer 'E' si une erreur est survenue (ex : paquets perdus, nombre incorrects de données)&lt;br /&gt;
*Ajout du support des logs au niveau serveur&lt;br /&gt;
**Impression sur la sortie standard des messages&lt;br /&gt;
**Formatage en fonction de la sévérité du log (info, warning, error...)&lt;br /&gt;
**Incrustation de la date et heure&lt;br /&gt;
**Possibilité de redirection dans une fichier, avec configuration (écriture à la suite d'un fichier existant, écrasement...)&lt;br /&gt;
**Le tout dans une classe Java flexible et réutilisable pour d'autres projets&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 6===&lt;br /&gt;
&lt;br /&gt;
*Installation de la librairie Java Pi4j sur la raspberry pi qui permet le contrôle des GPIO de celle-ci et notamment le port I²C (basé sur WiringPi)&lt;br /&gt;
*Amélioration coté serveur websocket&lt;br /&gt;
**Gestion de message plus longs (maximum des trames websockets soit 2^63 octets)&lt;br /&gt;
**Différenciation, à la réception de messages, des trames textes ou binaires des trames de contrôle comme les requête ping, pong ou de fermeture de connexion &lt;br /&gt;
**Ajout d'un mode de debug de trames&lt;br /&gt;
*Interface web&lt;br /&gt;
**Mise en place du code css pour améliorer le rendu visuel de la page&lt;br /&gt;
**Amélioration de l'envoie des données vers le serveur&lt;br /&gt;
&lt;br /&gt;
===Semaine 7===&lt;br /&gt;
&lt;br /&gt;
*Améliorations du serveur WebSocket&lt;br /&gt;
**Gestion de la fragmentation TCP&lt;br /&gt;
**Gestion de la fragmentation WebSocket&lt;br /&gt;
**Gestion des requêtes ping envoyés par le client en renvoyant une trames de contrôle pong afin de maintenir la connexion&lt;br /&gt;
**Gestion des déconnexion de clients afin d'optimiser le serveur&lt;br /&gt;
**Amélioration de l'émission de messages en augmentant la taille maximale pouvant être émise (2^63 octets)&lt;br /&gt;
&lt;br /&gt;
*Amélioration du code css&lt;br /&gt;
*Mise en place d'une partie 'Home' et 'About'&lt;br /&gt;
**Home : Communication avec le serveur web&lt;br /&gt;
**About : Information complémentaire sur la page web&lt;br /&gt;
&lt;br /&gt;
A ce stade du développement, le client et le serveur sont opérationnels et peuvent s'échanger des messages ainsi que des images que le serveur traite pour extraire les contours.&lt;br /&gt;
&lt;br /&gt;
===Semaine 8===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Montage projecteur&lt;br /&gt;
**Intégralité des composants fixés par vis dans le boîtier ABS&lt;br /&gt;
**Fusion des alimentations&lt;br /&gt;
**Présence d'une led témoin de mise en tension&lt;br /&gt;
**Position laser réglable grâce à une vis&lt;br /&gt;
**Présence d'un switch à bascule pour allumer et éteindre le laser&lt;br /&gt;
**Isolation et vérification des composants&lt;br /&gt;
**Tests empiriques de température et de fonctionnement des lasers et galvanomètres&lt;br /&gt;
&lt;br /&gt;
Le montage boîtier est donc terminé et s’alimente en 230V par intermédiaire d'un câble secteur avec connecteur C14. Le résultat s'avère plutôt compact. Les quelques tests de température ont montrés que malgré le manque d'espace la température globale du boîtier ne dépasse pas les 50°C pendant plus d'une heure de fonctionnement. L'intégralité des connexions sont isolées avec de la gaine thermodynamique et les zones &amp;quot;sensibles&amp;quot; sont correctement vérifiés ainsi que protégées avec de la matière isolante.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:proj1.jpg|550px|Boîtier après perçage]] [[Fichier:proj2.jpg|550px|Boîtier finalisé]] [[Fichier:proj3.jpg|550px|Projecteur en fonctionnement]]&lt;br /&gt;
&lt;br /&gt;
*Page web et serveur WebSocket&lt;br /&gt;
**Ajout d'un bouton &amp;quot;reboot&amp;quot; et &amp;quot;shutdown&amp;quot; sur la page web&lt;br /&gt;
***Reboot : Permet le redémarrage de la Raspberry&lt;br /&gt;
***Shutdown : Permet l'extinction de la Raspberry&lt;br /&gt;
**Ajout d'un slider pour le flou gaussien (échelle 1 à 100)&lt;br /&gt;
&lt;br /&gt;
===Semaine 9===&lt;br /&gt;
*Installation du programme 'bind9' permettant de mettre en place un serveur DNS qui permet de remplacer les adresses IP par un nom&lt;br /&gt;
**Problème de configuration (à corriger)&lt;br /&gt;
*Prise en compte du message de retour du serveur&lt;br /&gt;
**Récupération d'un tableau de points représentants les contours de l'image envoyé par le client&lt;br /&gt;
*Mise à jour du slider du flou gaussien&lt;br /&gt;
**Double spider permettant de sélectionner un segment de valeur&lt;br /&gt;
**Echelle comprise entre 0 et 1, pour faciliter la lecture les valeurs sont écrites en pourcent&lt;br /&gt;
&lt;br /&gt;
===Semaine 10===&lt;br /&gt;
[[Fichier:Capture_du_2017-04-12_15-53-15.png|200px|thumb|right|Image envoyée -&amp;gt; Image laser]]&lt;br /&gt;
&lt;br /&gt;
*Récupération d'un ensemble de points envoyés par le serveur permettant de tracer l'image telle que sera projetée par le laser&lt;br /&gt;
**Mise en place du canvas&lt;br /&gt;
**Traçage de l'image par l'intermédiaire de &amp;quot;lineto&amp;quot; puisqu'il s'agit d'un contour&lt;br /&gt;
*Ajout d'une sécurité sur les boutons &amp;quot;reset&amp;quot; et &amp;quot;shutdown&amp;quot;&lt;br /&gt;
**Pop-up de confirmation pour les deux actions&lt;br /&gt;
*Mise à jour du Double slider&lt;br /&gt;
**Redimensionnement&lt;br /&gt;
**Récupération des valeurs&lt;br /&gt;
**Envois des valeurs vers le serveur par un tableau de binaires&lt;br /&gt;
&lt;br /&gt;
===Semaines Supplémentaires===&lt;br /&gt;
&lt;br /&gt;
*Finalisation du code css de la page web&lt;br /&gt;
**Amélioration visuelle&lt;br /&gt;
**Rendu dynamique de la page&lt;br /&gt;
[[Fichier:Page_accueil.png|396px|Page d’accueil]]&lt;br /&gt;
[[Fichier:Page2.png|396px|Image chargée]]&lt;br /&gt;
[[Fichier:Page3.png|396px|Contours récupérés]]&lt;br /&gt;
&lt;br /&gt;
==A faire==&lt;br /&gt;
&lt;br /&gt;
MAJ 19 Avril&lt;br /&gt;
&lt;br /&gt;
*Client websocket et page web&lt;br /&gt;
**Ajout slider pour de finir amplitude de la projection&lt;br /&gt;
**Ajout message de confirmation quand le serveur quitte ou relance&lt;br /&gt;
**Ajout boutons &amp;quot;projeter&amp;quot; &amp;quot;centrer&amp;quot; &amp;quot;etendre&amp;quot;&lt;br /&gt;
**Redimensionnement automatique de l'image !!&lt;br /&gt;
**Gestion de plusieurs images avec délai&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Serveur WebSocket&lt;br /&gt;
**Ajout fonctionnalité envoi image de prévisualisation&lt;br /&gt;
&lt;br /&gt;
*RaspberryPi&lt;br /&gt;
**Utilisation d'un serveur bind9 pour éviter de taper IP&lt;br /&gt;
&lt;br /&gt;
*Détection de contours&lt;br /&gt;
**Implémentation algorithme de tri de la plus courte disance&lt;br /&gt;
&lt;br /&gt;
*Commande galvanomêtre&lt;br /&gt;
**Utilisation API I²C&lt;br /&gt;
**Fonction de transfert position-&amp;gt;angle-&amp;gt;tension&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;br /&gt;
&lt;br /&gt;
[[Media:CptProjetIMA4.pdf‎ |Compte-rendu Projet]]&lt;br /&gt;
&lt;br /&gt;
==Bibliographie==&lt;br /&gt;
&lt;br /&gt;
*Galvanomètres et laser&lt;br /&gt;
http://www.ebay.com/itm/20KPPS-30KPPS-laser-scanning-galvo-scanner-ILDA-Closed-Loop-max-30kpps-for-laser-/261517002270?hash=item3ce3a0c61e&lt;br /&gt;
&lt;br /&gt;
http://sciences.ulb.ac.be/printemps/download/2016/dossier_pedagogique/02.pdf&lt;br /&gt;
&lt;br /&gt;
*Websocket&lt;br /&gt;
http://stackoverflow.com/questions/8125507/how-can-i-send-and-receive-websocket-messages-on-the-server-side&lt;br /&gt;
&lt;br /&gt;
https://tools.ietf.org/html/rfc6455&lt;br /&gt;
&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_a_WebSocket_server_in_Java&lt;br /&gt;
&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers&lt;br /&gt;
&lt;br /&gt;
*Traitement d'image&lt;br /&gt;
https://en.wikipedia.org/wiki/Gaussian_blur&lt;br /&gt;
&lt;br /&gt;
http://www.zebulon.fr/questions-reponses/traitement-d-image-detection-de-contours-55.html&lt;br /&gt;
&lt;br /&gt;
http://patrick-bonnin.developpez.com/cours/vision/apprendre-bases-traitement-image/partie-5-segmentation-contour/&lt;br /&gt;
&lt;br /&gt;
http://www.isir.upmc.fr/UserFiles/File/clady_homepage/EPU/2-Contour&lt;br /&gt;
&lt;br /&gt;
*Autre&lt;br /&gt;
https://icn.fenelonlille.org/mediawiki/index.php/Projet_ICN_commun_2016/2017&lt;br /&gt;
&lt;br /&gt;
https://www.g33k-zone.org/post/2016/05/11/Configurer-le-Raspberry-Pi-en-point-d-acc%C3%A8s-Wifi&lt;br /&gt;
&lt;br /&gt;
https://blogs.oracle.com/acaicedo/resource/Parallax-I2C/Sensors.java&lt;br /&gt;
&lt;br /&gt;
http://stackoverflow.com/questions/22087076/how-to-make-a-simple-image-upload-using-javascript-html&lt;/div&gt;</summary>
		<author><name>Mtrimbur</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=42156</id>
		<title>IMA4 2016/2017 P39</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=42156"/>
				<updated>2017-05-12T12:34:20Z</updated>
		
		<summary type="html">&lt;p&gt;Mtrimbur : /* Fichiers Rendus */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
===Contexte===&lt;br /&gt;
&lt;br /&gt;
Le laser est une technologie largement utilisé de nos jours dans de diverses applications. En effet, on retrouve cette technologie dans le domaine médical notamment pour la chirurgie oculaire ou encore dans industrie avec la découpe laser ou la soudure au laser.&lt;br /&gt;
&lt;br /&gt;
Le laser est une émission de photons produit par excitation d'un milieu amplificateur (ex : CO2), le rayonnement produit est unidirectionnel et monochromatique. Ce sont ces propriétés que nous allons exploiter afin réaliser un projecteur laser qui mis en mouvement est capable de dessiner des formes sur une surface à l'instar de systèmes existants utilisés pour des effets lumineux lors de festivités.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
L'objectif du projet est de créer un système de projection laser à plusieurs couleurs (au minimum deux) avec une application web pour programmer les formes à dessiner afin d'agrémenter des compétitions de gymnastique rythmique.&lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
Le projet consiste à réaliser avec des lasers des figures géométriques par l'intermédiaire d'un système galvanométrique. &lt;br /&gt;
&lt;br /&gt;
Notre premier travail sera de concevoir la partie projection. Pour cela, nous devrons aligner les lasers et les galvanomètres. En effet, ces derniers posséderont des miroirs à l'extrémité, ainsi les miroirs changeront d'inclinaison suivant le courant traversant les galvanomètres (similaire à l'image ci-contre). Il nous faudra également créer un système d'alimentation qui à partir d'une même source (réseau 230 V) sera capable d'alimenter les lasers et les galvanomètres ainsi qu'une Arduino et une Raspberry Pi.&lt;br /&gt;
[[File:Scanhead.jpeg|thumb]]&lt;br /&gt;
&lt;br /&gt;
Ensuite nous nous intéresserons à l'utilisation d'un système embarqué pour contrôler les galvanomètres et donc dessiner avec les lasers sur un plan 2D. En effet, le laser restera toujours fixe, seuls les galvanomètres, et donc les miroirs bougeront. Les galvanomètres étant contrôlés en courant il faudra réaliser une interface électronique pour convertir une commande en tension en commande de courant. La commande en tension sera assuré par une carte Arduino. Nous n'utiliserons qu'une seule paire de galvanomètres pour les deux laser. Il faudra donc multiplexer les deux faisceaux. La programmation des formes à effectuer, se fera par l'intermédiaire d'une application web PHP hébergée sur une RaspberryPi qui permettra de récupérer une image, d'y appliquer divers traitements et filtres afin d'en extraire les contours, et de calculer les commandes pour positionner les galvanomètres. Un serveur WebSocket également hébergé sur la RaspberryPi servira d'interface entre l'application web et L'arduino qui sera connecté via une liaison série sur la raspberryPI.&lt;br /&gt;
&lt;br /&gt;
Comme animation de test, nous dessinerons le contour d'une gymnaste avec une couleur et son ballon d'une autre couleur. La gymnaste devra lancer son ballon, réaliser quelques difficultés et récupérer son ballon.&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
Nous utiliserons comme matériels :&lt;br /&gt;
*Deux lasers de différentes couleurs&lt;br /&gt;
*Une paire de galvanomètres à miroir&lt;br /&gt;
*Arduino&lt;br /&gt;
*Raspberry Pi3&lt;br /&gt;
*Alimentation 230V/5V 1A [http://www.miniinthebox.com/fr/dual-usb-eu-prise-murale-5v-2a-voyage-adaptateur-chargeur-d-alimentation-pour-iphone7-6-xiaomi-samsung-et-autre-telephone-portable_p5410410.html?currency=EUR&amp;amp;litb_from=paid_adwords_shopping&amp;amp;sku=429_6917%7C752_20648&amp;amp;utm_source=google_shopping&amp;amp;utm_medium=cpc&amp;amp;adword_mt=&amp;amp;adword_ct=138705676724&amp;amp;adword_kw=&amp;amp;adword_pos=1o5&amp;amp;adword_pl=&amp;amp;adword_net=g&amp;amp;adword_tar=&amp;amp;adw_src_id=9653316068_661261352_33588296076_aud-79897721311:pla-256966386459&amp;amp;gclid=Cj0KEQiA_KvEBRCtzNil4-KR-LIBEiQAmgekFxxKjJJWBYCJlDZEa3Ke_2_WR0DzGVbz-jaCZHVIBoMaAvld8P8HAQ]&lt;br /&gt;
*Drivers galvanomètres x2&lt;br /&gt;
*Alimentation laser&lt;br /&gt;
*Lunette de sécurité x2 [https://www.amazon.fr/Uvex-S1933X-Eyewear-SCTOrange-Anti-Fog/dp/B000USRG90/ref=sr_1_1?ie=UTF8&amp;amp;qid=1485441383&amp;amp;sr=8-1&amp;amp;keywords=uvex+s1933x]&lt;br /&gt;
*Boitier ABS [http://fr.farnell.com/multicomp/g3118/boitier-abs-240x120x60mm-ip65/dp/1526656]&lt;br /&gt;
*DAC 4 canaux, avec interface I²C [https://www.adafruit.com/products/1083]&lt;br /&gt;
*Connecteur C14 [http://www.conrad.fr/ce/fr/product/715001/Connecteur-secteur-C14-Embase-male-verticale-715001-Nombre-de-poles-2-PE-10-A-noir-1-pcs/?ref=detview1&amp;amp;rt=detview1&amp;amp;rb=1]&lt;br /&gt;
*Câble secteur&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Logiciel :&lt;br /&gt;
&lt;br /&gt;
*Serveur web : Apache2, HTML5, PHP5, CSS&lt;br /&gt;
*Base de donnée : MySQL&lt;br /&gt;
*Serveur WebSocket : JQuerry, websocket&lt;br /&gt;
*Arduino : IDE Arduino&lt;br /&gt;
&lt;br /&gt;
===Calendrier prévisionnel===&lt;br /&gt;
&lt;br /&gt;
====Liste des tâches à effectuer====&lt;br /&gt;
Les différentes tâches à effectuer sont :&lt;br /&gt;
*Partie préliminaire : étude de fonctionnement des galvanomètres&lt;br /&gt;
**Déterminer comment est effectuée la commande des galvanomètres (protocole, tension...)&lt;br /&gt;
**Effectuer des tests avec l'Arduino ou la Raspberry Pi&lt;br /&gt;
**Effectuer des tests avec une LED à la place du laser &lt;br /&gt;
*Partie projection&lt;br /&gt;
**Fixer les lasers&lt;br /&gt;
**Aligner les lasers et les galvanomètres&lt;br /&gt;
**Créer le système d'alimentation&lt;br /&gt;
**Création d'un boitier&lt;br /&gt;
*Partie système embarqué&lt;br /&gt;
**Asservissement des galvanomètres avec l'Arduino&lt;br /&gt;
**Système électronique de commande en courant pour les galvanomètres&lt;br /&gt;
*Interface Web&lt;br /&gt;
**Installation et configuration Apache2&lt;br /&gt;
**Création d'une interface graphique simple&lt;br /&gt;
**Implémentation d'algorithmes de traitement d'image&lt;br /&gt;
**Mise en forme avec des CSS&lt;br /&gt;
**Sytème d'authentification avec mot de passe&lt;br /&gt;
**Utilisation d'une base de données pour enregistrer toutes les images déjà utilisés afin de les réutiliser&lt;br /&gt;
*Serveur Web Socket&lt;br /&gt;
**Récupération des données de l'interface web&lt;br /&gt;
**Mise en place de la liaison série avec l'Arduino&lt;br /&gt;
&lt;br /&gt;
====Calendrier====&lt;br /&gt;
Répartition du temps consacré au projet (240h) :&lt;br /&gt;
*Partie projection : 80h&lt;br /&gt;
*Partie système embarqué : 40h&lt;br /&gt;
*Partie interface web et websocket: 120h&lt;br /&gt;
&lt;br /&gt;
==Feuille d'heures==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!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&lt;br /&gt;
|-&lt;br /&gt;
| Définition cahier des charges &lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 14&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|38&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Finalisation du cahier des charges avec les responsables&lt;br /&gt;
&lt;br /&gt;
*Acquisition de matériels :&lt;br /&gt;
**Projecteur Laser&lt;br /&gt;
**Galvanomètres&lt;br /&gt;
**Alimentation des galvanomètres&lt;br /&gt;
&lt;br /&gt;
*Listage du matériels à acquérir :&lt;br /&gt;
**Lunettes de sécurité&lt;br /&gt;
**DAC&lt;br /&gt;
**Alimentation 230V/5V 1A&lt;br /&gt;
** Boitier ABS &lt;br /&gt;
**...&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
*Obtention de l'arduino et de la raspberryPI&lt;br /&gt;
&lt;br /&gt;
*Démontage du projecteur laser&lt;br /&gt;
**Deux lasers de classe 3b (vert et rouge)&lt;br /&gt;
**Circuit d'alimentation des deux lasers&lt;br /&gt;
&lt;br /&gt;
*Initialisation du port série de la raspberryPI&lt;br /&gt;
**Modification du fichier ''config.txt'' dans la partition boot&lt;br /&gt;
**Ajout d'une ligne autorisant la communication série ('''enable_uart=1''')&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
*Installation du serveur apache sur la raspberryPI&lt;br /&gt;
**Modification du fichier ''/etc/network/interfaces'' (Static, Address, Netmask, Gateway)&lt;br /&gt;
**Modification du fichier ''/etc/resolv.conf'' (Adresse du serveur)&lt;br /&gt;
**Utilisation d'un proxy pour la récupération outils de programmation (Apache2, Php5)&lt;br /&gt;
&lt;br /&gt;
*Mise en place du point d’accès wifi de la raspberryPI&lt;br /&gt;
**Récupération des logiciels nécessaires (dnsmasq, hostapd)&lt;br /&gt;
**Mise en place d'une adresse IP statique pour le point d'accès par l'intermédiaire du fichier ''/etc/dhcpcd.conf''&lt;br /&gt;
**Désactivation de la négociation automatique de bail dans le fichier ''/etc/network/interfaces''&lt;br /&gt;
**Configuration du logiciel hostapd ''/etc/hostapd/hostapd.conf''&lt;br /&gt;
**Activation du démarrage automatique du point d'accès ''/etc/default/hostapd''&lt;br /&gt;
**Configuration du serveur DNS par ''/etc/dnsmasq.conf''&lt;br /&gt;
&lt;br /&gt;
*Instauration de la page d'accueil de l'interface web à l'adresse ''192.168.3.1''&lt;br /&gt;
**Téléversement de fichiers images sur la page web et affichage de celle-ci&lt;br /&gt;
**Voyant de confirmation du bon fonctionnement du serveur web&lt;br /&gt;
&lt;br /&gt;
*Développement du serveur websocket&lt;br /&gt;
&lt;br /&gt;
Le développement du serveur websocket, initialement prévu en C (il était prévu de reprendre les sources utilisées l'année précédente dans le cadre des projet IMA3 SC), a finalement été réalisé en JAVA pour plusieurs raisons.&lt;br /&gt;
Premièrement, un seul programme met en œuvre le serveur websocket, les divers traitements d'image, ainsi que les contrôles des galvanomètres (par l'intermédiaire des DAC) via la liaison I²C de la Raspberry Pi. Le langage JAVA fournit nativement des bibliothèques d'objets pour manipuler assez simplement des images, il existe également des librairies pour contrôler le port GPIO de la Raspberry et il était également intéressant de travailler avec un langage de plus haut niveau que le C.&lt;br /&gt;
En outre, la totale portabilité de ce langage nous permet de travailler sur n'importe quelle machine et ensuite transférer notre programme sur la Raspberry Pi et l’exécuter sans même repasser par une phase de compilation. Et finalement, c'est le langage que nous étudions actuellement en cours de programmation orientée objet, ce qui permet de nous perfectionner.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Serveur WebSocket====&lt;br /&gt;
&lt;br /&gt;
N'ayant pas trouvé d'API WebSocket en Java satisfaisante (qui ne nécessitent pas l'installation et la configuration de nombreux outils additionnels), j'ai estimé plus commode et plus formateur de développer notre propre serveur WebSocket en se basant sur les librairies sockets de Java avec l'aide d'une documentation assez exhaustive [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers].&lt;br /&gt;
&lt;br /&gt;
Les WebSockets désignent à la fois un protocole réseau qui étend le protocole TCP ainsi qu'une API du World Wide Web. Nous nous en servons afin d'établir une communication asynchrone et bidirectionnelle entre un navigateur web et le serveur, notamment pour envoyer l'image à projeter. L’implémentation du serveur repose sur plusieurs étapes.&lt;br /&gt;
&lt;br /&gt;
1) Connexion d'un client &lt;br /&gt;
&lt;br /&gt;
2) Handshake : permet de faire le lien entre le protocole HTTP et WS. Le client envoie une requête HTTP demandant un upgrade de la connexion en protocole WS et le serveur répond en configurant la connexion (détail dans la documentation [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers]).&lt;br /&gt;
&lt;br /&gt;
3) Réception et décodage des messages : le serveurs reçoit des trames brutes, on extrait donc la taille du message ainsi que le message. De plus, les données son encodées (cryptage XOR) par un masque qui doit également être extrait.&lt;br /&gt;
&lt;br /&gt;
4) Fermeture de la communication.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le serveur supporte le multi-client il est donc nécessaire qu'il effectue ces étapes en &amp;quot;parallèle&amp;quot;. Nous utilisons donc les threads ou fils d’exécution. Un thread est donc responsable d'attendre qu'un nouveau client se connecte et effectue le &amp;quot;handshake&amp;quot;, il crée ensuite un thread associé à ce client afin d'établir un canal de communication. Il y a donc au moins un thread par client. Par la suite il faudra également implémenter une déconnexion automatique d'un client notamment après un timeout.&lt;br /&gt;
&lt;br /&gt;
Exemple d’exécution du serveur avec deux clients qui se connectent et envoient un message : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testServeur.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Les clients sont des navigateurs web. Pour les tests nous avons repris les exemples utilisés dans le cadre das projets IMA3 SC avec le titre de la page HTML qui se colore en vert lorsque le client est connecté, et un champ de saisie pour envoyer des messages au serveur : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testClient.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 4===&lt;br /&gt;
&lt;br /&gt;
*Mise en place d’algorithmes de traitement d'image&lt;br /&gt;
&lt;br /&gt;
====Détection de contour====&lt;br /&gt;
&lt;br /&gt;
L'objectif de notre projet est de pouvoir projeter n'importe quelle image envoyé grâce à l'application web. Pour cela nous allons tracer à une vitesse élevée les contours de l'image sur par exemple un mur grâce au laser. Il est donc nécessaire de détecter les contours de l'image grâce à plusieurs traitements.&lt;br /&gt;
&lt;br /&gt;
=====Conversion en niveau de gris=====&lt;br /&gt;
&lt;br /&gt;
Une des étapes préliminaires pour effectuer la détection de contour est de convertir l'image couleur en niveau de gris. Pour cela l'algorithme est simple : il suffit pour chaque pixel de l'image d'effectuer la moyenne des composantes rouge, verte, bleu de chaque pixel. En effet, si l'on considère une image matricielle (l'image est considérée comme un tableau à deux dimensions avec chaque case qui contient la couleur du pixel), chaque pixel contient les composantes RGB codées sur un octet. La couleur gris correspond aux composantes RGB égales. Le niveau de gris est donc codé de 0 à 255, avec 0 donnant du noir et 255 du blanc. &lt;br /&gt;
&lt;br /&gt;
Voici le résultat obtenu : [[Fichier:testGrayScale.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Filtre de Prewit et Sobel=====&lt;br /&gt;
&lt;br /&gt;
Un contour est défini par un changement brutal d'intensité lumineuse, il s'agit donc de détecter selon plusieurs directions (au moins 2) ces changements. Il existe de nombreuses techniques afin de détecter les contours d'une image (gradient, Laplacien). L'une des techniques avec un rapport efficacité/temps d'exécution correct repose sur les algorithmes de Prewit ou Sobel. L'algorithme repose sur la convolution de matrices.&lt;br /&gt;
Cela consiste à appliquer sur chaque pixel de l'image la matrice de Prewit définie comme &lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L_x = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; ainsi que sa transposée : &amp;lt;math&amp;gt;&lt;br /&gt;
L_y = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; -1 &amp;amp; -1 \\&lt;br /&gt;
 0 &amp;amp; 0 &amp;amp; 0 \\&lt;br /&gt;
+1 &amp;amp; +1 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Convoluer ces deux filtres sur l'image permet de détecter respectivement les contours verticaux et horizontaux.&lt;br /&gt;
&lt;br /&gt;
D'après wikipedia [https://fr.wikipedia.org/wiki/D%C3%A9tection_de_contours], on obtient de meilleurs résultats en appliquant un filtre triangulaire, on introduit donc la matrice de Sobel :&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-2 &amp;amp; 0 &amp;amp; +2 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
On obtient le résultat suivant : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testOutline1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Pré-traitement : Flou Gaussien=====&lt;br /&gt;
&lt;br /&gt;
Afin de réduire significativement le nombre de contours, il est nécessaire d'effectuer un pré-traitement avant la détection de contours. On utilise généralement un flou gaussien afin de réduire les transitions lumineuses et ainsi réduire le nombre de contours. L’algorithme de flou gaussien repose également sur la convolution de matrices sauf qu'ici la matrice filtre est générée grâce à une fonction gaussienne paramétrée par '''Sigma''' qui va directement impacter le niveau de flou. Plus la matrice de filtrage est grande plus la qualité du résultat est meilleure, mais le temps d’exécution devient également plus grand.&lt;br /&gt;
&lt;br /&gt;
Voici la fonction de génération du filtre : &amp;lt;math&amp;gt;G(x,y) = \frac{1}{{2\pi \sigma^2}} e^{-\frac{x^2 + y^2}{2 \sigma^2}}&amp;lt;/math&amp;gt; où x et y correspondent aux indices de la cellule de la matrice.&lt;br /&gt;
&lt;br /&gt;
On obtient ce résultat :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testGaussianBlur.png]]&lt;br /&gt;
&lt;br /&gt;
On note un bien meilleur résultat. Cependant on remarque que les composantes horizontales ne sont pas correctement détectées il subsiste un problème avec le filtrage vertical que je n'ai pas réussi à identifier. De plus, il s'agit par sa suite d'éliminer les contours parasites ainsi que d'affiner le trait pour n'avoir plus qu'un pixel d'épaisseur.&lt;br /&gt;
&lt;br /&gt;
=====Post-traitement : Algorithme de Canny=====&lt;br /&gt;
&lt;br /&gt;
Afin d'obtenir un résultat exploitable il est nécessaire d'appliquer encore quelques traitements. Pour cela nous utilisons l’algorithme de Canny qui repose que celui de Sobel mais qui ajoute un algorithme de seuillage par hysteresis qui permet de retirer les contours secondaires et de ne garder que les contours connexes dans une seuil haut et un seuil bas définis. En outre, cette algorithme affine également le trait obtenu. Pour cet algorithme nous avons directement trouvé des sources libres de droits [http://www.tomgibara.com/computer-vision/canny-edge-detector] qui donne des résultats très corrects.&lt;br /&gt;
&lt;br /&gt;
Par exemple :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ou encore : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny2.png|1500px]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 5===&lt;br /&gt;
&lt;br /&gt;
*Établissement d'un protocole de transfert d'image basé sur les WebSockets&lt;br /&gt;
**Envoie d'un requête &amp;quot;send&amp;quot; par le client dans une trame websocket texte&lt;br /&gt;
**Réponse serveur 'Y' si aucun autre client tente d'envoyer une image simultanément, 'N' sinon&lt;br /&gt;
**Si et seulement si le client reçoit 'Y' il débute le transfert en envoyant la largeur et la longueur de l'image sur 4 octets, puis les données de l'image soit 4 valeurs pour chaque pixels (r,g,b,alpha)&lt;br /&gt;
**Le serveur renvoie 'D' une fois le transfert achevé (à l'avenir, le serveur renverra l'image après filtrage).&lt;br /&gt;
**A tout moment, le serveur peut renvoyer 'E' si une erreur est survenue (ex : paquets perdus, nombre incorrects de données)&lt;br /&gt;
*Ajout du support des logs au niveau serveur&lt;br /&gt;
**Impression sur la sortie standard des messages&lt;br /&gt;
**Formatage en fonction de la sévérité du log (info, warning, error...)&lt;br /&gt;
**Incrustation de la date et heure&lt;br /&gt;
**Possibilité de redirection dans une fichier, avec configuration (écriture à la suite d'un fichier existant, écrasement...)&lt;br /&gt;
**Le tout dans une classe Java flexible et réutilisable pour d'autres projets&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 6===&lt;br /&gt;
&lt;br /&gt;
*Installation de la librairie Java Pi4j sur la raspberry pi qui permet le contrôle des GPIO de celle-ci et notamment le port I²C (basé sur WiringPi)&lt;br /&gt;
*Amélioration coté serveur websocket&lt;br /&gt;
**Gestion de message plus longs (maximum des trames websockets soit 2^63 octets)&lt;br /&gt;
**Différenciation, à la réception de messages, des trames textes ou binaires des trames de contrôle comme les requête ping, pong ou de fermeture de connexion &lt;br /&gt;
**Ajout d'un mode de debug de trames&lt;br /&gt;
*Interface web&lt;br /&gt;
**Mise en place du code css pour améliorer le rendu visuel de la page&lt;br /&gt;
**Amélioration de l'envoie des données vers le serveur&lt;br /&gt;
&lt;br /&gt;
===Semaine 7===&lt;br /&gt;
&lt;br /&gt;
*Améliorations du serveur WebSocket&lt;br /&gt;
**Gestion de la fragmentation TCP&lt;br /&gt;
**Gestion de la fragmentation WebSocket&lt;br /&gt;
**Gestion des requêtes ping envoyés par le client en renvoyant une trames de contrôle pong afin de maintenir la connexion&lt;br /&gt;
**Gestion des déconnexion de clients afin d'optimiser le serveur&lt;br /&gt;
**Amélioration de l'émission de messages en augmentant la taille maximale pouvant être émise (2^63 octets)&lt;br /&gt;
&lt;br /&gt;
*Amélioration du code css&lt;br /&gt;
*Mise en place d'une partie 'Home' et 'About'&lt;br /&gt;
**Home : Communication avec le serveur web&lt;br /&gt;
**About : Information complémentaire sur la page web&lt;br /&gt;
&lt;br /&gt;
A ce stade du développement, le client et le serveur sont opérationnels et peuvent s'échanger des messages ainsi que des images que le serveur traite pour extraire les contours.&lt;br /&gt;
&lt;br /&gt;
===Semaine 8===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Montage projecteur&lt;br /&gt;
**Intégralité des composants fixés par vis dans le boîtier ABS&lt;br /&gt;
**Fusion des alimentations&lt;br /&gt;
**Présence d'une led témoin de mise en tension&lt;br /&gt;
**Position laser réglable grâce à une vis&lt;br /&gt;
**Présence d'un switch à bascule pour allumer et éteindre le laser&lt;br /&gt;
**Isolation et vérification des composants&lt;br /&gt;
**Tests empiriques de température et de fonctionnement des lasers et galvanomètres&lt;br /&gt;
&lt;br /&gt;
Le montage boîtier est donc terminé et s’alimente en 230V par intermédiaire d'un câble secteur avec connecteur C14. Le résultat s'avère plutôt compact. Les quelques tests de température ont montrés que malgré le manque d'espace la température globale du boîtier ne dépasse pas les 50°C pendant plus d'une heure de fonctionnement. L'intégralité des connexions sont isolées avec de la gaine thermodynamique et les zones &amp;quot;sensibles&amp;quot; sont correctement vérifiés ainsi que protégées avec de la matière isolante.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:proj1.jpg|550px|Boîtier après perçage]] [[Fichier:proj2.jpg|550px|Boîtier finalisé]] [[Fichier:proj3.jpg|550px|Projecteur en fonctionnement]]&lt;br /&gt;
&lt;br /&gt;
*Page web et serveur WebSocket&lt;br /&gt;
**Ajout d'un bouton &amp;quot;reboot&amp;quot; et &amp;quot;shutdown&amp;quot; sur la page web&lt;br /&gt;
***Reboot : Permet le redémarrage de la Raspberry&lt;br /&gt;
***Shutdown : Permet l'extinction de la Raspberry&lt;br /&gt;
**Ajout d'un slider pour le flou gaussien (échelle 1 à 100)&lt;br /&gt;
&lt;br /&gt;
===Semaine 9===&lt;br /&gt;
*Installation du programme 'bind9' permettant de mettre en place un serveur DNS qui permet de remplacer les adresses IP par un nom&lt;br /&gt;
**Problème de configuration (à corriger)&lt;br /&gt;
*Prise en compte du message de retour du serveur&lt;br /&gt;
**Récupération d'un tableau de points représentants les contours de l'image envoyé par le client&lt;br /&gt;
*Mise à jour du slider du flou gaussien&lt;br /&gt;
**Double spider permettant de sélectionner un segment de valeur&lt;br /&gt;
**Echelle comprise entre 0 et 1, pour faciliter la lecture les valeurs sont écrites en pourcent&lt;br /&gt;
&lt;br /&gt;
===Semaine 10===&lt;br /&gt;
[[Fichier:Capture_du_2017-04-12_15-53-15.png|200px|thumb|right|Image envoyée -&amp;gt; Image laser]]&lt;br /&gt;
&lt;br /&gt;
*Récupération d'un ensemble de points envoyés par le serveur permettant de tracer l'image telle que sera projetée par le laser&lt;br /&gt;
**Mise en place du canvas&lt;br /&gt;
**Traçage de l'image par l'intermédiaire de &amp;quot;lineto&amp;quot; puisqu'il s'agit d'un contour&lt;br /&gt;
*Ajout d'une sécurité sur les boutons &amp;quot;reset&amp;quot; et &amp;quot;shutdown&amp;quot;&lt;br /&gt;
**Pop-up de confirmation pour les deux actions&lt;br /&gt;
*Mise à jour du Double slider&lt;br /&gt;
**Redimensionnement&lt;br /&gt;
**Récupération des valeurs&lt;br /&gt;
**Envois des valeurs vers le serveur par un tableau de binaires&lt;br /&gt;
&lt;br /&gt;
===Semaines Supplémentaires===&lt;br /&gt;
&lt;br /&gt;
*Finalisation du code css de la page web&lt;br /&gt;
**Amélioration visuelle&lt;br /&gt;
**Rendu dynamique de la page&lt;br /&gt;
[[Fichier:Page_accueil.png|396px|Page d’accueil]]&lt;br /&gt;
[[Fichier:Page2.png|396px|Image chargée]]&lt;br /&gt;
[[Fichier:Page3.png|396px|Contours récupérés]]&lt;br /&gt;
&lt;br /&gt;
==A faire==&lt;br /&gt;
&lt;br /&gt;
MAJ 19 Avril&lt;br /&gt;
&lt;br /&gt;
*Client websocket et page web&lt;br /&gt;
**Ajout slider pour de finir amplitude de la projection&lt;br /&gt;
**Ajout message de confirmation quand le serveur quitte ou relance&lt;br /&gt;
**Ajout boutons &amp;quot;projeter&amp;quot; &amp;quot;centrer&amp;quot; &amp;quot;etendre&amp;quot;&lt;br /&gt;
**Redimensionnement automatique de l'image !!&lt;br /&gt;
**Gestion de plusieurs images avec délai&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Serveur WebSocket&lt;br /&gt;
**Ajout fonctionnalité envoi image de prévisualisation&lt;br /&gt;
&lt;br /&gt;
*RaspberryPi&lt;br /&gt;
**Utilisation d'un serveur bind9 pour éviter de taper IP&lt;br /&gt;
&lt;br /&gt;
*Détection de contours&lt;br /&gt;
**Implémentation algorithme de tri de la plus courte disance&lt;br /&gt;
&lt;br /&gt;
*Commande galvanomêtre&lt;br /&gt;
**Utilisation API I²C&lt;br /&gt;
**Fonction de transfert position-&amp;gt;angle-&amp;gt;tension&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Compte-rendu_TOMBAZZI_TRIMBUR]]&lt;br /&gt;
&lt;br /&gt;
==Bibliographie==&lt;br /&gt;
&lt;br /&gt;
*Galvanomètres et laser&lt;br /&gt;
http://www.ebay.com/itm/20KPPS-30KPPS-laser-scanning-galvo-scanner-ILDA-Closed-Loop-max-30kpps-for-laser-/261517002270?hash=item3ce3a0c61e&lt;br /&gt;
&lt;br /&gt;
http://sciences.ulb.ac.be/printemps/download/2016/dossier_pedagogique/02.pdf&lt;br /&gt;
&lt;br /&gt;
*Websocket&lt;br /&gt;
http://stackoverflow.com/questions/8125507/how-can-i-send-and-receive-websocket-messages-on-the-server-side&lt;br /&gt;
&lt;br /&gt;
https://tools.ietf.org/html/rfc6455&lt;br /&gt;
&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_a_WebSocket_server_in_Java&lt;br /&gt;
&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers&lt;br /&gt;
&lt;br /&gt;
*Traitement d'image&lt;br /&gt;
https://en.wikipedia.org/wiki/Gaussian_blur&lt;br /&gt;
&lt;br /&gt;
http://www.zebulon.fr/questions-reponses/traitement-d-image-detection-de-contours-55.html&lt;br /&gt;
&lt;br /&gt;
http://patrick-bonnin.developpez.com/cours/vision/apprendre-bases-traitement-image/partie-5-segmentation-contour/&lt;br /&gt;
&lt;br /&gt;
http://www.isir.upmc.fr/UserFiles/File/clady_homepage/EPU/2-Contour&lt;br /&gt;
&lt;br /&gt;
*Autre&lt;br /&gt;
https://icn.fenelonlille.org/mediawiki/index.php/Projet_ICN_commun_2016/2017&lt;br /&gt;
&lt;br /&gt;
https://www.g33k-zone.org/post/2016/05/11/Configurer-le-Raspberry-Pi-en-point-d-acc%C3%A8s-Wifi&lt;br /&gt;
&lt;br /&gt;
https://blogs.oracle.com/acaicedo/resource/Parallax-I2C/Sensors.java&lt;br /&gt;
&lt;br /&gt;
http://stackoverflow.com/questions/22087076/how-to-make-a-simple-image-upload-using-javascript-html&lt;br /&gt;
&lt;br /&gt;
export http_proxy=http://proxy.polytech-lille.fr:3128&lt;/div&gt;</summary>
		<author><name>Mtrimbur</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=42155</id>
		<title>IMA4 2016/2017 P39</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=42155"/>
				<updated>2017-05-12T12:33:49Z</updated>
		
		<summary type="html">&lt;p&gt;Mtrimbur : /* Fichiers Rendus */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
===Contexte===&lt;br /&gt;
&lt;br /&gt;
Le laser est une technologie largement utilisé de nos jours dans de diverses applications. En effet, on retrouve cette technologie dans le domaine médical notamment pour la chirurgie oculaire ou encore dans industrie avec la découpe laser ou la soudure au laser.&lt;br /&gt;
&lt;br /&gt;
Le laser est une émission de photons produit par excitation d'un milieu amplificateur (ex : CO2), le rayonnement produit est unidirectionnel et monochromatique. Ce sont ces propriétés que nous allons exploiter afin réaliser un projecteur laser qui mis en mouvement est capable de dessiner des formes sur une surface à l'instar de systèmes existants utilisés pour des effets lumineux lors de festivités.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
L'objectif du projet est de créer un système de projection laser à plusieurs couleurs (au minimum deux) avec une application web pour programmer les formes à dessiner afin d'agrémenter des compétitions de gymnastique rythmique.&lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
Le projet consiste à réaliser avec des lasers des figures géométriques par l'intermédiaire d'un système galvanométrique. &lt;br /&gt;
&lt;br /&gt;
Notre premier travail sera de concevoir la partie projection. Pour cela, nous devrons aligner les lasers et les galvanomètres. En effet, ces derniers posséderont des miroirs à l'extrémité, ainsi les miroirs changeront d'inclinaison suivant le courant traversant les galvanomètres (similaire à l'image ci-contre). Il nous faudra également créer un système d'alimentation qui à partir d'une même source (réseau 230 V) sera capable d'alimenter les lasers et les galvanomètres ainsi qu'une Arduino et une Raspberry Pi.&lt;br /&gt;
[[File:Scanhead.jpeg|thumb]]&lt;br /&gt;
&lt;br /&gt;
Ensuite nous nous intéresserons à l'utilisation d'un système embarqué pour contrôler les galvanomètres et donc dessiner avec les lasers sur un plan 2D. En effet, le laser restera toujours fixe, seuls les galvanomètres, et donc les miroirs bougeront. Les galvanomètres étant contrôlés en courant il faudra réaliser une interface électronique pour convertir une commande en tension en commande de courant. La commande en tension sera assuré par une carte Arduino. Nous n'utiliserons qu'une seule paire de galvanomètres pour les deux laser. Il faudra donc multiplexer les deux faisceaux. La programmation des formes à effectuer, se fera par l'intermédiaire d'une application web PHP hébergée sur une RaspberryPi qui permettra de récupérer une image, d'y appliquer divers traitements et filtres afin d'en extraire les contours, et de calculer les commandes pour positionner les galvanomètres. Un serveur WebSocket également hébergé sur la RaspberryPi servira d'interface entre l'application web et L'arduino qui sera connecté via une liaison série sur la raspberryPI.&lt;br /&gt;
&lt;br /&gt;
Comme animation de test, nous dessinerons le contour d'une gymnaste avec une couleur et son ballon d'une autre couleur. La gymnaste devra lancer son ballon, réaliser quelques difficultés et récupérer son ballon.&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
Nous utiliserons comme matériels :&lt;br /&gt;
*Deux lasers de différentes couleurs&lt;br /&gt;
*Une paire de galvanomètres à miroir&lt;br /&gt;
*Arduino&lt;br /&gt;
*Raspberry Pi3&lt;br /&gt;
*Alimentation 230V/5V 1A [http://www.miniinthebox.com/fr/dual-usb-eu-prise-murale-5v-2a-voyage-adaptateur-chargeur-d-alimentation-pour-iphone7-6-xiaomi-samsung-et-autre-telephone-portable_p5410410.html?currency=EUR&amp;amp;litb_from=paid_adwords_shopping&amp;amp;sku=429_6917%7C752_20648&amp;amp;utm_source=google_shopping&amp;amp;utm_medium=cpc&amp;amp;adword_mt=&amp;amp;adword_ct=138705676724&amp;amp;adword_kw=&amp;amp;adword_pos=1o5&amp;amp;adword_pl=&amp;amp;adword_net=g&amp;amp;adword_tar=&amp;amp;adw_src_id=9653316068_661261352_33588296076_aud-79897721311:pla-256966386459&amp;amp;gclid=Cj0KEQiA_KvEBRCtzNil4-KR-LIBEiQAmgekFxxKjJJWBYCJlDZEa3Ke_2_WR0DzGVbz-jaCZHVIBoMaAvld8P8HAQ]&lt;br /&gt;
*Drivers galvanomètres x2&lt;br /&gt;
*Alimentation laser&lt;br /&gt;
*Lunette de sécurité x2 [https://www.amazon.fr/Uvex-S1933X-Eyewear-SCTOrange-Anti-Fog/dp/B000USRG90/ref=sr_1_1?ie=UTF8&amp;amp;qid=1485441383&amp;amp;sr=8-1&amp;amp;keywords=uvex+s1933x]&lt;br /&gt;
*Boitier ABS [http://fr.farnell.com/multicomp/g3118/boitier-abs-240x120x60mm-ip65/dp/1526656]&lt;br /&gt;
*DAC 4 canaux, avec interface I²C [https://www.adafruit.com/products/1083]&lt;br /&gt;
*Connecteur C14 [http://www.conrad.fr/ce/fr/product/715001/Connecteur-secteur-C14-Embase-male-verticale-715001-Nombre-de-poles-2-PE-10-A-noir-1-pcs/?ref=detview1&amp;amp;rt=detview1&amp;amp;rb=1]&lt;br /&gt;
*Câble secteur&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Logiciel :&lt;br /&gt;
&lt;br /&gt;
*Serveur web : Apache2, HTML5, PHP5, CSS&lt;br /&gt;
*Base de donnée : MySQL&lt;br /&gt;
*Serveur WebSocket : JQuerry, websocket&lt;br /&gt;
*Arduino : IDE Arduino&lt;br /&gt;
&lt;br /&gt;
===Calendrier prévisionnel===&lt;br /&gt;
&lt;br /&gt;
====Liste des tâches à effectuer====&lt;br /&gt;
Les différentes tâches à effectuer sont :&lt;br /&gt;
*Partie préliminaire : étude de fonctionnement des galvanomètres&lt;br /&gt;
**Déterminer comment est effectuée la commande des galvanomètres (protocole, tension...)&lt;br /&gt;
**Effectuer des tests avec l'Arduino ou la Raspberry Pi&lt;br /&gt;
**Effectuer des tests avec une LED à la place du laser &lt;br /&gt;
*Partie projection&lt;br /&gt;
**Fixer les lasers&lt;br /&gt;
**Aligner les lasers et les galvanomètres&lt;br /&gt;
**Créer le système d'alimentation&lt;br /&gt;
**Création d'un boitier&lt;br /&gt;
*Partie système embarqué&lt;br /&gt;
**Asservissement des galvanomètres avec l'Arduino&lt;br /&gt;
**Système électronique de commande en courant pour les galvanomètres&lt;br /&gt;
*Interface Web&lt;br /&gt;
**Installation et configuration Apache2&lt;br /&gt;
**Création d'une interface graphique simple&lt;br /&gt;
**Implémentation d'algorithmes de traitement d'image&lt;br /&gt;
**Mise en forme avec des CSS&lt;br /&gt;
**Sytème d'authentification avec mot de passe&lt;br /&gt;
**Utilisation d'une base de données pour enregistrer toutes les images déjà utilisés afin de les réutiliser&lt;br /&gt;
*Serveur Web Socket&lt;br /&gt;
**Récupération des données de l'interface web&lt;br /&gt;
**Mise en place de la liaison série avec l'Arduino&lt;br /&gt;
&lt;br /&gt;
====Calendrier====&lt;br /&gt;
Répartition du temps consacré au projet (240h) :&lt;br /&gt;
*Partie projection : 80h&lt;br /&gt;
*Partie système embarqué : 40h&lt;br /&gt;
*Partie interface web et websocket: 120h&lt;br /&gt;
&lt;br /&gt;
==Feuille d'heures==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!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&lt;br /&gt;
|-&lt;br /&gt;
| Définition cahier des charges &lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 14&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|38&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Finalisation du cahier des charges avec les responsables&lt;br /&gt;
&lt;br /&gt;
*Acquisition de matériels :&lt;br /&gt;
**Projecteur Laser&lt;br /&gt;
**Galvanomètres&lt;br /&gt;
**Alimentation des galvanomètres&lt;br /&gt;
&lt;br /&gt;
*Listage du matériels à acquérir :&lt;br /&gt;
**Lunettes de sécurité&lt;br /&gt;
**DAC&lt;br /&gt;
**Alimentation 230V/5V 1A&lt;br /&gt;
** Boitier ABS &lt;br /&gt;
**...&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
*Obtention de l'arduino et de la raspberryPI&lt;br /&gt;
&lt;br /&gt;
*Démontage du projecteur laser&lt;br /&gt;
**Deux lasers de classe 3b (vert et rouge)&lt;br /&gt;
**Circuit d'alimentation des deux lasers&lt;br /&gt;
&lt;br /&gt;
*Initialisation du port série de la raspberryPI&lt;br /&gt;
**Modification du fichier ''config.txt'' dans la partition boot&lt;br /&gt;
**Ajout d'une ligne autorisant la communication série ('''enable_uart=1''')&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
*Installation du serveur apache sur la raspberryPI&lt;br /&gt;
**Modification du fichier ''/etc/network/interfaces'' (Static, Address, Netmask, Gateway)&lt;br /&gt;
**Modification du fichier ''/etc/resolv.conf'' (Adresse du serveur)&lt;br /&gt;
**Utilisation d'un proxy pour la récupération outils de programmation (Apache2, Php5)&lt;br /&gt;
&lt;br /&gt;
*Mise en place du point d’accès wifi de la raspberryPI&lt;br /&gt;
**Récupération des logiciels nécessaires (dnsmasq, hostapd)&lt;br /&gt;
**Mise en place d'une adresse IP statique pour le point d'accès par l'intermédiaire du fichier ''/etc/dhcpcd.conf''&lt;br /&gt;
**Désactivation de la négociation automatique de bail dans le fichier ''/etc/network/interfaces''&lt;br /&gt;
**Configuration du logiciel hostapd ''/etc/hostapd/hostapd.conf''&lt;br /&gt;
**Activation du démarrage automatique du point d'accès ''/etc/default/hostapd''&lt;br /&gt;
**Configuration du serveur DNS par ''/etc/dnsmasq.conf''&lt;br /&gt;
&lt;br /&gt;
*Instauration de la page d'accueil de l'interface web à l'adresse ''192.168.3.1''&lt;br /&gt;
**Téléversement de fichiers images sur la page web et affichage de celle-ci&lt;br /&gt;
**Voyant de confirmation du bon fonctionnement du serveur web&lt;br /&gt;
&lt;br /&gt;
*Développement du serveur websocket&lt;br /&gt;
&lt;br /&gt;
Le développement du serveur websocket, initialement prévu en C (il était prévu de reprendre les sources utilisées l'année précédente dans le cadre des projet IMA3 SC), a finalement été réalisé en JAVA pour plusieurs raisons.&lt;br /&gt;
Premièrement, un seul programme met en œuvre le serveur websocket, les divers traitements d'image, ainsi que les contrôles des galvanomètres (par l'intermédiaire des DAC) via la liaison I²C de la Raspberry Pi. Le langage JAVA fournit nativement des bibliothèques d'objets pour manipuler assez simplement des images, il existe également des librairies pour contrôler le port GPIO de la Raspberry et il était également intéressant de travailler avec un langage de plus haut niveau que le C.&lt;br /&gt;
En outre, la totale portabilité de ce langage nous permet de travailler sur n'importe quelle machine et ensuite transférer notre programme sur la Raspberry Pi et l’exécuter sans même repasser par une phase de compilation. Et finalement, c'est le langage que nous étudions actuellement en cours de programmation orientée objet, ce qui permet de nous perfectionner.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Serveur WebSocket====&lt;br /&gt;
&lt;br /&gt;
N'ayant pas trouvé d'API WebSocket en Java satisfaisante (qui ne nécessitent pas l'installation et la configuration de nombreux outils additionnels), j'ai estimé plus commode et plus formateur de développer notre propre serveur WebSocket en se basant sur les librairies sockets de Java avec l'aide d'une documentation assez exhaustive [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers].&lt;br /&gt;
&lt;br /&gt;
Les WebSockets désignent à la fois un protocole réseau qui étend le protocole TCP ainsi qu'une API du World Wide Web. Nous nous en servons afin d'établir une communication asynchrone et bidirectionnelle entre un navigateur web et le serveur, notamment pour envoyer l'image à projeter. L’implémentation du serveur repose sur plusieurs étapes.&lt;br /&gt;
&lt;br /&gt;
1) Connexion d'un client &lt;br /&gt;
&lt;br /&gt;
2) Handshake : permet de faire le lien entre le protocole HTTP et WS. Le client envoie une requête HTTP demandant un upgrade de la connexion en protocole WS et le serveur répond en configurant la connexion (détail dans la documentation [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers]).&lt;br /&gt;
&lt;br /&gt;
3) Réception et décodage des messages : le serveurs reçoit des trames brutes, on extrait donc la taille du message ainsi que le message. De plus, les données son encodées (cryptage XOR) par un masque qui doit également être extrait.&lt;br /&gt;
&lt;br /&gt;
4) Fermeture de la communication.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le serveur supporte le multi-client il est donc nécessaire qu'il effectue ces étapes en &amp;quot;parallèle&amp;quot;. Nous utilisons donc les threads ou fils d’exécution. Un thread est donc responsable d'attendre qu'un nouveau client se connecte et effectue le &amp;quot;handshake&amp;quot;, il crée ensuite un thread associé à ce client afin d'établir un canal de communication. Il y a donc au moins un thread par client. Par la suite il faudra également implémenter une déconnexion automatique d'un client notamment après un timeout.&lt;br /&gt;
&lt;br /&gt;
Exemple d’exécution du serveur avec deux clients qui se connectent et envoient un message : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testServeur.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Les clients sont des navigateurs web. Pour les tests nous avons repris les exemples utilisés dans le cadre das projets IMA3 SC avec le titre de la page HTML qui se colore en vert lorsque le client est connecté, et un champ de saisie pour envoyer des messages au serveur : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testClient.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 4===&lt;br /&gt;
&lt;br /&gt;
*Mise en place d’algorithmes de traitement d'image&lt;br /&gt;
&lt;br /&gt;
====Détection de contour====&lt;br /&gt;
&lt;br /&gt;
L'objectif de notre projet est de pouvoir projeter n'importe quelle image envoyé grâce à l'application web. Pour cela nous allons tracer à une vitesse élevée les contours de l'image sur par exemple un mur grâce au laser. Il est donc nécessaire de détecter les contours de l'image grâce à plusieurs traitements.&lt;br /&gt;
&lt;br /&gt;
=====Conversion en niveau de gris=====&lt;br /&gt;
&lt;br /&gt;
Une des étapes préliminaires pour effectuer la détection de contour est de convertir l'image couleur en niveau de gris. Pour cela l'algorithme est simple : il suffit pour chaque pixel de l'image d'effectuer la moyenne des composantes rouge, verte, bleu de chaque pixel. En effet, si l'on considère une image matricielle (l'image est considérée comme un tableau à deux dimensions avec chaque case qui contient la couleur du pixel), chaque pixel contient les composantes RGB codées sur un octet. La couleur gris correspond aux composantes RGB égales. Le niveau de gris est donc codé de 0 à 255, avec 0 donnant du noir et 255 du blanc. &lt;br /&gt;
&lt;br /&gt;
Voici le résultat obtenu : [[Fichier:testGrayScale.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Filtre de Prewit et Sobel=====&lt;br /&gt;
&lt;br /&gt;
Un contour est défini par un changement brutal d'intensité lumineuse, il s'agit donc de détecter selon plusieurs directions (au moins 2) ces changements. Il existe de nombreuses techniques afin de détecter les contours d'une image (gradient, Laplacien). L'une des techniques avec un rapport efficacité/temps d'exécution correct repose sur les algorithmes de Prewit ou Sobel. L'algorithme repose sur la convolution de matrices.&lt;br /&gt;
Cela consiste à appliquer sur chaque pixel de l'image la matrice de Prewit définie comme &lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L_x = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; ainsi que sa transposée : &amp;lt;math&amp;gt;&lt;br /&gt;
L_y = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; -1 &amp;amp; -1 \\&lt;br /&gt;
 0 &amp;amp; 0 &amp;amp; 0 \\&lt;br /&gt;
+1 &amp;amp; +1 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Convoluer ces deux filtres sur l'image permet de détecter respectivement les contours verticaux et horizontaux.&lt;br /&gt;
&lt;br /&gt;
D'après wikipedia [https://fr.wikipedia.org/wiki/D%C3%A9tection_de_contours], on obtient de meilleurs résultats en appliquant un filtre triangulaire, on introduit donc la matrice de Sobel :&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-2 &amp;amp; 0 &amp;amp; +2 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
On obtient le résultat suivant : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testOutline1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Pré-traitement : Flou Gaussien=====&lt;br /&gt;
&lt;br /&gt;
Afin de réduire significativement le nombre de contours, il est nécessaire d'effectuer un pré-traitement avant la détection de contours. On utilise généralement un flou gaussien afin de réduire les transitions lumineuses et ainsi réduire le nombre de contours. L’algorithme de flou gaussien repose également sur la convolution de matrices sauf qu'ici la matrice filtre est générée grâce à une fonction gaussienne paramétrée par '''Sigma''' qui va directement impacter le niveau de flou. Plus la matrice de filtrage est grande plus la qualité du résultat est meilleure, mais le temps d’exécution devient également plus grand.&lt;br /&gt;
&lt;br /&gt;
Voici la fonction de génération du filtre : &amp;lt;math&amp;gt;G(x,y) = \frac{1}{{2\pi \sigma^2}} e^{-\frac{x^2 + y^2}{2 \sigma^2}}&amp;lt;/math&amp;gt; où x et y correspondent aux indices de la cellule de la matrice.&lt;br /&gt;
&lt;br /&gt;
On obtient ce résultat :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testGaussianBlur.png]]&lt;br /&gt;
&lt;br /&gt;
On note un bien meilleur résultat. Cependant on remarque que les composantes horizontales ne sont pas correctement détectées il subsiste un problème avec le filtrage vertical que je n'ai pas réussi à identifier. De plus, il s'agit par sa suite d'éliminer les contours parasites ainsi que d'affiner le trait pour n'avoir plus qu'un pixel d'épaisseur.&lt;br /&gt;
&lt;br /&gt;
=====Post-traitement : Algorithme de Canny=====&lt;br /&gt;
&lt;br /&gt;
Afin d'obtenir un résultat exploitable il est nécessaire d'appliquer encore quelques traitements. Pour cela nous utilisons l’algorithme de Canny qui repose que celui de Sobel mais qui ajoute un algorithme de seuillage par hysteresis qui permet de retirer les contours secondaires et de ne garder que les contours connexes dans une seuil haut et un seuil bas définis. En outre, cette algorithme affine également le trait obtenu. Pour cet algorithme nous avons directement trouvé des sources libres de droits [http://www.tomgibara.com/computer-vision/canny-edge-detector] qui donne des résultats très corrects.&lt;br /&gt;
&lt;br /&gt;
Par exemple :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ou encore : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny2.png|1500px]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 5===&lt;br /&gt;
&lt;br /&gt;
*Établissement d'un protocole de transfert d'image basé sur les WebSockets&lt;br /&gt;
**Envoie d'un requête &amp;quot;send&amp;quot; par le client dans une trame websocket texte&lt;br /&gt;
**Réponse serveur 'Y' si aucun autre client tente d'envoyer une image simultanément, 'N' sinon&lt;br /&gt;
**Si et seulement si le client reçoit 'Y' il débute le transfert en envoyant la largeur et la longueur de l'image sur 4 octets, puis les données de l'image soit 4 valeurs pour chaque pixels (r,g,b,alpha)&lt;br /&gt;
**Le serveur renvoie 'D' une fois le transfert achevé (à l'avenir, le serveur renverra l'image après filtrage).&lt;br /&gt;
**A tout moment, le serveur peut renvoyer 'E' si une erreur est survenue (ex : paquets perdus, nombre incorrects de données)&lt;br /&gt;
*Ajout du support des logs au niveau serveur&lt;br /&gt;
**Impression sur la sortie standard des messages&lt;br /&gt;
**Formatage en fonction de la sévérité du log (info, warning, error...)&lt;br /&gt;
**Incrustation de la date et heure&lt;br /&gt;
**Possibilité de redirection dans une fichier, avec configuration (écriture à la suite d'un fichier existant, écrasement...)&lt;br /&gt;
**Le tout dans une classe Java flexible et réutilisable pour d'autres projets&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 6===&lt;br /&gt;
&lt;br /&gt;
*Installation de la librairie Java Pi4j sur la raspberry pi qui permet le contrôle des GPIO de celle-ci et notamment le port I²C (basé sur WiringPi)&lt;br /&gt;
*Amélioration coté serveur websocket&lt;br /&gt;
**Gestion de message plus longs (maximum des trames websockets soit 2^63 octets)&lt;br /&gt;
**Différenciation, à la réception de messages, des trames textes ou binaires des trames de contrôle comme les requête ping, pong ou de fermeture de connexion &lt;br /&gt;
**Ajout d'un mode de debug de trames&lt;br /&gt;
*Interface web&lt;br /&gt;
**Mise en place du code css pour améliorer le rendu visuel de la page&lt;br /&gt;
**Amélioration de l'envoie des données vers le serveur&lt;br /&gt;
&lt;br /&gt;
===Semaine 7===&lt;br /&gt;
&lt;br /&gt;
*Améliorations du serveur WebSocket&lt;br /&gt;
**Gestion de la fragmentation TCP&lt;br /&gt;
**Gestion de la fragmentation WebSocket&lt;br /&gt;
**Gestion des requêtes ping envoyés par le client en renvoyant une trames de contrôle pong afin de maintenir la connexion&lt;br /&gt;
**Gestion des déconnexion de clients afin d'optimiser le serveur&lt;br /&gt;
**Amélioration de l'émission de messages en augmentant la taille maximale pouvant être émise (2^63 octets)&lt;br /&gt;
&lt;br /&gt;
*Amélioration du code css&lt;br /&gt;
*Mise en place d'une partie 'Home' et 'About'&lt;br /&gt;
**Home : Communication avec le serveur web&lt;br /&gt;
**About : Information complémentaire sur la page web&lt;br /&gt;
&lt;br /&gt;
A ce stade du développement, le client et le serveur sont opérationnels et peuvent s'échanger des messages ainsi que des images que le serveur traite pour extraire les contours.&lt;br /&gt;
&lt;br /&gt;
===Semaine 8===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Montage projecteur&lt;br /&gt;
**Intégralité des composants fixés par vis dans le boîtier ABS&lt;br /&gt;
**Fusion des alimentations&lt;br /&gt;
**Présence d'une led témoin de mise en tension&lt;br /&gt;
**Position laser réglable grâce à une vis&lt;br /&gt;
**Présence d'un switch à bascule pour allumer et éteindre le laser&lt;br /&gt;
**Isolation et vérification des composants&lt;br /&gt;
**Tests empiriques de température et de fonctionnement des lasers et galvanomètres&lt;br /&gt;
&lt;br /&gt;
Le montage boîtier est donc terminé et s’alimente en 230V par intermédiaire d'un câble secteur avec connecteur C14. Le résultat s'avère plutôt compact. Les quelques tests de température ont montrés que malgré le manque d'espace la température globale du boîtier ne dépasse pas les 50°C pendant plus d'une heure de fonctionnement. L'intégralité des connexions sont isolées avec de la gaine thermodynamique et les zones &amp;quot;sensibles&amp;quot; sont correctement vérifiés ainsi que protégées avec de la matière isolante.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:proj1.jpg|550px|Boîtier après perçage]] [[Fichier:proj2.jpg|550px|Boîtier finalisé]] [[Fichier:proj3.jpg|550px|Projecteur en fonctionnement]]&lt;br /&gt;
&lt;br /&gt;
*Page web et serveur WebSocket&lt;br /&gt;
**Ajout d'un bouton &amp;quot;reboot&amp;quot; et &amp;quot;shutdown&amp;quot; sur la page web&lt;br /&gt;
***Reboot : Permet le redémarrage de la Raspberry&lt;br /&gt;
***Shutdown : Permet l'extinction de la Raspberry&lt;br /&gt;
**Ajout d'un slider pour le flou gaussien (échelle 1 à 100)&lt;br /&gt;
&lt;br /&gt;
===Semaine 9===&lt;br /&gt;
*Installation du programme 'bind9' permettant de mettre en place un serveur DNS qui permet de remplacer les adresses IP par un nom&lt;br /&gt;
**Problème de configuration (à corriger)&lt;br /&gt;
*Prise en compte du message de retour du serveur&lt;br /&gt;
**Récupération d'un tableau de points représentants les contours de l'image envoyé par le client&lt;br /&gt;
*Mise à jour du slider du flou gaussien&lt;br /&gt;
**Double spider permettant de sélectionner un segment de valeur&lt;br /&gt;
**Echelle comprise entre 0 et 1, pour faciliter la lecture les valeurs sont écrites en pourcent&lt;br /&gt;
&lt;br /&gt;
===Semaine 10===&lt;br /&gt;
[[Fichier:Capture_du_2017-04-12_15-53-15.png|200px|thumb|right|Image envoyée -&amp;gt; Image laser]]&lt;br /&gt;
&lt;br /&gt;
*Récupération d'un ensemble de points envoyés par le serveur permettant de tracer l'image telle que sera projetée par le laser&lt;br /&gt;
**Mise en place du canvas&lt;br /&gt;
**Traçage de l'image par l'intermédiaire de &amp;quot;lineto&amp;quot; puisqu'il s'agit d'un contour&lt;br /&gt;
*Ajout d'une sécurité sur les boutons &amp;quot;reset&amp;quot; et &amp;quot;shutdown&amp;quot;&lt;br /&gt;
**Pop-up de confirmation pour les deux actions&lt;br /&gt;
*Mise à jour du Double slider&lt;br /&gt;
**Redimensionnement&lt;br /&gt;
**Récupération des valeurs&lt;br /&gt;
**Envois des valeurs vers le serveur par un tableau de binaires&lt;br /&gt;
&lt;br /&gt;
===Semaines Supplémentaires===&lt;br /&gt;
&lt;br /&gt;
*Finalisation du code css de la page web&lt;br /&gt;
**Amélioration visuelle&lt;br /&gt;
**Rendu dynamique de la page&lt;br /&gt;
[[Fichier:Page_accueil.png|396px|Page d’accueil]]&lt;br /&gt;
[[Fichier:Page2.png|396px|Image chargée]]&lt;br /&gt;
[[Fichier:Page3.png|396px|Contours récupérés]]&lt;br /&gt;
&lt;br /&gt;
==A faire==&lt;br /&gt;
&lt;br /&gt;
MAJ 19 Avril&lt;br /&gt;
&lt;br /&gt;
*Client websocket et page web&lt;br /&gt;
**Ajout slider pour de finir amplitude de la projection&lt;br /&gt;
**Ajout message de confirmation quand le serveur quitte ou relance&lt;br /&gt;
**Ajout boutons &amp;quot;projeter&amp;quot; &amp;quot;centrer&amp;quot; &amp;quot;etendre&amp;quot;&lt;br /&gt;
**Redimensionnement automatique de l'image !!&lt;br /&gt;
**Gestion de plusieurs images avec délai&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Serveur WebSocket&lt;br /&gt;
**Ajout fonctionnalité envoi image de prévisualisation&lt;br /&gt;
&lt;br /&gt;
*RaspberryPi&lt;br /&gt;
**Utilisation d'un serveur bind9 pour éviter de taper IP&lt;br /&gt;
&lt;br /&gt;
*Détection de contours&lt;br /&gt;
**Implémentation algorithme de tri de la plus courte disance&lt;br /&gt;
&lt;br /&gt;
*Commande galvanomêtre&lt;br /&gt;
**Utilisation API I²C&lt;br /&gt;
**Fonction de transfert position-&amp;gt;angle-&amp;gt;tension&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;br /&gt;
&lt;br /&gt;
[[Compte-rendu_TOMBAZZI_TRIMBUR]]&lt;br /&gt;
&lt;br /&gt;
==Bibliographie==&lt;br /&gt;
&lt;br /&gt;
*Galvanomètres et laser&lt;br /&gt;
http://www.ebay.com/itm/20KPPS-30KPPS-laser-scanning-galvo-scanner-ILDA-Closed-Loop-max-30kpps-for-laser-/261517002270?hash=item3ce3a0c61e&lt;br /&gt;
&lt;br /&gt;
http://sciences.ulb.ac.be/printemps/download/2016/dossier_pedagogique/02.pdf&lt;br /&gt;
&lt;br /&gt;
*Websocket&lt;br /&gt;
http://stackoverflow.com/questions/8125507/how-can-i-send-and-receive-websocket-messages-on-the-server-side&lt;br /&gt;
&lt;br /&gt;
https://tools.ietf.org/html/rfc6455&lt;br /&gt;
&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_a_WebSocket_server_in_Java&lt;br /&gt;
&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers&lt;br /&gt;
&lt;br /&gt;
*Traitement d'image&lt;br /&gt;
https://en.wikipedia.org/wiki/Gaussian_blur&lt;br /&gt;
&lt;br /&gt;
http://www.zebulon.fr/questions-reponses/traitement-d-image-detection-de-contours-55.html&lt;br /&gt;
&lt;br /&gt;
http://patrick-bonnin.developpez.com/cours/vision/apprendre-bases-traitement-image/partie-5-segmentation-contour/&lt;br /&gt;
&lt;br /&gt;
http://www.isir.upmc.fr/UserFiles/File/clady_homepage/EPU/2-Contour&lt;br /&gt;
&lt;br /&gt;
*Autre&lt;br /&gt;
https://icn.fenelonlille.org/mediawiki/index.php/Projet_ICN_commun_2016/2017&lt;br /&gt;
&lt;br /&gt;
https://www.g33k-zone.org/post/2016/05/11/Configurer-le-Raspberry-Pi-en-point-d-acc%C3%A8s-Wifi&lt;br /&gt;
&lt;br /&gt;
https://blogs.oracle.com/acaicedo/resource/Parallax-I2C/Sensors.java&lt;br /&gt;
&lt;br /&gt;
http://stackoverflow.com/questions/22087076/how-to-make-a-simple-image-upload-using-javascript-html&lt;br /&gt;
&lt;br /&gt;
export http_proxy=http://proxy.polytech-lille.fr:3128&lt;/div&gt;</summary>
		<author><name>Mtrimbur</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=42153</id>
		<title>IMA4 2016/2017 P39</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=42153"/>
				<updated>2017-05-12T12:32:02Z</updated>
		
		<summary type="html">&lt;p&gt;Mtrimbur : /* Fichiers Rendus */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
===Contexte===&lt;br /&gt;
&lt;br /&gt;
Le laser est une technologie largement utilisé de nos jours dans de diverses applications. En effet, on retrouve cette technologie dans le domaine médical notamment pour la chirurgie oculaire ou encore dans industrie avec la découpe laser ou la soudure au laser.&lt;br /&gt;
&lt;br /&gt;
Le laser est une émission de photons produit par excitation d'un milieu amplificateur (ex : CO2), le rayonnement produit est unidirectionnel et monochromatique. Ce sont ces propriétés que nous allons exploiter afin réaliser un projecteur laser qui mis en mouvement est capable de dessiner des formes sur une surface à l'instar de systèmes existants utilisés pour des effets lumineux lors de festivités.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
L'objectif du projet est de créer un système de projection laser à plusieurs couleurs (au minimum deux) avec une application web pour programmer les formes à dessiner afin d'agrémenter des compétitions de gymnastique rythmique.&lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
Le projet consiste à réaliser avec des lasers des figures géométriques par l'intermédiaire d'un système galvanométrique. &lt;br /&gt;
&lt;br /&gt;
Notre premier travail sera de concevoir la partie projection. Pour cela, nous devrons aligner les lasers et les galvanomètres. En effet, ces derniers posséderont des miroirs à l'extrémité, ainsi les miroirs changeront d'inclinaison suivant le courant traversant les galvanomètres (similaire à l'image ci-contre). Il nous faudra également créer un système d'alimentation qui à partir d'une même source (réseau 230 V) sera capable d'alimenter les lasers et les galvanomètres ainsi qu'une Arduino et une Raspberry Pi.&lt;br /&gt;
[[File:Scanhead.jpeg|thumb]]&lt;br /&gt;
&lt;br /&gt;
Ensuite nous nous intéresserons à l'utilisation d'un système embarqué pour contrôler les galvanomètres et donc dessiner avec les lasers sur un plan 2D. En effet, le laser restera toujours fixe, seuls les galvanomètres, et donc les miroirs bougeront. Les galvanomètres étant contrôlés en courant il faudra réaliser une interface électronique pour convertir une commande en tension en commande de courant. La commande en tension sera assuré par une carte Arduino. Nous n'utiliserons qu'une seule paire de galvanomètres pour les deux laser. Il faudra donc multiplexer les deux faisceaux. La programmation des formes à effectuer, se fera par l'intermédiaire d'une application web PHP hébergée sur une RaspberryPi qui permettra de récupérer une image, d'y appliquer divers traitements et filtres afin d'en extraire les contours, et de calculer les commandes pour positionner les galvanomètres. Un serveur WebSocket également hébergé sur la RaspberryPi servira d'interface entre l'application web et L'arduino qui sera connecté via une liaison série sur la raspberryPI.&lt;br /&gt;
&lt;br /&gt;
Comme animation de test, nous dessinerons le contour d'une gymnaste avec une couleur et son ballon d'une autre couleur. La gymnaste devra lancer son ballon, réaliser quelques difficultés et récupérer son ballon.&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
Nous utiliserons comme matériels :&lt;br /&gt;
*Deux lasers de différentes couleurs&lt;br /&gt;
*Une paire de galvanomètres à miroir&lt;br /&gt;
*Arduino&lt;br /&gt;
*Raspberry Pi3&lt;br /&gt;
*Alimentation 230V/5V 1A [http://www.miniinthebox.com/fr/dual-usb-eu-prise-murale-5v-2a-voyage-adaptateur-chargeur-d-alimentation-pour-iphone7-6-xiaomi-samsung-et-autre-telephone-portable_p5410410.html?currency=EUR&amp;amp;litb_from=paid_adwords_shopping&amp;amp;sku=429_6917%7C752_20648&amp;amp;utm_source=google_shopping&amp;amp;utm_medium=cpc&amp;amp;adword_mt=&amp;amp;adword_ct=138705676724&amp;amp;adword_kw=&amp;amp;adword_pos=1o5&amp;amp;adword_pl=&amp;amp;adword_net=g&amp;amp;adword_tar=&amp;amp;adw_src_id=9653316068_661261352_33588296076_aud-79897721311:pla-256966386459&amp;amp;gclid=Cj0KEQiA_KvEBRCtzNil4-KR-LIBEiQAmgekFxxKjJJWBYCJlDZEa3Ke_2_WR0DzGVbz-jaCZHVIBoMaAvld8P8HAQ]&lt;br /&gt;
*Drivers galvanomètres x2&lt;br /&gt;
*Alimentation laser&lt;br /&gt;
*Lunette de sécurité x2 [https://www.amazon.fr/Uvex-S1933X-Eyewear-SCTOrange-Anti-Fog/dp/B000USRG90/ref=sr_1_1?ie=UTF8&amp;amp;qid=1485441383&amp;amp;sr=8-1&amp;amp;keywords=uvex+s1933x]&lt;br /&gt;
*Boitier ABS [http://fr.farnell.com/multicomp/g3118/boitier-abs-240x120x60mm-ip65/dp/1526656]&lt;br /&gt;
*DAC 4 canaux, avec interface I²C [https://www.adafruit.com/products/1083]&lt;br /&gt;
*Connecteur C14 [http://www.conrad.fr/ce/fr/product/715001/Connecteur-secteur-C14-Embase-male-verticale-715001-Nombre-de-poles-2-PE-10-A-noir-1-pcs/?ref=detview1&amp;amp;rt=detview1&amp;amp;rb=1]&lt;br /&gt;
*Câble secteur&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Logiciel :&lt;br /&gt;
&lt;br /&gt;
*Serveur web : Apache2, HTML5, PHP5, CSS&lt;br /&gt;
*Base de donnée : MySQL&lt;br /&gt;
*Serveur WebSocket : JQuerry, websocket&lt;br /&gt;
*Arduino : IDE Arduino&lt;br /&gt;
&lt;br /&gt;
===Calendrier prévisionnel===&lt;br /&gt;
&lt;br /&gt;
====Liste des tâches à effectuer====&lt;br /&gt;
Les différentes tâches à effectuer sont :&lt;br /&gt;
*Partie préliminaire : étude de fonctionnement des galvanomètres&lt;br /&gt;
**Déterminer comment est effectuée la commande des galvanomètres (protocole, tension...)&lt;br /&gt;
**Effectuer des tests avec l'Arduino ou la Raspberry Pi&lt;br /&gt;
**Effectuer des tests avec une LED à la place du laser &lt;br /&gt;
*Partie projection&lt;br /&gt;
**Fixer les lasers&lt;br /&gt;
**Aligner les lasers et les galvanomètres&lt;br /&gt;
**Créer le système d'alimentation&lt;br /&gt;
**Création d'un boitier&lt;br /&gt;
*Partie système embarqué&lt;br /&gt;
**Asservissement des galvanomètres avec l'Arduino&lt;br /&gt;
**Système électronique de commande en courant pour les galvanomètres&lt;br /&gt;
*Interface Web&lt;br /&gt;
**Installation et configuration Apache2&lt;br /&gt;
**Création d'une interface graphique simple&lt;br /&gt;
**Implémentation d'algorithmes de traitement d'image&lt;br /&gt;
**Mise en forme avec des CSS&lt;br /&gt;
**Sytème d'authentification avec mot de passe&lt;br /&gt;
**Utilisation d'une base de données pour enregistrer toutes les images déjà utilisés afin de les réutiliser&lt;br /&gt;
*Serveur Web Socket&lt;br /&gt;
**Récupération des données de l'interface web&lt;br /&gt;
**Mise en place de la liaison série avec l'Arduino&lt;br /&gt;
&lt;br /&gt;
====Calendrier====&lt;br /&gt;
Répartition du temps consacré au projet (240h) :&lt;br /&gt;
*Partie projection : 80h&lt;br /&gt;
*Partie système embarqué : 40h&lt;br /&gt;
*Partie interface web et websocket: 120h&lt;br /&gt;
&lt;br /&gt;
==Feuille d'heures==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!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&lt;br /&gt;
|-&lt;br /&gt;
| Définition cahier des charges &lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 14&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|38&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Finalisation du cahier des charges avec les responsables&lt;br /&gt;
&lt;br /&gt;
*Acquisition de matériels :&lt;br /&gt;
**Projecteur Laser&lt;br /&gt;
**Galvanomètres&lt;br /&gt;
**Alimentation des galvanomètres&lt;br /&gt;
&lt;br /&gt;
*Listage du matériels à acquérir :&lt;br /&gt;
**Lunettes de sécurité&lt;br /&gt;
**DAC&lt;br /&gt;
**Alimentation 230V/5V 1A&lt;br /&gt;
** Boitier ABS &lt;br /&gt;
**...&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
*Obtention de l'arduino et de la raspberryPI&lt;br /&gt;
&lt;br /&gt;
*Démontage du projecteur laser&lt;br /&gt;
**Deux lasers de classe 3b (vert et rouge)&lt;br /&gt;
**Circuit d'alimentation des deux lasers&lt;br /&gt;
&lt;br /&gt;
*Initialisation du port série de la raspberryPI&lt;br /&gt;
**Modification du fichier ''config.txt'' dans la partition boot&lt;br /&gt;
**Ajout d'une ligne autorisant la communication série ('''enable_uart=1''')&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
*Installation du serveur apache sur la raspberryPI&lt;br /&gt;
**Modification du fichier ''/etc/network/interfaces'' (Static, Address, Netmask, Gateway)&lt;br /&gt;
**Modification du fichier ''/etc/resolv.conf'' (Adresse du serveur)&lt;br /&gt;
**Utilisation d'un proxy pour la récupération outils de programmation (Apache2, Php5)&lt;br /&gt;
&lt;br /&gt;
*Mise en place du point d’accès wifi de la raspberryPI&lt;br /&gt;
**Récupération des logiciels nécessaires (dnsmasq, hostapd)&lt;br /&gt;
**Mise en place d'une adresse IP statique pour le point d'accès par l'intermédiaire du fichier ''/etc/dhcpcd.conf''&lt;br /&gt;
**Désactivation de la négociation automatique de bail dans le fichier ''/etc/network/interfaces''&lt;br /&gt;
**Configuration du logiciel hostapd ''/etc/hostapd/hostapd.conf''&lt;br /&gt;
**Activation du démarrage automatique du point d'accès ''/etc/default/hostapd''&lt;br /&gt;
**Configuration du serveur DNS par ''/etc/dnsmasq.conf''&lt;br /&gt;
&lt;br /&gt;
*Instauration de la page d'accueil de l'interface web à l'adresse ''192.168.3.1''&lt;br /&gt;
**Téléversement de fichiers images sur la page web et affichage de celle-ci&lt;br /&gt;
**Voyant de confirmation du bon fonctionnement du serveur web&lt;br /&gt;
&lt;br /&gt;
*Développement du serveur websocket&lt;br /&gt;
&lt;br /&gt;
Le développement du serveur websocket, initialement prévu en C (il était prévu de reprendre les sources utilisées l'année précédente dans le cadre des projet IMA3 SC), a finalement été réalisé en JAVA pour plusieurs raisons.&lt;br /&gt;
Premièrement, un seul programme met en œuvre le serveur websocket, les divers traitements d'image, ainsi que les contrôles des galvanomètres (par l'intermédiaire des DAC) via la liaison I²C de la Raspberry Pi. Le langage JAVA fournit nativement des bibliothèques d'objets pour manipuler assez simplement des images, il existe également des librairies pour contrôler le port GPIO de la Raspberry et il était également intéressant de travailler avec un langage de plus haut niveau que le C.&lt;br /&gt;
En outre, la totale portabilité de ce langage nous permet de travailler sur n'importe quelle machine et ensuite transférer notre programme sur la Raspberry Pi et l’exécuter sans même repasser par une phase de compilation. Et finalement, c'est le langage que nous étudions actuellement en cours de programmation orientée objet, ce qui permet de nous perfectionner.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Serveur WebSocket====&lt;br /&gt;
&lt;br /&gt;
N'ayant pas trouvé d'API WebSocket en Java satisfaisante (qui ne nécessitent pas l'installation et la configuration de nombreux outils additionnels), j'ai estimé plus commode et plus formateur de développer notre propre serveur WebSocket en se basant sur les librairies sockets de Java avec l'aide d'une documentation assez exhaustive [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers].&lt;br /&gt;
&lt;br /&gt;
Les WebSockets désignent à la fois un protocole réseau qui étend le protocole TCP ainsi qu'une API du World Wide Web. Nous nous en servons afin d'établir une communication asynchrone et bidirectionnelle entre un navigateur web et le serveur, notamment pour envoyer l'image à projeter. L’implémentation du serveur repose sur plusieurs étapes.&lt;br /&gt;
&lt;br /&gt;
1) Connexion d'un client &lt;br /&gt;
&lt;br /&gt;
2) Handshake : permet de faire le lien entre le protocole HTTP et WS. Le client envoie une requête HTTP demandant un upgrade de la connexion en protocole WS et le serveur répond en configurant la connexion (détail dans la documentation [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers]).&lt;br /&gt;
&lt;br /&gt;
3) Réception et décodage des messages : le serveurs reçoit des trames brutes, on extrait donc la taille du message ainsi que le message. De plus, les données son encodées (cryptage XOR) par un masque qui doit également être extrait.&lt;br /&gt;
&lt;br /&gt;
4) Fermeture de la communication.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le serveur supporte le multi-client il est donc nécessaire qu'il effectue ces étapes en &amp;quot;parallèle&amp;quot;. Nous utilisons donc les threads ou fils d’exécution. Un thread est donc responsable d'attendre qu'un nouveau client se connecte et effectue le &amp;quot;handshake&amp;quot;, il crée ensuite un thread associé à ce client afin d'établir un canal de communication. Il y a donc au moins un thread par client. Par la suite il faudra également implémenter une déconnexion automatique d'un client notamment après un timeout.&lt;br /&gt;
&lt;br /&gt;
Exemple d’exécution du serveur avec deux clients qui se connectent et envoient un message : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testServeur.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Les clients sont des navigateurs web. Pour les tests nous avons repris les exemples utilisés dans le cadre das projets IMA3 SC avec le titre de la page HTML qui se colore en vert lorsque le client est connecté, et un champ de saisie pour envoyer des messages au serveur : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testClient.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 4===&lt;br /&gt;
&lt;br /&gt;
*Mise en place d’algorithmes de traitement d'image&lt;br /&gt;
&lt;br /&gt;
====Détection de contour====&lt;br /&gt;
&lt;br /&gt;
L'objectif de notre projet est de pouvoir projeter n'importe quelle image envoyé grâce à l'application web. Pour cela nous allons tracer à une vitesse élevée les contours de l'image sur par exemple un mur grâce au laser. Il est donc nécessaire de détecter les contours de l'image grâce à plusieurs traitements.&lt;br /&gt;
&lt;br /&gt;
=====Conversion en niveau de gris=====&lt;br /&gt;
&lt;br /&gt;
Une des étapes préliminaires pour effectuer la détection de contour est de convertir l'image couleur en niveau de gris. Pour cela l'algorithme est simple : il suffit pour chaque pixel de l'image d'effectuer la moyenne des composantes rouge, verte, bleu de chaque pixel. En effet, si l'on considère une image matricielle (l'image est considérée comme un tableau à deux dimensions avec chaque case qui contient la couleur du pixel), chaque pixel contient les composantes RGB codées sur un octet. La couleur gris correspond aux composantes RGB égales. Le niveau de gris est donc codé de 0 à 255, avec 0 donnant du noir et 255 du blanc. &lt;br /&gt;
&lt;br /&gt;
Voici le résultat obtenu : [[Fichier:testGrayScale.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Filtre de Prewit et Sobel=====&lt;br /&gt;
&lt;br /&gt;
Un contour est défini par un changement brutal d'intensité lumineuse, il s'agit donc de détecter selon plusieurs directions (au moins 2) ces changements. Il existe de nombreuses techniques afin de détecter les contours d'une image (gradient, Laplacien). L'une des techniques avec un rapport efficacité/temps d'exécution correct repose sur les algorithmes de Prewit ou Sobel. L'algorithme repose sur la convolution de matrices.&lt;br /&gt;
Cela consiste à appliquer sur chaque pixel de l'image la matrice de Prewit définie comme &lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L_x = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; ainsi que sa transposée : &amp;lt;math&amp;gt;&lt;br /&gt;
L_y = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; -1 &amp;amp; -1 \\&lt;br /&gt;
 0 &amp;amp; 0 &amp;amp; 0 \\&lt;br /&gt;
+1 &amp;amp; +1 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Convoluer ces deux filtres sur l'image permet de détecter respectivement les contours verticaux et horizontaux.&lt;br /&gt;
&lt;br /&gt;
D'après wikipedia [https://fr.wikipedia.org/wiki/D%C3%A9tection_de_contours], on obtient de meilleurs résultats en appliquant un filtre triangulaire, on introduit donc la matrice de Sobel :&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-2 &amp;amp; 0 &amp;amp; +2 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
On obtient le résultat suivant : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testOutline1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Pré-traitement : Flou Gaussien=====&lt;br /&gt;
&lt;br /&gt;
Afin de réduire significativement le nombre de contours, il est nécessaire d'effectuer un pré-traitement avant la détection de contours. On utilise généralement un flou gaussien afin de réduire les transitions lumineuses et ainsi réduire le nombre de contours. L’algorithme de flou gaussien repose également sur la convolution de matrices sauf qu'ici la matrice filtre est générée grâce à une fonction gaussienne paramétrée par '''Sigma''' qui va directement impacter le niveau de flou. Plus la matrice de filtrage est grande plus la qualité du résultat est meilleure, mais le temps d’exécution devient également plus grand.&lt;br /&gt;
&lt;br /&gt;
Voici la fonction de génération du filtre : &amp;lt;math&amp;gt;G(x,y) = \frac{1}{{2\pi \sigma^2}} e^{-\frac{x^2 + y^2}{2 \sigma^2}}&amp;lt;/math&amp;gt; où x et y correspondent aux indices de la cellule de la matrice.&lt;br /&gt;
&lt;br /&gt;
On obtient ce résultat :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testGaussianBlur.png]]&lt;br /&gt;
&lt;br /&gt;
On note un bien meilleur résultat. Cependant on remarque que les composantes horizontales ne sont pas correctement détectées il subsiste un problème avec le filtrage vertical que je n'ai pas réussi à identifier. De plus, il s'agit par sa suite d'éliminer les contours parasites ainsi que d'affiner le trait pour n'avoir plus qu'un pixel d'épaisseur.&lt;br /&gt;
&lt;br /&gt;
=====Post-traitement : Algorithme de Canny=====&lt;br /&gt;
&lt;br /&gt;
Afin d'obtenir un résultat exploitable il est nécessaire d'appliquer encore quelques traitements. Pour cela nous utilisons l’algorithme de Canny qui repose que celui de Sobel mais qui ajoute un algorithme de seuillage par hysteresis qui permet de retirer les contours secondaires et de ne garder que les contours connexes dans une seuil haut et un seuil bas définis. En outre, cette algorithme affine également le trait obtenu. Pour cet algorithme nous avons directement trouvé des sources libres de droits [http://www.tomgibara.com/computer-vision/canny-edge-detector] qui donne des résultats très corrects.&lt;br /&gt;
&lt;br /&gt;
Par exemple :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ou encore : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny2.png|1500px]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 5===&lt;br /&gt;
&lt;br /&gt;
*Établissement d'un protocole de transfert d'image basé sur les WebSockets&lt;br /&gt;
**Envoie d'un requête &amp;quot;send&amp;quot; par le client dans une trame websocket texte&lt;br /&gt;
**Réponse serveur 'Y' si aucun autre client tente d'envoyer une image simultanément, 'N' sinon&lt;br /&gt;
**Si et seulement si le client reçoit 'Y' il débute le transfert en envoyant la largeur et la longueur de l'image sur 4 octets, puis les données de l'image soit 4 valeurs pour chaque pixels (r,g,b,alpha)&lt;br /&gt;
**Le serveur renvoie 'D' une fois le transfert achevé (à l'avenir, le serveur renverra l'image après filtrage).&lt;br /&gt;
**A tout moment, le serveur peut renvoyer 'E' si une erreur est survenue (ex : paquets perdus, nombre incorrects de données)&lt;br /&gt;
*Ajout du support des logs au niveau serveur&lt;br /&gt;
**Impression sur la sortie standard des messages&lt;br /&gt;
**Formatage en fonction de la sévérité du log (info, warning, error...)&lt;br /&gt;
**Incrustation de la date et heure&lt;br /&gt;
**Possibilité de redirection dans une fichier, avec configuration (écriture à la suite d'un fichier existant, écrasement...)&lt;br /&gt;
**Le tout dans une classe Java flexible et réutilisable pour d'autres projets&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 6===&lt;br /&gt;
&lt;br /&gt;
*Installation de la librairie Java Pi4j sur la raspberry pi qui permet le contrôle des GPIO de celle-ci et notamment le port I²C (basé sur WiringPi)&lt;br /&gt;
*Amélioration coté serveur websocket&lt;br /&gt;
**Gestion de message plus longs (maximum des trames websockets soit 2^63 octets)&lt;br /&gt;
**Différenciation, à la réception de messages, des trames textes ou binaires des trames de contrôle comme les requête ping, pong ou de fermeture de connexion &lt;br /&gt;
**Ajout d'un mode de debug de trames&lt;br /&gt;
*Interface web&lt;br /&gt;
**Mise en place du code css pour améliorer le rendu visuel de la page&lt;br /&gt;
**Amélioration de l'envoie des données vers le serveur&lt;br /&gt;
&lt;br /&gt;
===Semaine 7===&lt;br /&gt;
&lt;br /&gt;
*Améliorations du serveur WebSocket&lt;br /&gt;
**Gestion de la fragmentation TCP&lt;br /&gt;
**Gestion de la fragmentation WebSocket&lt;br /&gt;
**Gestion des requêtes ping envoyés par le client en renvoyant une trames de contrôle pong afin de maintenir la connexion&lt;br /&gt;
**Gestion des déconnexion de clients afin d'optimiser le serveur&lt;br /&gt;
**Amélioration de l'émission de messages en augmentant la taille maximale pouvant être émise (2^63 octets)&lt;br /&gt;
&lt;br /&gt;
*Amélioration du code css&lt;br /&gt;
*Mise en place d'une partie 'Home' et 'About'&lt;br /&gt;
**Home : Communication avec le serveur web&lt;br /&gt;
**About : Information complémentaire sur la page web&lt;br /&gt;
&lt;br /&gt;
A ce stade du développement, le client et le serveur sont opérationnels et peuvent s'échanger des messages ainsi que des images que le serveur traite pour extraire les contours.&lt;br /&gt;
&lt;br /&gt;
===Semaine 8===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Montage projecteur&lt;br /&gt;
**Intégralité des composants fixés par vis dans le boîtier ABS&lt;br /&gt;
**Fusion des alimentations&lt;br /&gt;
**Présence d'une led témoin de mise en tension&lt;br /&gt;
**Position laser réglable grâce à une vis&lt;br /&gt;
**Présence d'un switch à bascule pour allumer et éteindre le laser&lt;br /&gt;
**Isolation et vérification des composants&lt;br /&gt;
**Tests empiriques de température et de fonctionnement des lasers et galvanomètres&lt;br /&gt;
&lt;br /&gt;
Le montage boîtier est donc terminé et s’alimente en 230V par intermédiaire d'un câble secteur avec connecteur C14. Le résultat s'avère plutôt compact. Les quelques tests de température ont montrés que malgré le manque d'espace la température globale du boîtier ne dépasse pas les 50°C pendant plus d'une heure de fonctionnement. L'intégralité des connexions sont isolées avec de la gaine thermodynamique et les zones &amp;quot;sensibles&amp;quot; sont correctement vérifiés ainsi que protégées avec de la matière isolante.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:proj1.jpg|550px|Boîtier après perçage]] [[Fichier:proj2.jpg|550px|Boîtier finalisé]] [[Fichier:proj3.jpg|550px|Projecteur en fonctionnement]]&lt;br /&gt;
&lt;br /&gt;
*Page web et serveur WebSocket&lt;br /&gt;
**Ajout d'un bouton &amp;quot;reboot&amp;quot; et &amp;quot;shutdown&amp;quot; sur la page web&lt;br /&gt;
***Reboot : Permet le redémarrage de la Raspberry&lt;br /&gt;
***Shutdown : Permet l'extinction de la Raspberry&lt;br /&gt;
**Ajout d'un slider pour le flou gaussien (échelle 1 à 100)&lt;br /&gt;
&lt;br /&gt;
===Semaine 9===&lt;br /&gt;
*Installation du programme 'bind9' permettant de mettre en place un serveur DNS qui permet de remplacer les adresses IP par un nom&lt;br /&gt;
**Problème de configuration (à corriger)&lt;br /&gt;
*Prise en compte du message de retour du serveur&lt;br /&gt;
**Récupération d'un tableau de points représentants les contours de l'image envoyé par le client&lt;br /&gt;
*Mise à jour du slider du flou gaussien&lt;br /&gt;
**Double spider permettant de sélectionner un segment de valeur&lt;br /&gt;
**Echelle comprise entre 0 et 1, pour faciliter la lecture les valeurs sont écrites en pourcent&lt;br /&gt;
&lt;br /&gt;
===Semaine 10===&lt;br /&gt;
[[Fichier:Capture_du_2017-04-12_15-53-15.png|200px|thumb|right|Image envoyée -&amp;gt; Image laser]]&lt;br /&gt;
&lt;br /&gt;
*Récupération d'un ensemble de points envoyés par le serveur permettant de tracer l'image telle que sera projetée par le laser&lt;br /&gt;
**Mise en place du canvas&lt;br /&gt;
**Traçage de l'image par l'intermédiaire de &amp;quot;lineto&amp;quot; puisqu'il s'agit d'un contour&lt;br /&gt;
*Ajout d'une sécurité sur les boutons &amp;quot;reset&amp;quot; et &amp;quot;shutdown&amp;quot;&lt;br /&gt;
**Pop-up de confirmation pour les deux actions&lt;br /&gt;
*Mise à jour du Double slider&lt;br /&gt;
**Redimensionnement&lt;br /&gt;
**Récupération des valeurs&lt;br /&gt;
**Envois des valeurs vers le serveur par un tableau de binaires&lt;br /&gt;
&lt;br /&gt;
===Semaines Supplémentaires===&lt;br /&gt;
&lt;br /&gt;
*Finalisation du code css de la page web&lt;br /&gt;
**Amélioration visuelle&lt;br /&gt;
**Rendu dynamique de la page&lt;br /&gt;
[[Fichier:Page_accueil.png|396px|Page d’accueil]]&lt;br /&gt;
[[Fichier:Page2.png|396px|Image chargée]]&lt;br /&gt;
[[Fichier:Page3.png|396px|Contours récupérés]]&lt;br /&gt;
&lt;br /&gt;
==A faire==&lt;br /&gt;
&lt;br /&gt;
MAJ 19 Avril&lt;br /&gt;
&lt;br /&gt;
*Client websocket et page web&lt;br /&gt;
**Ajout slider pour de finir amplitude de la projection&lt;br /&gt;
**Ajout message de confirmation quand le serveur quitte ou relance&lt;br /&gt;
**Ajout boutons &amp;quot;projeter&amp;quot; &amp;quot;centrer&amp;quot; &amp;quot;etendre&amp;quot;&lt;br /&gt;
**Redimensionnement automatique de l'image !!&lt;br /&gt;
**Gestion de plusieurs images avec délai&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Serveur WebSocket&lt;br /&gt;
**Ajout fonctionnalité envoi image de prévisualisation&lt;br /&gt;
&lt;br /&gt;
*RaspberryPi&lt;br /&gt;
**Utilisation d'un serveur bind9 pour éviter de taper IP&lt;br /&gt;
&lt;br /&gt;
*Détection de contours&lt;br /&gt;
**Implémentation algorithme de tri de la plus courte disance&lt;br /&gt;
&lt;br /&gt;
*Commande galvanomêtre&lt;br /&gt;
**Utilisation API I²C&lt;br /&gt;
**Fonction de transfert position-&amp;gt;angle-&amp;gt;tension&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Compte-rendu_TOMBAZZI_TRIMBUR]]&lt;br /&gt;
&lt;br /&gt;
==Bibliographie==&lt;br /&gt;
&lt;br /&gt;
*Galvanomètres et laser&lt;br /&gt;
http://www.ebay.com/itm/20KPPS-30KPPS-laser-scanning-galvo-scanner-ILDA-Closed-Loop-max-30kpps-for-laser-/261517002270?hash=item3ce3a0c61e&lt;br /&gt;
&lt;br /&gt;
http://sciences.ulb.ac.be/printemps/download/2016/dossier_pedagogique/02.pdf&lt;br /&gt;
&lt;br /&gt;
*Websocket&lt;br /&gt;
http://stackoverflow.com/questions/8125507/how-can-i-send-and-receive-websocket-messages-on-the-server-side&lt;br /&gt;
&lt;br /&gt;
https://tools.ietf.org/html/rfc6455&lt;br /&gt;
&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_a_WebSocket_server_in_Java&lt;br /&gt;
&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers&lt;br /&gt;
&lt;br /&gt;
*Traitement d'image&lt;br /&gt;
https://en.wikipedia.org/wiki/Gaussian_blur&lt;br /&gt;
&lt;br /&gt;
http://www.zebulon.fr/questions-reponses/traitement-d-image-detection-de-contours-55.html&lt;br /&gt;
&lt;br /&gt;
http://patrick-bonnin.developpez.com/cours/vision/apprendre-bases-traitement-image/partie-5-segmentation-contour/&lt;br /&gt;
&lt;br /&gt;
http://www.isir.upmc.fr/UserFiles/File/clady_homepage/EPU/2-Contour&lt;br /&gt;
&lt;br /&gt;
*Autre&lt;br /&gt;
https://icn.fenelonlille.org/mediawiki/index.php/Projet_ICN_commun_2016/2017&lt;br /&gt;
&lt;br /&gt;
https://www.g33k-zone.org/post/2016/05/11/Configurer-le-Raspberry-Pi-en-point-d-acc%C3%A8s-Wifi&lt;br /&gt;
&lt;br /&gt;
https://blogs.oracle.com/acaicedo/resource/Parallax-I2C/Sensors.java&lt;br /&gt;
&lt;br /&gt;
http://stackoverflow.com/questions/22087076/how-to-make-a-simple-image-upload-using-javascript-html&lt;br /&gt;
&lt;br /&gt;
export http_proxy=http://proxy.polytech-lille.fr:3128&lt;/div&gt;</summary>
		<author><name>Mtrimbur</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=40912</id>
		<title>IMA4 2016/2017 P39</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=40912"/>
				<updated>2017-03-28T17:40:00Z</updated>
		
		<summary type="html">&lt;p&gt;Mtrimbur : /* A faire */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
===Contexte===&lt;br /&gt;
&lt;br /&gt;
Le laser est une technologie largement utilisé de nos jours dans de diverses applications. En effet, on retrouve cette technologie dans le domaine médical notamment pour la chirurgie oculaire ou encore dans industrie avec la découpe laser ou la soudure au laser.&lt;br /&gt;
&lt;br /&gt;
Le laser est une émission de photons produit par excitation d'un milieu amplificateur (ex : CO2), le rayonnement produit est unidirectionnel et monochromatique. Ce sont ces propriétés que nous allons exploiter afin réaliser un projecteur laser qui mis en mouvement est capable de dessiner des formes sur une surface à l'instar de systèmes existants utilisés pour des effets lumineux lors de festivités.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
L'objectif du projet est de créer un système de projection laser à plusieurs couleurs (au minimum deux) avec une application web pour programmer les formes à dessiner afin d'agrémenter des compétitions de gymnastique rythmique.&lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
Le projet consiste à réaliser avec des lasers des figures géométriques par l'intermédiaire d'un système galvanométrique. &lt;br /&gt;
&lt;br /&gt;
Notre premier travail sera de concevoir la partie projection. Pour cela, nous devrons aligner les lasers et les galvanomètres. En effet, ces derniers posséderont des miroirs à l'extrémité, ainsi les miroirs changeront d'inclinaison suivant le courant traversant les galvanomètres (similaire à l'image ci-contre). Il nous faudra également créer un système d'alimentation qui à partir d'une même source (réseau 230 V) sera capable d'alimenter les lasers et les galvanomètres ainsi qu'une Arduino et une Raspberry Pi.&lt;br /&gt;
[[File:Scanhead.jpeg|thumb]]&lt;br /&gt;
&lt;br /&gt;
Ensuite nous nous intéresserons à l'utilisation d'un système embarqué pour contrôler les galvanomètres et donc dessiner avec les lasers sur un plan 2D. En effet, le laser restera toujours fixe, seuls les galvanomètres, et donc les miroirs bougeront. Les galvanomètres étant contrôlés en courant il faudra réaliser une interface électronique pour convertir une commande en tension en commande de courant. La commande en tension sera assuré par une carte Arduino. Nous n'utiliserons qu'une seule paire de galvanomètres pour les deux laser. Il faudra donc multiplexer les deux faisceaux. La programmation des formes à effectuer, se fera par l'intermédiaire d'une application web PHP hébergée sur une RaspberryPi qui permettra de récupérer une image, d'y appliquer divers traitements et filtres afin d'en extraire les contours, et de calculer les commandes pour positionner les galvanomètres. Un serveur WebSocket également hébergé sur la RaspberryPi servira d'interface entre l'application web et L'arduino qui sera connecté via une liaison série sur la raspberryPI.&lt;br /&gt;
&lt;br /&gt;
Comme animation de test, nous dessinerons le contour d'une gymnaste avec une couleur et son ballon d'une autre couleur. La gymnaste devra lancer son ballon, réaliser quelques difficultés et récupérer son ballon.&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
Nous utiliserons comme matériels :&lt;br /&gt;
*Deux lasers de différentes couleurs&lt;br /&gt;
*Une paire de galvanomètres à miroir&lt;br /&gt;
*Arduino&lt;br /&gt;
*Raspberry Pi3&lt;br /&gt;
*Alimentation 230V/5V 1A [http://www.miniinthebox.com/fr/dual-usb-eu-prise-murale-5v-2a-voyage-adaptateur-chargeur-d-alimentation-pour-iphone7-6-xiaomi-samsung-et-autre-telephone-portable_p5410410.html?currency=EUR&amp;amp;litb_from=paid_adwords_shopping&amp;amp;sku=429_6917%7C752_20648&amp;amp;utm_source=google_shopping&amp;amp;utm_medium=cpc&amp;amp;adword_mt=&amp;amp;adword_ct=138705676724&amp;amp;adword_kw=&amp;amp;adword_pos=1o5&amp;amp;adword_pl=&amp;amp;adword_net=g&amp;amp;adword_tar=&amp;amp;adw_src_id=9653316068_661261352_33588296076_aud-79897721311:pla-256966386459&amp;amp;gclid=Cj0KEQiA_KvEBRCtzNil4-KR-LIBEiQAmgekFxxKjJJWBYCJlDZEa3Ke_2_WR0DzGVbz-jaCZHVIBoMaAvld8P8HAQ]&lt;br /&gt;
*Drivers galvanomètres x2&lt;br /&gt;
*Alimentation laser&lt;br /&gt;
*Lunette de sécurité x2 [https://www.amazon.fr/Uvex-S1933X-Eyewear-SCTOrange-Anti-Fog/dp/B000USRG90/ref=sr_1_1?ie=UTF8&amp;amp;qid=1485441383&amp;amp;sr=8-1&amp;amp;keywords=uvex+s1933x]&lt;br /&gt;
*Boitier ABS [http://fr.farnell.com/multicomp/g3118/boitier-abs-240x120x60mm-ip65/dp/1526656]&lt;br /&gt;
*DAC 4 canaux, avec interface I²C [https://www.adafruit.com/products/1083]&lt;br /&gt;
*Connecteur C14 [http://www.conrad.fr/ce/fr/product/715001/Connecteur-secteur-C14-Embase-male-verticale-715001-Nombre-de-poles-2-PE-10-A-noir-1-pcs/?ref=detview1&amp;amp;rt=detview1&amp;amp;rb=1]&lt;br /&gt;
*Câble secteur&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Logiciel :&lt;br /&gt;
&lt;br /&gt;
*Serveur web : Apache2, HTML5, PHP5, CSS&lt;br /&gt;
*Base de donnée : MySQL&lt;br /&gt;
*Serveur WebSocket : JQuerry, websocket&lt;br /&gt;
*Arduino : IDE Arduino&lt;br /&gt;
&lt;br /&gt;
===Calendrier prévisionnel===&lt;br /&gt;
&lt;br /&gt;
====Liste des tâches à effectuer====&lt;br /&gt;
Les différentes tâches à effectuer sont :&lt;br /&gt;
*Partie préliminaire : étude de fonctionnement des galvanomètres&lt;br /&gt;
**Déterminer comment est effectuée la commande des galvanomètres (protocole, tension...)&lt;br /&gt;
**Effectuer des tests avec l'Arduino ou la Raspberry Pi&lt;br /&gt;
**Effectuer des tests avec une LED à la place du laser &lt;br /&gt;
*Partie projection&lt;br /&gt;
**Fixer les lasers&lt;br /&gt;
**Aligner les lasers et les galvanomètres&lt;br /&gt;
**Créer le système d'alimentation&lt;br /&gt;
**Création d'un boitier&lt;br /&gt;
*Partie système embarqué&lt;br /&gt;
**Asservissement des galvanomètres avec l'Arduino&lt;br /&gt;
**Système électronique de commande en courant pour les galvanomètres&lt;br /&gt;
*Interface Web&lt;br /&gt;
**Installation et configuration Apache2&lt;br /&gt;
**Création d'une interface graphique simple&lt;br /&gt;
**Implémentation d'algorithmes de traitement d'image&lt;br /&gt;
**Mise en forme avec des CSS&lt;br /&gt;
**Sytème d'authentification avec mot de passe&lt;br /&gt;
**Utilisation d'une base de données pour enregistrer toutes les images déjà utilisés afin de les réutiliser&lt;br /&gt;
*Serveur Web Socket&lt;br /&gt;
**Récupération des données de l'interface web&lt;br /&gt;
**Mise en place de la liaison série avec l'Arduino&lt;br /&gt;
&lt;br /&gt;
====Calendrier====&lt;br /&gt;
Répartition du temps consacré au projet (240h) :&lt;br /&gt;
*Partie projection : 80h&lt;br /&gt;
*Partie système embarqué : 40h&lt;br /&gt;
*Partie interface web et websocket: 120h&lt;br /&gt;
&lt;br /&gt;
==Feuille d'heures==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!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&lt;br /&gt;
|-&lt;br /&gt;
| Définition cahier des charges &lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 14&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|38&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Finalisation du cahier des charges avec les responsables&lt;br /&gt;
&lt;br /&gt;
*Acquisition de matériels :&lt;br /&gt;
**Projecteur Laser&lt;br /&gt;
**Galvanomètres&lt;br /&gt;
**Alimentation des galvanomètres&lt;br /&gt;
&lt;br /&gt;
*Listage du matériels à acquérir :&lt;br /&gt;
**Lunettes de sécurité&lt;br /&gt;
**DAC&lt;br /&gt;
**Alimentation 230V/5V 1A&lt;br /&gt;
** Boitier ABS &lt;br /&gt;
**...&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
*Obtention de l'arduino et de la raspberryPI&lt;br /&gt;
&lt;br /&gt;
*Démontage du projecteur laser&lt;br /&gt;
**Deux lasers de classe 3b (vert et rouge)&lt;br /&gt;
**Circuit d'alimentation des deux lasers&lt;br /&gt;
&lt;br /&gt;
*Initialisation du port série de la raspberryPI&lt;br /&gt;
**Modification du fichier ''config.txt'' dans la partition boot&lt;br /&gt;
**Ajout d'une ligne autorisant la communication série ('''enable_uart=1''')&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
*Installation du serveur apache sur la raspberryPI&lt;br /&gt;
**Modification du fichier ''/etc/network/interfaces'' (Static, Address, Netmask, Gateway)&lt;br /&gt;
**Modification du fichier ''/etc/resolv.conf'' (Adresse du serveur)&lt;br /&gt;
**Utilisation d'un proxy pour la récupération outils de programmation (Apache2, Php5)&lt;br /&gt;
&lt;br /&gt;
*Mise en place du point d’accès wifi de la raspberryPI&lt;br /&gt;
**Récupération des logiciels nécessaires (dnsmasq, hostapd)&lt;br /&gt;
**Mise en place d'une adresse IP statique pour le point d'accès par l'intermédiaire du fichier ''/etc/dhcpcd.conf''&lt;br /&gt;
**Désactivation de la négociation automatique de bail dans le fichier ''/etc/network/interfaces''&lt;br /&gt;
**Configuration du logiciel hostapd ''/etc/hostapd/hostapd.conf''&lt;br /&gt;
**Activation du démarrage automatique du point d'accès ''/etc/default/hostapd''&lt;br /&gt;
**Configuration du serveur DNS par ''/etc/dnsmasq.conf''&lt;br /&gt;
&lt;br /&gt;
*Instauration de la page d'accueil de l'interface web à l'adresse ''192.168.3.1''&lt;br /&gt;
**Téléversement de fichiers images sur la page web et affichage de celle-ci&lt;br /&gt;
**Voyant de confirmation du bon fonctionnement du serveur web&lt;br /&gt;
&lt;br /&gt;
*Développement du serveur websocket&lt;br /&gt;
&lt;br /&gt;
Le développement du serveur websocket, initialement prévu en C (il était prévu de reprendre les sources utilisées l'année précédente dans le cadre des projet IMA3 SC), a finalement été réalisé en JAVA pour plusieurs raisons.&lt;br /&gt;
Premièrement, un seul programme met en œuvre le serveur websocket, les divers traitements d'image, ainsi que les contrôles des galvanomètres (par l'intermédiaire des DAC) via la liaison I²C de la Raspberry Pi. Le langage JAVA fournit nativement des bibliothèques d'objets pour manipuler assez simplement des images, il existe également des librairies pour contrôler le port GPIO de la Raspberry et il était également intéressant de travailler avec un langage de plus haut niveau que le C.&lt;br /&gt;
En outre, la totale portabilité de ce langage nous permet de travailler sur n'importe quelle machine et ensuite transférer notre programme sur la Raspberry Pi et l’exécuter sans même repasser par une phase de compilation. Et finalement, c'est le langage que nous étudions actuellement en cours de programmation orientée objet, ce qui permet de nous perfectionner.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Serveur WebSocket====&lt;br /&gt;
&lt;br /&gt;
N'ayant pas trouvé d'API WebSocket en Java satisfaisante (qui ne nécessitent pas l'installation et la configuration de nombreux outils additionnels), j'ai estimé plus commode et plus formateur de développer notre propre serveur WebSocket en se basant sur les librairies sockets de Java avec l'aide d'une documentation assez exhaustive [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers].&lt;br /&gt;
&lt;br /&gt;
Les WebSockets désignent à la fois un protocole réseau qui étend le protocole TCP ainsi qu'une API du World Wide Web. Nous nous en servons afin d'établir une communication asynchrone et bidirectionnelle entre un navigateur web et le serveur, notamment pour envoyer l'image à projeter. L’implémentation du serveur repose sur plusieurs étapes.&lt;br /&gt;
&lt;br /&gt;
1) Connexion d'un client &lt;br /&gt;
&lt;br /&gt;
2) Handshake : permet de faire le lien entre le protocole HTTP et WS. Le client envoie une requête HTTP demandant un upgrade de la connexion en protocole WS et le serveur répond en configurant la connexion (détail dans la documentation [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers]).&lt;br /&gt;
&lt;br /&gt;
3) Réception et décodage des messages : le serveurs reçoit des trames brutes, on extrait donc la taille du message ainsi que le message. De plus, les données son encodées (cryptage XOR) par un masque qui doit également être extrait.&lt;br /&gt;
&lt;br /&gt;
4) Fermeture de la communication.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le serveur supporte le multi-client il est donc nécessaire qu'il effectue ces étapes en &amp;quot;parallèle&amp;quot;. Nous utilisons donc les threads ou fils d’exécution. Un thread est donc responsable d'attendre qu'un nouveau client se connecte et effectue le &amp;quot;handshake&amp;quot;, il crée ensuite un thread associé à ce client afin d'établir un canal de communication. Il y a donc au moins un thread par client. Par la suite il faudra également implémenter une déconnexion automatique d'un client notamment après un timeout.&lt;br /&gt;
&lt;br /&gt;
Exemple d’exécution du serveur avec deux clients qui se connectent et envoient un message : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testServeur.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Les clients sont des navigateurs web. Pour les tests nous avons repris les exemples utilisés dans le cadre das projets IMA3 SC avec le titre de la page HTML qui se colore en vert lorsque le client est connecté, et un champ de saisie pour envoyer des messages au serveur : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testClient.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 4===&lt;br /&gt;
&lt;br /&gt;
*Mise en place d’algorithmes de traitement d'image&lt;br /&gt;
&lt;br /&gt;
====Détection de contour====&lt;br /&gt;
&lt;br /&gt;
L'objectif de notre projet est de pouvoir projeter n'importe quelle image envoyé grâce à l'application web. Pour cela nous allons tracer à une vitesse élevée les contours de l'image sur par exemple un mur grâce au laser. Il est donc nécessaire de détecter les contours de l'image grâce à plusieurs traitements.&lt;br /&gt;
&lt;br /&gt;
=====Conversion en niveau de gris=====&lt;br /&gt;
&lt;br /&gt;
Une des étapes préliminaires pour effectuer la détection de contour est de convertir l'image couleur en niveau de gris. Pour cela l'algorithme est simple : il suffit pour chaque pixel de l'image d'effectuer la moyenne des composantes rouge, verte, bleu de chaque pixel. En effet, si l'on considère une image matricielle (l'image est considérée comme un tableau à deux dimensions avec chaque case qui contient la couleur du pixel), chaque pixel contient les composantes RGB codées sur un octet. La couleur gris correspond aux composantes RGB égales. Le niveau de gris est donc codé de 0 à 255, avec 0 donnant du noir et 255 du blanc. &lt;br /&gt;
&lt;br /&gt;
Voici le résultat obtenu : [[Fichier:testGrayScale.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Filtre de Prewit et Sobel=====&lt;br /&gt;
&lt;br /&gt;
Un contour est défini par un changement brutal d'intensité lumineuse, il s'agit donc de détecter selon plusieurs directions (au moins 2) ces changements. Il existe de nombreuses techniques afin de détecter les contours d'une image (gradient, Laplacien). L'une des techniques avec un rapport efficacité/temps d'exécution correct repose sur les algorithmes de Prewit ou Sobel. L'algorithme repose sur la convolution de matrices.&lt;br /&gt;
Cela consiste à appliquer sur chaque pixel de l'image la matrice de Prewit définie comme &lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L_x = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; ainsi que sa transposée : &amp;lt;math&amp;gt;&lt;br /&gt;
L_y = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; -1 &amp;amp; -1 \\&lt;br /&gt;
 0 &amp;amp; 0 &amp;amp; 0 \\&lt;br /&gt;
+1 &amp;amp; +1 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Convoluer ces deux filtres sur l'image permet de détecter respectivement les contours verticaux et horizontaux.&lt;br /&gt;
&lt;br /&gt;
D'après wikipedia [https://fr.wikipedia.org/wiki/D%C3%A9tection_de_contours], on obtient de meilleurs résultats en appliquant un filtre triangulaire, on introduit donc la matrice de Sobel :&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-2 &amp;amp; 0 &amp;amp; +2 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
On obtient le résultat suivant : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testOutline1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Pré-traitement : Flou Gaussien=====&lt;br /&gt;
&lt;br /&gt;
Afin de réduire significativement le nombre de contours, il est nécessaire d'effectuer un pré-traitement avant la détection de contours. On utilise généralement un flou gaussien afin de réduire les transitions lumineuses et ainsi réduire le nombre de contours. L’algorithme de flou gaussien repose également sur la convolution de matrices sauf qu'ici la matrice filtre est générée grâce à une fonction gaussienne paramétrée par '''Sigma''' qui va directement impacter le niveau de flou. Plus la matrice de filtrage est grande plus la qualité du résultat est meilleure, mais le temps d’exécution devient également plus grand.&lt;br /&gt;
&lt;br /&gt;
Voici la fonction de génération du filtre : &amp;lt;math&amp;gt;G(x,y) = \frac{1}{{2\pi \sigma^2}} e^{-\frac{x^2 + y^2}{2 \sigma^2}}&amp;lt;/math&amp;gt; où x et y correspondent aux indices de la cellule de la matrice.&lt;br /&gt;
&lt;br /&gt;
On obtient ce résultat :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testGaussianBlur.png]]&lt;br /&gt;
&lt;br /&gt;
On note un bien meilleur résultat. Cependant on remarque que les composantes horizontales ne sont pas correctement détectées il subsiste un problème avec le filtrage vertical que je n'ai pas réussi à identifier. De plus, il s'agit par sa suite d'éliminer les contours parasites ainsi que d'affiner le trait pour n'avoir plus qu'un pixel d'épaisseur.&lt;br /&gt;
&lt;br /&gt;
=====Post-traitement : Algorithme de Canny=====&lt;br /&gt;
&lt;br /&gt;
Afin d'obtenir un résultat exploitable il est nécessaire d'appliquer encore quelques traitements. Pour cela nous utilisons l’algorithme de Canny qui repose que celui de Sobel mais qui ajoute un algorithme de seuillage par hysteresis qui permet de retirer les contours secondaires et de ne garder que les contours connexes dans une seuil haut et un seuil bas définis. En outre, cette algorithme affine également le trait obtenu. Pour cet algorithme nous avons directement trouvé des sources libres de droits [http://www.tomgibara.com/computer-vision/canny-edge-detector] qui donne des résultats très corrects.&lt;br /&gt;
&lt;br /&gt;
Par exemple :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ou encore : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny2.png|1500px]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 5===&lt;br /&gt;
&lt;br /&gt;
*Établissement d'un protocole de transfert d'image basé sur les WebSockets&lt;br /&gt;
**Envoie d'un requête &amp;quot;send&amp;quot; par le client dans une trame websocket texte&lt;br /&gt;
**Réponse serveur 'Y' si aucun autre client tente d'envoyer une image simultanément, 'N' sinon&lt;br /&gt;
**Si et seulement si le client reçoit 'Y' il débute le transfert en envoyant la largeur et la longueur de l'image sur 4 octets, puis les données de l'image soit 4 valeurs pour chaque pixels (r,g,b,alpha)&lt;br /&gt;
**Le serveur renvoie 'D' une fois le transfert achevé (à l'avenir, le serveur renverra l'image après filtrage).&lt;br /&gt;
**A tout moment, le serveur peut renvoyer 'E' si une erreur est survenue (ex : paquets perdus, nombre incorrects de données)&lt;br /&gt;
*Ajout du support des logs au niveau serveur&lt;br /&gt;
**Impression sur la sortie standard des messages&lt;br /&gt;
**Formatage en fonction de la sévérité du log (info, warning, error...)&lt;br /&gt;
**Incrustation de la date et heure&lt;br /&gt;
**Possibilité de redirection dans une fichier, avec configuration (écriture à la suite d'un fichier existant, écrasement...)&lt;br /&gt;
**Le tout dans une classe Java flexible et réutilisable pour d'autres projets&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 6===&lt;br /&gt;
&lt;br /&gt;
*Installation de la librairie Java Pi4j sur la raspberry pi qui permet le contrôle des GPIO de celle-ci et notamment le port I²C (basé sur WiringPi)&lt;br /&gt;
*Amélioration coté serveur websocket&lt;br /&gt;
**Gestion de message plus longs (maximum des trames websockets soit 2^63 octets)&lt;br /&gt;
**Différenciation, à la réception de messages, des trames textes ou binaires des trames de contrôle comme les requête ping, pong ou de fermeture de connexion &lt;br /&gt;
**Ajout d'un mode de debug de trames &lt;br /&gt;
&lt;br /&gt;
===Semaine 7===&lt;br /&gt;
&lt;br /&gt;
*Améliorations du serveur WebSocket&lt;br /&gt;
**Gestion de la fragmentation TCP&lt;br /&gt;
**Gestion de la fragmentation WebSocket&lt;br /&gt;
**Gestion des requêtes ping envoyés par le client en renvoyant une trames de contrôle pong afin de maintenir la connexion&lt;br /&gt;
**Gestion des déconnexion de clients afin d'optimiser le serveur&lt;br /&gt;
**Amélioration de l'émission de messages en augmentant la taille maximale pouvant être émise (2^63 octets)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A ce stade du développement, le client et le serveur sont opérationnels et peuvent s'échanger des messages ainsi que des images que le serveur traite pour extraire les contours.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 8===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Montage projecteur&lt;br /&gt;
**Intégralité des composants fixés par vis dans le boîtier ABS&lt;br /&gt;
**Fusion des alimentations&lt;br /&gt;
**Présence d'une led témoin de mise en tension&lt;br /&gt;
**Position laser réglable grâce à une vis&lt;br /&gt;
**Présence d'un switch à bascule pour allumer et éteindre le laser&lt;br /&gt;
**Isolation et vérification des composants&lt;br /&gt;
**Tests empiriques de température et de fonctionnement des lasers et galvanomètres&lt;br /&gt;
&lt;br /&gt;
Le montage boîtier est donc terminé et s’alimente en 230V par intermédiaire d'un câble secteur avec connecteur C14. Le résultat s'avère plutôt compact. Les quelques tests de température ont montrés que malgré le manque d'espace la température globale du boîtier ne dépasse pas les 50°C pendant plus d'une heure de fonctionnement. L'intégralité des connexions sont isolées avec de la gaine thermodynamique et les zones &amp;quot;sensibles&amp;quot; sont correctement vérifiés ainsi que protégées avec de la matière isolante.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:proj1.jpg|550px|Boîtier après perçage]] [[Fichier:proj2.jpg|550px|Boîtier finalisé]] [[Fichier:proj3.jpg|550px|Projecteur en fonctionnement]]&lt;br /&gt;
&lt;br /&gt;
*Page web et serveur WebSocket&lt;br /&gt;
**Ajout d'un bouton &amp;quot;reboot&amp;quot; et &amp;quot;shutdown&amp;quot; qui permettent respectivement de redémarrer et d'éteindre la Raspberry directement à partir de la page web&lt;br /&gt;
&lt;br /&gt;
===Semaine 9===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 10===&lt;br /&gt;
&lt;br /&gt;
==A faire==&lt;br /&gt;
&lt;br /&gt;
MAJ 26 mars &lt;br /&gt;
&lt;br /&gt;
*Client websocket et page web&lt;br /&gt;
**Mise en page CSS&lt;br /&gt;
**Ajout canvas pour prévisualisation image projeté&lt;br /&gt;
**Ajout &amp;quot;slider&amp;quot; pour régler niveau du flou Gaussien DOUBLE !!&lt;br /&gt;
**Ajout slider pour de finir amplitude de la projection&lt;br /&gt;
**Afficher statut de connexion&lt;br /&gt;
**Ajout message de confirmation quand le serveur quitte ou relance&lt;br /&gt;
**Ajout boutons &amp;quot;projeter&amp;quot; &amp;quot;centrer&amp;quot; &amp;quot;eteindre&amp;quot;&lt;br /&gt;
**Redimensionnement automatique de l'image !!&lt;br /&gt;
**Gestion de plusieurs images avec délai&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Serveur WebSocket&lt;br /&gt;
**Ajout fonctionnalité envoi image de prévisualisation&lt;br /&gt;
&lt;br /&gt;
*RaspberryPi&lt;br /&gt;
**Utilisation d'un serveur bind9 pour éviter de taper IP&lt;br /&gt;
&lt;br /&gt;
*Détection de contours&lt;br /&gt;
**Implémentation algorithme de tri de la plus courte disance&lt;br /&gt;
&lt;br /&gt;
*Commande galvanomêtre&lt;br /&gt;
**Utilisation API I²C&lt;br /&gt;
**Fonction de transfert position-&amp;gt;angle-&amp;gt;tension&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;br /&gt;
&lt;br /&gt;
==Bibliographie==&lt;br /&gt;
&lt;br /&gt;
*Galvanomètres et laser&lt;br /&gt;
http://www.ebay.com/itm/20KPPS-30KPPS-laser-scanning-galvo-scanner-ILDA-Closed-Loop-max-30kpps-for-laser-/261517002270?hash=item3ce3a0c61e&lt;br /&gt;
&lt;br /&gt;
http://sciences.ulb.ac.be/printemps/download/2016/dossier_pedagogique/02.pdf&lt;br /&gt;
&lt;br /&gt;
*Websocket&lt;br /&gt;
http://stackoverflow.com/questions/8125507/how-can-i-send-and-receive-websocket-messages-on-the-server-side&lt;br /&gt;
&lt;br /&gt;
https://tools.ietf.org/html/rfc6455&lt;br /&gt;
&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_a_WebSocket_server_in_Java&lt;br /&gt;
&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers&lt;br /&gt;
&lt;br /&gt;
*Traitement d'image&lt;br /&gt;
https://en.wikipedia.org/wiki/Gaussian_blur&lt;br /&gt;
&lt;br /&gt;
http://www.zebulon.fr/questions-reponses/traitement-d-image-detection-de-contours-55.html&lt;br /&gt;
&lt;br /&gt;
http://patrick-bonnin.developpez.com/cours/vision/apprendre-bases-traitement-image/partie-5-segmentation-contour/&lt;br /&gt;
&lt;br /&gt;
http://www.isir.upmc.fr/UserFiles/File/clady_homepage/EPU/2-Contour&lt;br /&gt;
&lt;br /&gt;
*Autre&lt;br /&gt;
https://icn.fenelonlille.org/mediawiki/index.php/Projet_ICN_commun_2016/2017&lt;br /&gt;
&lt;br /&gt;
https://www.g33k-zone.org/post/2016/05/11/Configurer-le-Raspberry-Pi-en-point-d-acc%C3%A8s-Wifi&lt;br /&gt;
&lt;br /&gt;
https://blogs.oracle.com/acaicedo/resource/Parallax-I2C/Sensors.java&lt;br /&gt;
&lt;br /&gt;
http://stackoverflow.com/questions/22087076/how-to-make-a-simple-image-upload-using-javascript-html&lt;br /&gt;
&lt;br /&gt;
export http_proxy=http://proxy.polytech-lille.fr:3128&lt;/div&gt;</summary>
		<author><name>Mtrimbur</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=40835</id>
		<title>IMA4 2016/2017 P39</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=40835"/>
				<updated>2017-03-27T18:23:44Z</updated>
		
		<summary type="html">&lt;p&gt;Mtrimbur : /* Bibliographie */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
===Contexte===&lt;br /&gt;
&lt;br /&gt;
Le laser est une technologie largement utilisé de nos jours dans de diverses applications. En effet, on retrouve cette technologie dans le domaine médical notamment pour la chirurgie oculaire ou encore dans industrie avec la découpe laser ou la soudure au laser.&lt;br /&gt;
&lt;br /&gt;
Le laser est une émission de photons produit par excitation d'un milieu amplificateur (ex : CO2), le rayonnement produit est unidirectionnel et monochromatique. Ce sont ces propriétés que nous allons exploiter afin réaliser un projecteur laser qui mis en mouvement est capable de dessiner des formes sur une surface à l'instar de systèmes existants utilisés pour des effets lumineux lors de festivités.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
L'objectif du projet est de créer un système de projection laser à plusieurs couleurs (au minimum deux) avec une application web pour programmer les formes à dessiner afin d'agrémenter des compétitions de gymnastique rythmique.&lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
Le projet consiste à réaliser avec des lasers des figures géométriques par l'intermédiaire d'un système galvanométrique. &lt;br /&gt;
&lt;br /&gt;
Notre premier travail sera de concevoir la partie projection. Pour cela, nous devrons aligner les lasers et les galvanomètres. En effet, ces derniers posséderont des miroirs à l'extrémité, ainsi les miroirs changeront d'inclinaison suivant le courant traversant les galvanomètres (similaire à l'image ci-contre). Il nous faudra également créer un système d'alimentation qui à partir d'une même source (réseau 230 V) sera capable d'alimenter les lasers et les galvanomètres ainsi qu'une Arduino et une Raspberry Pi.&lt;br /&gt;
[[File:Scanhead.jpeg|thumb]]&lt;br /&gt;
&lt;br /&gt;
Ensuite nous nous intéresserons à l'utilisation d'un système embarqué pour contrôler les galvanomètres et donc dessiner avec les lasers sur un plan 2D. En effet, le laser restera toujours fixe, seuls les galvanomètres, et donc les miroirs bougeront. Les galvanomètres étant contrôlés en courant il faudra réaliser une interface électronique pour convertir une commande en tension en commande de courant. La commande en tension sera assuré par une carte Arduino. Nous n'utiliserons qu'une seule paire de galvanomètres pour les deux laser. Il faudra donc multiplexer les deux faisceaux. La programmation des formes à effectuer, se fera par l'intermédiaire d'une application web PHP hébergée sur une RaspberryPi qui permettra de récupérer une image, d'y appliquer divers traitements et filtres afin d'en extraire les contours, et de calculer les commandes pour positionner les galvanomètres. Un serveur WebSocket également hébergé sur la RaspberryPi servira d'interface entre l'application web et L'arduino qui sera connecté via une liaison série sur la raspberryPI.&lt;br /&gt;
&lt;br /&gt;
Comme animation de test, nous dessinerons le contour d'une gymnaste avec une couleur et son ballon d'une autre couleur. La gymnaste devra lancer son ballon, réaliser quelques difficultés et récupérer son ballon.&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
Nous utiliserons comme matériels :&lt;br /&gt;
*Deux lasers de différentes couleurs&lt;br /&gt;
*Une paire de galvanomètres à miroir&lt;br /&gt;
*Arduino&lt;br /&gt;
*Raspberry Pi3&lt;br /&gt;
*Alimentation 230V/5V 1A [http://www.miniinthebox.com/fr/dual-usb-eu-prise-murale-5v-2a-voyage-adaptateur-chargeur-d-alimentation-pour-iphone7-6-xiaomi-samsung-et-autre-telephone-portable_p5410410.html?currency=EUR&amp;amp;litb_from=paid_adwords_shopping&amp;amp;sku=429_6917%7C752_20648&amp;amp;utm_source=google_shopping&amp;amp;utm_medium=cpc&amp;amp;adword_mt=&amp;amp;adword_ct=138705676724&amp;amp;adword_kw=&amp;amp;adword_pos=1o5&amp;amp;adword_pl=&amp;amp;adword_net=g&amp;amp;adword_tar=&amp;amp;adw_src_id=9653316068_661261352_33588296076_aud-79897721311:pla-256966386459&amp;amp;gclid=Cj0KEQiA_KvEBRCtzNil4-KR-LIBEiQAmgekFxxKjJJWBYCJlDZEa3Ke_2_WR0DzGVbz-jaCZHVIBoMaAvld8P8HAQ]&lt;br /&gt;
*Drivers galvanomètres x2&lt;br /&gt;
*Alimentation laser&lt;br /&gt;
*Lunette de sécurité x2 [https://www.amazon.fr/Uvex-S1933X-Eyewear-SCTOrange-Anti-Fog/dp/B000USRG90/ref=sr_1_1?ie=UTF8&amp;amp;qid=1485441383&amp;amp;sr=8-1&amp;amp;keywords=uvex+s1933x]&lt;br /&gt;
*Boitier ABS [http://fr.farnell.com/multicomp/g3118/boitier-abs-240x120x60mm-ip65/dp/1526656]&lt;br /&gt;
*DAC 4 canaux, avec interface I²C [https://www.adafruit.com/products/1083]&lt;br /&gt;
*Connecteur C14 [http://www.conrad.fr/ce/fr/product/715001/Connecteur-secteur-C14-Embase-male-verticale-715001-Nombre-de-poles-2-PE-10-A-noir-1-pcs/?ref=detview1&amp;amp;rt=detview1&amp;amp;rb=1]&lt;br /&gt;
*Câble secteur&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Logiciel :&lt;br /&gt;
&lt;br /&gt;
*Serveur web : Apache2, HTML5, PHP5, CSS&lt;br /&gt;
*Base de donnée : MySQL&lt;br /&gt;
*Serveur WebSocket : JQuerry, websocket&lt;br /&gt;
*Arduino : IDE Arduino&lt;br /&gt;
&lt;br /&gt;
===Calendrier prévisionnel===&lt;br /&gt;
&lt;br /&gt;
====Liste des tâches à effectuer====&lt;br /&gt;
Les différentes tâches à effectuer sont :&lt;br /&gt;
*Partie préliminaire : étude de fonctionnement des galvanomètres&lt;br /&gt;
**Déterminer comment est effectuée la commande des galvanomètres (protocole, tension...)&lt;br /&gt;
**Effectuer des tests avec l'Arduino ou la Raspberry Pi&lt;br /&gt;
**Effectuer des tests avec une LED à la place du laser &lt;br /&gt;
*Partie projection&lt;br /&gt;
**Fixer les lasers&lt;br /&gt;
**Aligner les lasers et les galvanomètres&lt;br /&gt;
**Créer le système d'alimentation&lt;br /&gt;
**Création d'un boitier&lt;br /&gt;
*Partie système embarqué&lt;br /&gt;
**Asservissement des galvanomètres avec l'Arduino&lt;br /&gt;
**Système électronique de commande en courant pour les galvanomètres&lt;br /&gt;
*Interface Web&lt;br /&gt;
**Installation et configuration Apache2&lt;br /&gt;
**Création d'une interface graphique simple&lt;br /&gt;
**Implémentation d'algorithmes de traitement d'image&lt;br /&gt;
**Mise en forme avec des CSS&lt;br /&gt;
**Sytème d'authentification avec mot de passe&lt;br /&gt;
**Utilisation d'une base de données pour enregistrer toutes les images déjà utilisés afin de les réutiliser&lt;br /&gt;
*Serveur Web Socket&lt;br /&gt;
**Récupération des données de l'interface web&lt;br /&gt;
**Mise en place de la liaison série avec l'Arduino&lt;br /&gt;
&lt;br /&gt;
====Calendrier====&lt;br /&gt;
Répartition du temps consacré au projet (240h) :&lt;br /&gt;
*Partie projection : 80h&lt;br /&gt;
*Partie système embarqué : 40h&lt;br /&gt;
*Partie interface web et websocket: 120h&lt;br /&gt;
&lt;br /&gt;
==Feuille d'heures==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!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&lt;br /&gt;
|-&lt;br /&gt;
| Définition cahier des charges &lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 14&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|38&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Finalisation du cahier des charges avec les responsables&lt;br /&gt;
&lt;br /&gt;
*Acquisition de matériels :&lt;br /&gt;
**Projecteur Laser&lt;br /&gt;
**Galvanomètres&lt;br /&gt;
**Alimentation des galvanomètres&lt;br /&gt;
&lt;br /&gt;
*Listage du matériels à acquérir :&lt;br /&gt;
**Lunettes de sécurité&lt;br /&gt;
**DAC&lt;br /&gt;
**Alimentation 230V/5V 1A&lt;br /&gt;
** Boitier ABS &lt;br /&gt;
**...&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
*Obtention de l'arduino et de la raspberryPI&lt;br /&gt;
&lt;br /&gt;
*Démontage du projecteur laser&lt;br /&gt;
**Deux lasers de classe 3b (vert et rouge)&lt;br /&gt;
**Circuit d'alimentation des deux lasers&lt;br /&gt;
&lt;br /&gt;
*Initialisation du port série de la raspberryPI&lt;br /&gt;
**Modification du fichier ''config.txt'' dans la partition boot&lt;br /&gt;
**Ajout d'une ligne autorisant la communication série ('''enable_uart=1''')&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
*Installation du serveur apache sur la raspberryPI&lt;br /&gt;
**Modification du fichier ''/etc/network/interfaces'' (Static, Address, Netmask, Gateway)&lt;br /&gt;
**Modification du fichier ''/etc/resolv.conf'' (Adresse du serveur)&lt;br /&gt;
**Utilisation d'un proxy pour la récupération outils de programmation (Apache2, Php5)&lt;br /&gt;
&lt;br /&gt;
*Mise en place du point d’accès wifi de la raspberryPI&lt;br /&gt;
**Récupération des logiciels nécessaires (dnsmasq, hostapd)&lt;br /&gt;
**Mise en place d'une adresse IP statique pour le point d'accès par l'intermédiaire du fichier ''/etc/dhcpcd.conf''&lt;br /&gt;
**Désactivation de la négociation automatique de bail dans le fichier ''/etc/network/interfaces''&lt;br /&gt;
**Configuration du logiciel hostapd ''/etc/hostapd/hostapd.conf''&lt;br /&gt;
**Activation du démarrage automatique du point d'accès ''/etc/default/hostapd''&lt;br /&gt;
**Configuration du serveur DNS par ''/etc/dnsmasq.conf''&lt;br /&gt;
&lt;br /&gt;
*Instauration de la page d'accueil de l'interface web à l'adresse ''192.168.3.1''&lt;br /&gt;
**Téléversement de fichiers images sur la page web et affichage de celle-ci&lt;br /&gt;
**Voyant de confirmation du bon fonctionnement du serveur web&lt;br /&gt;
&lt;br /&gt;
*Développement du serveur websocket&lt;br /&gt;
&lt;br /&gt;
Le développement du serveur websocket, initialement prévu en C (il était prévu de reprendre les sources utilisées l'année précédente dans le cadre des projet IMA3 SC), a finalement été réalisé en JAVA pour plusieurs raisons.&lt;br /&gt;
Premièrement, un seul programme met en œuvre le serveur websocket, les divers traitements d'image, ainsi que les contrôles des galvanomètres (par l'intermédiaire des DAC) via la liaison I²C de la Raspberry Pi. Le langage JAVA fournit nativement des bibliothèques d'objets pour manipuler assez simplement des images, il existe également des librairies pour contrôler le port GPIO de la Raspberry et il était également intéressant de travailler avec un langage de plus haut niveau que le C.&lt;br /&gt;
En outre, la totale portabilité de ce langage nous permet de travailler sur n'importe quelle machine et ensuite transférer notre programme sur la Raspberry Pi et l’exécuter sans même repasser par une phase de compilation. Et finalement, c'est le langage que nous étudions actuellement en cours de programmation orientée objet, ce qui permet de nous perfectionner.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Serveur WebSocket====&lt;br /&gt;
&lt;br /&gt;
N'ayant pas trouvé d'API WebSocket en Java satisfaisante (qui ne nécessitent pas l'installation et la configuration de nombreux outils additionnels), j'ai estimé plus commode et plus formateur de développer notre propre serveur WebSocket en se basant sur les librairies sockets de Java avec l'aide d'une documentation assez exhaustive [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers].&lt;br /&gt;
&lt;br /&gt;
Les WebSockets désignent à la fois un protocole réseau qui étend le protocole TCP ainsi qu'une API du World Wide Web. Nous nous en servons afin d'établir une communication asynchrone et bidirectionnelle entre un navigateur web et le serveur, notamment pour envoyer l'image à projeter. L’implémentation du serveur repose sur plusieurs étapes.&lt;br /&gt;
&lt;br /&gt;
1) Connexion d'un client &lt;br /&gt;
&lt;br /&gt;
2) Handshake : permet de faire le lien entre le protocole HTTP et WS. Le client envoie une requête HTTP demandant un upgrade de la connexion en protocole WS et le serveur répond en configurant la connexion (détail dans la documentation [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers]).&lt;br /&gt;
&lt;br /&gt;
3) Réception et décodage des messages : le serveurs reçoit des trames brutes, on extrait donc la taille du message ainsi que le message. De plus, les données son encodées (cryptage XOR) par un masque qui doit également être extrait.&lt;br /&gt;
&lt;br /&gt;
4) Fermeture de la communication.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le serveur supporte le multi-client il est donc nécessaire qu'il effectue ces étapes en &amp;quot;parallèle&amp;quot;. Nous utilisons donc les threads ou fils d’exécution. Un thread est donc responsable d'attendre qu'un nouveau client se connecte et effectue le &amp;quot;handshake&amp;quot;, il crée ensuite un thread associé à ce client afin d'établir un canal de communication. Il y a donc au moins un thread par client. Par la suite il faudra également implémenter une déconnexion automatique d'un client notamment après un timeout.&lt;br /&gt;
&lt;br /&gt;
Exemple d’exécution du serveur avec deux clients qui se connectent et envoient un message : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testServeur.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Les clients sont des navigateurs web. Pour les tests nous avons repris les exemples utilisés dans le cadre das projets IMA3 SC avec le titre de la page HTML qui se colore en vert lorsque le client est connecté, et un champ de saisie pour envoyer des messages au serveur : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testClient.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 4===&lt;br /&gt;
&lt;br /&gt;
*Mise en place d’algorithmes de traitement d'image&lt;br /&gt;
&lt;br /&gt;
====Détection de contour====&lt;br /&gt;
&lt;br /&gt;
L'objectif de notre projet est de pouvoir projeter n'importe quelle image envoyé grâce à l'application web. Pour cela nous allons tracer à une vitesse élevée les contours de l'image sur par exemple un mur grâce au laser. Il est donc nécessaire de détecter les contours de l'image grâce à plusieurs traitements.&lt;br /&gt;
&lt;br /&gt;
=====Conversion en niveau de gris=====&lt;br /&gt;
&lt;br /&gt;
Une des étapes préliminaires pour effectuer la détection de contour est de convertir l'image couleur en niveau de gris. Pour cela l'algorithme est simple : il suffit pour chaque pixel de l'image d'effectuer la moyenne des composantes rouge, verte, bleu de chaque pixel. En effet, si l'on considère une image matricielle (l'image est considérée comme un tableau à deux dimensions avec chaque case qui contient la couleur du pixel), chaque pixel contient les composantes RGB codées sur un octet. La couleur gris correspond aux composantes RGB égales. Le niveau de gris est donc codé de 0 à 255, avec 0 donnant du noir et 255 du blanc. &lt;br /&gt;
&lt;br /&gt;
Voici le résultat obtenu : [[Fichier:testGrayScale.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Filtre de Prewit et Sobel=====&lt;br /&gt;
&lt;br /&gt;
Un contour est défini par un changement brutal d'intensité lumineuse, il s'agit donc de détecter selon plusieurs directions (au moins 2) ces changements. Il existe de nombreuses techniques afin de détecter les contours d'une image (gradient, Laplacien). L'une des techniques avec un rapport efficacité/temps d'exécution correct repose sur les algorithmes de Prewit ou Sobel. L'algorithme repose sur la convolution de matrices.&lt;br /&gt;
Cela consiste à appliquer sur chaque pixel de l'image la matrice de Prewit définie comme &lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L_x = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; ainsi que sa transposée : &amp;lt;math&amp;gt;&lt;br /&gt;
L_y = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; -1 &amp;amp; -1 \\&lt;br /&gt;
 0 &amp;amp; 0 &amp;amp; 0 \\&lt;br /&gt;
+1 &amp;amp; +1 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Convoluer ces deux filtres sur l'image permet de détecter respectivement les contours verticaux et horizontaux.&lt;br /&gt;
&lt;br /&gt;
D'après wikipedia [https://fr.wikipedia.org/wiki/D%C3%A9tection_de_contours], on obtient de meilleurs résultats en appliquant un filtre triangulaire, on introduit donc la matrice de Sobel :&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-2 &amp;amp; 0 &amp;amp; +2 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
On obtient le résultat suivant : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testOutline1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Pré-traitement : Flou Gaussien=====&lt;br /&gt;
&lt;br /&gt;
Afin de réduire significativement le nombre de contours, il est nécessaire d'effectuer un pré-traitement avant la détection de contours. On utilise généralement un flou gaussien afin de réduire les transitions lumineuses et ainsi réduire le nombre de contours. L’algorithme de flou gaussien repose également sur la convolution de matrices sauf qu'ici la matrice filtre est générée grâce à une fonction gaussienne paramétrée par '''Sigma''' qui va directement impacter le niveau de flou. Plus la matrice de filtrage est grande plus la qualité du résultat est meilleure, mais le temps d’exécution devient également plus grand.&lt;br /&gt;
&lt;br /&gt;
Voici la fonction de génération du filtre : &amp;lt;math&amp;gt;G(x,y) = \frac{1}{{2\pi \sigma^2}} e^{-\frac{x^2 + y^2}{2 \sigma^2}}&amp;lt;/math&amp;gt; où x et y correspondent aux indices de la cellule de la matrice.&lt;br /&gt;
&lt;br /&gt;
On obtient ce résultat :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testGaussianBlur.png]]&lt;br /&gt;
&lt;br /&gt;
On note un bien meilleur résultat. Cependant on remarque que les composantes horizontales ne sont pas correctement détectées il subsiste un problème avec le filtrage vertical que je n'ai pas réussi à identifier. De plus, il s'agit par sa suite d'éliminer les contours parasites ainsi que d'affiner le trait pour n'avoir plus qu'un pixel d'épaisseur.&lt;br /&gt;
&lt;br /&gt;
=====Post-traitement : Algorithme de Canny=====&lt;br /&gt;
&lt;br /&gt;
Afin d'obtenir un résultat exploitable il est nécessaire d'appliquer encore quelques traitements. Pour cela nous utilisons l’algorithme de Canny qui repose que celui de Sobel mais qui ajoute un algorithme de seuillage par hysteresis qui permet de retirer les contours secondaires et de ne garder que les contours connexes dans une seuil haut et un seuil bas définis. En outre, cette algorithme affine également le trait obtenu. Pour cet algorithme nous avons directement trouvé des sources libres de droits [http://www.tomgibara.com/computer-vision/canny-edge-detector] qui donne des résultats très corrects.&lt;br /&gt;
&lt;br /&gt;
Par exemple :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ou encore : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny2.png|1500px]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 5===&lt;br /&gt;
&lt;br /&gt;
*Établissement d'un protocole de transfert d'image basé sur les WebSockets&lt;br /&gt;
**Envoie d'un requête &amp;quot;send&amp;quot; par le client dans une trame websocket texte&lt;br /&gt;
**Réponse serveur 'Y' si aucun autre client tente d'envoyer une image simultanément, 'N' sinon&lt;br /&gt;
**Si et seulement si le client reçoit 'Y' il débute le transfert en envoyant la largeur et la longueur de l'image sur 4 octets, puis les données de l'image soit 4 valeurs pour chaque pixels (r,g,b,alpha)&lt;br /&gt;
**Le serveur renvoie 'D' une fois le transfert achevé (à l'avenir, le serveur renverra l'image après filtrage).&lt;br /&gt;
**A tout moment, le serveur peut renvoyer 'E' si une erreur est survenue (ex : paquets perdus, nombre incorrects de données)&lt;br /&gt;
*Ajout du support des logs au niveau serveur&lt;br /&gt;
**Impression sur la sortie standard des messages&lt;br /&gt;
**Formatage en fonction de la sévérité du log (info, warning, error...)&lt;br /&gt;
**Incrustation de la date et heure&lt;br /&gt;
**Possibilité de redirection dans une fichier, avec configuration (écriture à la suite d'un fichier existant, écrasement...)&lt;br /&gt;
**Le tout dans une classe Java flexible et réutilisable pour d'autres projets&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 6===&lt;br /&gt;
&lt;br /&gt;
*Installation de la librairie Java Pi4j sur la raspberry pi qui permet le contrôle des GPIO de celle-ci et notamment le port I²C (basé sur WiringPi)&lt;br /&gt;
*Amélioration coté serveur websocket&lt;br /&gt;
**Gestion de message plus longs (maximum des trames websockets soit 2^63 octets)&lt;br /&gt;
**Différenciation, à la réception de messages, des trames textes ou binaires des trames de contrôle comme les requête ping, pong ou de fermeture de connexion &lt;br /&gt;
**Ajout d'un mode de debug de trames &lt;br /&gt;
&lt;br /&gt;
===Semaine 7===&lt;br /&gt;
&lt;br /&gt;
*Améliorations du serveur WebSocket&lt;br /&gt;
**Gestion de la fragmentation TCP&lt;br /&gt;
**Gestion de la fragmentation WebSocket&lt;br /&gt;
**Gestion des requêtes ping envoyés par le client en renvoyant une trames de contrôle pong afin de maintenir la connexion&lt;br /&gt;
**Gestion des déconnexion de clients afin d'optimiser le serveur&lt;br /&gt;
**Amélioration de l'émission de messages en augmentant la taille maximale pouvant être émise (2^63 octets)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A ce stade du développement, le client et le serveur sont opérationnels et peuvent s'échanger des messages ainsi que des images que le serveur traite pour extraire les contours.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 8===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Montage projecteur&lt;br /&gt;
**Intégralité des composants fixés par vis dans le boîtier ABS&lt;br /&gt;
**Fusion des alimentations&lt;br /&gt;
**Présence d'une led témoin de mise en tension&lt;br /&gt;
**Position laser réglable grâce à une vis&lt;br /&gt;
**Présence d'un switch à bascule pour allumer et éteindre le laser&lt;br /&gt;
**Isolation et vérification des composants&lt;br /&gt;
**Tests empiriques de température et de fonctionnement des lasers et galvanomètres&lt;br /&gt;
&lt;br /&gt;
Le montage boîtier est donc terminé et s’alimente en 230V par intermédiaire d'un câble secteur avec connecteur C14. Le résultat s'avère plutôt compact. Les quelques tests de température ont montrés que malgré le manque d'espace la température globale du boîtier ne dépasse pas les 50°C pendant plus d'une heure de fonctionnement. L'intégralité des connexions sont isolées avec de la gaine thermodynamique et les zones &amp;quot;sensibles&amp;quot; sont correctement vérifiés ainsi que protégées avec de la matière isolante.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:proj1.jpg|550px|Boîtier après perçage]] [[Fichier:proj2.jpg|550px|Boîtier finalisé]] [[Fichier:proj3.jpg|550px|Projecteur en fonctionnement]]&lt;br /&gt;
&lt;br /&gt;
*Page web et serveur WebSocket&lt;br /&gt;
**Ajout d'un bouton &amp;quot;reboot&amp;quot; et &amp;quot;shutdown&amp;quot; qui permettent respectivement de redémarrer et d'éteindre la Raspberry directement à partir de la page web&lt;br /&gt;
&lt;br /&gt;
===Semaine 9===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 10===&lt;br /&gt;
&lt;br /&gt;
==A faire==&lt;br /&gt;
&lt;br /&gt;
MAJ 26 mars &lt;br /&gt;
&lt;br /&gt;
*Client websocket et page web&lt;br /&gt;
**Mise en page CSS&lt;br /&gt;
**Ajout canvas pour prévisualisation image projeté&lt;br /&gt;
**Ajout &amp;quot;slider&amp;quot; pour régler niveau du flou Gaussien DOUBLE&lt;br /&gt;
**Ajout slider pour de finir amplitude de la projection&lt;br /&gt;
**Afficher statut de connexion&lt;br /&gt;
**Ajout message de confirmation quand le serveur quitte ou relance&lt;br /&gt;
**Ajout boutons &amp;quot;projeter&amp;quot; &amp;quot;centrer&amp;quot; &amp;quot;eteindre&amp;quot;&lt;br /&gt;
**Gestion de plusieurs images avec délai&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Serveur WebSocket&lt;br /&gt;
**Ajout fonctionnalité envoi image de prévisualisation&lt;br /&gt;
&lt;br /&gt;
*RaspberryPi&lt;br /&gt;
**Utilisation d'un serveur bind9 pour éviter de taper IP&lt;br /&gt;
&lt;br /&gt;
*Détection de contours&lt;br /&gt;
**Implémentation algorithme de tri de la plus courte disance&lt;br /&gt;
&lt;br /&gt;
*Commande galvanomêtre&lt;br /&gt;
**Utilisation API I²C&lt;br /&gt;
**Fonction de transfert position-&amp;gt;angle-&amp;gt;tension&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;br /&gt;
&lt;br /&gt;
==Bibliographie==&lt;br /&gt;
&lt;br /&gt;
*Galvanomètres et laser&lt;br /&gt;
http://www.ebay.com/itm/20KPPS-30KPPS-laser-scanning-galvo-scanner-ILDA-Closed-Loop-max-30kpps-for-laser-/261517002270?hash=item3ce3a0c61e&lt;br /&gt;
&lt;br /&gt;
http://sciences.ulb.ac.be/printemps/download/2016/dossier_pedagogique/02.pdf&lt;br /&gt;
&lt;br /&gt;
*Websocket&lt;br /&gt;
http://stackoverflow.com/questions/8125507/how-can-i-send-and-receive-websocket-messages-on-the-server-side&lt;br /&gt;
&lt;br /&gt;
https://tools.ietf.org/html/rfc6455&lt;br /&gt;
&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_a_WebSocket_server_in_Java&lt;br /&gt;
&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers&lt;br /&gt;
&lt;br /&gt;
*Traitement d'image&lt;br /&gt;
https://en.wikipedia.org/wiki/Gaussian_blur&lt;br /&gt;
&lt;br /&gt;
http://www.zebulon.fr/questions-reponses/traitement-d-image-detection-de-contours-55.html&lt;br /&gt;
&lt;br /&gt;
http://patrick-bonnin.developpez.com/cours/vision/apprendre-bases-traitement-image/partie-5-segmentation-contour/&lt;br /&gt;
&lt;br /&gt;
http://www.isir.upmc.fr/UserFiles/File/clady_homepage/EPU/2-Contour&lt;br /&gt;
&lt;br /&gt;
*Autre&lt;br /&gt;
https://icn.fenelonlille.org/mediawiki/index.php/Projet_ICN_commun_2016/2017&lt;br /&gt;
&lt;br /&gt;
https://www.g33k-zone.org/post/2016/05/11/Configurer-le-Raspberry-Pi-en-point-d-acc%C3%A8s-Wifi&lt;br /&gt;
&lt;br /&gt;
https://blogs.oracle.com/acaicedo/resource/Parallax-I2C/Sensors.java&lt;br /&gt;
&lt;br /&gt;
http://stackoverflow.com/questions/22087076/how-to-make-a-simple-image-upload-using-javascript-html&lt;br /&gt;
&lt;br /&gt;
export http_proxy=http://proxy.polytech-lille.fr:3128&lt;/div&gt;</summary>
		<author><name>Mtrimbur</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=40834</id>
		<title>IMA4 2016/2017 P39</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=40834"/>
				<updated>2017-03-27T18:22:16Z</updated>
		
		<summary type="html">&lt;p&gt;Mtrimbur : /* Bibliographie */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
===Contexte===&lt;br /&gt;
&lt;br /&gt;
Le laser est une technologie largement utilisé de nos jours dans de diverses applications. En effet, on retrouve cette technologie dans le domaine médical notamment pour la chirurgie oculaire ou encore dans industrie avec la découpe laser ou la soudure au laser.&lt;br /&gt;
&lt;br /&gt;
Le laser est une émission de photons produit par excitation d'un milieu amplificateur (ex : CO2), le rayonnement produit est unidirectionnel et monochromatique. Ce sont ces propriétés que nous allons exploiter afin réaliser un projecteur laser qui mis en mouvement est capable de dessiner des formes sur une surface à l'instar de systèmes existants utilisés pour des effets lumineux lors de festivités.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
L'objectif du projet est de créer un système de projection laser à plusieurs couleurs (au minimum deux) avec une application web pour programmer les formes à dessiner afin d'agrémenter des compétitions de gymnastique rythmique.&lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
Le projet consiste à réaliser avec des lasers des figures géométriques par l'intermédiaire d'un système galvanométrique. &lt;br /&gt;
&lt;br /&gt;
Notre premier travail sera de concevoir la partie projection. Pour cela, nous devrons aligner les lasers et les galvanomètres. En effet, ces derniers posséderont des miroirs à l'extrémité, ainsi les miroirs changeront d'inclinaison suivant le courant traversant les galvanomètres (similaire à l'image ci-contre). Il nous faudra également créer un système d'alimentation qui à partir d'une même source (réseau 230 V) sera capable d'alimenter les lasers et les galvanomètres ainsi qu'une Arduino et une Raspberry Pi.&lt;br /&gt;
[[File:Scanhead.jpeg|thumb]]&lt;br /&gt;
&lt;br /&gt;
Ensuite nous nous intéresserons à l'utilisation d'un système embarqué pour contrôler les galvanomètres et donc dessiner avec les lasers sur un plan 2D. En effet, le laser restera toujours fixe, seuls les galvanomètres, et donc les miroirs bougeront. Les galvanomètres étant contrôlés en courant il faudra réaliser une interface électronique pour convertir une commande en tension en commande de courant. La commande en tension sera assuré par une carte Arduino. Nous n'utiliserons qu'une seule paire de galvanomètres pour les deux laser. Il faudra donc multiplexer les deux faisceaux. La programmation des formes à effectuer, se fera par l'intermédiaire d'une application web PHP hébergée sur une RaspberryPi qui permettra de récupérer une image, d'y appliquer divers traitements et filtres afin d'en extraire les contours, et de calculer les commandes pour positionner les galvanomètres. Un serveur WebSocket également hébergé sur la RaspberryPi servira d'interface entre l'application web et L'arduino qui sera connecté via une liaison série sur la raspberryPI.&lt;br /&gt;
&lt;br /&gt;
Comme animation de test, nous dessinerons le contour d'une gymnaste avec une couleur et son ballon d'une autre couleur. La gymnaste devra lancer son ballon, réaliser quelques difficultés et récupérer son ballon.&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
Nous utiliserons comme matériels :&lt;br /&gt;
*Deux lasers de différentes couleurs&lt;br /&gt;
*Une paire de galvanomètres à miroir&lt;br /&gt;
*Arduino&lt;br /&gt;
*Raspberry Pi3&lt;br /&gt;
*Alimentation 230V/5V 1A [http://www.miniinthebox.com/fr/dual-usb-eu-prise-murale-5v-2a-voyage-adaptateur-chargeur-d-alimentation-pour-iphone7-6-xiaomi-samsung-et-autre-telephone-portable_p5410410.html?currency=EUR&amp;amp;litb_from=paid_adwords_shopping&amp;amp;sku=429_6917%7C752_20648&amp;amp;utm_source=google_shopping&amp;amp;utm_medium=cpc&amp;amp;adword_mt=&amp;amp;adword_ct=138705676724&amp;amp;adword_kw=&amp;amp;adword_pos=1o5&amp;amp;adword_pl=&amp;amp;adword_net=g&amp;amp;adword_tar=&amp;amp;adw_src_id=9653316068_661261352_33588296076_aud-79897721311:pla-256966386459&amp;amp;gclid=Cj0KEQiA_KvEBRCtzNil4-KR-LIBEiQAmgekFxxKjJJWBYCJlDZEa3Ke_2_WR0DzGVbz-jaCZHVIBoMaAvld8P8HAQ]&lt;br /&gt;
*Drivers galvanomètres x2&lt;br /&gt;
*Alimentation laser&lt;br /&gt;
*Lunette de sécurité x2 [https://www.amazon.fr/Uvex-S1933X-Eyewear-SCTOrange-Anti-Fog/dp/B000USRG90/ref=sr_1_1?ie=UTF8&amp;amp;qid=1485441383&amp;amp;sr=8-1&amp;amp;keywords=uvex+s1933x]&lt;br /&gt;
*Boitier ABS [http://fr.farnell.com/multicomp/g3118/boitier-abs-240x120x60mm-ip65/dp/1526656]&lt;br /&gt;
*DAC 4 canaux, avec interface I²C [https://www.adafruit.com/products/1083]&lt;br /&gt;
*Connecteur C14 [http://www.conrad.fr/ce/fr/product/715001/Connecteur-secteur-C14-Embase-male-verticale-715001-Nombre-de-poles-2-PE-10-A-noir-1-pcs/?ref=detview1&amp;amp;rt=detview1&amp;amp;rb=1]&lt;br /&gt;
*Câble secteur&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Logiciel :&lt;br /&gt;
&lt;br /&gt;
*Serveur web : Apache2, HTML5, PHP5, CSS&lt;br /&gt;
*Base de donnée : MySQL&lt;br /&gt;
*Serveur WebSocket : JQuerry, websocket&lt;br /&gt;
*Arduino : IDE Arduino&lt;br /&gt;
&lt;br /&gt;
===Calendrier prévisionnel===&lt;br /&gt;
&lt;br /&gt;
====Liste des tâches à effectuer====&lt;br /&gt;
Les différentes tâches à effectuer sont :&lt;br /&gt;
*Partie préliminaire : étude de fonctionnement des galvanomètres&lt;br /&gt;
**Déterminer comment est effectuée la commande des galvanomètres (protocole, tension...)&lt;br /&gt;
**Effectuer des tests avec l'Arduino ou la Raspberry Pi&lt;br /&gt;
**Effectuer des tests avec une LED à la place du laser &lt;br /&gt;
*Partie projection&lt;br /&gt;
**Fixer les lasers&lt;br /&gt;
**Aligner les lasers et les galvanomètres&lt;br /&gt;
**Créer le système d'alimentation&lt;br /&gt;
**Création d'un boitier&lt;br /&gt;
*Partie système embarqué&lt;br /&gt;
**Asservissement des galvanomètres avec l'Arduino&lt;br /&gt;
**Système électronique de commande en courant pour les galvanomètres&lt;br /&gt;
*Interface Web&lt;br /&gt;
**Installation et configuration Apache2&lt;br /&gt;
**Création d'une interface graphique simple&lt;br /&gt;
**Implémentation d'algorithmes de traitement d'image&lt;br /&gt;
**Mise en forme avec des CSS&lt;br /&gt;
**Sytème d'authentification avec mot de passe&lt;br /&gt;
**Utilisation d'une base de données pour enregistrer toutes les images déjà utilisés afin de les réutiliser&lt;br /&gt;
*Serveur Web Socket&lt;br /&gt;
**Récupération des données de l'interface web&lt;br /&gt;
**Mise en place de la liaison série avec l'Arduino&lt;br /&gt;
&lt;br /&gt;
====Calendrier====&lt;br /&gt;
Répartition du temps consacré au projet (240h) :&lt;br /&gt;
*Partie projection : 80h&lt;br /&gt;
*Partie système embarqué : 40h&lt;br /&gt;
*Partie interface web et websocket: 120h&lt;br /&gt;
&lt;br /&gt;
==Feuille d'heures==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!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&lt;br /&gt;
|-&lt;br /&gt;
| Définition cahier des charges &lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 14&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|38&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Finalisation du cahier des charges avec les responsables&lt;br /&gt;
&lt;br /&gt;
*Acquisition de matériels :&lt;br /&gt;
**Projecteur Laser&lt;br /&gt;
**Galvanomètres&lt;br /&gt;
**Alimentation des galvanomètres&lt;br /&gt;
&lt;br /&gt;
*Listage du matériels à acquérir :&lt;br /&gt;
**Lunettes de sécurité&lt;br /&gt;
**DAC&lt;br /&gt;
**Alimentation 230V/5V 1A&lt;br /&gt;
** Boitier ABS &lt;br /&gt;
**...&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
*Obtention de l'arduino et de la raspberryPI&lt;br /&gt;
&lt;br /&gt;
*Démontage du projecteur laser&lt;br /&gt;
**Deux lasers de classe 3b (vert et rouge)&lt;br /&gt;
**Circuit d'alimentation des deux lasers&lt;br /&gt;
&lt;br /&gt;
*Initialisation du port série de la raspberryPI&lt;br /&gt;
**Modification du fichier ''config.txt'' dans la partition boot&lt;br /&gt;
**Ajout d'une ligne autorisant la communication série ('''enable_uart=1''')&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
*Installation du serveur apache sur la raspberryPI&lt;br /&gt;
**Modification du fichier ''/etc/network/interfaces'' (Static, Address, Netmask, Gateway)&lt;br /&gt;
**Modification du fichier ''/etc/resolv.conf'' (Adresse du serveur)&lt;br /&gt;
**Utilisation d'un proxy pour la récupération outils de programmation (Apache2, Php5)&lt;br /&gt;
&lt;br /&gt;
*Mise en place du point d’accès wifi de la raspberryPI&lt;br /&gt;
**Récupération des logiciels nécessaires (dnsmasq, hostapd)&lt;br /&gt;
**Mise en place d'une adresse IP statique pour le point d'accès par l'intermédiaire du fichier ''/etc/dhcpcd.conf''&lt;br /&gt;
**Désactivation de la négociation automatique de bail dans le fichier ''/etc/network/interfaces''&lt;br /&gt;
**Configuration du logiciel hostapd ''/etc/hostapd/hostapd.conf''&lt;br /&gt;
**Activation du démarrage automatique du point d'accès ''/etc/default/hostapd''&lt;br /&gt;
**Configuration du serveur DNS par ''/etc/dnsmasq.conf''&lt;br /&gt;
&lt;br /&gt;
*Instauration de la page d'accueil de l'interface web à l'adresse ''192.168.3.1''&lt;br /&gt;
**Téléversement de fichiers images sur la page web et affichage de celle-ci&lt;br /&gt;
**Voyant de confirmation du bon fonctionnement du serveur web&lt;br /&gt;
&lt;br /&gt;
*Développement du serveur websocket&lt;br /&gt;
&lt;br /&gt;
Le développement du serveur websocket, initialement prévu en C (il était prévu de reprendre les sources utilisées l'année précédente dans le cadre des projet IMA3 SC), a finalement été réalisé en JAVA pour plusieurs raisons.&lt;br /&gt;
Premièrement, un seul programme met en œuvre le serveur websocket, les divers traitements d'image, ainsi que les contrôles des galvanomètres (par l'intermédiaire des DAC) via la liaison I²C de la Raspberry Pi. Le langage JAVA fournit nativement des bibliothèques d'objets pour manipuler assez simplement des images, il existe également des librairies pour contrôler le port GPIO de la Raspberry et il était également intéressant de travailler avec un langage de plus haut niveau que le C.&lt;br /&gt;
En outre, la totale portabilité de ce langage nous permet de travailler sur n'importe quelle machine et ensuite transférer notre programme sur la Raspberry Pi et l’exécuter sans même repasser par une phase de compilation. Et finalement, c'est le langage que nous étudions actuellement en cours de programmation orientée objet, ce qui permet de nous perfectionner.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Serveur WebSocket====&lt;br /&gt;
&lt;br /&gt;
N'ayant pas trouvé d'API WebSocket en Java satisfaisante (qui ne nécessitent pas l'installation et la configuration de nombreux outils additionnels), j'ai estimé plus commode et plus formateur de développer notre propre serveur WebSocket en se basant sur les librairies sockets de Java avec l'aide d'une documentation assez exhaustive [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers].&lt;br /&gt;
&lt;br /&gt;
Les WebSockets désignent à la fois un protocole réseau qui étend le protocole TCP ainsi qu'une API du World Wide Web. Nous nous en servons afin d'établir une communication asynchrone et bidirectionnelle entre un navigateur web et le serveur, notamment pour envoyer l'image à projeter. L’implémentation du serveur repose sur plusieurs étapes.&lt;br /&gt;
&lt;br /&gt;
1) Connexion d'un client &lt;br /&gt;
&lt;br /&gt;
2) Handshake : permet de faire le lien entre le protocole HTTP et WS. Le client envoie une requête HTTP demandant un upgrade de la connexion en protocole WS et le serveur répond en configurant la connexion (détail dans la documentation [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers]).&lt;br /&gt;
&lt;br /&gt;
3) Réception et décodage des messages : le serveurs reçoit des trames brutes, on extrait donc la taille du message ainsi que le message. De plus, les données son encodées (cryptage XOR) par un masque qui doit également être extrait.&lt;br /&gt;
&lt;br /&gt;
4) Fermeture de la communication.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le serveur supporte le multi-client il est donc nécessaire qu'il effectue ces étapes en &amp;quot;parallèle&amp;quot;. Nous utilisons donc les threads ou fils d’exécution. Un thread est donc responsable d'attendre qu'un nouveau client se connecte et effectue le &amp;quot;handshake&amp;quot;, il crée ensuite un thread associé à ce client afin d'établir un canal de communication. Il y a donc au moins un thread par client. Par la suite il faudra également implémenter une déconnexion automatique d'un client notamment après un timeout.&lt;br /&gt;
&lt;br /&gt;
Exemple d’exécution du serveur avec deux clients qui se connectent et envoient un message : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testServeur.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Les clients sont des navigateurs web. Pour les tests nous avons repris les exemples utilisés dans le cadre das projets IMA3 SC avec le titre de la page HTML qui se colore en vert lorsque le client est connecté, et un champ de saisie pour envoyer des messages au serveur : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testClient.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 4===&lt;br /&gt;
&lt;br /&gt;
*Mise en place d’algorithmes de traitement d'image&lt;br /&gt;
&lt;br /&gt;
====Détection de contour====&lt;br /&gt;
&lt;br /&gt;
L'objectif de notre projet est de pouvoir projeter n'importe quelle image envoyé grâce à l'application web. Pour cela nous allons tracer à une vitesse élevée les contours de l'image sur par exemple un mur grâce au laser. Il est donc nécessaire de détecter les contours de l'image grâce à plusieurs traitements.&lt;br /&gt;
&lt;br /&gt;
=====Conversion en niveau de gris=====&lt;br /&gt;
&lt;br /&gt;
Une des étapes préliminaires pour effectuer la détection de contour est de convertir l'image couleur en niveau de gris. Pour cela l'algorithme est simple : il suffit pour chaque pixel de l'image d'effectuer la moyenne des composantes rouge, verte, bleu de chaque pixel. En effet, si l'on considère une image matricielle (l'image est considérée comme un tableau à deux dimensions avec chaque case qui contient la couleur du pixel), chaque pixel contient les composantes RGB codées sur un octet. La couleur gris correspond aux composantes RGB égales. Le niveau de gris est donc codé de 0 à 255, avec 0 donnant du noir et 255 du blanc. &lt;br /&gt;
&lt;br /&gt;
Voici le résultat obtenu : [[Fichier:testGrayScale.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Filtre de Prewit et Sobel=====&lt;br /&gt;
&lt;br /&gt;
Un contour est défini par un changement brutal d'intensité lumineuse, il s'agit donc de détecter selon plusieurs directions (au moins 2) ces changements. Il existe de nombreuses techniques afin de détecter les contours d'une image (gradient, Laplacien). L'une des techniques avec un rapport efficacité/temps d'exécution correct repose sur les algorithmes de Prewit ou Sobel. L'algorithme repose sur la convolution de matrices.&lt;br /&gt;
Cela consiste à appliquer sur chaque pixel de l'image la matrice de Prewit définie comme &lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L_x = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; ainsi que sa transposée : &amp;lt;math&amp;gt;&lt;br /&gt;
L_y = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; -1 &amp;amp; -1 \\&lt;br /&gt;
 0 &amp;amp; 0 &amp;amp; 0 \\&lt;br /&gt;
+1 &amp;amp; +1 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Convoluer ces deux filtres sur l'image permet de détecter respectivement les contours verticaux et horizontaux.&lt;br /&gt;
&lt;br /&gt;
D'après wikipedia [https://fr.wikipedia.org/wiki/D%C3%A9tection_de_contours], on obtient de meilleurs résultats en appliquant un filtre triangulaire, on introduit donc la matrice de Sobel :&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-2 &amp;amp; 0 &amp;amp; +2 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
On obtient le résultat suivant : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testOutline1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Pré-traitement : Flou Gaussien=====&lt;br /&gt;
&lt;br /&gt;
Afin de réduire significativement le nombre de contours, il est nécessaire d'effectuer un pré-traitement avant la détection de contours. On utilise généralement un flou gaussien afin de réduire les transitions lumineuses et ainsi réduire le nombre de contours. L’algorithme de flou gaussien repose également sur la convolution de matrices sauf qu'ici la matrice filtre est générée grâce à une fonction gaussienne paramétrée par '''Sigma''' qui va directement impacter le niveau de flou. Plus la matrice de filtrage est grande plus la qualité du résultat est meilleure, mais le temps d’exécution devient également plus grand.&lt;br /&gt;
&lt;br /&gt;
Voici la fonction de génération du filtre : &amp;lt;math&amp;gt;G(x,y) = \frac{1}{{2\pi \sigma^2}} e^{-\frac{x^2 + y^2}{2 \sigma^2}}&amp;lt;/math&amp;gt; où x et y correspondent aux indices de la cellule de la matrice.&lt;br /&gt;
&lt;br /&gt;
On obtient ce résultat :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testGaussianBlur.png]]&lt;br /&gt;
&lt;br /&gt;
On note un bien meilleur résultat. Cependant on remarque que les composantes horizontales ne sont pas correctement détectées il subsiste un problème avec le filtrage vertical que je n'ai pas réussi à identifier. De plus, il s'agit par sa suite d'éliminer les contours parasites ainsi que d'affiner le trait pour n'avoir plus qu'un pixel d'épaisseur.&lt;br /&gt;
&lt;br /&gt;
=====Post-traitement : Algorithme de Canny=====&lt;br /&gt;
&lt;br /&gt;
Afin d'obtenir un résultat exploitable il est nécessaire d'appliquer encore quelques traitements. Pour cela nous utilisons l’algorithme de Canny qui repose que celui de Sobel mais qui ajoute un algorithme de seuillage par hysteresis qui permet de retirer les contours secondaires et de ne garder que les contours connexes dans une seuil haut et un seuil bas définis. En outre, cette algorithme affine également le trait obtenu. Pour cet algorithme nous avons directement trouvé des sources libres de droits [http://www.tomgibara.com/computer-vision/canny-edge-detector] qui donne des résultats très corrects.&lt;br /&gt;
&lt;br /&gt;
Par exemple :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ou encore : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny2.png|1500px]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 5===&lt;br /&gt;
&lt;br /&gt;
*Établissement d'un protocole de transfert d'image basé sur les WebSockets&lt;br /&gt;
**Envoie d'un requête &amp;quot;send&amp;quot; par le client dans une trame websocket texte&lt;br /&gt;
**Réponse serveur 'Y' si aucun autre client tente d'envoyer une image simultanément, 'N' sinon&lt;br /&gt;
**Si et seulement si le client reçoit 'Y' il débute le transfert en envoyant la largeur et la longueur de l'image sur 4 octets, puis les données de l'image soit 4 valeurs pour chaque pixels (r,g,b,alpha)&lt;br /&gt;
**Le serveur renvoie 'D' une fois le transfert achevé (à l'avenir, le serveur renverra l'image après filtrage).&lt;br /&gt;
**A tout moment, le serveur peut renvoyer 'E' si une erreur est survenue (ex : paquets perdus, nombre incorrects de données)&lt;br /&gt;
*Ajout du support des logs au niveau serveur&lt;br /&gt;
**Impression sur la sortie standard des messages&lt;br /&gt;
**Formatage en fonction de la sévérité du log (info, warning, error...)&lt;br /&gt;
**Incrustation de la date et heure&lt;br /&gt;
**Possibilité de redirection dans une fichier, avec configuration (écriture à la suite d'un fichier existant, écrasement...)&lt;br /&gt;
**Le tout dans une classe Java flexible et réutilisable pour d'autres projets&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 6===&lt;br /&gt;
&lt;br /&gt;
*Installation de la librairie Java Pi4j sur la raspberry pi qui permet le contrôle des GPIO de celle-ci et notamment le port I²C (basé sur WiringPi)&lt;br /&gt;
*Amélioration coté serveur websocket&lt;br /&gt;
**Gestion de message plus longs (maximum des trames websockets soit 2^63 octets)&lt;br /&gt;
**Différenciation, à la réception de messages, des trames textes ou binaires des trames de contrôle comme les requête ping, pong ou de fermeture de connexion &lt;br /&gt;
**Ajout d'un mode de debug de trames &lt;br /&gt;
&lt;br /&gt;
===Semaine 7===&lt;br /&gt;
&lt;br /&gt;
*Améliorations du serveur WebSocket&lt;br /&gt;
**Gestion de la fragmentation TCP&lt;br /&gt;
**Gestion de la fragmentation WebSocket&lt;br /&gt;
**Gestion des requêtes ping envoyés par le client en renvoyant une trames de contrôle pong afin de maintenir la connexion&lt;br /&gt;
**Gestion des déconnexion de clients afin d'optimiser le serveur&lt;br /&gt;
**Amélioration de l'émission de messages en augmentant la taille maximale pouvant être émise (2^63 octets)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A ce stade du développement, le client et le serveur sont opérationnels et peuvent s'échanger des messages ainsi que des images que le serveur traite pour extraire les contours.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 8===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Montage projecteur&lt;br /&gt;
**Intégralité des composants fixés par vis dans le boîtier ABS&lt;br /&gt;
**Fusion des alimentations&lt;br /&gt;
**Présence d'une led témoin de mise en tension&lt;br /&gt;
**Position laser réglable grâce à une vis&lt;br /&gt;
**Présence d'un switch à bascule pour allumer et éteindre le laser&lt;br /&gt;
**Isolation et vérification des composants&lt;br /&gt;
**Tests empiriques de température et de fonctionnement des lasers et galvanomètres&lt;br /&gt;
&lt;br /&gt;
Le montage boîtier est donc terminé et s’alimente en 230V par intermédiaire d'un câble secteur avec connecteur C14. Le résultat s'avère plutôt compact. Les quelques tests de température ont montrés que malgré le manque d'espace la température globale du boîtier ne dépasse pas les 50°C pendant plus d'une heure de fonctionnement. L'intégralité des connexions sont isolées avec de la gaine thermodynamique et les zones &amp;quot;sensibles&amp;quot; sont correctement vérifiés ainsi que protégées avec de la matière isolante.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:proj1.jpg|550px|Boîtier après perçage]] [[Fichier:proj2.jpg|550px|Boîtier finalisé]] [[Fichier:proj3.jpg|550px|Projecteur en fonctionnement]]&lt;br /&gt;
&lt;br /&gt;
*Page web et serveur WebSocket&lt;br /&gt;
**Ajout d'un bouton &amp;quot;reboot&amp;quot; et &amp;quot;shutdown&amp;quot; qui permettent respectivement de redémarrer et d'éteindre la Raspberry directement à partir de la page web&lt;br /&gt;
&lt;br /&gt;
===Semaine 9===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 10===&lt;br /&gt;
&lt;br /&gt;
==A faire==&lt;br /&gt;
&lt;br /&gt;
MAJ 26 mars &lt;br /&gt;
&lt;br /&gt;
*Client websocket et page web&lt;br /&gt;
**Mise en page CSS&lt;br /&gt;
**Ajout canvas pour prévisualisation image projeté&lt;br /&gt;
**Ajout &amp;quot;slider&amp;quot; pour régler niveau du flou Gaussien DOUBLE&lt;br /&gt;
**Ajout slider pour de finir amplitude de la projection&lt;br /&gt;
**Afficher statut de connexion&lt;br /&gt;
**Ajout message de confirmation quand le serveur quitte ou relance&lt;br /&gt;
**Ajout boutons &amp;quot;projeter&amp;quot; &amp;quot;centrer&amp;quot; &amp;quot;eteindre&amp;quot;&lt;br /&gt;
**Gestion de plusieurs images avec délai&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Serveur WebSocket&lt;br /&gt;
**Ajout fonctionnalité envoi image de prévisualisation&lt;br /&gt;
&lt;br /&gt;
*RaspberryPi&lt;br /&gt;
**Utilisation d'un serveur bind9 pour éviter de taper IP&lt;br /&gt;
&lt;br /&gt;
*Détection de contours&lt;br /&gt;
**Implémentation algorithme de tri de la plus courte disance&lt;br /&gt;
&lt;br /&gt;
*Commande galvanomêtre&lt;br /&gt;
**Utilisation API I²C&lt;br /&gt;
**Fonction de transfert position-&amp;gt;angle-&amp;gt;tension&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;br /&gt;
&lt;br /&gt;
==Bibliographie==&lt;br /&gt;
&lt;br /&gt;
*Galvanomètres et laser&lt;br /&gt;
http://www.ebay.com/itm/20KPPS-30KPPS-laser-scanning-galvo-scanner-ILDA-Closed-Loop-max-30kpps-for-laser-/261517002270?hash=item3ce3a0c61e&lt;br /&gt;
&lt;br /&gt;
http://sciences.ulb.ac.be/printemps/download/2016/dossier_pedagogique/02.pdf&lt;br /&gt;
&lt;br /&gt;
*Websocket&lt;br /&gt;
http://stackoverflow.com/questions/8125507/how-can-i-send-and-receive-websocket-messages-on-the-server-side&lt;br /&gt;
&lt;br /&gt;
https://tools.ietf.org/html/rfc6455&lt;br /&gt;
&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_a_WebSocket_server_in_Java&lt;br /&gt;
&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers&lt;br /&gt;
&lt;br /&gt;
*Traitement d'image&lt;br /&gt;
https://en.wikipedia.org/wiki/Gaussian_blur&lt;br /&gt;
&lt;br /&gt;
http://www.zebulon.fr/questions-reponses/traitement-d-image-detection-de-contours-55.html&lt;br /&gt;
&lt;br /&gt;
http://patrick-bonnin.developpez.com/cours/vision/apprendre-bases-traitement-image/partie-5-segmentation-contour/&lt;br /&gt;
&lt;br /&gt;
http://www.isir.upmc.fr/UserFiles/File/clady_homepage/EPU/2-Contour&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Autre&lt;br /&gt;
https://icn.fenelonlille.org/mediawiki/index.php/Projet_ICN_commun_2016/2017&lt;br /&gt;
&lt;br /&gt;
https://www.g33k-zone.org/post/2016/05/11/Configurer-le-Raspberry-Pi-en-point-d-acc%C3%A8s-Wifi&lt;br /&gt;
&lt;br /&gt;
https://blogs.oracle.com/acaicedo/resource/Parallax-I2C/Sensors.java&lt;br /&gt;
&lt;br /&gt;
http://stackoverflow.com/questions/22087076/how-to-make-a-simple-image-upload-using-javascript-html&lt;br /&gt;
&lt;br /&gt;
export http_proxy=http://proxy.polytech-lille.fr:3128&lt;/div&gt;</summary>
		<author><name>Mtrimbur</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=40833</id>
		<title>IMA4 2016/2017 P39</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=40833"/>
				<updated>2017-03-27T18:21:27Z</updated>
		
		<summary type="html">&lt;p&gt;Mtrimbur : /* Bibliographie */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
===Contexte===&lt;br /&gt;
&lt;br /&gt;
Le laser est une technologie largement utilisé de nos jours dans de diverses applications. En effet, on retrouve cette technologie dans le domaine médical notamment pour la chirurgie oculaire ou encore dans industrie avec la découpe laser ou la soudure au laser.&lt;br /&gt;
&lt;br /&gt;
Le laser est une émission de photons produit par excitation d'un milieu amplificateur (ex : CO2), le rayonnement produit est unidirectionnel et monochromatique. Ce sont ces propriétés que nous allons exploiter afin réaliser un projecteur laser qui mis en mouvement est capable de dessiner des formes sur une surface à l'instar de systèmes existants utilisés pour des effets lumineux lors de festivités.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
L'objectif du projet est de créer un système de projection laser à plusieurs couleurs (au minimum deux) avec une application web pour programmer les formes à dessiner afin d'agrémenter des compétitions de gymnastique rythmique.&lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
Le projet consiste à réaliser avec des lasers des figures géométriques par l'intermédiaire d'un système galvanométrique. &lt;br /&gt;
&lt;br /&gt;
Notre premier travail sera de concevoir la partie projection. Pour cela, nous devrons aligner les lasers et les galvanomètres. En effet, ces derniers posséderont des miroirs à l'extrémité, ainsi les miroirs changeront d'inclinaison suivant le courant traversant les galvanomètres (similaire à l'image ci-contre). Il nous faudra également créer un système d'alimentation qui à partir d'une même source (réseau 230 V) sera capable d'alimenter les lasers et les galvanomètres ainsi qu'une Arduino et une Raspberry Pi.&lt;br /&gt;
[[File:Scanhead.jpeg|thumb]]&lt;br /&gt;
&lt;br /&gt;
Ensuite nous nous intéresserons à l'utilisation d'un système embarqué pour contrôler les galvanomètres et donc dessiner avec les lasers sur un plan 2D. En effet, le laser restera toujours fixe, seuls les galvanomètres, et donc les miroirs bougeront. Les galvanomètres étant contrôlés en courant il faudra réaliser une interface électronique pour convertir une commande en tension en commande de courant. La commande en tension sera assuré par une carte Arduino. Nous n'utiliserons qu'une seule paire de galvanomètres pour les deux laser. Il faudra donc multiplexer les deux faisceaux. La programmation des formes à effectuer, se fera par l'intermédiaire d'une application web PHP hébergée sur une RaspberryPi qui permettra de récupérer une image, d'y appliquer divers traitements et filtres afin d'en extraire les contours, et de calculer les commandes pour positionner les galvanomètres. Un serveur WebSocket également hébergé sur la RaspberryPi servira d'interface entre l'application web et L'arduino qui sera connecté via une liaison série sur la raspberryPI.&lt;br /&gt;
&lt;br /&gt;
Comme animation de test, nous dessinerons le contour d'une gymnaste avec une couleur et son ballon d'une autre couleur. La gymnaste devra lancer son ballon, réaliser quelques difficultés et récupérer son ballon.&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
Nous utiliserons comme matériels :&lt;br /&gt;
*Deux lasers de différentes couleurs&lt;br /&gt;
*Une paire de galvanomètres à miroir&lt;br /&gt;
*Arduino&lt;br /&gt;
*Raspberry Pi3&lt;br /&gt;
*Alimentation 230V/5V 1A [http://www.miniinthebox.com/fr/dual-usb-eu-prise-murale-5v-2a-voyage-adaptateur-chargeur-d-alimentation-pour-iphone7-6-xiaomi-samsung-et-autre-telephone-portable_p5410410.html?currency=EUR&amp;amp;litb_from=paid_adwords_shopping&amp;amp;sku=429_6917%7C752_20648&amp;amp;utm_source=google_shopping&amp;amp;utm_medium=cpc&amp;amp;adword_mt=&amp;amp;adword_ct=138705676724&amp;amp;adword_kw=&amp;amp;adword_pos=1o5&amp;amp;adword_pl=&amp;amp;adword_net=g&amp;amp;adword_tar=&amp;amp;adw_src_id=9653316068_661261352_33588296076_aud-79897721311:pla-256966386459&amp;amp;gclid=Cj0KEQiA_KvEBRCtzNil4-KR-LIBEiQAmgekFxxKjJJWBYCJlDZEa3Ke_2_WR0DzGVbz-jaCZHVIBoMaAvld8P8HAQ]&lt;br /&gt;
*Drivers galvanomètres x2&lt;br /&gt;
*Alimentation laser&lt;br /&gt;
*Lunette de sécurité x2 [https://www.amazon.fr/Uvex-S1933X-Eyewear-SCTOrange-Anti-Fog/dp/B000USRG90/ref=sr_1_1?ie=UTF8&amp;amp;qid=1485441383&amp;amp;sr=8-1&amp;amp;keywords=uvex+s1933x]&lt;br /&gt;
*Boitier ABS [http://fr.farnell.com/multicomp/g3118/boitier-abs-240x120x60mm-ip65/dp/1526656]&lt;br /&gt;
*DAC 4 canaux, avec interface I²C [https://www.adafruit.com/products/1083]&lt;br /&gt;
*Connecteur C14 [http://www.conrad.fr/ce/fr/product/715001/Connecteur-secteur-C14-Embase-male-verticale-715001-Nombre-de-poles-2-PE-10-A-noir-1-pcs/?ref=detview1&amp;amp;rt=detview1&amp;amp;rb=1]&lt;br /&gt;
*Câble secteur&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Logiciel :&lt;br /&gt;
&lt;br /&gt;
*Serveur web : Apache2, HTML5, PHP5, CSS&lt;br /&gt;
*Base de donnée : MySQL&lt;br /&gt;
*Serveur WebSocket : JQuerry, websocket&lt;br /&gt;
*Arduino : IDE Arduino&lt;br /&gt;
&lt;br /&gt;
===Calendrier prévisionnel===&lt;br /&gt;
&lt;br /&gt;
====Liste des tâches à effectuer====&lt;br /&gt;
Les différentes tâches à effectuer sont :&lt;br /&gt;
*Partie préliminaire : étude de fonctionnement des galvanomètres&lt;br /&gt;
**Déterminer comment est effectuée la commande des galvanomètres (protocole, tension...)&lt;br /&gt;
**Effectuer des tests avec l'Arduino ou la Raspberry Pi&lt;br /&gt;
**Effectuer des tests avec une LED à la place du laser &lt;br /&gt;
*Partie projection&lt;br /&gt;
**Fixer les lasers&lt;br /&gt;
**Aligner les lasers et les galvanomètres&lt;br /&gt;
**Créer le système d'alimentation&lt;br /&gt;
**Création d'un boitier&lt;br /&gt;
*Partie système embarqué&lt;br /&gt;
**Asservissement des galvanomètres avec l'Arduino&lt;br /&gt;
**Système électronique de commande en courant pour les galvanomètres&lt;br /&gt;
*Interface Web&lt;br /&gt;
**Installation et configuration Apache2&lt;br /&gt;
**Création d'une interface graphique simple&lt;br /&gt;
**Implémentation d'algorithmes de traitement d'image&lt;br /&gt;
**Mise en forme avec des CSS&lt;br /&gt;
**Sytème d'authentification avec mot de passe&lt;br /&gt;
**Utilisation d'une base de données pour enregistrer toutes les images déjà utilisés afin de les réutiliser&lt;br /&gt;
*Serveur Web Socket&lt;br /&gt;
**Récupération des données de l'interface web&lt;br /&gt;
**Mise en place de la liaison série avec l'Arduino&lt;br /&gt;
&lt;br /&gt;
====Calendrier====&lt;br /&gt;
Répartition du temps consacré au projet (240h) :&lt;br /&gt;
*Partie projection : 80h&lt;br /&gt;
*Partie système embarqué : 40h&lt;br /&gt;
*Partie interface web et websocket: 120h&lt;br /&gt;
&lt;br /&gt;
==Feuille d'heures==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!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&lt;br /&gt;
|-&lt;br /&gt;
| Définition cahier des charges &lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 14&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|38&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Finalisation du cahier des charges avec les responsables&lt;br /&gt;
&lt;br /&gt;
*Acquisition de matériels :&lt;br /&gt;
**Projecteur Laser&lt;br /&gt;
**Galvanomètres&lt;br /&gt;
**Alimentation des galvanomètres&lt;br /&gt;
&lt;br /&gt;
*Listage du matériels à acquérir :&lt;br /&gt;
**Lunettes de sécurité&lt;br /&gt;
**DAC&lt;br /&gt;
**Alimentation 230V/5V 1A&lt;br /&gt;
** Boitier ABS &lt;br /&gt;
**...&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
*Obtention de l'arduino et de la raspberryPI&lt;br /&gt;
&lt;br /&gt;
*Démontage du projecteur laser&lt;br /&gt;
**Deux lasers de classe 3b (vert et rouge)&lt;br /&gt;
**Circuit d'alimentation des deux lasers&lt;br /&gt;
&lt;br /&gt;
*Initialisation du port série de la raspberryPI&lt;br /&gt;
**Modification du fichier ''config.txt'' dans la partition boot&lt;br /&gt;
**Ajout d'une ligne autorisant la communication série ('''enable_uart=1''')&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
*Installation du serveur apache sur la raspberryPI&lt;br /&gt;
**Modification du fichier ''/etc/network/interfaces'' (Static, Address, Netmask, Gateway)&lt;br /&gt;
**Modification du fichier ''/etc/resolv.conf'' (Adresse du serveur)&lt;br /&gt;
**Utilisation d'un proxy pour la récupération outils de programmation (Apache2, Php5)&lt;br /&gt;
&lt;br /&gt;
*Mise en place du point d’accès wifi de la raspberryPI&lt;br /&gt;
**Récupération des logiciels nécessaires (dnsmasq, hostapd)&lt;br /&gt;
**Mise en place d'une adresse IP statique pour le point d'accès par l'intermédiaire du fichier ''/etc/dhcpcd.conf''&lt;br /&gt;
**Désactivation de la négociation automatique de bail dans le fichier ''/etc/network/interfaces''&lt;br /&gt;
**Configuration du logiciel hostapd ''/etc/hostapd/hostapd.conf''&lt;br /&gt;
**Activation du démarrage automatique du point d'accès ''/etc/default/hostapd''&lt;br /&gt;
**Configuration du serveur DNS par ''/etc/dnsmasq.conf''&lt;br /&gt;
&lt;br /&gt;
*Instauration de la page d'accueil de l'interface web à l'adresse ''192.168.3.1''&lt;br /&gt;
**Téléversement de fichiers images sur la page web et affichage de celle-ci&lt;br /&gt;
**Voyant de confirmation du bon fonctionnement du serveur web&lt;br /&gt;
&lt;br /&gt;
*Développement du serveur websocket&lt;br /&gt;
&lt;br /&gt;
Le développement du serveur websocket, initialement prévu en C (il était prévu de reprendre les sources utilisées l'année précédente dans le cadre des projet IMA3 SC), a finalement été réalisé en JAVA pour plusieurs raisons.&lt;br /&gt;
Premièrement, un seul programme met en œuvre le serveur websocket, les divers traitements d'image, ainsi que les contrôles des galvanomètres (par l'intermédiaire des DAC) via la liaison I²C de la Raspberry Pi. Le langage JAVA fournit nativement des bibliothèques d'objets pour manipuler assez simplement des images, il existe également des librairies pour contrôler le port GPIO de la Raspberry et il était également intéressant de travailler avec un langage de plus haut niveau que le C.&lt;br /&gt;
En outre, la totale portabilité de ce langage nous permet de travailler sur n'importe quelle machine et ensuite transférer notre programme sur la Raspberry Pi et l’exécuter sans même repasser par une phase de compilation. Et finalement, c'est le langage que nous étudions actuellement en cours de programmation orientée objet, ce qui permet de nous perfectionner.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Serveur WebSocket====&lt;br /&gt;
&lt;br /&gt;
N'ayant pas trouvé d'API WebSocket en Java satisfaisante (qui ne nécessitent pas l'installation et la configuration de nombreux outils additionnels), j'ai estimé plus commode et plus formateur de développer notre propre serveur WebSocket en se basant sur les librairies sockets de Java avec l'aide d'une documentation assez exhaustive [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers].&lt;br /&gt;
&lt;br /&gt;
Les WebSockets désignent à la fois un protocole réseau qui étend le protocole TCP ainsi qu'une API du World Wide Web. Nous nous en servons afin d'établir une communication asynchrone et bidirectionnelle entre un navigateur web et le serveur, notamment pour envoyer l'image à projeter. L’implémentation du serveur repose sur plusieurs étapes.&lt;br /&gt;
&lt;br /&gt;
1) Connexion d'un client &lt;br /&gt;
&lt;br /&gt;
2) Handshake : permet de faire le lien entre le protocole HTTP et WS. Le client envoie une requête HTTP demandant un upgrade de la connexion en protocole WS et le serveur répond en configurant la connexion (détail dans la documentation [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers]).&lt;br /&gt;
&lt;br /&gt;
3) Réception et décodage des messages : le serveurs reçoit des trames brutes, on extrait donc la taille du message ainsi que le message. De plus, les données son encodées (cryptage XOR) par un masque qui doit également être extrait.&lt;br /&gt;
&lt;br /&gt;
4) Fermeture de la communication.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le serveur supporte le multi-client il est donc nécessaire qu'il effectue ces étapes en &amp;quot;parallèle&amp;quot;. Nous utilisons donc les threads ou fils d’exécution. Un thread est donc responsable d'attendre qu'un nouveau client se connecte et effectue le &amp;quot;handshake&amp;quot;, il crée ensuite un thread associé à ce client afin d'établir un canal de communication. Il y a donc au moins un thread par client. Par la suite il faudra également implémenter une déconnexion automatique d'un client notamment après un timeout.&lt;br /&gt;
&lt;br /&gt;
Exemple d’exécution du serveur avec deux clients qui se connectent et envoient un message : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testServeur.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Les clients sont des navigateurs web. Pour les tests nous avons repris les exemples utilisés dans le cadre das projets IMA3 SC avec le titre de la page HTML qui se colore en vert lorsque le client est connecté, et un champ de saisie pour envoyer des messages au serveur : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testClient.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 4===&lt;br /&gt;
&lt;br /&gt;
*Mise en place d’algorithmes de traitement d'image&lt;br /&gt;
&lt;br /&gt;
====Détection de contour====&lt;br /&gt;
&lt;br /&gt;
L'objectif de notre projet est de pouvoir projeter n'importe quelle image envoyé grâce à l'application web. Pour cela nous allons tracer à une vitesse élevée les contours de l'image sur par exemple un mur grâce au laser. Il est donc nécessaire de détecter les contours de l'image grâce à plusieurs traitements.&lt;br /&gt;
&lt;br /&gt;
=====Conversion en niveau de gris=====&lt;br /&gt;
&lt;br /&gt;
Une des étapes préliminaires pour effectuer la détection de contour est de convertir l'image couleur en niveau de gris. Pour cela l'algorithme est simple : il suffit pour chaque pixel de l'image d'effectuer la moyenne des composantes rouge, verte, bleu de chaque pixel. En effet, si l'on considère une image matricielle (l'image est considérée comme un tableau à deux dimensions avec chaque case qui contient la couleur du pixel), chaque pixel contient les composantes RGB codées sur un octet. La couleur gris correspond aux composantes RGB égales. Le niveau de gris est donc codé de 0 à 255, avec 0 donnant du noir et 255 du blanc. &lt;br /&gt;
&lt;br /&gt;
Voici le résultat obtenu : [[Fichier:testGrayScale.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Filtre de Prewit et Sobel=====&lt;br /&gt;
&lt;br /&gt;
Un contour est défini par un changement brutal d'intensité lumineuse, il s'agit donc de détecter selon plusieurs directions (au moins 2) ces changements. Il existe de nombreuses techniques afin de détecter les contours d'une image (gradient, Laplacien). L'une des techniques avec un rapport efficacité/temps d'exécution correct repose sur les algorithmes de Prewit ou Sobel. L'algorithme repose sur la convolution de matrices.&lt;br /&gt;
Cela consiste à appliquer sur chaque pixel de l'image la matrice de Prewit définie comme &lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L_x = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; ainsi que sa transposée : &amp;lt;math&amp;gt;&lt;br /&gt;
L_y = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; -1 &amp;amp; -1 \\&lt;br /&gt;
 0 &amp;amp; 0 &amp;amp; 0 \\&lt;br /&gt;
+1 &amp;amp; +1 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Convoluer ces deux filtres sur l'image permet de détecter respectivement les contours verticaux et horizontaux.&lt;br /&gt;
&lt;br /&gt;
D'après wikipedia [https://fr.wikipedia.org/wiki/D%C3%A9tection_de_contours], on obtient de meilleurs résultats en appliquant un filtre triangulaire, on introduit donc la matrice de Sobel :&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-2 &amp;amp; 0 &amp;amp; +2 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
On obtient le résultat suivant : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testOutline1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Pré-traitement : Flou Gaussien=====&lt;br /&gt;
&lt;br /&gt;
Afin de réduire significativement le nombre de contours, il est nécessaire d'effectuer un pré-traitement avant la détection de contours. On utilise généralement un flou gaussien afin de réduire les transitions lumineuses et ainsi réduire le nombre de contours. L’algorithme de flou gaussien repose également sur la convolution de matrices sauf qu'ici la matrice filtre est générée grâce à une fonction gaussienne paramétrée par '''Sigma''' qui va directement impacter le niveau de flou. Plus la matrice de filtrage est grande plus la qualité du résultat est meilleure, mais le temps d’exécution devient également plus grand.&lt;br /&gt;
&lt;br /&gt;
Voici la fonction de génération du filtre : &amp;lt;math&amp;gt;G(x,y) = \frac{1}{{2\pi \sigma^2}} e^{-\frac{x^2 + y^2}{2 \sigma^2}}&amp;lt;/math&amp;gt; où x et y correspondent aux indices de la cellule de la matrice.&lt;br /&gt;
&lt;br /&gt;
On obtient ce résultat :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testGaussianBlur.png]]&lt;br /&gt;
&lt;br /&gt;
On note un bien meilleur résultat. Cependant on remarque que les composantes horizontales ne sont pas correctement détectées il subsiste un problème avec le filtrage vertical que je n'ai pas réussi à identifier. De plus, il s'agit par sa suite d'éliminer les contours parasites ainsi que d'affiner le trait pour n'avoir plus qu'un pixel d'épaisseur.&lt;br /&gt;
&lt;br /&gt;
=====Post-traitement : Algorithme de Canny=====&lt;br /&gt;
&lt;br /&gt;
Afin d'obtenir un résultat exploitable il est nécessaire d'appliquer encore quelques traitements. Pour cela nous utilisons l’algorithme de Canny qui repose que celui de Sobel mais qui ajoute un algorithme de seuillage par hysteresis qui permet de retirer les contours secondaires et de ne garder que les contours connexes dans une seuil haut et un seuil bas définis. En outre, cette algorithme affine également le trait obtenu. Pour cet algorithme nous avons directement trouvé des sources libres de droits [http://www.tomgibara.com/computer-vision/canny-edge-detector] qui donne des résultats très corrects.&lt;br /&gt;
&lt;br /&gt;
Par exemple :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ou encore : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny2.png|1500px]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 5===&lt;br /&gt;
&lt;br /&gt;
*Établissement d'un protocole de transfert d'image basé sur les WebSockets&lt;br /&gt;
**Envoie d'un requête &amp;quot;send&amp;quot; par le client dans une trame websocket texte&lt;br /&gt;
**Réponse serveur 'Y' si aucun autre client tente d'envoyer une image simultanément, 'N' sinon&lt;br /&gt;
**Si et seulement si le client reçoit 'Y' il débute le transfert en envoyant la largeur et la longueur de l'image sur 4 octets, puis les données de l'image soit 4 valeurs pour chaque pixels (r,g,b,alpha)&lt;br /&gt;
**Le serveur renvoie 'D' une fois le transfert achevé (à l'avenir, le serveur renverra l'image après filtrage).&lt;br /&gt;
**A tout moment, le serveur peut renvoyer 'E' si une erreur est survenue (ex : paquets perdus, nombre incorrects de données)&lt;br /&gt;
*Ajout du support des logs au niveau serveur&lt;br /&gt;
**Impression sur la sortie standard des messages&lt;br /&gt;
**Formatage en fonction de la sévérité du log (info, warning, error...)&lt;br /&gt;
**Incrustation de la date et heure&lt;br /&gt;
**Possibilité de redirection dans une fichier, avec configuration (écriture à la suite d'un fichier existant, écrasement...)&lt;br /&gt;
**Le tout dans une classe Java flexible et réutilisable pour d'autres projets&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 6===&lt;br /&gt;
&lt;br /&gt;
*Installation de la librairie Java Pi4j sur la raspberry pi qui permet le contrôle des GPIO de celle-ci et notamment le port I²C (basé sur WiringPi)&lt;br /&gt;
*Amélioration coté serveur websocket&lt;br /&gt;
**Gestion de message plus longs (maximum des trames websockets soit 2^63 octets)&lt;br /&gt;
**Différenciation, à la réception de messages, des trames textes ou binaires des trames de contrôle comme les requête ping, pong ou de fermeture de connexion &lt;br /&gt;
**Ajout d'un mode de debug de trames &lt;br /&gt;
&lt;br /&gt;
===Semaine 7===&lt;br /&gt;
&lt;br /&gt;
*Améliorations du serveur WebSocket&lt;br /&gt;
**Gestion de la fragmentation TCP&lt;br /&gt;
**Gestion de la fragmentation WebSocket&lt;br /&gt;
**Gestion des requêtes ping envoyés par le client en renvoyant une trames de contrôle pong afin de maintenir la connexion&lt;br /&gt;
**Gestion des déconnexion de clients afin d'optimiser le serveur&lt;br /&gt;
**Amélioration de l'émission de messages en augmentant la taille maximale pouvant être émise (2^63 octets)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A ce stade du développement, le client et le serveur sont opérationnels et peuvent s'échanger des messages ainsi que des images que le serveur traite pour extraire les contours.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 8===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Montage projecteur&lt;br /&gt;
**Intégralité des composants fixés par vis dans le boîtier ABS&lt;br /&gt;
**Fusion des alimentations&lt;br /&gt;
**Présence d'une led témoin de mise en tension&lt;br /&gt;
**Position laser réglable grâce à une vis&lt;br /&gt;
**Présence d'un switch à bascule pour allumer et éteindre le laser&lt;br /&gt;
**Isolation et vérification des composants&lt;br /&gt;
**Tests empiriques de température et de fonctionnement des lasers et galvanomètres&lt;br /&gt;
&lt;br /&gt;
Le montage boîtier est donc terminé et s’alimente en 230V par intermédiaire d'un câble secteur avec connecteur C14. Le résultat s'avère plutôt compact. Les quelques tests de température ont montrés que malgré le manque d'espace la température globale du boîtier ne dépasse pas les 50°C pendant plus d'une heure de fonctionnement. L'intégralité des connexions sont isolées avec de la gaine thermodynamique et les zones &amp;quot;sensibles&amp;quot; sont correctement vérifiés ainsi que protégées avec de la matière isolante.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:proj1.jpg|550px|Boîtier après perçage]] [[Fichier:proj2.jpg|550px|Boîtier finalisé]] [[Fichier:proj3.jpg|550px|Projecteur en fonctionnement]]&lt;br /&gt;
&lt;br /&gt;
*Page web et serveur WebSocket&lt;br /&gt;
**Ajout d'un bouton &amp;quot;reboot&amp;quot; et &amp;quot;shutdown&amp;quot; qui permettent respectivement de redémarrer et d'éteindre la Raspberry directement à partir de la page web&lt;br /&gt;
&lt;br /&gt;
===Semaine 9===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 10===&lt;br /&gt;
&lt;br /&gt;
==A faire==&lt;br /&gt;
&lt;br /&gt;
MAJ 26 mars &lt;br /&gt;
&lt;br /&gt;
*Client websocket et page web&lt;br /&gt;
**Mise en page CSS&lt;br /&gt;
**Ajout canvas pour prévisualisation image projeté&lt;br /&gt;
**Ajout &amp;quot;slider&amp;quot; pour régler niveau du flou Gaussien DOUBLE&lt;br /&gt;
**Ajout slider pour de finir amplitude de la projection&lt;br /&gt;
**Afficher statut de connexion&lt;br /&gt;
**Ajout message de confirmation quand le serveur quitte ou relance&lt;br /&gt;
**Ajout boutons &amp;quot;projeter&amp;quot; &amp;quot;centrer&amp;quot; &amp;quot;eteindre&amp;quot;&lt;br /&gt;
**Gestion de plusieurs images avec délai&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Serveur WebSocket&lt;br /&gt;
**Ajout fonctionnalité envoi image de prévisualisation&lt;br /&gt;
&lt;br /&gt;
*RaspberryPi&lt;br /&gt;
**Utilisation d'un serveur bind9 pour éviter de taper IP&lt;br /&gt;
&lt;br /&gt;
*Détection de contours&lt;br /&gt;
**Implémentation algorithme de tri de la plus courte disance&lt;br /&gt;
&lt;br /&gt;
*Commande galvanomêtre&lt;br /&gt;
**Utilisation API I²C&lt;br /&gt;
**Fonction de transfert position-&amp;gt;angle-&amp;gt;tension&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;br /&gt;
&lt;br /&gt;
==Bibliographie==&lt;br /&gt;
&lt;br /&gt;
*Galvanomètres et laser&lt;br /&gt;
http://www.ebay.com/itm/20KPPS-30KPPS-laser-scanning-galvo-scanner-ILDA-Closed-Loop-max-30kpps-for-laser-/261517002270?hash=item3ce3a0c61e&lt;br /&gt;
http://sciences.ulb.ac.be/printemps/download/2016/dossier_pedagogique/02.pdf&lt;br /&gt;
&lt;br /&gt;
*Websocket&lt;br /&gt;
http://stackoverflow.com/questions/8125507/how-can-i-send-and-receive-websocket-messages-on-the-server-side&lt;br /&gt;
https://tools.ietf.org/html/rfc6455&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_a_WebSocket_server_in_Java&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers&lt;br /&gt;
&lt;br /&gt;
*Traitement d'image&lt;br /&gt;
https://en.wikipedia.org/wiki/Gaussian_blur&lt;br /&gt;
http://www.zebulon.fr/questions-reponses/traitement-d-image-detection-de-contours-55.html&lt;br /&gt;
http://patrick-bonnin.developpez.com/cours/vision/apprendre-bases-traitement-image/partie-5-segmentation-contour/&lt;br /&gt;
http://www.isir.upmc.fr/UserFiles/File/clady_homepage/EPU/2-Contour&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Autre&lt;br /&gt;
https://icn.fenelonlille.org/mediawiki/index.php/Projet_ICN_commun_2016/2017&lt;br /&gt;
https://www.g33k-zone.org/post/2016/05/11/Configurer-le-Raspberry-Pi-en-point-d-acc%C3%A8s-Wifi&lt;br /&gt;
https://blogs.oracle.com/acaicedo/resource/Parallax-I2C/Sensors.java&lt;br /&gt;
http://stackoverflow.com/questions/22087076/how-to-make-a-simple-image-upload-using-javascript-html&lt;br /&gt;
&lt;br /&gt;
export http_proxy=http://proxy.polytech-lille.fr:3128&lt;/div&gt;</summary>
		<author><name>Mtrimbur</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=40832</id>
		<title>IMA4 2016/2017 P39</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=40832"/>
				<updated>2017-03-27T18:13:43Z</updated>
		
		<summary type="html">&lt;p&gt;Mtrimbur : /* Bibliographie */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
===Contexte===&lt;br /&gt;
&lt;br /&gt;
Le laser est une technologie largement utilisé de nos jours dans de diverses applications. En effet, on retrouve cette technologie dans le domaine médical notamment pour la chirurgie oculaire ou encore dans industrie avec la découpe laser ou la soudure au laser.&lt;br /&gt;
&lt;br /&gt;
Le laser est une émission de photons produit par excitation d'un milieu amplificateur (ex : CO2), le rayonnement produit est unidirectionnel et monochromatique. Ce sont ces propriétés que nous allons exploiter afin réaliser un projecteur laser qui mis en mouvement est capable de dessiner des formes sur une surface à l'instar de systèmes existants utilisés pour des effets lumineux lors de festivités.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
L'objectif du projet est de créer un système de projection laser à plusieurs couleurs (au minimum deux) avec une application web pour programmer les formes à dessiner afin d'agrémenter des compétitions de gymnastique rythmique.&lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
Le projet consiste à réaliser avec des lasers des figures géométriques par l'intermédiaire d'un système galvanométrique. &lt;br /&gt;
&lt;br /&gt;
Notre premier travail sera de concevoir la partie projection. Pour cela, nous devrons aligner les lasers et les galvanomètres. En effet, ces derniers posséderont des miroirs à l'extrémité, ainsi les miroirs changeront d'inclinaison suivant le courant traversant les galvanomètres (similaire à l'image ci-contre). Il nous faudra également créer un système d'alimentation qui à partir d'une même source (réseau 230 V) sera capable d'alimenter les lasers et les galvanomètres ainsi qu'une Arduino et une Raspberry Pi.&lt;br /&gt;
[[File:Scanhead.jpeg|thumb]]&lt;br /&gt;
&lt;br /&gt;
Ensuite nous nous intéresserons à l'utilisation d'un système embarqué pour contrôler les galvanomètres et donc dessiner avec les lasers sur un plan 2D. En effet, le laser restera toujours fixe, seuls les galvanomètres, et donc les miroirs bougeront. Les galvanomètres étant contrôlés en courant il faudra réaliser une interface électronique pour convertir une commande en tension en commande de courant. La commande en tension sera assuré par une carte Arduino. Nous n'utiliserons qu'une seule paire de galvanomètres pour les deux laser. Il faudra donc multiplexer les deux faisceaux. La programmation des formes à effectuer, se fera par l'intermédiaire d'une application web PHP hébergée sur une RaspberryPi qui permettra de récupérer une image, d'y appliquer divers traitements et filtres afin d'en extraire les contours, et de calculer les commandes pour positionner les galvanomètres. Un serveur WebSocket également hébergé sur la RaspberryPi servira d'interface entre l'application web et L'arduino qui sera connecté via une liaison série sur la raspberryPI.&lt;br /&gt;
&lt;br /&gt;
Comme animation de test, nous dessinerons le contour d'une gymnaste avec une couleur et son ballon d'une autre couleur. La gymnaste devra lancer son ballon, réaliser quelques difficultés et récupérer son ballon.&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
Nous utiliserons comme matériels :&lt;br /&gt;
*Deux lasers de différentes couleurs&lt;br /&gt;
*Une paire de galvanomètres à miroir&lt;br /&gt;
*Arduino&lt;br /&gt;
*Raspberry Pi3&lt;br /&gt;
*Alimentation 230V/5V 1A [http://www.miniinthebox.com/fr/dual-usb-eu-prise-murale-5v-2a-voyage-adaptateur-chargeur-d-alimentation-pour-iphone7-6-xiaomi-samsung-et-autre-telephone-portable_p5410410.html?currency=EUR&amp;amp;litb_from=paid_adwords_shopping&amp;amp;sku=429_6917%7C752_20648&amp;amp;utm_source=google_shopping&amp;amp;utm_medium=cpc&amp;amp;adword_mt=&amp;amp;adword_ct=138705676724&amp;amp;adword_kw=&amp;amp;adword_pos=1o5&amp;amp;adword_pl=&amp;amp;adword_net=g&amp;amp;adword_tar=&amp;amp;adw_src_id=9653316068_661261352_33588296076_aud-79897721311:pla-256966386459&amp;amp;gclid=Cj0KEQiA_KvEBRCtzNil4-KR-LIBEiQAmgekFxxKjJJWBYCJlDZEa3Ke_2_WR0DzGVbz-jaCZHVIBoMaAvld8P8HAQ]&lt;br /&gt;
*Drivers galvanomètres x2&lt;br /&gt;
*Alimentation laser&lt;br /&gt;
*Lunette de sécurité x2 [https://www.amazon.fr/Uvex-S1933X-Eyewear-SCTOrange-Anti-Fog/dp/B000USRG90/ref=sr_1_1?ie=UTF8&amp;amp;qid=1485441383&amp;amp;sr=8-1&amp;amp;keywords=uvex+s1933x]&lt;br /&gt;
*Boitier ABS [http://fr.farnell.com/multicomp/g3118/boitier-abs-240x120x60mm-ip65/dp/1526656]&lt;br /&gt;
*DAC 4 canaux, avec interface I²C [https://www.adafruit.com/products/1083]&lt;br /&gt;
*Connecteur C14 [http://www.conrad.fr/ce/fr/product/715001/Connecteur-secteur-C14-Embase-male-verticale-715001-Nombre-de-poles-2-PE-10-A-noir-1-pcs/?ref=detview1&amp;amp;rt=detview1&amp;amp;rb=1]&lt;br /&gt;
*Câble secteur&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Logiciel :&lt;br /&gt;
&lt;br /&gt;
*Serveur web : Apache2, HTML5, PHP5, CSS&lt;br /&gt;
*Base de donnée : MySQL&lt;br /&gt;
*Serveur WebSocket : JQuerry, websocket&lt;br /&gt;
*Arduino : IDE Arduino&lt;br /&gt;
&lt;br /&gt;
===Calendrier prévisionnel===&lt;br /&gt;
&lt;br /&gt;
====Liste des tâches à effectuer====&lt;br /&gt;
Les différentes tâches à effectuer sont :&lt;br /&gt;
*Partie préliminaire : étude de fonctionnement des galvanomètres&lt;br /&gt;
**Déterminer comment est effectuée la commande des galvanomètres (protocole, tension...)&lt;br /&gt;
**Effectuer des tests avec l'Arduino ou la Raspberry Pi&lt;br /&gt;
**Effectuer des tests avec une LED à la place du laser &lt;br /&gt;
*Partie projection&lt;br /&gt;
**Fixer les lasers&lt;br /&gt;
**Aligner les lasers et les galvanomètres&lt;br /&gt;
**Créer le système d'alimentation&lt;br /&gt;
**Création d'un boitier&lt;br /&gt;
*Partie système embarqué&lt;br /&gt;
**Asservissement des galvanomètres avec l'Arduino&lt;br /&gt;
**Système électronique de commande en courant pour les galvanomètres&lt;br /&gt;
*Interface Web&lt;br /&gt;
**Installation et configuration Apache2&lt;br /&gt;
**Création d'une interface graphique simple&lt;br /&gt;
**Implémentation d'algorithmes de traitement d'image&lt;br /&gt;
**Mise en forme avec des CSS&lt;br /&gt;
**Sytème d'authentification avec mot de passe&lt;br /&gt;
**Utilisation d'une base de données pour enregistrer toutes les images déjà utilisés afin de les réutiliser&lt;br /&gt;
*Serveur Web Socket&lt;br /&gt;
**Récupération des données de l'interface web&lt;br /&gt;
**Mise en place de la liaison série avec l'Arduino&lt;br /&gt;
&lt;br /&gt;
====Calendrier====&lt;br /&gt;
Répartition du temps consacré au projet (240h) :&lt;br /&gt;
*Partie projection : 80h&lt;br /&gt;
*Partie système embarqué : 40h&lt;br /&gt;
*Partie interface web et websocket: 120h&lt;br /&gt;
&lt;br /&gt;
==Feuille d'heures==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!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&lt;br /&gt;
|-&lt;br /&gt;
| Définition cahier des charges &lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 14&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|38&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Finalisation du cahier des charges avec les responsables&lt;br /&gt;
&lt;br /&gt;
*Acquisition de matériels :&lt;br /&gt;
**Projecteur Laser&lt;br /&gt;
**Galvanomètres&lt;br /&gt;
**Alimentation des galvanomètres&lt;br /&gt;
&lt;br /&gt;
*Listage du matériels à acquérir :&lt;br /&gt;
**Lunettes de sécurité&lt;br /&gt;
**DAC&lt;br /&gt;
**Alimentation 230V/5V 1A&lt;br /&gt;
** Boitier ABS &lt;br /&gt;
**...&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
*Obtention de l'arduino et de la raspberryPI&lt;br /&gt;
&lt;br /&gt;
*Démontage du projecteur laser&lt;br /&gt;
**Deux lasers de classe 3b (vert et rouge)&lt;br /&gt;
**Circuit d'alimentation des deux lasers&lt;br /&gt;
&lt;br /&gt;
*Initialisation du port série de la raspberryPI&lt;br /&gt;
**Modification du fichier ''config.txt'' dans la partition boot&lt;br /&gt;
**Ajout d'une ligne autorisant la communication série ('''enable_uart=1''')&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
*Installation du serveur apache sur la raspberryPI&lt;br /&gt;
**Modification du fichier ''/etc/network/interfaces'' (Static, Address, Netmask, Gateway)&lt;br /&gt;
**Modification du fichier ''/etc/resolv.conf'' (Adresse du serveur)&lt;br /&gt;
**Utilisation d'un proxy pour la récupération outils de programmation (Apache2, Php5)&lt;br /&gt;
&lt;br /&gt;
*Mise en place du point d’accès wifi de la raspberryPI&lt;br /&gt;
**Récupération des logiciels nécessaires (dnsmasq, hostapd)&lt;br /&gt;
**Mise en place d'une adresse IP statique pour le point d'accès par l'intermédiaire du fichier ''/etc/dhcpcd.conf''&lt;br /&gt;
**Désactivation de la négociation automatique de bail dans le fichier ''/etc/network/interfaces''&lt;br /&gt;
**Configuration du logiciel hostapd ''/etc/hostapd/hostapd.conf''&lt;br /&gt;
**Activation du démarrage automatique du point d'accès ''/etc/default/hostapd''&lt;br /&gt;
**Configuration du serveur DNS par ''/etc/dnsmasq.conf''&lt;br /&gt;
&lt;br /&gt;
*Instauration de la page d'accueil de l'interface web à l'adresse ''192.168.3.1''&lt;br /&gt;
**Téléversement de fichiers images sur la page web et affichage de celle-ci&lt;br /&gt;
**Voyant de confirmation du bon fonctionnement du serveur web&lt;br /&gt;
&lt;br /&gt;
*Développement du serveur websocket&lt;br /&gt;
&lt;br /&gt;
Le développement du serveur websocket, initialement prévu en C (il était prévu de reprendre les sources utilisées l'année précédente dans le cadre des projet IMA3 SC), a finalement été réalisé en JAVA pour plusieurs raisons.&lt;br /&gt;
Premièrement, un seul programme met en œuvre le serveur websocket, les divers traitements d'image, ainsi que les contrôles des galvanomètres (par l'intermédiaire des DAC) via la liaison I²C de la Raspberry Pi. Le langage JAVA fournit nativement des bibliothèques d'objets pour manipuler assez simplement des images, il existe également des librairies pour contrôler le port GPIO de la Raspberry et il était également intéressant de travailler avec un langage de plus haut niveau que le C.&lt;br /&gt;
En outre, la totale portabilité de ce langage nous permet de travailler sur n'importe quelle machine et ensuite transférer notre programme sur la Raspberry Pi et l’exécuter sans même repasser par une phase de compilation. Et finalement, c'est le langage que nous étudions actuellement en cours de programmation orientée objet, ce qui permet de nous perfectionner.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Serveur WebSocket====&lt;br /&gt;
&lt;br /&gt;
N'ayant pas trouvé d'API WebSocket en Java satisfaisante (qui ne nécessitent pas l'installation et la configuration de nombreux outils additionnels), j'ai estimé plus commode et plus formateur de développer notre propre serveur WebSocket en se basant sur les librairies sockets de Java avec l'aide d'une documentation assez exhaustive [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers].&lt;br /&gt;
&lt;br /&gt;
Les WebSockets désignent à la fois un protocole réseau qui étend le protocole TCP ainsi qu'une API du World Wide Web. Nous nous en servons afin d'établir une communication asynchrone et bidirectionnelle entre un navigateur web et le serveur, notamment pour envoyer l'image à projeter. L’implémentation du serveur repose sur plusieurs étapes.&lt;br /&gt;
&lt;br /&gt;
1) Connexion d'un client &lt;br /&gt;
&lt;br /&gt;
2) Handshake : permet de faire le lien entre le protocole HTTP et WS. Le client envoie une requête HTTP demandant un upgrade de la connexion en protocole WS et le serveur répond en configurant la connexion (détail dans la documentation [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers]).&lt;br /&gt;
&lt;br /&gt;
3) Réception et décodage des messages : le serveurs reçoit des trames brutes, on extrait donc la taille du message ainsi que le message. De plus, les données son encodées (cryptage XOR) par un masque qui doit également être extrait.&lt;br /&gt;
&lt;br /&gt;
4) Fermeture de la communication.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le serveur supporte le multi-client il est donc nécessaire qu'il effectue ces étapes en &amp;quot;parallèle&amp;quot;. Nous utilisons donc les threads ou fils d’exécution. Un thread est donc responsable d'attendre qu'un nouveau client se connecte et effectue le &amp;quot;handshake&amp;quot;, il crée ensuite un thread associé à ce client afin d'établir un canal de communication. Il y a donc au moins un thread par client. Par la suite il faudra également implémenter une déconnexion automatique d'un client notamment après un timeout.&lt;br /&gt;
&lt;br /&gt;
Exemple d’exécution du serveur avec deux clients qui se connectent et envoient un message : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testServeur.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Les clients sont des navigateurs web. Pour les tests nous avons repris les exemples utilisés dans le cadre das projets IMA3 SC avec le titre de la page HTML qui se colore en vert lorsque le client est connecté, et un champ de saisie pour envoyer des messages au serveur : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testClient.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 4===&lt;br /&gt;
&lt;br /&gt;
*Mise en place d’algorithmes de traitement d'image&lt;br /&gt;
&lt;br /&gt;
====Détection de contour====&lt;br /&gt;
&lt;br /&gt;
L'objectif de notre projet est de pouvoir projeter n'importe quelle image envoyé grâce à l'application web. Pour cela nous allons tracer à une vitesse élevée les contours de l'image sur par exemple un mur grâce au laser. Il est donc nécessaire de détecter les contours de l'image grâce à plusieurs traitements.&lt;br /&gt;
&lt;br /&gt;
=====Conversion en niveau de gris=====&lt;br /&gt;
&lt;br /&gt;
Une des étapes préliminaires pour effectuer la détection de contour est de convertir l'image couleur en niveau de gris. Pour cela l'algorithme est simple : il suffit pour chaque pixel de l'image d'effectuer la moyenne des composantes rouge, verte, bleu de chaque pixel. En effet, si l'on considère une image matricielle (l'image est considérée comme un tableau à deux dimensions avec chaque case qui contient la couleur du pixel), chaque pixel contient les composantes RGB codées sur un octet. La couleur gris correspond aux composantes RGB égales. Le niveau de gris est donc codé de 0 à 255, avec 0 donnant du noir et 255 du blanc. &lt;br /&gt;
&lt;br /&gt;
Voici le résultat obtenu : [[Fichier:testGrayScale.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Filtre de Prewit et Sobel=====&lt;br /&gt;
&lt;br /&gt;
Un contour est défini par un changement brutal d'intensité lumineuse, il s'agit donc de détecter selon plusieurs directions (au moins 2) ces changements. Il existe de nombreuses techniques afin de détecter les contours d'une image (gradient, Laplacien). L'une des techniques avec un rapport efficacité/temps d'exécution correct repose sur les algorithmes de Prewit ou Sobel. L'algorithme repose sur la convolution de matrices.&lt;br /&gt;
Cela consiste à appliquer sur chaque pixel de l'image la matrice de Prewit définie comme &lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L_x = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; ainsi que sa transposée : &amp;lt;math&amp;gt;&lt;br /&gt;
L_y = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; -1 &amp;amp; -1 \\&lt;br /&gt;
 0 &amp;amp; 0 &amp;amp; 0 \\&lt;br /&gt;
+1 &amp;amp; +1 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Convoluer ces deux filtres sur l'image permet de détecter respectivement les contours verticaux et horizontaux.&lt;br /&gt;
&lt;br /&gt;
D'après wikipedia [https://fr.wikipedia.org/wiki/D%C3%A9tection_de_contours], on obtient de meilleurs résultats en appliquant un filtre triangulaire, on introduit donc la matrice de Sobel :&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-2 &amp;amp; 0 &amp;amp; +2 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
On obtient le résultat suivant : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testOutline1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Pré-traitement : Flou Gaussien=====&lt;br /&gt;
&lt;br /&gt;
Afin de réduire significativement le nombre de contours, il est nécessaire d'effectuer un pré-traitement avant la détection de contours. On utilise généralement un flou gaussien afin de réduire les transitions lumineuses et ainsi réduire le nombre de contours. L’algorithme de flou gaussien repose également sur la convolution de matrices sauf qu'ici la matrice filtre est générée grâce à une fonction gaussienne paramétrée par '''Sigma''' qui va directement impacter le niveau de flou. Plus la matrice de filtrage est grande plus la qualité du résultat est meilleure, mais le temps d’exécution devient également plus grand.&lt;br /&gt;
&lt;br /&gt;
Voici la fonction de génération du filtre : &amp;lt;math&amp;gt;G(x,y) = \frac{1}{{2\pi \sigma^2}} e^{-\frac{x^2 + y^2}{2 \sigma^2}}&amp;lt;/math&amp;gt; où x et y correspondent aux indices de la cellule de la matrice.&lt;br /&gt;
&lt;br /&gt;
On obtient ce résultat :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testGaussianBlur.png]]&lt;br /&gt;
&lt;br /&gt;
On note un bien meilleur résultat. Cependant on remarque que les composantes horizontales ne sont pas correctement détectées il subsiste un problème avec le filtrage vertical que je n'ai pas réussi à identifier. De plus, il s'agit par sa suite d'éliminer les contours parasites ainsi que d'affiner le trait pour n'avoir plus qu'un pixel d'épaisseur.&lt;br /&gt;
&lt;br /&gt;
=====Post-traitement : Algorithme de Canny=====&lt;br /&gt;
&lt;br /&gt;
Afin d'obtenir un résultat exploitable il est nécessaire d'appliquer encore quelques traitements. Pour cela nous utilisons l’algorithme de Canny qui repose que celui de Sobel mais qui ajoute un algorithme de seuillage par hysteresis qui permet de retirer les contours secondaires et de ne garder que les contours connexes dans une seuil haut et un seuil bas définis. En outre, cette algorithme affine également le trait obtenu. Pour cet algorithme nous avons directement trouvé des sources libres de droits [http://www.tomgibara.com/computer-vision/canny-edge-detector] qui donne des résultats très corrects.&lt;br /&gt;
&lt;br /&gt;
Par exemple :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ou encore : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny2.png|1500px]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 5===&lt;br /&gt;
&lt;br /&gt;
*Établissement d'un protocole de transfert d'image basé sur les WebSockets&lt;br /&gt;
**Envoie d'un requête &amp;quot;send&amp;quot; par le client dans une trame websocket texte&lt;br /&gt;
**Réponse serveur 'Y' si aucun autre client tente d'envoyer une image simultanément, 'N' sinon&lt;br /&gt;
**Si et seulement si le client reçoit 'Y' il débute le transfert en envoyant la largeur et la longueur de l'image sur 4 octets, puis les données de l'image soit 4 valeurs pour chaque pixels (r,g,b,alpha)&lt;br /&gt;
**Le serveur renvoie 'D' une fois le transfert achevé (à l'avenir, le serveur renverra l'image après filtrage).&lt;br /&gt;
**A tout moment, le serveur peut renvoyer 'E' si une erreur est survenue (ex : paquets perdus, nombre incorrects de données)&lt;br /&gt;
*Ajout du support des logs au niveau serveur&lt;br /&gt;
**Impression sur la sortie standard des messages&lt;br /&gt;
**Formatage en fonction de la sévérité du log (info, warning, error...)&lt;br /&gt;
**Incrustation de la date et heure&lt;br /&gt;
**Possibilité de redirection dans une fichier, avec configuration (écriture à la suite d'un fichier existant, écrasement...)&lt;br /&gt;
**Le tout dans une classe Java flexible et réutilisable pour d'autres projets&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 6===&lt;br /&gt;
&lt;br /&gt;
*Installation de la librairie Java Pi4j sur la raspberry pi qui permet le contrôle des GPIO de celle-ci et notamment le port I²C (basé sur WiringPi)&lt;br /&gt;
*Amélioration coté serveur websocket&lt;br /&gt;
**Gestion de message plus longs (maximum des trames websockets soit 2^63 octets)&lt;br /&gt;
**Différenciation, à la réception de messages, des trames textes ou binaires des trames de contrôle comme les requête ping, pong ou de fermeture de connexion &lt;br /&gt;
**Ajout d'un mode de debug de trames &lt;br /&gt;
&lt;br /&gt;
===Semaine 7===&lt;br /&gt;
&lt;br /&gt;
*Améliorations du serveur WebSocket&lt;br /&gt;
**Gestion de la fragmentation TCP&lt;br /&gt;
**Gestion de la fragmentation WebSocket&lt;br /&gt;
**Gestion des requêtes ping envoyés par le client en renvoyant une trames de contrôle pong afin de maintenir la connexion&lt;br /&gt;
**Gestion des déconnexion de clients afin d'optimiser le serveur&lt;br /&gt;
**Amélioration de l'émission de messages en augmentant la taille maximale pouvant être émise (2^63 octets)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A ce stade du développement, le client et le serveur sont opérationnels et peuvent s'échanger des messages ainsi que des images que le serveur traite pour extraire les contours.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 8===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Montage projecteur&lt;br /&gt;
**Intégralité des composants fixés par vis dans le boîtier ABS&lt;br /&gt;
**Fusion des alimentations&lt;br /&gt;
**Présence d'une led témoin de mise en tension&lt;br /&gt;
**Position laser réglable grâce à une vis&lt;br /&gt;
**Présence d'un switch à bascule pour allumer et éteindre le laser&lt;br /&gt;
**Isolation et vérification des composants&lt;br /&gt;
**Tests empiriques de température et de fonctionnement des lasers et galvanomètres&lt;br /&gt;
&lt;br /&gt;
Le montage boîtier est donc terminé et s’alimente en 230V par intermédiaire d'un câble secteur avec connecteur C14. Le résultat s'avère plutôt compact. Les quelques tests de température ont montrés que malgré le manque d'espace la température globale du boîtier ne dépasse pas les 50°C pendant plus d'une heure de fonctionnement. L'intégralité des connexions sont isolées avec de la gaine thermodynamique et les zones &amp;quot;sensibles&amp;quot; sont correctement vérifiés ainsi que protégées avec de la matière isolante.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:proj1.jpg|550px|Boîtier après perçage]] [[Fichier:proj2.jpg|550px|Boîtier finalisé]] [[Fichier:proj3.jpg|550px|Projecteur en fonctionnement]]&lt;br /&gt;
&lt;br /&gt;
*Page web et serveur WebSocket&lt;br /&gt;
**Ajout d'un bouton &amp;quot;reboot&amp;quot; et &amp;quot;shutdown&amp;quot; qui permettent respectivement de redémarrer et d'éteindre la Raspberry directement à partir de la page web&lt;br /&gt;
&lt;br /&gt;
===Semaine 9===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 10===&lt;br /&gt;
&lt;br /&gt;
==A faire==&lt;br /&gt;
&lt;br /&gt;
MAJ 26 mars &lt;br /&gt;
&lt;br /&gt;
*Client websocket et page web&lt;br /&gt;
**Mise en page CSS&lt;br /&gt;
**Ajout canvas pour prévisualisation image projeté&lt;br /&gt;
**Ajout &amp;quot;slider&amp;quot; pour régler niveau du flou Gaussien DOUBLE&lt;br /&gt;
**Ajout slider pour de finir amplitude de la projection&lt;br /&gt;
**Afficher statut de connexion&lt;br /&gt;
**Ajout message de confirmation quand le serveur quitte ou relance&lt;br /&gt;
**Ajout boutons &amp;quot;projeter&amp;quot; &amp;quot;centrer&amp;quot; &amp;quot;eteindre&amp;quot;&lt;br /&gt;
**Gestion de plusieurs images avec délai&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Serveur WebSocket&lt;br /&gt;
**Ajout fonctionnalité envoi image de prévisualisation&lt;br /&gt;
&lt;br /&gt;
*RaspberryPi&lt;br /&gt;
**Utilisation d'un serveur bind9 pour éviter de taper IP&lt;br /&gt;
&lt;br /&gt;
*Détection de contours&lt;br /&gt;
**Implémentation algorithme de tri de la plus courte disance&lt;br /&gt;
&lt;br /&gt;
*Commande galvanomêtre&lt;br /&gt;
**Utilisation API I²C&lt;br /&gt;
**Fonction de transfert position-&amp;gt;angle-&amp;gt;tension&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;br /&gt;
&lt;br /&gt;
==Bibliographie==&lt;br /&gt;
&lt;br /&gt;
*Galvanomètres&lt;br /&gt;
&lt;br /&gt;
http://www.ebay.com/itm/20KPPS-30KPPS-laser-scanning-galvo-scanner-ILDA-Closed-Loop-max-30kpps-for-laser-/261517002270?hash=item3ce3a0c61e&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Websocket&lt;br /&gt;
&lt;br /&gt;
http://stackoverflow.com/questions/22087076/how-to-make-a-simple-image-upload-using-javascript-html&lt;br /&gt;
&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_a_WebSocket_server_in_Java&lt;br /&gt;
&lt;br /&gt;
*Autre&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
https://icn.fenelonlille.org/mediawiki/index.php/Projet_ICN_commun_2016/2017&lt;br /&gt;
&lt;br /&gt;
https://www.g33k-zone.org/post/2016/05/11/Configurer-le-Raspberry-Pi-en-point-d-acc%C3%A8s-Wifi&lt;br /&gt;
&lt;br /&gt;
export http_proxy=http://proxy.polytech-lille.fr:3128&lt;/div&gt;</summary>
		<author><name>Mtrimbur</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=40831</id>
		<title>IMA4 2016/2017 P39</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=40831"/>
				<updated>2017-03-27T18:08:46Z</updated>
		
		<summary type="html">&lt;p&gt;Mtrimbur : /* Semaine 8 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
===Contexte===&lt;br /&gt;
&lt;br /&gt;
Le laser est une technologie largement utilisé de nos jours dans de diverses applications. En effet, on retrouve cette technologie dans le domaine médical notamment pour la chirurgie oculaire ou encore dans industrie avec la découpe laser ou la soudure au laser.&lt;br /&gt;
&lt;br /&gt;
Le laser est une émission de photons produit par excitation d'un milieu amplificateur (ex : CO2), le rayonnement produit est unidirectionnel et monochromatique. Ce sont ces propriétés que nous allons exploiter afin réaliser un projecteur laser qui mis en mouvement est capable de dessiner des formes sur une surface à l'instar de systèmes existants utilisés pour des effets lumineux lors de festivités.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
L'objectif du projet est de créer un système de projection laser à plusieurs couleurs (au minimum deux) avec une application web pour programmer les formes à dessiner afin d'agrémenter des compétitions de gymnastique rythmique.&lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
Le projet consiste à réaliser avec des lasers des figures géométriques par l'intermédiaire d'un système galvanométrique. &lt;br /&gt;
&lt;br /&gt;
Notre premier travail sera de concevoir la partie projection. Pour cela, nous devrons aligner les lasers et les galvanomètres. En effet, ces derniers posséderont des miroirs à l'extrémité, ainsi les miroirs changeront d'inclinaison suivant le courant traversant les galvanomètres (similaire à l'image ci-contre). Il nous faudra également créer un système d'alimentation qui à partir d'une même source (réseau 230 V) sera capable d'alimenter les lasers et les galvanomètres ainsi qu'une Arduino et une Raspberry Pi.&lt;br /&gt;
[[File:Scanhead.jpeg|thumb]]&lt;br /&gt;
&lt;br /&gt;
Ensuite nous nous intéresserons à l'utilisation d'un système embarqué pour contrôler les galvanomètres et donc dessiner avec les lasers sur un plan 2D. En effet, le laser restera toujours fixe, seuls les galvanomètres, et donc les miroirs bougeront. Les galvanomètres étant contrôlés en courant il faudra réaliser une interface électronique pour convertir une commande en tension en commande de courant. La commande en tension sera assuré par une carte Arduino. Nous n'utiliserons qu'une seule paire de galvanomètres pour les deux laser. Il faudra donc multiplexer les deux faisceaux. La programmation des formes à effectuer, se fera par l'intermédiaire d'une application web PHP hébergée sur une RaspberryPi qui permettra de récupérer une image, d'y appliquer divers traitements et filtres afin d'en extraire les contours, et de calculer les commandes pour positionner les galvanomètres. Un serveur WebSocket également hébergé sur la RaspberryPi servira d'interface entre l'application web et L'arduino qui sera connecté via une liaison série sur la raspberryPI.&lt;br /&gt;
&lt;br /&gt;
Comme animation de test, nous dessinerons le contour d'une gymnaste avec une couleur et son ballon d'une autre couleur. La gymnaste devra lancer son ballon, réaliser quelques difficultés et récupérer son ballon.&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
Nous utiliserons comme matériels :&lt;br /&gt;
*Deux lasers de différentes couleurs&lt;br /&gt;
*Une paire de galvanomètres à miroir&lt;br /&gt;
*Arduino&lt;br /&gt;
*Raspberry Pi3&lt;br /&gt;
*Alimentation 230V/5V 1A [http://www.miniinthebox.com/fr/dual-usb-eu-prise-murale-5v-2a-voyage-adaptateur-chargeur-d-alimentation-pour-iphone7-6-xiaomi-samsung-et-autre-telephone-portable_p5410410.html?currency=EUR&amp;amp;litb_from=paid_adwords_shopping&amp;amp;sku=429_6917%7C752_20648&amp;amp;utm_source=google_shopping&amp;amp;utm_medium=cpc&amp;amp;adword_mt=&amp;amp;adword_ct=138705676724&amp;amp;adword_kw=&amp;amp;adword_pos=1o5&amp;amp;adword_pl=&amp;amp;adword_net=g&amp;amp;adword_tar=&amp;amp;adw_src_id=9653316068_661261352_33588296076_aud-79897721311:pla-256966386459&amp;amp;gclid=Cj0KEQiA_KvEBRCtzNil4-KR-LIBEiQAmgekFxxKjJJWBYCJlDZEa3Ke_2_WR0DzGVbz-jaCZHVIBoMaAvld8P8HAQ]&lt;br /&gt;
*Drivers galvanomètres x2&lt;br /&gt;
*Alimentation laser&lt;br /&gt;
*Lunette de sécurité x2 [https://www.amazon.fr/Uvex-S1933X-Eyewear-SCTOrange-Anti-Fog/dp/B000USRG90/ref=sr_1_1?ie=UTF8&amp;amp;qid=1485441383&amp;amp;sr=8-1&amp;amp;keywords=uvex+s1933x]&lt;br /&gt;
*Boitier ABS [http://fr.farnell.com/multicomp/g3118/boitier-abs-240x120x60mm-ip65/dp/1526656]&lt;br /&gt;
*DAC 4 canaux, avec interface I²C [https://www.adafruit.com/products/1083]&lt;br /&gt;
*Connecteur C14 [http://www.conrad.fr/ce/fr/product/715001/Connecteur-secteur-C14-Embase-male-verticale-715001-Nombre-de-poles-2-PE-10-A-noir-1-pcs/?ref=detview1&amp;amp;rt=detview1&amp;amp;rb=1]&lt;br /&gt;
*Câble secteur&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Logiciel :&lt;br /&gt;
&lt;br /&gt;
*Serveur web : Apache2, HTML5, PHP5, CSS&lt;br /&gt;
*Base de donnée : MySQL&lt;br /&gt;
*Serveur WebSocket : JQuerry, websocket&lt;br /&gt;
*Arduino : IDE Arduino&lt;br /&gt;
&lt;br /&gt;
===Calendrier prévisionnel===&lt;br /&gt;
&lt;br /&gt;
====Liste des tâches à effectuer====&lt;br /&gt;
Les différentes tâches à effectuer sont :&lt;br /&gt;
*Partie préliminaire : étude de fonctionnement des galvanomètres&lt;br /&gt;
**Déterminer comment est effectuée la commande des galvanomètres (protocole, tension...)&lt;br /&gt;
**Effectuer des tests avec l'Arduino ou la Raspberry Pi&lt;br /&gt;
**Effectuer des tests avec une LED à la place du laser &lt;br /&gt;
*Partie projection&lt;br /&gt;
**Fixer les lasers&lt;br /&gt;
**Aligner les lasers et les galvanomètres&lt;br /&gt;
**Créer le système d'alimentation&lt;br /&gt;
**Création d'un boitier&lt;br /&gt;
*Partie système embarqué&lt;br /&gt;
**Asservissement des galvanomètres avec l'Arduino&lt;br /&gt;
**Système électronique de commande en courant pour les galvanomètres&lt;br /&gt;
*Interface Web&lt;br /&gt;
**Installation et configuration Apache2&lt;br /&gt;
**Création d'une interface graphique simple&lt;br /&gt;
**Implémentation d'algorithmes de traitement d'image&lt;br /&gt;
**Mise en forme avec des CSS&lt;br /&gt;
**Sytème d'authentification avec mot de passe&lt;br /&gt;
**Utilisation d'une base de données pour enregistrer toutes les images déjà utilisés afin de les réutiliser&lt;br /&gt;
*Serveur Web Socket&lt;br /&gt;
**Récupération des données de l'interface web&lt;br /&gt;
**Mise en place de la liaison série avec l'Arduino&lt;br /&gt;
&lt;br /&gt;
====Calendrier====&lt;br /&gt;
Répartition du temps consacré au projet (240h) :&lt;br /&gt;
*Partie projection : 80h&lt;br /&gt;
*Partie système embarqué : 40h&lt;br /&gt;
*Partie interface web et websocket: 120h&lt;br /&gt;
&lt;br /&gt;
==Feuille d'heures==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!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&lt;br /&gt;
|-&lt;br /&gt;
| Définition cahier des charges &lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 14&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|38&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Finalisation du cahier des charges avec les responsables&lt;br /&gt;
&lt;br /&gt;
*Acquisition de matériels :&lt;br /&gt;
**Projecteur Laser&lt;br /&gt;
**Galvanomètres&lt;br /&gt;
**Alimentation des galvanomètres&lt;br /&gt;
&lt;br /&gt;
*Listage du matériels à acquérir :&lt;br /&gt;
**Lunettes de sécurité&lt;br /&gt;
**DAC&lt;br /&gt;
**Alimentation 230V/5V 1A&lt;br /&gt;
** Boitier ABS &lt;br /&gt;
**...&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
*Obtention de l'arduino et de la raspberryPI&lt;br /&gt;
&lt;br /&gt;
*Démontage du projecteur laser&lt;br /&gt;
**Deux lasers de classe 3b (vert et rouge)&lt;br /&gt;
**Circuit d'alimentation des deux lasers&lt;br /&gt;
&lt;br /&gt;
*Initialisation du port série de la raspberryPI&lt;br /&gt;
**Modification du fichier ''config.txt'' dans la partition boot&lt;br /&gt;
**Ajout d'une ligne autorisant la communication série ('''enable_uart=1''')&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
*Installation du serveur apache sur la raspberryPI&lt;br /&gt;
**Modification du fichier ''/etc/network/interfaces'' (Static, Address, Netmask, Gateway)&lt;br /&gt;
**Modification du fichier ''/etc/resolv.conf'' (Adresse du serveur)&lt;br /&gt;
**Utilisation d'un proxy pour la récupération outils de programmation (Apache2, Php5)&lt;br /&gt;
&lt;br /&gt;
*Mise en place du point d’accès wifi de la raspberryPI&lt;br /&gt;
**Récupération des logiciels nécessaires (dnsmasq, hostapd)&lt;br /&gt;
**Mise en place d'une adresse IP statique pour le point d'accès par l'intermédiaire du fichier ''/etc/dhcpcd.conf''&lt;br /&gt;
**Désactivation de la négociation automatique de bail dans le fichier ''/etc/network/interfaces''&lt;br /&gt;
**Configuration du logiciel hostapd ''/etc/hostapd/hostapd.conf''&lt;br /&gt;
**Activation du démarrage automatique du point d'accès ''/etc/default/hostapd''&lt;br /&gt;
**Configuration du serveur DNS par ''/etc/dnsmasq.conf''&lt;br /&gt;
&lt;br /&gt;
*Instauration de la page d'accueil de l'interface web à l'adresse ''192.168.3.1''&lt;br /&gt;
**Téléversement de fichiers images sur la page web et affichage de celle-ci&lt;br /&gt;
**Voyant de confirmation du bon fonctionnement du serveur web&lt;br /&gt;
&lt;br /&gt;
*Développement du serveur websocket&lt;br /&gt;
&lt;br /&gt;
Le développement du serveur websocket, initialement prévu en C (il était prévu de reprendre les sources utilisées l'année précédente dans le cadre des projet IMA3 SC), a finalement été réalisé en JAVA pour plusieurs raisons.&lt;br /&gt;
Premièrement, un seul programme met en œuvre le serveur websocket, les divers traitements d'image, ainsi que les contrôles des galvanomètres (par l'intermédiaire des DAC) via la liaison I²C de la Raspberry Pi. Le langage JAVA fournit nativement des bibliothèques d'objets pour manipuler assez simplement des images, il existe également des librairies pour contrôler le port GPIO de la Raspberry et il était également intéressant de travailler avec un langage de plus haut niveau que le C.&lt;br /&gt;
En outre, la totale portabilité de ce langage nous permet de travailler sur n'importe quelle machine et ensuite transférer notre programme sur la Raspberry Pi et l’exécuter sans même repasser par une phase de compilation. Et finalement, c'est le langage que nous étudions actuellement en cours de programmation orientée objet, ce qui permet de nous perfectionner.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Serveur WebSocket====&lt;br /&gt;
&lt;br /&gt;
N'ayant pas trouvé d'API WebSocket en Java satisfaisante (qui ne nécessitent pas l'installation et la configuration de nombreux outils additionnels), j'ai estimé plus commode et plus formateur de développer notre propre serveur WebSocket en se basant sur les librairies sockets de Java avec l'aide d'une documentation assez exhaustive [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers].&lt;br /&gt;
&lt;br /&gt;
Les WebSockets désignent à la fois un protocole réseau qui étend le protocole TCP ainsi qu'une API du World Wide Web. Nous nous en servons afin d'établir une communication asynchrone et bidirectionnelle entre un navigateur web et le serveur, notamment pour envoyer l'image à projeter. L’implémentation du serveur repose sur plusieurs étapes.&lt;br /&gt;
&lt;br /&gt;
1) Connexion d'un client &lt;br /&gt;
&lt;br /&gt;
2) Handshake : permet de faire le lien entre le protocole HTTP et WS. Le client envoie une requête HTTP demandant un upgrade de la connexion en protocole WS et le serveur répond en configurant la connexion (détail dans la documentation [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers]).&lt;br /&gt;
&lt;br /&gt;
3) Réception et décodage des messages : le serveurs reçoit des trames brutes, on extrait donc la taille du message ainsi que le message. De plus, les données son encodées (cryptage XOR) par un masque qui doit également être extrait.&lt;br /&gt;
&lt;br /&gt;
4) Fermeture de la communication.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le serveur supporte le multi-client il est donc nécessaire qu'il effectue ces étapes en &amp;quot;parallèle&amp;quot;. Nous utilisons donc les threads ou fils d’exécution. Un thread est donc responsable d'attendre qu'un nouveau client se connecte et effectue le &amp;quot;handshake&amp;quot;, il crée ensuite un thread associé à ce client afin d'établir un canal de communication. Il y a donc au moins un thread par client. Par la suite il faudra également implémenter une déconnexion automatique d'un client notamment après un timeout.&lt;br /&gt;
&lt;br /&gt;
Exemple d’exécution du serveur avec deux clients qui se connectent et envoient un message : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testServeur.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Les clients sont des navigateurs web. Pour les tests nous avons repris les exemples utilisés dans le cadre das projets IMA3 SC avec le titre de la page HTML qui se colore en vert lorsque le client est connecté, et un champ de saisie pour envoyer des messages au serveur : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testClient.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 4===&lt;br /&gt;
&lt;br /&gt;
*Mise en place d’algorithmes de traitement d'image&lt;br /&gt;
&lt;br /&gt;
====Détection de contour====&lt;br /&gt;
&lt;br /&gt;
L'objectif de notre projet est de pouvoir projeter n'importe quelle image envoyé grâce à l'application web. Pour cela nous allons tracer à une vitesse élevée les contours de l'image sur par exemple un mur grâce au laser. Il est donc nécessaire de détecter les contours de l'image grâce à plusieurs traitements.&lt;br /&gt;
&lt;br /&gt;
=====Conversion en niveau de gris=====&lt;br /&gt;
&lt;br /&gt;
Une des étapes préliminaires pour effectuer la détection de contour est de convertir l'image couleur en niveau de gris. Pour cela l'algorithme est simple : il suffit pour chaque pixel de l'image d'effectuer la moyenne des composantes rouge, verte, bleu de chaque pixel. En effet, si l'on considère une image matricielle (l'image est considérée comme un tableau à deux dimensions avec chaque case qui contient la couleur du pixel), chaque pixel contient les composantes RGB codées sur un octet. La couleur gris correspond aux composantes RGB égales. Le niveau de gris est donc codé de 0 à 255, avec 0 donnant du noir et 255 du blanc. &lt;br /&gt;
&lt;br /&gt;
Voici le résultat obtenu : [[Fichier:testGrayScale.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Filtre de Prewit et Sobel=====&lt;br /&gt;
&lt;br /&gt;
Un contour est défini par un changement brutal d'intensité lumineuse, il s'agit donc de détecter selon plusieurs directions (au moins 2) ces changements. Il existe de nombreuses techniques afin de détecter les contours d'une image (gradient, Laplacien). L'une des techniques avec un rapport efficacité/temps d'exécution correct repose sur les algorithmes de Prewit ou Sobel. L'algorithme repose sur la convolution de matrices.&lt;br /&gt;
Cela consiste à appliquer sur chaque pixel de l'image la matrice de Prewit définie comme &lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L_x = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; ainsi que sa transposée : &amp;lt;math&amp;gt;&lt;br /&gt;
L_y = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; -1 &amp;amp; -1 \\&lt;br /&gt;
 0 &amp;amp; 0 &amp;amp; 0 \\&lt;br /&gt;
+1 &amp;amp; +1 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Convoluer ces deux filtres sur l'image permet de détecter respectivement les contours verticaux et horizontaux.&lt;br /&gt;
&lt;br /&gt;
D'après wikipedia [https://fr.wikipedia.org/wiki/D%C3%A9tection_de_contours], on obtient de meilleurs résultats en appliquant un filtre triangulaire, on introduit donc la matrice de Sobel :&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-2 &amp;amp; 0 &amp;amp; +2 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
On obtient le résultat suivant : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testOutline1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Pré-traitement : Flou Gaussien=====&lt;br /&gt;
&lt;br /&gt;
Afin de réduire significativement le nombre de contours, il est nécessaire d'effectuer un pré-traitement avant la détection de contours. On utilise généralement un flou gaussien afin de réduire les transitions lumineuses et ainsi réduire le nombre de contours. L’algorithme de flou gaussien repose également sur la convolution de matrices sauf qu'ici la matrice filtre est générée grâce à une fonction gaussienne paramétrée par '''Sigma''' qui va directement impacter le niveau de flou. Plus la matrice de filtrage est grande plus la qualité du résultat est meilleure, mais le temps d’exécution devient également plus grand.&lt;br /&gt;
&lt;br /&gt;
Voici la fonction de génération du filtre : &amp;lt;math&amp;gt;G(x,y) = \frac{1}{{2\pi \sigma^2}} e^{-\frac{x^2 + y^2}{2 \sigma^2}}&amp;lt;/math&amp;gt; où x et y correspondent aux indices de la cellule de la matrice.&lt;br /&gt;
&lt;br /&gt;
On obtient ce résultat :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testGaussianBlur.png]]&lt;br /&gt;
&lt;br /&gt;
On note un bien meilleur résultat. Cependant on remarque que les composantes horizontales ne sont pas correctement détectées il subsiste un problème avec le filtrage vertical que je n'ai pas réussi à identifier. De plus, il s'agit par sa suite d'éliminer les contours parasites ainsi que d'affiner le trait pour n'avoir plus qu'un pixel d'épaisseur.&lt;br /&gt;
&lt;br /&gt;
=====Post-traitement : Algorithme de Canny=====&lt;br /&gt;
&lt;br /&gt;
Afin d'obtenir un résultat exploitable il est nécessaire d'appliquer encore quelques traitements. Pour cela nous utilisons l’algorithme de Canny qui repose que celui de Sobel mais qui ajoute un algorithme de seuillage par hysteresis qui permet de retirer les contours secondaires et de ne garder que les contours connexes dans une seuil haut et un seuil bas définis. En outre, cette algorithme affine également le trait obtenu. Pour cet algorithme nous avons directement trouvé des sources libres de droits [http://www.tomgibara.com/computer-vision/canny-edge-detector] qui donne des résultats très corrects.&lt;br /&gt;
&lt;br /&gt;
Par exemple :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ou encore : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny2.png|1500px]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 5===&lt;br /&gt;
&lt;br /&gt;
*Établissement d'un protocole de transfert d'image basé sur les WebSockets&lt;br /&gt;
**Envoie d'un requête &amp;quot;send&amp;quot; par le client dans une trame websocket texte&lt;br /&gt;
**Réponse serveur 'Y' si aucun autre client tente d'envoyer une image simultanément, 'N' sinon&lt;br /&gt;
**Si et seulement si le client reçoit 'Y' il débute le transfert en envoyant la largeur et la longueur de l'image sur 4 octets, puis les données de l'image soit 4 valeurs pour chaque pixels (r,g,b,alpha)&lt;br /&gt;
**Le serveur renvoie 'D' une fois le transfert achevé (à l'avenir, le serveur renverra l'image après filtrage).&lt;br /&gt;
**A tout moment, le serveur peut renvoyer 'E' si une erreur est survenue (ex : paquets perdus, nombre incorrects de données)&lt;br /&gt;
*Ajout du support des logs au niveau serveur&lt;br /&gt;
**Impression sur la sortie standard des messages&lt;br /&gt;
**Formatage en fonction de la sévérité du log (info, warning, error...)&lt;br /&gt;
**Incrustation de la date et heure&lt;br /&gt;
**Possibilité de redirection dans une fichier, avec configuration (écriture à la suite d'un fichier existant, écrasement...)&lt;br /&gt;
**Le tout dans une classe Java flexible et réutilisable pour d'autres projets&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 6===&lt;br /&gt;
&lt;br /&gt;
*Installation de la librairie Java Pi4j sur la raspberry pi qui permet le contrôle des GPIO de celle-ci et notamment le port I²C (basé sur WiringPi)&lt;br /&gt;
*Amélioration coté serveur websocket&lt;br /&gt;
**Gestion de message plus longs (maximum des trames websockets soit 2^63 octets)&lt;br /&gt;
**Différenciation, à la réception de messages, des trames textes ou binaires des trames de contrôle comme les requête ping, pong ou de fermeture de connexion &lt;br /&gt;
**Ajout d'un mode de debug de trames &lt;br /&gt;
&lt;br /&gt;
===Semaine 7===&lt;br /&gt;
&lt;br /&gt;
*Améliorations du serveur WebSocket&lt;br /&gt;
**Gestion de la fragmentation TCP&lt;br /&gt;
**Gestion de la fragmentation WebSocket&lt;br /&gt;
**Gestion des requêtes ping envoyés par le client en renvoyant une trames de contrôle pong afin de maintenir la connexion&lt;br /&gt;
**Gestion des déconnexion de clients afin d'optimiser le serveur&lt;br /&gt;
**Amélioration de l'émission de messages en augmentant la taille maximale pouvant être émise (2^63 octets)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A ce stade du développement, le client et le serveur sont opérationnels et peuvent s'échanger des messages ainsi que des images que le serveur traite pour extraire les contours.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 8===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Montage projecteur&lt;br /&gt;
**Intégralité des composants fixés par vis dans le boîtier ABS&lt;br /&gt;
**Fusion des alimentations&lt;br /&gt;
**Présence d'une led témoin de mise en tension&lt;br /&gt;
**Position laser réglable grâce à une vis&lt;br /&gt;
**Présence d'un switch à bascule pour allumer et éteindre le laser&lt;br /&gt;
**Isolation et vérification des composants&lt;br /&gt;
**Tests empiriques de température et de fonctionnement des lasers et galvanomètres&lt;br /&gt;
&lt;br /&gt;
Le montage boîtier est donc terminé et s’alimente en 230V par intermédiaire d'un câble secteur avec connecteur C14. Le résultat s'avère plutôt compact. Les quelques tests de température ont montrés que malgré le manque d'espace la température globale du boîtier ne dépasse pas les 50°C pendant plus d'une heure de fonctionnement. L'intégralité des connexions sont isolées avec de la gaine thermodynamique et les zones &amp;quot;sensibles&amp;quot; sont correctement vérifiés ainsi que protégées avec de la matière isolante.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:proj1.jpg|550px|Boîtier après perçage]] [[Fichier:proj2.jpg|550px|Boîtier finalisé]] [[Fichier:proj3.jpg|550px|Projecteur en fonctionnement]]&lt;br /&gt;
&lt;br /&gt;
*Page web et serveur WebSocket&lt;br /&gt;
**Ajout d'un bouton &amp;quot;reboot&amp;quot; et &amp;quot;shutdown&amp;quot; qui permettent respectivement de redémarrer et d'éteindre la Raspberry directement à partir de la page web&lt;br /&gt;
&lt;br /&gt;
===Semaine 9===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 10===&lt;br /&gt;
&lt;br /&gt;
==A faire==&lt;br /&gt;
&lt;br /&gt;
MAJ 26 mars &lt;br /&gt;
&lt;br /&gt;
*Client websocket et page web&lt;br /&gt;
**Mise en page CSS&lt;br /&gt;
**Ajout canvas pour prévisualisation image projeté&lt;br /&gt;
**Ajout &amp;quot;slider&amp;quot; pour régler niveau du flou Gaussien DOUBLE&lt;br /&gt;
**Ajout slider pour de finir amplitude de la projection&lt;br /&gt;
**Afficher statut de connexion&lt;br /&gt;
**Ajout message de confirmation quand le serveur quitte ou relance&lt;br /&gt;
**Ajout boutons &amp;quot;projeter&amp;quot; &amp;quot;centrer&amp;quot; &amp;quot;eteindre&amp;quot;&lt;br /&gt;
**Gestion de plusieurs images avec délai&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Serveur WebSocket&lt;br /&gt;
**Ajout fonctionnalité envoi image de prévisualisation&lt;br /&gt;
&lt;br /&gt;
*RaspberryPi&lt;br /&gt;
**Utilisation d'un serveur bind9 pour éviter de taper IP&lt;br /&gt;
&lt;br /&gt;
*Détection de contours&lt;br /&gt;
**Implémentation algorithme de tri de la plus courte disance&lt;br /&gt;
&lt;br /&gt;
*Commande galvanomêtre&lt;br /&gt;
**Utilisation API I²C&lt;br /&gt;
**Fonction de transfert position-&amp;gt;angle-&amp;gt;tension&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;br /&gt;
&lt;br /&gt;
==Bibliographie==&lt;br /&gt;
&lt;br /&gt;
http://www.ebay.com/itm/20KPPS-30KPPS-laser-scanning-galvo-scanner-ILDA-Closed-Loop-max-30kpps-for-laser-/261517002270?hash=item3ce3a0c61e&lt;br /&gt;
&lt;br /&gt;
https://icn.fenelonlille.org/mediawiki/index.php/Projet_ICN_commun_2016/2017&lt;br /&gt;
&lt;br /&gt;
https://www.g33k-zone.org/post/2016/05/11/Configurer-le-Raspberry-Pi-en-point-d-acc%C3%A8s-Wifi&lt;br /&gt;
&lt;br /&gt;
http://stackoverflow.com/questions/22087076/how-to-make-a-simple-image-upload-using-javascript-html&lt;br /&gt;
&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_a_WebSocket_server_in_Java&lt;br /&gt;
&lt;br /&gt;
export http_proxy=http://proxy.polytech-lille.fr:3128&lt;/div&gt;</summary>
		<author><name>Mtrimbur</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=40830</id>
		<title>IMA4 2016/2017 P39</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=40830"/>
				<updated>2017-03-27T18:07:46Z</updated>
		
		<summary type="html">&lt;p&gt;Mtrimbur : /* Post-traitement : Algorithme de Canny */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
===Contexte===&lt;br /&gt;
&lt;br /&gt;
Le laser est une technologie largement utilisé de nos jours dans de diverses applications. En effet, on retrouve cette technologie dans le domaine médical notamment pour la chirurgie oculaire ou encore dans industrie avec la découpe laser ou la soudure au laser.&lt;br /&gt;
&lt;br /&gt;
Le laser est une émission de photons produit par excitation d'un milieu amplificateur (ex : CO2), le rayonnement produit est unidirectionnel et monochromatique. Ce sont ces propriétés que nous allons exploiter afin réaliser un projecteur laser qui mis en mouvement est capable de dessiner des formes sur une surface à l'instar de systèmes existants utilisés pour des effets lumineux lors de festivités.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
L'objectif du projet est de créer un système de projection laser à plusieurs couleurs (au minimum deux) avec une application web pour programmer les formes à dessiner afin d'agrémenter des compétitions de gymnastique rythmique.&lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
Le projet consiste à réaliser avec des lasers des figures géométriques par l'intermédiaire d'un système galvanométrique. &lt;br /&gt;
&lt;br /&gt;
Notre premier travail sera de concevoir la partie projection. Pour cela, nous devrons aligner les lasers et les galvanomètres. En effet, ces derniers posséderont des miroirs à l'extrémité, ainsi les miroirs changeront d'inclinaison suivant le courant traversant les galvanomètres (similaire à l'image ci-contre). Il nous faudra également créer un système d'alimentation qui à partir d'une même source (réseau 230 V) sera capable d'alimenter les lasers et les galvanomètres ainsi qu'une Arduino et une Raspberry Pi.&lt;br /&gt;
[[File:Scanhead.jpeg|thumb]]&lt;br /&gt;
&lt;br /&gt;
Ensuite nous nous intéresserons à l'utilisation d'un système embarqué pour contrôler les galvanomètres et donc dessiner avec les lasers sur un plan 2D. En effet, le laser restera toujours fixe, seuls les galvanomètres, et donc les miroirs bougeront. Les galvanomètres étant contrôlés en courant il faudra réaliser une interface électronique pour convertir une commande en tension en commande de courant. La commande en tension sera assuré par une carte Arduino. Nous n'utiliserons qu'une seule paire de galvanomètres pour les deux laser. Il faudra donc multiplexer les deux faisceaux. La programmation des formes à effectuer, se fera par l'intermédiaire d'une application web PHP hébergée sur une RaspberryPi qui permettra de récupérer une image, d'y appliquer divers traitements et filtres afin d'en extraire les contours, et de calculer les commandes pour positionner les galvanomètres. Un serveur WebSocket également hébergé sur la RaspberryPi servira d'interface entre l'application web et L'arduino qui sera connecté via une liaison série sur la raspberryPI.&lt;br /&gt;
&lt;br /&gt;
Comme animation de test, nous dessinerons le contour d'une gymnaste avec une couleur et son ballon d'une autre couleur. La gymnaste devra lancer son ballon, réaliser quelques difficultés et récupérer son ballon.&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
Nous utiliserons comme matériels :&lt;br /&gt;
*Deux lasers de différentes couleurs&lt;br /&gt;
*Une paire de galvanomètres à miroir&lt;br /&gt;
*Arduino&lt;br /&gt;
*Raspberry Pi3&lt;br /&gt;
*Alimentation 230V/5V 1A [http://www.miniinthebox.com/fr/dual-usb-eu-prise-murale-5v-2a-voyage-adaptateur-chargeur-d-alimentation-pour-iphone7-6-xiaomi-samsung-et-autre-telephone-portable_p5410410.html?currency=EUR&amp;amp;litb_from=paid_adwords_shopping&amp;amp;sku=429_6917%7C752_20648&amp;amp;utm_source=google_shopping&amp;amp;utm_medium=cpc&amp;amp;adword_mt=&amp;amp;adword_ct=138705676724&amp;amp;adword_kw=&amp;amp;adword_pos=1o5&amp;amp;adword_pl=&amp;amp;adword_net=g&amp;amp;adword_tar=&amp;amp;adw_src_id=9653316068_661261352_33588296076_aud-79897721311:pla-256966386459&amp;amp;gclid=Cj0KEQiA_KvEBRCtzNil4-KR-LIBEiQAmgekFxxKjJJWBYCJlDZEa3Ke_2_WR0DzGVbz-jaCZHVIBoMaAvld8P8HAQ]&lt;br /&gt;
*Drivers galvanomètres x2&lt;br /&gt;
*Alimentation laser&lt;br /&gt;
*Lunette de sécurité x2 [https://www.amazon.fr/Uvex-S1933X-Eyewear-SCTOrange-Anti-Fog/dp/B000USRG90/ref=sr_1_1?ie=UTF8&amp;amp;qid=1485441383&amp;amp;sr=8-1&amp;amp;keywords=uvex+s1933x]&lt;br /&gt;
*Boitier ABS [http://fr.farnell.com/multicomp/g3118/boitier-abs-240x120x60mm-ip65/dp/1526656]&lt;br /&gt;
*DAC 4 canaux, avec interface I²C [https://www.adafruit.com/products/1083]&lt;br /&gt;
*Connecteur C14 [http://www.conrad.fr/ce/fr/product/715001/Connecteur-secteur-C14-Embase-male-verticale-715001-Nombre-de-poles-2-PE-10-A-noir-1-pcs/?ref=detview1&amp;amp;rt=detview1&amp;amp;rb=1]&lt;br /&gt;
*Câble secteur&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Logiciel :&lt;br /&gt;
&lt;br /&gt;
*Serveur web : Apache2, HTML5, PHP5, CSS&lt;br /&gt;
*Base de donnée : MySQL&lt;br /&gt;
*Serveur WebSocket : JQuerry, websocket&lt;br /&gt;
*Arduino : IDE Arduino&lt;br /&gt;
&lt;br /&gt;
===Calendrier prévisionnel===&lt;br /&gt;
&lt;br /&gt;
====Liste des tâches à effectuer====&lt;br /&gt;
Les différentes tâches à effectuer sont :&lt;br /&gt;
*Partie préliminaire : étude de fonctionnement des galvanomètres&lt;br /&gt;
**Déterminer comment est effectuée la commande des galvanomètres (protocole, tension...)&lt;br /&gt;
**Effectuer des tests avec l'Arduino ou la Raspberry Pi&lt;br /&gt;
**Effectuer des tests avec une LED à la place du laser &lt;br /&gt;
*Partie projection&lt;br /&gt;
**Fixer les lasers&lt;br /&gt;
**Aligner les lasers et les galvanomètres&lt;br /&gt;
**Créer le système d'alimentation&lt;br /&gt;
**Création d'un boitier&lt;br /&gt;
*Partie système embarqué&lt;br /&gt;
**Asservissement des galvanomètres avec l'Arduino&lt;br /&gt;
**Système électronique de commande en courant pour les galvanomètres&lt;br /&gt;
*Interface Web&lt;br /&gt;
**Installation et configuration Apache2&lt;br /&gt;
**Création d'une interface graphique simple&lt;br /&gt;
**Implémentation d'algorithmes de traitement d'image&lt;br /&gt;
**Mise en forme avec des CSS&lt;br /&gt;
**Sytème d'authentification avec mot de passe&lt;br /&gt;
**Utilisation d'une base de données pour enregistrer toutes les images déjà utilisés afin de les réutiliser&lt;br /&gt;
*Serveur Web Socket&lt;br /&gt;
**Récupération des données de l'interface web&lt;br /&gt;
**Mise en place de la liaison série avec l'Arduino&lt;br /&gt;
&lt;br /&gt;
====Calendrier====&lt;br /&gt;
Répartition du temps consacré au projet (240h) :&lt;br /&gt;
*Partie projection : 80h&lt;br /&gt;
*Partie système embarqué : 40h&lt;br /&gt;
*Partie interface web et websocket: 120h&lt;br /&gt;
&lt;br /&gt;
==Feuille d'heures==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!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&lt;br /&gt;
|-&lt;br /&gt;
| Définition cahier des charges &lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 14&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|38&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Finalisation du cahier des charges avec les responsables&lt;br /&gt;
&lt;br /&gt;
*Acquisition de matériels :&lt;br /&gt;
**Projecteur Laser&lt;br /&gt;
**Galvanomètres&lt;br /&gt;
**Alimentation des galvanomètres&lt;br /&gt;
&lt;br /&gt;
*Listage du matériels à acquérir :&lt;br /&gt;
**Lunettes de sécurité&lt;br /&gt;
**DAC&lt;br /&gt;
**Alimentation 230V/5V 1A&lt;br /&gt;
** Boitier ABS &lt;br /&gt;
**...&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
*Obtention de l'arduino et de la raspberryPI&lt;br /&gt;
&lt;br /&gt;
*Démontage du projecteur laser&lt;br /&gt;
**Deux lasers de classe 3b (vert et rouge)&lt;br /&gt;
**Circuit d'alimentation des deux lasers&lt;br /&gt;
&lt;br /&gt;
*Initialisation du port série de la raspberryPI&lt;br /&gt;
**Modification du fichier ''config.txt'' dans la partition boot&lt;br /&gt;
**Ajout d'une ligne autorisant la communication série ('''enable_uart=1''')&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
*Installation du serveur apache sur la raspberryPI&lt;br /&gt;
**Modification du fichier ''/etc/network/interfaces'' (Static, Address, Netmask, Gateway)&lt;br /&gt;
**Modification du fichier ''/etc/resolv.conf'' (Adresse du serveur)&lt;br /&gt;
**Utilisation d'un proxy pour la récupération outils de programmation (Apache2, Php5)&lt;br /&gt;
&lt;br /&gt;
*Mise en place du point d’accès wifi de la raspberryPI&lt;br /&gt;
**Récupération des logiciels nécessaires (dnsmasq, hostapd)&lt;br /&gt;
**Mise en place d'une adresse IP statique pour le point d'accès par l'intermédiaire du fichier ''/etc/dhcpcd.conf''&lt;br /&gt;
**Désactivation de la négociation automatique de bail dans le fichier ''/etc/network/interfaces''&lt;br /&gt;
**Configuration du logiciel hostapd ''/etc/hostapd/hostapd.conf''&lt;br /&gt;
**Activation du démarrage automatique du point d'accès ''/etc/default/hostapd''&lt;br /&gt;
**Configuration du serveur DNS par ''/etc/dnsmasq.conf''&lt;br /&gt;
&lt;br /&gt;
*Instauration de la page d'accueil de l'interface web à l'adresse ''192.168.3.1''&lt;br /&gt;
**Téléversement de fichiers images sur la page web et affichage de celle-ci&lt;br /&gt;
**Voyant de confirmation du bon fonctionnement du serveur web&lt;br /&gt;
&lt;br /&gt;
*Développement du serveur websocket&lt;br /&gt;
&lt;br /&gt;
Le développement du serveur websocket, initialement prévu en C (il était prévu de reprendre les sources utilisées l'année précédente dans le cadre des projet IMA3 SC), a finalement été réalisé en JAVA pour plusieurs raisons.&lt;br /&gt;
Premièrement, un seul programme met en œuvre le serveur websocket, les divers traitements d'image, ainsi que les contrôles des galvanomètres (par l'intermédiaire des DAC) via la liaison I²C de la Raspberry Pi. Le langage JAVA fournit nativement des bibliothèques d'objets pour manipuler assez simplement des images, il existe également des librairies pour contrôler le port GPIO de la Raspberry et il était également intéressant de travailler avec un langage de plus haut niveau que le C.&lt;br /&gt;
En outre, la totale portabilité de ce langage nous permet de travailler sur n'importe quelle machine et ensuite transférer notre programme sur la Raspberry Pi et l’exécuter sans même repasser par une phase de compilation. Et finalement, c'est le langage que nous étudions actuellement en cours de programmation orientée objet, ce qui permet de nous perfectionner.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Serveur WebSocket====&lt;br /&gt;
&lt;br /&gt;
N'ayant pas trouvé d'API WebSocket en Java satisfaisante (qui ne nécessitent pas l'installation et la configuration de nombreux outils additionnels), j'ai estimé plus commode et plus formateur de développer notre propre serveur WebSocket en se basant sur les librairies sockets de Java avec l'aide d'une documentation assez exhaustive [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers].&lt;br /&gt;
&lt;br /&gt;
Les WebSockets désignent à la fois un protocole réseau qui étend le protocole TCP ainsi qu'une API du World Wide Web. Nous nous en servons afin d'établir une communication asynchrone et bidirectionnelle entre un navigateur web et le serveur, notamment pour envoyer l'image à projeter. L’implémentation du serveur repose sur plusieurs étapes.&lt;br /&gt;
&lt;br /&gt;
1) Connexion d'un client &lt;br /&gt;
&lt;br /&gt;
2) Handshake : permet de faire le lien entre le protocole HTTP et WS. Le client envoie une requête HTTP demandant un upgrade de la connexion en protocole WS et le serveur répond en configurant la connexion (détail dans la documentation [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers]).&lt;br /&gt;
&lt;br /&gt;
3) Réception et décodage des messages : le serveurs reçoit des trames brutes, on extrait donc la taille du message ainsi que le message. De plus, les données son encodées (cryptage XOR) par un masque qui doit également être extrait.&lt;br /&gt;
&lt;br /&gt;
4) Fermeture de la communication.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le serveur supporte le multi-client il est donc nécessaire qu'il effectue ces étapes en &amp;quot;parallèle&amp;quot;. Nous utilisons donc les threads ou fils d’exécution. Un thread est donc responsable d'attendre qu'un nouveau client se connecte et effectue le &amp;quot;handshake&amp;quot;, il crée ensuite un thread associé à ce client afin d'établir un canal de communication. Il y a donc au moins un thread par client. Par la suite il faudra également implémenter une déconnexion automatique d'un client notamment après un timeout.&lt;br /&gt;
&lt;br /&gt;
Exemple d’exécution du serveur avec deux clients qui se connectent et envoient un message : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testServeur.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Les clients sont des navigateurs web. Pour les tests nous avons repris les exemples utilisés dans le cadre das projets IMA3 SC avec le titre de la page HTML qui se colore en vert lorsque le client est connecté, et un champ de saisie pour envoyer des messages au serveur : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testClient.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 4===&lt;br /&gt;
&lt;br /&gt;
*Mise en place d’algorithmes de traitement d'image&lt;br /&gt;
&lt;br /&gt;
====Détection de contour====&lt;br /&gt;
&lt;br /&gt;
L'objectif de notre projet est de pouvoir projeter n'importe quelle image envoyé grâce à l'application web. Pour cela nous allons tracer à une vitesse élevée les contours de l'image sur par exemple un mur grâce au laser. Il est donc nécessaire de détecter les contours de l'image grâce à plusieurs traitements.&lt;br /&gt;
&lt;br /&gt;
=====Conversion en niveau de gris=====&lt;br /&gt;
&lt;br /&gt;
Une des étapes préliminaires pour effectuer la détection de contour est de convertir l'image couleur en niveau de gris. Pour cela l'algorithme est simple : il suffit pour chaque pixel de l'image d'effectuer la moyenne des composantes rouge, verte, bleu de chaque pixel. En effet, si l'on considère une image matricielle (l'image est considérée comme un tableau à deux dimensions avec chaque case qui contient la couleur du pixel), chaque pixel contient les composantes RGB codées sur un octet. La couleur gris correspond aux composantes RGB égales. Le niveau de gris est donc codé de 0 à 255, avec 0 donnant du noir et 255 du blanc. &lt;br /&gt;
&lt;br /&gt;
Voici le résultat obtenu : [[Fichier:testGrayScale.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Filtre de Prewit et Sobel=====&lt;br /&gt;
&lt;br /&gt;
Un contour est défini par un changement brutal d'intensité lumineuse, il s'agit donc de détecter selon plusieurs directions (au moins 2) ces changements. Il existe de nombreuses techniques afin de détecter les contours d'une image (gradient, Laplacien). L'une des techniques avec un rapport efficacité/temps d'exécution correct repose sur les algorithmes de Prewit ou Sobel. L'algorithme repose sur la convolution de matrices.&lt;br /&gt;
Cela consiste à appliquer sur chaque pixel de l'image la matrice de Prewit définie comme &lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L_x = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; ainsi que sa transposée : &amp;lt;math&amp;gt;&lt;br /&gt;
L_y = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; -1 &amp;amp; -1 \\&lt;br /&gt;
 0 &amp;amp; 0 &amp;amp; 0 \\&lt;br /&gt;
+1 &amp;amp; +1 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Convoluer ces deux filtres sur l'image permet de détecter respectivement les contours verticaux et horizontaux.&lt;br /&gt;
&lt;br /&gt;
D'après wikipedia [https://fr.wikipedia.org/wiki/D%C3%A9tection_de_contours], on obtient de meilleurs résultats en appliquant un filtre triangulaire, on introduit donc la matrice de Sobel :&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-2 &amp;amp; 0 &amp;amp; +2 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
On obtient le résultat suivant : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testOutline1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Pré-traitement : Flou Gaussien=====&lt;br /&gt;
&lt;br /&gt;
Afin de réduire significativement le nombre de contours, il est nécessaire d'effectuer un pré-traitement avant la détection de contours. On utilise généralement un flou gaussien afin de réduire les transitions lumineuses et ainsi réduire le nombre de contours. L’algorithme de flou gaussien repose également sur la convolution de matrices sauf qu'ici la matrice filtre est générée grâce à une fonction gaussienne paramétrée par '''Sigma''' qui va directement impacter le niveau de flou. Plus la matrice de filtrage est grande plus la qualité du résultat est meilleure, mais le temps d’exécution devient également plus grand.&lt;br /&gt;
&lt;br /&gt;
Voici la fonction de génération du filtre : &amp;lt;math&amp;gt;G(x,y) = \frac{1}{{2\pi \sigma^2}} e^{-\frac{x^2 + y^2}{2 \sigma^2}}&amp;lt;/math&amp;gt; où x et y correspondent aux indices de la cellule de la matrice.&lt;br /&gt;
&lt;br /&gt;
On obtient ce résultat :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testGaussianBlur.png]]&lt;br /&gt;
&lt;br /&gt;
On note un bien meilleur résultat. Cependant on remarque que les composantes horizontales ne sont pas correctement détectées il subsiste un problème avec le filtrage vertical que je n'ai pas réussi à identifier. De plus, il s'agit par sa suite d'éliminer les contours parasites ainsi que d'affiner le trait pour n'avoir plus qu'un pixel d'épaisseur.&lt;br /&gt;
&lt;br /&gt;
=====Post-traitement : Algorithme de Canny=====&lt;br /&gt;
&lt;br /&gt;
Afin d'obtenir un résultat exploitable il est nécessaire d'appliquer encore quelques traitements. Pour cela nous utilisons l’algorithme de Canny qui repose que celui de Sobel mais qui ajoute un algorithme de seuillage par hysteresis qui permet de retirer les contours secondaires et de ne garder que les contours connexes dans une seuil haut et un seuil bas définis. En outre, cette algorithme affine également le trait obtenu. Pour cet algorithme nous avons directement trouvé des sources libres de droits [http://www.tomgibara.com/computer-vision/canny-edge-detector] qui donne des résultats très corrects.&lt;br /&gt;
&lt;br /&gt;
Par exemple :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ou encore : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny2.png|1500px]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 5===&lt;br /&gt;
&lt;br /&gt;
*Établissement d'un protocole de transfert d'image basé sur les WebSockets&lt;br /&gt;
**Envoie d'un requête &amp;quot;send&amp;quot; par le client dans une trame websocket texte&lt;br /&gt;
**Réponse serveur 'Y' si aucun autre client tente d'envoyer une image simultanément, 'N' sinon&lt;br /&gt;
**Si et seulement si le client reçoit 'Y' il débute le transfert en envoyant la largeur et la longueur de l'image sur 4 octets, puis les données de l'image soit 4 valeurs pour chaque pixels (r,g,b,alpha)&lt;br /&gt;
**Le serveur renvoie 'D' une fois le transfert achevé (à l'avenir, le serveur renverra l'image après filtrage).&lt;br /&gt;
**A tout moment, le serveur peut renvoyer 'E' si une erreur est survenue (ex : paquets perdus, nombre incorrects de données)&lt;br /&gt;
*Ajout du support des logs au niveau serveur&lt;br /&gt;
**Impression sur la sortie standard des messages&lt;br /&gt;
**Formatage en fonction de la sévérité du log (info, warning, error...)&lt;br /&gt;
**Incrustation de la date et heure&lt;br /&gt;
**Possibilité de redirection dans une fichier, avec configuration (écriture à la suite d'un fichier existant, écrasement...)&lt;br /&gt;
**Le tout dans une classe Java flexible et réutilisable pour d'autres projets&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 6===&lt;br /&gt;
&lt;br /&gt;
*Installation de la librairie Java Pi4j sur la raspberry pi qui permet le contrôle des GPIO de celle-ci et notamment le port I²C (basé sur WiringPi)&lt;br /&gt;
*Amélioration coté serveur websocket&lt;br /&gt;
**Gestion de message plus longs (maximum des trames websockets soit 2^63 octets)&lt;br /&gt;
**Différenciation, à la réception de messages, des trames textes ou binaires des trames de contrôle comme les requête ping, pong ou de fermeture de connexion &lt;br /&gt;
**Ajout d'un mode de debug de trames &lt;br /&gt;
&lt;br /&gt;
===Semaine 7===&lt;br /&gt;
&lt;br /&gt;
*Améliorations du serveur WebSocket&lt;br /&gt;
**Gestion de la fragmentation TCP&lt;br /&gt;
**Gestion de la fragmentation WebSocket&lt;br /&gt;
**Gestion des requêtes ping envoyés par le client en renvoyant une trames de contrôle pong afin de maintenir la connexion&lt;br /&gt;
**Gestion des déconnexion de clients afin d'optimiser le serveur&lt;br /&gt;
**Amélioration de l'émission de messages en augmentant la taille maximale pouvant être émise (2^63 octets)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A ce stade du développement, le client et le serveur sont opérationnels et peuvent s'échanger des messages ainsi que des images que le serveur traite pour extraire les contours.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 8===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Montage projecteur&lt;br /&gt;
**Intégralité des composants fixés par vis dans le boîtier ABS&lt;br /&gt;
**Fusion des alimentations&lt;br /&gt;
**Présence d'une led témoin de mise en tension&lt;br /&gt;
**Position laser réglable grâce à une vis&lt;br /&gt;
**Présence d'un switch à bascule pour allumer et éteindre le laser&lt;br /&gt;
**Isolation et vérification des composants&lt;br /&gt;
**Tests empiriques de température et de fonctionnement des lasers et galvanomètres&lt;br /&gt;
&lt;br /&gt;
Le montage boîtier est donc terminé et s’alimente en 230V par intermédiaire d'un câble secteur avec connecteur C14. Le résultat s'avère plutôt compact. Les quelques tests de températures ont montrés que malgré le manque d'espace la température globale du boîtier ne dépasse pas les 50°C pendant plus d'une heure de fonctionnement. L'intégralité des connexions sont isolées avec de la gaine thermodynamique et les zones &amp;quot;sensibles&amp;quot; sont correctement vérifiés ainsi que protégées avec de la matière isolante.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:proj1.jpg|550px|Boîtier après perçage]] [[Fichier:proj2.jpg|550px|Boîtier finalisé]] [[Fichier:proj3.jpg|550px|Projecteur en fonctionnement]]&lt;br /&gt;
&lt;br /&gt;
*Page web et serveur WebSocket&lt;br /&gt;
**Ajout d'un bouton &amp;quot;reboot&amp;quot; et &amp;quot;shutdown&amp;quot; qui permettent respectivement de redémarrer et d'éteindre la Raspberry directement à partir de la page web&lt;br /&gt;
&lt;br /&gt;
===Semaine 9===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 10===&lt;br /&gt;
&lt;br /&gt;
==A faire==&lt;br /&gt;
&lt;br /&gt;
MAJ 26 mars &lt;br /&gt;
&lt;br /&gt;
*Client websocket et page web&lt;br /&gt;
**Mise en page CSS&lt;br /&gt;
**Ajout canvas pour prévisualisation image projeté&lt;br /&gt;
**Ajout &amp;quot;slider&amp;quot; pour régler niveau du flou Gaussien DOUBLE&lt;br /&gt;
**Ajout slider pour de finir amplitude de la projection&lt;br /&gt;
**Afficher statut de connexion&lt;br /&gt;
**Ajout message de confirmation quand le serveur quitte ou relance&lt;br /&gt;
**Ajout boutons &amp;quot;projeter&amp;quot; &amp;quot;centrer&amp;quot; &amp;quot;eteindre&amp;quot;&lt;br /&gt;
**Gestion de plusieurs images avec délai&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Serveur WebSocket&lt;br /&gt;
**Ajout fonctionnalité envoi image de prévisualisation&lt;br /&gt;
&lt;br /&gt;
*RaspberryPi&lt;br /&gt;
**Utilisation d'un serveur bind9 pour éviter de taper IP&lt;br /&gt;
&lt;br /&gt;
*Détection de contours&lt;br /&gt;
**Implémentation algorithme de tri de la plus courte disance&lt;br /&gt;
&lt;br /&gt;
*Commande galvanomêtre&lt;br /&gt;
**Utilisation API I²C&lt;br /&gt;
**Fonction de transfert position-&amp;gt;angle-&amp;gt;tension&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;br /&gt;
&lt;br /&gt;
==Bibliographie==&lt;br /&gt;
&lt;br /&gt;
http://www.ebay.com/itm/20KPPS-30KPPS-laser-scanning-galvo-scanner-ILDA-Closed-Loop-max-30kpps-for-laser-/261517002270?hash=item3ce3a0c61e&lt;br /&gt;
&lt;br /&gt;
https://icn.fenelonlille.org/mediawiki/index.php/Projet_ICN_commun_2016/2017&lt;br /&gt;
&lt;br /&gt;
https://www.g33k-zone.org/post/2016/05/11/Configurer-le-Raspberry-Pi-en-point-d-acc%C3%A8s-Wifi&lt;br /&gt;
&lt;br /&gt;
http://stackoverflow.com/questions/22087076/how-to-make-a-simple-image-upload-using-javascript-html&lt;br /&gt;
&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_a_WebSocket_server_in_Java&lt;br /&gt;
&lt;br /&gt;
export http_proxy=http://proxy.polytech-lille.fr:3128&lt;/div&gt;</summary>
		<author><name>Mtrimbur</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=40829</id>
		<title>IMA4 2016/2017 P39</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=40829"/>
				<updated>2017-03-27T18:06:12Z</updated>
		
		<summary type="html">&lt;p&gt;Mtrimbur : /* Semaine 8 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
===Contexte===&lt;br /&gt;
&lt;br /&gt;
Le laser est une technologie largement utilisé de nos jours dans de diverses applications. En effet, on retrouve cette technologie dans le domaine médical notamment pour la chirurgie oculaire ou encore dans industrie avec la découpe laser ou la soudure au laser.&lt;br /&gt;
&lt;br /&gt;
Le laser est une émission de photons produit par excitation d'un milieu amplificateur (ex : CO2), le rayonnement produit est unidirectionnel et monochromatique. Ce sont ces propriétés que nous allons exploiter afin réaliser un projecteur laser qui mis en mouvement est capable de dessiner des formes sur une surface à l'instar de systèmes existants utilisés pour des effets lumineux lors de festivités.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
L'objectif du projet est de créer un système de projection laser à plusieurs couleurs (au minimum deux) avec une application web pour programmer les formes à dessiner afin d'agrémenter des compétitions de gymnastique rythmique.&lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
Le projet consiste à réaliser avec des lasers des figures géométriques par l'intermédiaire d'un système galvanométrique. &lt;br /&gt;
&lt;br /&gt;
Notre premier travail sera de concevoir la partie projection. Pour cela, nous devrons aligner les lasers et les galvanomètres. En effet, ces derniers posséderont des miroirs à l'extrémité, ainsi les miroirs changeront d'inclinaison suivant le courant traversant les galvanomètres (similaire à l'image ci-contre). Il nous faudra également créer un système d'alimentation qui à partir d'une même source (réseau 230 V) sera capable d'alimenter les lasers et les galvanomètres ainsi qu'une Arduino et une Raspberry Pi.&lt;br /&gt;
[[File:Scanhead.jpeg|thumb]]&lt;br /&gt;
&lt;br /&gt;
Ensuite nous nous intéresserons à l'utilisation d'un système embarqué pour contrôler les galvanomètres et donc dessiner avec les lasers sur un plan 2D. En effet, le laser restera toujours fixe, seuls les galvanomètres, et donc les miroirs bougeront. Les galvanomètres étant contrôlés en courant il faudra réaliser une interface électronique pour convertir une commande en tension en commande de courant. La commande en tension sera assuré par une carte Arduino. Nous n'utiliserons qu'une seule paire de galvanomètres pour les deux laser. Il faudra donc multiplexer les deux faisceaux. La programmation des formes à effectuer, se fera par l'intermédiaire d'une application web PHP hébergée sur une RaspberryPi qui permettra de récupérer une image, d'y appliquer divers traitements et filtres afin d'en extraire les contours, et de calculer les commandes pour positionner les galvanomètres. Un serveur WebSocket également hébergé sur la RaspberryPi servira d'interface entre l'application web et L'arduino qui sera connecté via une liaison série sur la raspberryPI.&lt;br /&gt;
&lt;br /&gt;
Comme animation de test, nous dessinerons le contour d'une gymnaste avec une couleur et son ballon d'une autre couleur. La gymnaste devra lancer son ballon, réaliser quelques difficultés et récupérer son ballon.&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
Nous utiliserons comme matériels :&lt;br /&gt;
*Deux lasers de différentes couleurs&lt;br /&gt;
*Une paire de galvanomètres à miroir&lt;br /&gt;
*Arduino&lt;br /&gt;
*Raspberry Pi3&lt;br /&gt;
*Alimentation 230V/5V 1A [http://www.miniinthebox.com/fr/dual-usb-eu-prise-murale-5v-2a-voyage-adaptateur-chargeur-d-alimentation-pour-iphone7-6-xiaomi-samsung-et-autre-telephone-portable_p5410410.html?currency=EUR&amp;amp;litb_from=paid_adwords_shopping&amp;amp;sku=429_6917%7C752_20648&amp;amp;utm_source=google_shopping&amp;amp;utm_medium=cpc&amp;amp;adword_mt=&amp;amp;adword_ct=138705676724&amp;amp;adword_kw=&amp;amp;adword_pos=1o5&amp;amp;adword_pl=&amp;amp;adword_net=g&amp;amp;adword_tar=&amp;amp;adw_src_id=9653316068_661261352_33588296076_aud-79897721311:pla-256966386459&amp;amp;gclid=Cj0KEQiA_KvEBRCtzNil4-KR-LIBEiQAmgekFxxKjJJWBYCJlDZEa3Ke_2_WR0DzGVbz-jaCZHVIBoMaAvld8P8HAQ]&lt;br /&gt;
*Drivers galvanomètres x2&lt;br /&gt;
*Alimentation laser&lt;br /&gt;
*Lunette de sécurité x2 [https://www.amazon.fr/Uvex-S1933X-Eyewear-SCTOrange-Anti-Fog/dp/B000USRG90/ref=sr_1_1?ie=UTF8&amp;amp;qid=1485441383&amp;amp;sr=8-1&amp;amp;keywords=uvex+s1933x]&lt;br /&gt;
*Boitier ABS [http://fr.farnell.com/multicomp/g3118/boitier-abs-240x120x60mm-ip65/dp/1526656]&lt;br /&gt;
*DAC 4 canaux, avec interface I²C [https://www.adafruit.com/products/1083]&lt;br /&gt;
*Connecteur C14 [http://www.conrad.fr/ce/fr/product/715001/Connecteur-secteur-C14-Embase-male-verticale-715001-Nombre-de-poles-2-PE-10-A-noir-1-pcs/?ref=detview1&amp;amp;rt=detview1&amp;amp;rb=1]&lt;br /&gt;
*Câble secteur&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Logiciel :&lt;br /&gt;
&lt;br /&gt;
*Serveur web : Apache2, HTML5, PHP5, CSS&lt;br /&gt;
*Base de donnée : MySQL&lt;br /&gt;
*Serveur WebSocket : JQuerry, websocket&lt;br /&gt;
*Arduino : IDE Arduino&lt;br /&gt;
&lt;br /&gt;
===Calendrier prévisionnel===&lt;br /&gt;
&lt;br /&gt;
====Liste des tâches à effectuer====&lt;br /&gt;
Les différentes tâches à effectuer sont :&lt;br /&gt;
*Partie préliminaire : étude de fonctionnement des galvanomètres&lt;br /&gt;
**Déterminer comment est effectuée la commande des galvanomètres (protocole, tension...)&lt;br /&gt;
**Effectuer des tests avec l'Arduino ou la Raspberry Pi&lt;br /&gt;
**Effectuer des tests avec une LED à la place du laser &lt;br /&gt;
*Partie projection&lt;br /&gt;
**Fixer les lasers&lt;br /&gt;
**Aligner les lasers et les galvanomètres&lt;br /&gt;
**Créer le système d'alimentation&lt;br /&gt;
**Création d'un boitier&lt;br /&gt;
*Partie système embarqué&lt;br /&gt;
**Asservissement des galvanomètres avec l'Arduino&lt;br /&gt;
**Système électronique de commande en courant pour les galvanomètres&lt;br /&gt;
*Interface Web&lt;br /&gt;
**Installation et configuration Apache2&lt;br /&gt;
**Création d'une interface graphique simple&lt;br /&gt;
**Implémentation d'algorithmes de traitement d'image&lt;br /&gt;
**Mise en forme avec des CSS&lt;br /&gt;
**Sytème d'authentification avec mot de passe&lt;br /&gt;
**Utilisation d'une base de données pour enregistrer toutes les images déjà utilisés afin de les réutiliser&lt;br /&gt;
*Serveur Web Socket&lt;br /&gt;
**Récupération des données de l'interface web&lt;br /&gt;
**Mise en place de la liaison série avec l'Arduino&lt;br /&gt;
&lt;br /&gt;
====Calendrier====&lt;br /&gt;
Répartition du temps consacré au projet (240h) :&lt;br /&gt;
*Partie projection : 80h&lt;br /&gt;
*Partie système embarqué : 40h&lt;br /&gt;
*Partie interface web et websocket: 120h&lt;br /&gt;
&lt;br /&gt;
==Feuille d'heures==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!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&lt;br /&gt;
|-&lt;br /&gt;
| Définition cahier des charges &lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 14&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|38&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Finalisation du cahier des charges avec les responsables&lt;br /&gt;
&lt;br /&gt;
*Acquisition de matériels :&lt;br /&gt;
**Projecteur Laser&lt;br /&gt;
**Galvanomètres&lt;br /&gt;
**Alimentation des galvanomètres&lt;br /&gt;
&lt;br /&gt;
*Listage du matériels à acquérir :&lt;br /&gt;
**Lunettes de sécurité&lt;br /&gt;
**DAC&lt;br /&gt;
**Alimentation 230V/5V 1A&lt;br /&gt;
** Boitier ABS &lt;br /&gt;
**...&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
*Obtention de l'arduino et de la raspberryPI&lt;br /&gt;
&lt;br /&gt;
*Démontage du projecteur laser&lt;br /&gt;
**Deux lasers de classe 3b (vert et rouge)&lt;br /&gt;
**Circuit d'alimentation des deux lasers&lt;br /&gt;
&lt;br /&gt;
*Initialisation du port série de la raspberryPI&lt;br /&gt;
**Modification du fichier ''config.txt'' dans la partition boot&lt;br /&gt;
**Ajout d'une ligne autorisant la communication série ('''enable_uart=1''')&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
*Installation du serveur apache sur la raspberryPI&lt;br /&gt;
**Modification du fichier ''/etc/network/interfaces'' (Static, Address, Netmask, Gateway)&lt;br /&gt;
**Modification du fichier ''/etc/resolv.conf'' (Adresse du serveur)&lt;br /&gt;
**Utilisation d'un proxy pour la récupération outils de programmation (Apache2, Php5)&lt;br /&gt;
&lt;br /&gt;
*Mise en place du point d’accès wifi de la raspberryPI&lt;br /&gt;
**Récupération des logiciels nécessaires (dnsmasq, hostapd)&lt;br /&gt;
**Mise en place d'une adresse IP statique pour le point d'accès par l'intermédiaire du fichier ''/etc/dhcpcd.conf''&lt;br /&gt;
**Désactivation de la négociation automatique de bail dans le fichier ''/etc/network/interfaces''&lt;br /&gt;
**Configuration du logiciel hostapd ''/etc/hostapd/hostapd.conf''&lt;br /&gt;
**Activation du démarrage automatique du point d'accès ''/etc/default/hostapd''&lt;br /&gt;
**Configuration du serveur DNS par ''/etc/dnsmasq.conf''&lt;br /&gt;
&lt;br /&gt;
*Instauration de la page d'accueil de l'interface web à l'adresse ''192.168.3.1''&lt;br /&gt;
**Téléversement de fichiers images sur la page web et affichage de celle-ci&lt;br /&gt;
**Voyant de confirmation du bon fonctionnement du serveur web&lt;br /&gt;
&lt;br /&gt;
*Développement du serveur websocket&lt;br /&gt;
&lt;br /&gt;
Le développement du serveur websocket, initialement prévu en C (il était prévu de reprendre les sources utilisées l'année précédente dans le cadre des projet IMA3 SC), a finalement été réalisé en JAVA pour plusieurs raisons.&lt;br /&gt;
Premièrement, un seul programme met en œuvre le serveur websocket, les divers traitements d'image, ainsi que les contrôles des galvanomètres (par l'intermédiaire des DAC) via la liaison I²C de la Raspberry Pi. Le langage JAVA fournit nativement des bibliothèques d'objets pour manipuler assez simplement des images, il existe également des librairies pour contrôler le port GPIO de la Raspberry et il était également intéressant de travailler avec un langage de plus haut niveau que le C.&lt;br /&gt;
En outre, la totale portabilité de ce langage nous permet de travailler sur n'importe quelle machine et ensuite transférer notre programme sur la Raspberry Pi et l’exécuter sans même repasser par une phase de compilation. Et finalement, c'est le langage que nous étudions actuellement en cours de programmation orientée objet, ce qui permet de nous perfectionner.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Serveur WebSocket====&lt;br /&gt;
&lt;br /&gt;
N'ayant pas trouvé d'API WebSocket en Java satisfaisante (qui ne nécessitent pas l'installation et la configuration de nombreux outils additionnels), j'ai estimé plus commode et plus formateur de développer notre propre serveur WebSocket en se basant sur les librairies sockets de Java avec l'aide d'une documentation assez exhaustive [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers].&lt;br /&gt;
&lt;br /&gt;
Les WebSockets désignent à la fois un protocole réseau qui étend le protocole TCP ainsi qu'une API du World Wide Web. Nous nous en servons afin d'établir une communication asynchrone et bidirectionnelle entre un navigateur web et le serveur, notamment pour envoyer l'image à projeter. L’implémentation du serveur repose sur plusieurs étapes.&lt;br /&gt;
&lt;br /&gt;
1) Connexion d'un client &lt;br /&gt;
&lt;br /&gt;
2) Handshake : permet de faire le lien entre le protocole HTTP et WS. Le client envoie une requête HTTP demandant un upgrade de la connexion en protocole WS et le serveur répond en configurant la connexion (détail dans la documentation [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers]).&lt;br /&gt;
&lt;br /&gt;
3) Réception et décodage des messages : le serveurs reçoit des trames brutes, on extrait donc la taille du message ainsi que le message. De plus, les données son encodées (cryptage XOR) par un masque qui doit également être extrait.&lt;br /&gt;
&lt;br /&gt;
4) Fermeture de la communication.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le serveur supporte le multi-client il est donc nécessaire qu'il effectue ces étapes en &amp;quot;parallèle&amp;quot;. Nous utilisons donc les threads ou fils d’exécution. Un thread est donc responsable d'attendre qu'un nouveau client se connecte et effectue le &amp;quot;handshake&amp;quot;, il crée ensuite un thread associé à ce client afin d'établir un canal de communication. Il y a donc au moins un thread par client. Par la suite il faudra également implémenter une déconnexion automatique d'un client notamment après un timeout.&lt;br /&gt;
&lt;br /&gt;
Exemple d’exécution du serveur avec deux clients qui se connectent et envoient un message : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testServeur.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Les clients sont des navigateurs web. Pour les tests nous avons repris les exemples utilisés dans le cadre das projets IMA3 SC avec le titre de la page HTML qui se colore en vert lorsque le client est connecté, et un champ de saisie pour envoyer des messages au serveur : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testClient.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 4===&lt;br /&gt;
&lt;br /&gt;
*Mise en place d’algorithmes de traitement d'image&lt;br /&gt;
&lt;br /&gt;
====Détection de contour====&lt;br /&gt;
&lt;br /&gt;
L'objectif de notre projet est de pouvoir projeter n'importe quelle image envoyé grâce à l'application web. Pour cela nous allons tracer à une vitesse élevée les contours de l'image sur par exemple un mur grâce au laser. Il est donc nécessaire de détecter les contours de l'image grâce à plusieurs traitements.&lt;br /&gt;
&lt;br /&gt;
=====Conversion en niveau de gris=====&lt;br /&gt;
&lt;br /&gt;
Une des étapes préliminaires pour effectuer la détection de contour est de convertir l'image couleur en niveau de gris. Pour cela l'algorithme est simple : il suffit pour chaque pixel de l'image d'effectuer la moyenne des composantes rouge, verte, bleu de chaque pixel. En effet, si l'on considère une image matricielle (l'image est considérée comme un tableau à deux dimensions avec chaque case qui contient la couleur du pixel), chaque pixel contient les composantes RGB codées sur un octet. La couleur gris correspond aux composantes RGB égales. Le niveau de gris est donc codé de 0 à 255, avec 0 donnant du noir et 255 du blanc. &lt;br /&gt;
&lt;br /&gt;
Voici le résultat obtenu : [[Fichier:testGrayScale.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Filtre de Prewit et Sobel=====&lt;br /&gt;
&lt;br /&gt;
Un contour est défini par un changement brutal d'intensité lumineuse, il s'agit donc de détecter selon plusieurs directions (au moins 2) ces changements. Il existe de nombreuses techniques afin de détecter les contours d'une image (gradient, Laplacien). L'une des techniques avec un rapport efficacité/temps d'exécution correct repose sur les algorithmes de Prewit ou Sobel. L'algorithme repose sur la convolution de matrices.&lt;br /&gt;
Cela consiste à appliquer sur chaque pixel de l'image la matrice de Prewit définie comme &lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L_x = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; ainsi que sa transposée : &amp;lt;math&amp;gt;&lt;br /&gt;
L_y = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; -1 &amp;amp; -1 \\&lt;br /&gt;
 0 &amp;amp; 0 &amp;amp; 0 \\&lt;br /&gt;
+1 &amp;amp; +1 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Convoluer ces deux filtres sur l'image permet de détecter respectivement les contours verticaux et horizontaux.&lt;br /&gt;
&lt;br /&gt;
D'après wikipedia [https://fr.wikipedia.org/wiki/D%C3%A9tection_de_contours], on obtient de meilleurs résultats en appliquant un filtre triangulaire, on introduit donc la matrice de Sobel :&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-2 &amp;amp; 0 &amp;amp; +2 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
On obtient le résultat suivant : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testOutline1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Pré-traitement : Flou Gaussien=====&lt;br /&gt;
&lt;br /&gt;
Afin de réduire significativement le nombre de contours, il est nécessaire d'effectuer un pré-traitement avant la détection de contours. On utilise généralement un flou gaussien afin de réduire les transitions lumineuses et ainsi réduire le nombre de contours. L’algorithme de flou gaussien repose également sur la convolution de matrices sauf qu'ici la matrice filtre est générée grâce à une fonction gaussienne paramétrée par '''Sigma''' qui va directement impacter le niveau de flou. Plus la matrice de filtrage est grande plus la qualité du résultat est meilleure, mais le temps d’exécution devient également plus grand.&lt;br /&gt;
&lt;br /&gt;
Voici la fonction de génération du filtre : &amp;lt;math&amp;gt;G(x,y) = \frac{1}{{2\pi \sigma^2}} e^{-\frac{x^2 + y^2}{2 \sigma^2}}&amp;lt;/math&amp;gt; où x et y correspondent aux indices de la cellule de la matrice.&lt;br /&gt;
&lt;br /&gt;
On obtient ce résultat :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testGaussianBlur.png]]&lt;br /&gt;
&lt;br /&gt;
On note un bien meilleur résultat. Cependant on remarque que les composantes horizontales ne sont pas correctement détectées il subsiste un problème avec le filtrage vertical que je n'ai pas réussi à identifier. De plus, il s'agit par sa suite d'éliminer les contours parasites ainsi que d'affiner le trait pour n'avoir plus qu'un pixel d'épaisseur.&lt;br /&gt;
&lt;br /&gt;
=====Post-traitement : Algorithme de Canny=====&lt;br /&gt;
&lt;br /&gt;
Afin d'obtenir un résultat exploitable il est nécessaire d'appliquer encore quelques traitements. Pour cela nous utilisons l’algorithme de Canny qui repose que celui de Sobel mais qui ajoute un algorithme de seuillage par hysteresis qui permet de retirer les contours secondaires et de ne garder que les contours connexes dans une seuil haut et un seuil bas définis. En outre, cette algorithme affine également le trait obtenu. Pour cet algorithme nous avons directement trouvé des sources libres de droits [http://www.tomgibara.com/computer-vision/canny-edge-detector] qui donne des résultats très corrects.&lt;br /&gt;
&lt;br /&gt;
Par exemple :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ou encore : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny2.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 5===&lt;br /&gt;
&lt;br /&gt;
*Établissement d'un protocole de transfert d'image basé sur les WebSockets&lt;br /&gt;
**Envoie d'un requête &amp;quot;send&amp;quot; par le client dans une trame websocket texte&lt;br /&gt;
**Réponse serveur 'Y' si aucun autre client tente d'envoyer une image simultanément, 'N' sinon&lt;br /&gt;
**Si et seulement si le client reçoit 'Y' il débute le transfert en envoyant la largeur et la longueur de l'image sur 4 octets, puis les données de l'image soit 4 valeurs pour chaque pixels (r,g,b,alpha)&lt;br /&gt;
**Le serveur renvoie 'D' une fois le transfert achevé (à l'avenir, le serveur renverra l'image après filtrage).&lt;br /&gt;
**A tout moment, le serveur peut renvoyer 'E' si une erreur est survenue (ex : paquets perdus, nombre incorrects de données)&lt;br /&gt;
*Ajout du support des logs au niveau serveur&lt;br /&gt;
**Impression sur la sortie standard des messages&lt;br /&gt;
**Formatage en fonction de la sévérité du log (info, warning, error...)&lt;br /&gt;
**Incrustation de la date et heure&lt;br /&gt;
**Possibilité de redirection dans une fichier, avec configuration (écriture à la suite d'un fichier existant, écrasement...)&lt;br /&gt;
**Le tout dans une classe Java flexible et réutilisable pour d'autres projets&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 6===&lt;br /&gt;
&lt;br /&gt;
*Installation de la librairie Java Pi4j sur la raspberry pi qui permet le contrôle des GPIO de celle-ci et notamment le port I²C (basé sur WiringPi)&lt;br /&gt;
*Amélioration coté serveur websocket&lt;br /&gt;
**Gestion de message plus longs (maximum des trames websockets soit 2^63 octets)&lt;br /&gt;
**Différenciation, à la réception de messages, des trames textes ou binaires des trames de contrôle comme les requête ping, pong ou de fermeture de connexion &lt;br /&gt;
**Ajout d'un mode de debug de trames &lt;br /&gt;
&lt;br /&gt;
===Semaine 7===&lt;br /&gt;
&lt;br /&gt;
*Améliorations du serveur WebSocket&lt;br /&gt;
**Gestion de la fragmentation TCP&lt;br /&gt;
**Gestion de la fragmentation WebSocket&lt;br /&gt;
**Gestion des requêtes ping envoyés par le client en renvoyant une trames de contrôle pong afin de maintenir la connexion&lt;br /&gt;
**Gestion des déconnexion de clients afin d'optimiser le serveur&lt;br /&gt;
**Amélioration de l'émission de messages en augmentant la taille maximale pouvant être émise (2^63 octets)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A ce stade du développement, le client et le serveur sont opérationnels et peuvent s'échanger des messages ainsi que des images que le serveur traite pour extraire les contours.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 8===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Montage projecteur&lt;br /&gt;
**Intégralité des composants fixés par vis dans le boîtier ABS&lt;br /&gt;
**Fusion des alimentations&lt;br /&gt;
**Présence d'une led témoin de mise en tension&lt;br /&gt;
**Position laser réglable grâce à une vis&lt;br /&gt;
**Présence d'un switch à bascule pour allumer et éteindre le laser&lt;br /&gt;
**Isolation et vérification des composants&lt;br /&gt;
**Tests empiriques de température et de fonctionnement des lasers et galvanomètres&lt;br /&gt;
&lt;br /&gt;
Le montage boîtier est donc terminé et s’alimente en 230V par intermédiaire d'un câble secteur avec connecteur C14. Le résultat s'avère plutôt compact. Les quelques tests de températures ont montrés que malgré le manque d'espace la température globale du boîtier ne dépasse pas les 50°C pendant plus d'une heure de fonctionnement. L'intégralité des connexions sont isolées avec de la gaine thermodynamique et les zones &amp;quot;sensibles&amp;quot; sont correctement vérifiés ainsi que protégées avec de la matière isolante.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:proj1.jpg|550px|Boîtier après perçage]] [[Fichier:proj2.jpg|550px|Boîtier finalisé]] [[Fichier:proj3.jpg|550px|Projecteur en fonctionnement]]&lt;br /&gt;
&lt;br /&gt;
*Page web et serveur WebSocket&lt;br /&gt;
**Ajout d'un bouton &amp;quot;reboot&amp;quot; et &amp;quot;shutdown&amp;quot; qui permettent respectivement de redémarrer et d'éteindre la Raspberry directement à partir de la page web&lt;br /&gt;
&lt;br /&gt;
===Semaine 9===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 10===&lt;br /&gt;
&lt;br /&gt;
==A faire==&lt;br /&gt;
&lt;br /&gt;
MAJ 26 mars &lt;br /&gt;
&lt;br /&gt;
*Client websocket et page web&lt;br /&gt;
**Mise en page CSS&lt;br /&gt;
**Ajout canvas pour prévisualisation image projeté&lt;br /&gt;
**Ajout &amp;quot;slider&amp;quot; pour régler niveau du flou Gaussien DOUBLE&lt;br /&gt;
**Ajout slider pour de finir amplitude de la projection&lt;br /&gt;
**Afficher statut de connexion&lt;br /&gt;
**Ajout message de confirmation quand le serveur quitte ou relance&lt;br /&gt;
**Ajout boutons &amp;quot;projeter&amp;quot; &amp;quot;centrer&amp;quot; &amp;quot;eteindre&amp;quot;&lt;br /&gt;
**Gestion de plusieurs images avec délai&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Serveur WebSocket&lt;br /&gt;
**Ajout fonctionnalité envoi image de prévisualisation&lt;br /&gt;
&lt;br /&gt;
*RaspberryPi&lt;br /&gt;
**Utilisation d'un serveur bind9 pour éviter de taper IP&lt;br /&gt;
&lt;br /&gt;
*Détection de contours&lt;br /&gt;
**Implémentation algorithme de tri de la plus courte disance&lt;br /&gt;
&lt;br /&gt;
*Commande galvanomêtre&lt;br /&gt;
**Utilisation API I²C&lt;br /&gt;
**Fonction de transfert position-&amp;gt;angle-&amp;gt;tension&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;br /&gt;
&lt;br /&gt;
==Bibliographie==&lt;br /&gt;
&lt;br /&gt;
http://www.ebay.com/itm/20KPPS-30KPPS-laser-scanning-galvo-scanner-ILDA-Closed-Loop-max-30kpps-for-laser-/261517002270?hash=item3ce3a0c61e&lt;br /&gt;
&lt;br /&gt;
https://icn.fenelonlille.org/mediawiki/index.php/Projet_ICN_commun_2016/2017&lt;br /&gt;
&lt;br /&gt;
https://www.g33k-zone.org/post/2016/05/11/Configurer-le-Raspberry-Pi-en-point-d-acc%C3%A8s-Wifi&lt;br /&gt;
&lt;br /&gt;
http://stackoverflow.com/questions/22087076/how-to-make-a-simple-image-upload-using-javascript-html&lt;br /&gt;
&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_a_WebSocket_server_in_Java&lt;br /&gt;
&lt;br /&gt;
export http_proxy=http://proxy.polytech-lille.fr:3128&lt;/div&gt;</summary>
		<author><name>Mtrimbur</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=40828</id>
		<title>IMA4 2016/2017 P39</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=40828"/>
				<updated>2017-03-27T18:01:15Z</updated>
		
		<summary type="html">&lt;p&gt;Mtrimbur : /* Semaine 8 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
===Contexte===&lt;br /&gt;
&lt;br /&gt;
Le laser est une technologie largement utilisé de nos jours dans de diverses applications. En effet, on retrouve cette technologie dans le domaine médical notamment pour la chirurgie oculaire ou encore dans industrie avec la découpe laser ou la soudure au laser.&lt;br /&gt;
&lt;br /&gt;
Le laser est une émission de photons produit par excitation d'un milieu amplificateur (ex : CO2), le rayonnement produit est unidirectionnel et monochromatique. Ce sont ces propriétés que nous allons exploiter afin réaliser un projecteur laser qui mis en mouvement est capable de dessiner des formes sur une surface à l'instar de systèmes existants utilisés pour des effets lumineux lors de festivités.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
L'objectif du projet est de créer un système de projection laser à plusieurs couleurs (au minimum deux) avec une application web pour programmer les formes à dessiner afin d'agrémenter des compétitions de gymnastique rythmique.&lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
Le projet consiste à réaliser avec des lasers des figures géométriques par l'intermédiaire d'un système galvanométrique. &lt;br /&gt;
&lt;br /&gt;
Notre premier travail sera de concevoir la partie projection. Pour cela, nous devrons aligner les lasers et les galvanomètres. En effet, ces derniers posséderont des miroirs à l'extrémité, ainsi les miroirs changeront d'inclinaison suivant le courant traversant les galvanomètres (similaire à l'image ci-contre). Il nous faudra également créer un système d'alimentation qui à partir d'une même source (réseau 230 V) sera capable d'alimenter les lasers et les galvanomètres ainsi qu'une Arduino et une Raspberry Pi.&lt;br /&gt;
[[File:Scanhead.jpeg|thumb]]&lt;br /&gt;
&lt;br /&gt;
Ensuite nous nous intéresserons à l'utilisation d'un système embarqué pour contrôler les galvanomètres et donc dessiner avec les lasers sur un plan 2D. En effet, le laser restera toujours fixe, seuls les galvanomètres, et donc les miroirs bougeront. Les galvanomètres étant contrôlés en courant il faudra réaliser une interface électronique pour convertir une commande en tension en commande de courant. La commande en tension sera assuré par une carte Arduino. Nous n'utiliserons qu'une seule paire de galvanomètres pour les deux laser. Il faudra donc multiplexer les deux faisceaux. La programmation des formes à effectuer, se fera par l'intermédiaire d'une application web PHP hébergée sur une RaspberryPi qui permettra de récupérer une image, d'y appliquer divers traitements et filtres afin d'en extraire les contours, et de calculer les commandes pour positionner les galvanomètres. Un serveur WebSocket également hébergé sur la RaspberryPi servira d'interface entre l'application web et L'arduino qui sera connecté via une liaison série sur la raspberryPI.&lt;br /&gt;
&lt;br /&gt;
Comme animation de test, nous dessinerons le contour d'une gymnaste avec une couleur et son ballon d'une autre couleur. La gymnaste devra lancer son ballon, réaliser quelques difficultés et récupérer son ballon.&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
Nous utiliserons comme matériels :&lt;br /&gt;
*Deux lasers de différentes couleurs&lt;br /&gt;
*Une paire de galvanomètres à miroir&lt;br /&gt;
*Arduino&lt;br /&gt;
*Raspberry Pi3&lt;br /&gt;
*Alimentation 230V/5V 1A [http://www.miniinthebox.com/fr/dual-usb-eu-prise-murale-5v-2a-voyage-adaptateur-chargeur-d-alimentation-pour-iphone7-6-xiaomi-samsung-et-autre-telephone-portable_p5410410.html?currency=EUR&amp;amp;litb_from=paid_adwords_shopping&amp;amp;sku=429_6917%7C752_20648&amp;amp;utm_source=google_shopping&amp;amp;utm_medium=cpc&amp;amp;adword_mt=&amp;amp;adword_ct=138705676724&amp;amp;adword_kw=&amp;amp;adword_pos=1o5&amp;amp;adword_pl=&amp;amp;adword_net=g&amp;amp;adword_tar=&amp;amp;adw_src_id=9653316068_661261352_33588296076_aud-79897721311:pla-256966386459&amp;amp;gclid=Cj0KEQiA_KvEBRCtzNil4-KR-LIBEiQAmgekFxxKjJJWBYCJlDZEa3Ke_2_WR0DzGVbz-jaCZHVIBoMaAvld8P8HAQ]&lt;br /&gt;
*Drivers galvanomètres x2&lt;br /&gt;
*Alimentation laser&lt;br /&gt;
*Lunette de sécurité x2 [https://www.amazon.fr/Uvex-S1933X-Eyewear-SCTOrange-Anti-Fog/dp/B000USRG90/ref=sr_1_1?ie=UTF8&amp;amp;qid=1485441383&amp;amp;sr=8-1&amp;amp;keywords=uvex+s1933x]&lt;br /&gt;
*Boitier ABS [http://fr.farnell.com/multicomp/g3118/boitier-abs-240x120x60mm-ip65/dp/1526656]&lt;br /&gt;
*DAC 4 canaux, avec interface I²C [https://www.adafruit.com/products/1083]&lt;br /&gt;
*Connecteur C14 [http://www.conrad.fr/ce/fr/product/715001/Connecteur-secteur-C14-Embase-male-verticale-715001-Nombre-de-poles-2-PE-10-A-noir-1-pcs/?ref=detview1&amp;amp;rt=detview1&amp;amp;rb=1]&lt;br /&gt;
*Câble secteur&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Logiciel :&lt;br /&gt;
&lt;br /&gt;
*Serveur web : Apache2, HTML5, PHP5, CSS&lt;br /&gt;
*Base de donnée : MySQL&lt;br /&gt;
*Serveur WebSocket : JQuerry, websocket&lt;br /&gt;
*Arduino : IDE Arduino&lt;br /&gt;
&lt;br /&gt;
===Calendrier prévisionnel===&lt;br /&gt;
&lt;br /&gt;
====Liste des tâches à effectuer====&lt;br /&gt;
Les différentes tâches à effectuer sont :&lt;br /&gt;
*Partie préliminaire : étude de fonctionnement des galvanomètres&lt;br /&gt;
**Déterminer comment est effectuée la commande des galvanomètres (protocole, tension...)&lt;br /&gt;
**Effectuer des tests avec l'Arduino ou la Raspberry Pi&lt;br /&gt;
**Effectuer des tests avec une LED à la place du laser &lt;br /&gt;
*Partie projection&lt;br /&gt;
**Fixer les lasers&lt;br /&gt;
**Aligner les lasers et les galvanomètres&lt;br /&gt;
**Créer le système d'alimentation&lt;br /&gt;
**Création d'un boitier&lt;br /&gt;
*Partie système embarqué&lt;br /&gt;
**Asservissement des galvanomètres avec l'Arduino&lt;br /&gt;
**Système électronique de commande en courant pour les galvanomètres&lt;br /&gt;
*Interface Web&lt;br /&gt;
**Installation et configuration Apache2&lt;br /&gt;
**Création d'une interface graphique simple&lt;br /&gt;
**Implémentation d'algorithmes de traitement d'image&lt;br /&gt;
**Mise en forme avec des CSS&lt;br /&gt;
**Sytème d'authentification avec mot de passe&lt;br /&gt;
**Utilisation d'une base de données pour enregistrer toutes les images déjà utilisés afin de les réutiliser&lt;br /&gt;
*Serveur Web Socket&lt;br /&gt;
**Récupération des données de l'interface web&lt;br /&gt;
**Mise en place de la liaison série avec l'Arduino&lt;br /&gt;
&lt;br /&gt;
====Calendrier====&lt;br /&gt;
Répartition du temps consacré au projet (240h) :&lt;br /&gt;
*Partie projection : 80h&lt;br /&gt;
*Partie système embarqué : 40h&lt;br /&gt;
*Partie interface web et websocket: 120h&lt;br /&gt;
&lt;br /&gt;
==Feuille d'heures==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!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&lt;br /&gt;
|-&lt;br /&gt;
| Définition cahier des charges &lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 14&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|38&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Finalisation du cahier des charges avec les responsables&lt;br /&gt;
&lt;br /&gt;
*Acquisition de matériels :&lt;br /&gt;
**Projecteur Laser&lt;br /&gt;
**Galvanomètres&lt;br /&gt;
**Alimentation des galvanomètres&lt;br /&gt;
&lt;br /&gt;
*Listage du matériels à acquérir :&lt;br /&gt;
**Lunettes de sécurité&lt;br /&gt;
**DAC&lt;br /&gt;
**Alimentation 230V/5V 1A&lt;br /&gt;
** Boitier ABS &lt;br /&gt;
**...&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
*Obtention de l'arduino et de la raspberryPI&lt;br /&gt;
&lt;br /&gt;
*Démontage du projecteur laser&lt;br /&gt;
**Deux lasers de classe 3b (vert et rouge)&lt;br /&gt;
**Circuit d'alimentation des deux lasers&lt;br /&gt;
&lt;br /&gt;
*Initialisation du port série de la raspberryPI&lt;br /&gt;
**Modification du fichier ''config.txt'' dans la partition boot&lt;br /&gt;
**Ajout d'une ligne autorisant la communication série ('''enable_uart=1''')&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
*Installation du serveur apache sur la raspberryPI&lt;br /&gt;
**Modification du fichier ''/etc/network/interfaces'' (Static, Address, Netmask, Gateway)&lt;br /&gt;
**Modification du fichier ''/etc/resolv.conf'' (Adresse du serveur)&lt;br /&gt;
**Utilisation d'un proxy pour la récupération outils de programmation (Apache2, Php5)&lt;br /&gt;
&lt;br /&gt;
*Mise en place du point d’accès wifi de la raspberryPI&lt;br /&gt;
**Récupération des logiciels nécessaires (dnsmasq, hostapd)&lt;br /&gt;
**Mise en place d'une adresse IP statique pour le point d'accès par l'intermédiaire du fichier ''/etc/dhcpcd.conf''&lt;br /&gt;
**Désactivation de la négociation automatique de bail dans le fichier ''/etc/network/interfaces''&lt;br /&gt;
**Configuration du logiciel hostapd ''/etc/hostapd/hostapd.conf''&lt;br /&gt;
**Activation du démarrage automatique du point d'accès ''/etc/default/hostapd''&lt;br /&gt;
**Configuration du serveur DNS par ''/etc/dnsmasq.conf''&lt;br /&gt;
&lt;br /&gt;
*Instauration de la page d'accueil de l'interface web à l'adresse ''192.168.3.1''&lt;br /&gt;
**Téléversement de fichiers images sur la page web et affichage de celle-ci&lt;br /&gt;
**Voyant de confirmation du bon fonctionnement du serveur web&lt;br /&gt;
&lt;br /&gt;
*Développement du serveur websocket&lt;br /&gt;
&lt;br /&gt;
Le développement du serveur websocket, initialement prévu en C (il était prévu de reprendre les sources utilisées l'année précédente dans le cadre des projet IMA3 SC), a finalement été réalisé en JAVA pour plusieurs raisons.&lt;br /&gt;
Premièrement, un seul programme met en œuvre le serveur websocket, les divers traitements d'image, ainsi que les contrôles des galvanomètres (par l'intermédiaire des DAC) via la liaison I²C de la Raspberry Pi. Le langage JAVA fournit nativement des bibliothèques d'objets pour manipuler assez simplement des images, il existe également des librairies pour contrôler le port GPIO de la Raspberry et il était également intéressant de travailler avec un langage de plus haut niveau que le C.&lt;br /&gt;
En outre, la totale portabilité de ce langage nous permet de travailler sur n'importe quelle machine et ensuite transférer notre programme sur la Raspberry Pi et l’exécuter sans même repasser par une phase de compilation. Et finalement, c'est le langage que nous étudions actuellement en cours de programmation orientée objet, ce qui permet de nous perfectionner.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Serveur WebSocket====&lt;br /&gt;
&lt;br /&gt;
N'ayant pas trouvé d'API WebSocket en Java satisfaisante (qui ne nécessitent pas l'installation et la configuration de nombreux outils additionnels), j'ai estimé plus commode et plus formateur de développer notre propre serveur WebSocket en se basant sur les librairies sockets de Java avec l'aide d'une documentation assez exhaustive [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers].&lt;br /&gt;
&lt;br /&gt;
Les WebSockets désignent à la fois un protocole réseau qui étend le protocole TCP ainsi qu'une API du World Wide Web. Nous nous en servons afin d'établir une communication asynchrone et bidirectionnelle entre un navigateur web et le serveur, notamment pour envoyer l'image à projeter. L’implémentation du serveur repose sur plusieurs étapes.&lt;br /&gt;
&lt;br /&gt;
1) Connexion d'un client &lt;br /&gt;
&lt;br /&gt;
2) Handshake : permet de faire le lien entre le protocole HTTP et WS. Le client envoie une requête HTTP demandant un upgrade de la connexion en protocole WS et le serveur répond en configurant la connexion (détail dans la documentation [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers]).&lt;br /&gt;
&lt;br /&gt;
3) Réception et décodage des messages : le serveurs reçoit des trames brutes, on extrait donc la taille du message ainsi que le message. De plus, les données son encodées (cryptage XOR) par un masque qui doit également être extrait.&lt;br /&gt;
&lt;br /&gt;
4) Fermeture de la communication.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le serveur supporte le multi-client il est donc nécessaire qu'il effectue ces étapes en &amp;quot;parallèle&amp;quot;. Nous utilisons donc les threads ou fils d’exécution. Un thread est donc responsable d'attendre qu'un nouveau client se connecte et effectue le &amp;quot;handshake&amp;quot;, il crée ensuite un thread associé à ce client afin d'établir un canal de communication. Il y a donc au moins un thread par client. Par la suite il faudra également implémenter une déconnexion automatique d'un client notamment après un timeout.&lt;br /&gt;
&lt;br /&gt;
Exemple d’exécution du serveur avec deux clients qui se connectent et envoient un message : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testServeur.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Les clients sont des navigateurs web. Pour les tests nous avons repris les exemples utilisés dans le cadre das projets IMA3 SC avec le titre de la page HTML qui se colore en vert lorsque le client est connecté, et un champ de saisie pour envoyer des messages au serveur : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testClient.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 4===&lt;br /&gt;
&lt;br /&gt;
*Mise en place d’algorithmes de traitement d'image&lt;br /&gt;
&lt;br /&gt;
====Détection de contour====&lt;br /&gt;
&lt;br /&gt;
L'objectif de notre projet est de pouvoir projeter n'importe quelle image envoyé grâce à l'application web. Pour cela nous allons tracer à une vitesse élevée les contours de l'image sur par exemple un mur grâce au laser. Il est donc nécessaire de détecter les contours de l'image grâce à plusieurs traitements.&lt;br /&gt;
&lt;br /&gt;
=====Conversion en niveau de gris=====&lt;br /&gt;
&lt;br /&gt;
Une des étapes préliminaires pour effectuer la détection de contour est de convertir l'image couleur en niveau de gris. Pour cela l'algorithme est simple : il suffit pour chaque pixel de l'image d'effectuer la moyenne des composantes rouge, verte, bleu de chaque pixel. En effet, si l'on considère une image matricielle (l'image est considérée comme un tableau à deux dimensions avec chaque case qui contient la couleur du pixel), chaque pixel contient les composantes RGB codées sur un octet. La couleur gris correspond aux composantes RGB égales. Le niveau de gris est donc codé de 0 à 255, avec 0 donnant du noir et 255 du blanc. &lt;br /&gt;
&lt;br /&gt;
Voici le résultat obtenu : [[Fichier:testGrayScale.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Filtre de Prewit et Sobel=====&lt;br /&gt;
&lt;br /&gt;
Un contour est défini par un changement brutal d'intensité lumineuse, il s'agit donc de détecter selon plusieurs directions (au moins 2) ces changements. Il existe de nombreuses techniques afin de détecter les contours d'une image (gradient, Laplacien). L'une des techniques avec un rapport efficacité/temps d'exécution correct repose sur les algorithmes de Prewit ou Sobel. L'algorithme repose sur la convolution de matrices.&lt;br /&gt;
Cela consiste à appliquer sur chaque pixel de l'image la matrice de Prewit définie comme &lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L_x = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; ainsi que sa transposée : &amp;lt;math&amp;gt;&lt;br /&gt;
L_y = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; -1 &amp;amp; -1 \\&lt;br /&gt;
 0 &amp;amp; 0 &amp;amp; 0 \\&lt;br /&gt;
+1 &amp;amp; +1 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Convoluer ces deux filtres sur l'image permet de détecter respectivement les contours verticaux et horizontaux.&lt;br /&gt;
&lt;br /&gt;
D'après wikipedia [https://fr.wikipedia.org/wiki/D%C3%A9tection_de_contours], on obtient de meilleurs résultats en appliquant un filtre triangulaire, on introduit donc la matrice de Sobel :&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-2 &amp;amp; 0 &amp;amp; +2 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
On obtient le résultat suivant : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testOutline1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Pré-traitement : Flou Gaussien=====&lt;br /&gt;
&lt;br /&gt;
Afin de réduire significativement le nombre de contours, il est nécessaire d'effectuer un pré-traitement avant la détection de contours. On utilise généralement un flou gaussien afin de réduire les transitions lumineuses et ainsi réduire le nombre de contours. L’algorithme de flou gaussien repose également sur la convolution de matrices sauf qu'ici la matrice filtre est générée grâce à une fonction gaussienne paramétrée par '''Sigma''' qui va directement impacter le niveau de flou. Plus la matrice de filtrage est grande plus la qualité du résultat est meilleure, mais le temps d’exécution devient également plus grand.&lt;br /&gt;
&lt;br /&gt;
Voici la fonction de génération du filtre : &amp;lt;math&amp;gt;G(x,y) = \frac{1}{{2\pi \sigma^2}} e^{-\frac{x^2 + y^2}{2 \sigma^2}}&amp;lt;/math&amp;gt; où x et y correspondent aux indices de la cellule de la matrice.&lt;br /&gt;
&lt;br /&gt;
On obtient ce résultat :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testGaussianBlur.png]]&lt;br /&gt;
&lt;br /&gt;
On note un bien meilleur résultat. Cependant on remarque que les composantes horizontales ne sont pas correctement détectées il subsiste un problème avec le filtrage vertical que je n'ai pas réussi à identifier. De plus, il s'agit par sa suite d'éliminer les contours parasites ainsi que d'affiner le trait pour n'avoir plus qu'un pixel d'épaisseur.&lt;br /&gt;
&lt;br /&gt;
=====Post-traitement : Algorithme de Canny=====&lt;br /&gt;
&lt;br /&gt;
Afin d'obtenir un résultat exploitable il est nécessaire d'appliquer encore quelques traitements. Pour cela nous utilisons l’algorithme de Canny qui repose que celui de Sobel mais qui ajoute un algorithme de seuillage par hysteresis qui permet de retirer les contours secondaires et de ne garder que les contours connexes dans une seuil haut et un seuil bas définis. En outre, cette algorithme affine également le trait obtenu. Pour cet algorithme nous avons directement trouvé des sources libres de droits [http://www.tomgibara.com/computer-vision/canny-edge-detector] qui donne des résultats très corrects.&lt;br /&gt;
&lt;br /&gt;
Par exemple :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ou encore : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny2.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 5===&lt;br /&gt;
&lt;br /&gt;
*Établissement d'un protocole de transfert d'image basé sur les WebSockets&lt;br /&gt;
**Envoie d'un requête &amp;quot;send&amp;quot; par le client dans une trame websocket texte&lt;br /&gt;
**Réponse serveur 'Y' si aucun autre client tente d'envoyer une image simultanément, 'N' sinon&lt;br /&gt;
**Si et seulement si le client reçoit 'Y' il débute le transfert en envoyant la largeur et la longueur de l'image sur 4 octets, puis les données de l'image soit 4 valeurs pour chaque pixels (r,g,b,alpha)&lt;br /&gt;
**Le serveur renvoie 'D' une fois le transfert achevé (à l'avenir, le serveur renverra l'image après filtrage).&lt;br /&gt;
**A tout moment, le serveur peut renvoyer 'E' si une erreur est survenue (ex : paquets perdus, nombre incorrects de données)&lt;br /&gt;
*Ajout du support des logs au niveau serveur&lt;br /&gt;
**Impression sur la sortie standard des messages&lt;br /&gt;
**Formatage en fonction de la sévérité du log (info, warning, error...)&lt;br /&gt;
**Incrustation de la date et heure&lt;br /&gt;
**Possibilité de redirection dans une fichier, avec configuration (écriture à la suite d'un fichier existant, écrasement...)&lt;br /&gt;
**Le tout dans une classe Java flexible et réutilisable pour d'autres projets&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 6===&lt;br /&gt;
&lt;br /&gt;
*Installation de la librairie Java Pi4j sur la raspberry pi qui permet le contrôle des GPIO de celle-ci et notamment le port I²C (basé sur WiringPi)&lt;br /&gt;
*Amélioration coté serveur websocket&lt;br /&gt;
**Gestion de message plus longs (maximum des trames websockets soit 2^63 octets)&lt;br /&gt;
**Différenciation, à la réception de messages, des trames textes ou binaires des trames de contrôle comme les requête ping, pong ou de fermeture de connexion &lt;br /&gt;
**Ajout d'un mode de debug de trames &lt;br /&gt;
&lt;br /&gt;
===Semaine 7===&lt;br /&gt;
&lt;br /&gt;
*Améliorations du serveur WebSocket&lt;br /&gt;
**Gestion de la fragmentation TCP&lt;br /&gt;
**Gestion de la fragmentation WebSocket&lt;br /&gt;
**Gestion des requêtes ping envoyés par le client en renvoyant une trames de contrôle pong afin de maintenir la connexion&lt;br /&gt;
**Gestion des déconnexion de clients afin d'optimiser le serveur&lt;br /&gt;
**Amélioration de l'émission de messages en augmentant la taille maximale pouvant être émise (2^63 octets)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A ce stade du développement, le client et le serveur sont opérationnels et peuvent s'échanger des messages ainsi que des images que le serveur traite pour extraire les contours.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 8===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Montage projecteur&lt;br /&gt;
**Intégralité des composants fixés par vis dans le boîtier ABS&lt;br /&gt;
**Fusion des alimentations&lt;br /&gt;
**Présence d'une led témoin de mise en tension&lt;br /&gt;
**Position laser réglable grâce à une vis&lt;br /&gt;
**Présence d'un switch à bascule pour allumer et éteindre le laser&lt;br /&gt;
**Isolation et vérification des composants&lt;br /&gt;
**Tests empiriques de température et de fonctionnement des lasers et galvanomètres&lt;br /&gt;
&lt;br /&gt;
Le montage boîtier est donc terminé et s’alimente en 230V par intermédiaire d'un câble secteur avec connecteur C14. Le résultat s'avère plutôt compact. Les quelques tests de températures ont montrés que malgré le manque d'espace la température globale du boîtier ne dépasse pas les 50°C pendant plus d'une heure de fonctionnement. L'intégralité des connexions sont isolées avec de la gaine thermodynamique et les zones &amp;quot;sensibles&amp;quot; sont correctement vérifiés ainsi que protégées avec de la matière isolante.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:proj1.jpg|450px|thumb|left|Boîtier après perçage]] [[Fichier:proj2.jpg|450px|thumb|center|Boîtier finalisé]] [[Fichier:proj3.jpg|450px|thumb|right|Projecteur en fonctionnement]]&lt;br /&gt;
&lt;br /&gt;
*Page web et serveur WebSocket&lt;br /&gt;
**Ajout d'un bouton &amp;quot;reboot&amp;quot; et &amp;quot;shutdown&amp;quot; qui permettent respectivement de redémarrer et d'éteindre la Raspberry directement à partir de la page web&lt;br /&gt;
&lt;br /&gt;
===Semaine 9===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 10===&lt;br /&gt;
&lt;br /&gt;
==A faire==&lt;br /&gt;
&lt;br /&gt;
MAJ 26 mars &lt;br /&gt;
&lt;br /&gt;
*Client websocket et page web&lt;br /&gt;
**Mise en page CSS&lt;br /&gt;
**Ajout canvas pour prévisualisation image projeté&lt;br /&gt;
**Ajout &amp;quot;slider&amp;quot; pour régler niveau du flou Gaussien DOUBLE&lt;br /&gt;
**Ajout slider pour de finir amplitude de la projection&lt;br /&gt;
**Afficher statut de connexion&lt;br /&gt;
**Ajout message de confirmation quand le serveur quitte ou relance&lt;br /&gt;
**Ajout boutons &amp;quot;projeter&amp;quot; &amp;quot;centrer&amp;quot; &amp;quot;eteindre&amp;quot;&lt;br /&gt;
**Gestion de plusieurs images avec délai&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Serveur WebSocket&lt;br /&gt;
**Ajout fonctionnalité envoi image de prévisualisation&lt;br /&gt;
&lt;br /&gt;
*RaspberryPi&lt;br /&gt;
**Utilisation d'un serveur bind9 pour éviter de taper IP&lt;br /&gt;
&lt;br /&gt;
*Détection de contours&lt;br /&gt;
**Implémentation algorithme de tri de la plus courte disance&lt;br /&gt;
&lt;br /&gt;
*Commande galvanomêtre&lt;br /&gt;
**Utilisation API I²C&lt;br /&gt;
**Fonction de transfert position-&amp;gt;angle-&amp;gt;tension&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;br /&gt;
&lt;br /&gt;
==Bibliographie==&lt;br /&gt;
&lt;br /&gt;
http://www.ebay.com/itm/20KPPS-30KPPS-laser-scanning-galvo-scanner-ILDA-Closed-Loop-max-30kpps-for-laser-/261517002270?hash=item3ce3a0c61e&lt;br /&gt;
&lt;br /&gt;
https://icn.fenelonlille.org/mediawiki/index.php/Projet_ICN_commun_2016/2017&lt;br /&gt;
&lt;br /&gt;
https://www.g33k-zone.org/post/2016/05/11/Configurer-le-Raspberry-Pi-en-point-d-acc%C3%A8s-Wifi&lt;br /&gt;
&lt;br /&gt;
http://stackoverflow.com/questions/22087076/how-to-make-a-simple-image-upload-using-javascript-html&lt;br /&gt;
&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_a_WebSocket_server_in_Java&lt;br /&gt;
&lt;br /&gt;
export http_proxy=http://proxy.polytech-lille.fr:3128&lt;/div&gt;</summary>
		<author><name>Mtrimbur</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=40827</id>
		<title>IMA4 2016/2017 P39</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=40827"/>
				<updated>2017-03-27T18:00:41Z</updated>
		
		<summary type="html">&lt;p&gt;Mtrimbur : /* Semaine 8 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
===Contexte===&lt;br /&gt;
&lt;br /&gt;
Le laser est une technologie largement utilisé de nos jours dans de diverses applications. En effet, on retrouve cette technologie dans le domaine médical notamment pour la chirurgie oculaire ou encore dans industrie avec la découpe laser ou la soudure au laser.&lt;br /&gt;
&lt;br /&gt;
Le laser est une émission de photons produit par excitation d'un milieu amplificateur (ex : CO2), le rayonnement produit est unidirectionnel et monochromatique. Ce sont ces propriétés que nous allons exploiter afin réaliser un projecteur laser qui mis en mouvement est capable de dessiner des formes sur une surface à l'instar de systèmes existants utilisés pour des effets lumineux lors de festivités.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
L'objectif du projet est de créer un système de projection laser à plusieurs couleurs (au minimum deux) avec une application web pour programmer les formes à dessiner afin d'agrémenter des compétitions de gymnastique rythmique.&lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
Le projet consiste à réaliser avec des lasers des figures géométriques par l'intermédiaire d'un système galvanométrique. &lt;br /&gt;
&lt;br /&gt;
Notre premier travail sera de concevoir la partie projection. Pour cela, nous devrons aligner les lasers et les galvanomètres. En effet, ces derniers posséderont des miroirs à l'extrémité, ainsi les miroirs changeront d'inclinaison suivant le courant traversant les galvanomètres (similaire à l'image ci-contre). Il nous faudra également créer un système d'alimentation qui à partir d'une même source (réseau 230 V) sera capable d'alimenter les lasers et les galvanomètres ainsi qu'une Arduino et une Raspberry Pi.&lt;br /&gt;
[[File:Scanhead.jpeg|thumb]]&lt;br /&gt;
&lt;br /&gt;
Ensuite nous nous intéresserons à l'utilisation d'un système embarqué pour contrôler les galvanomètres et donc dessiner avec les lasers sur un plan 2D. En effet, le laser restera toujours fixe, seuls les galvanomètres, et donc les miroirs bougeront. Les galvanomètres étant contrôlés en courant il faudra réaliser une interface électronique pour convertir une commande en tension en commande de courant. La commande en tension sera assuré par une carte Arduino. Nous n'utiliserons qu'une seule paire de galvanomètres pour les deux laser. Il faudra donc multiplexer les deux faisceaux. La programmation des formes à effectuer, se fera par l'intermédiaire d'une application web PHP hébergée sur une RaspberryPi qui permettra de récupérer une image, d'y appliquer divers traitements et filtres afin d'en extraire les contours, et de calculer les commandes pour positionner les galvanomètres. Un serveur WebSocket également hébergé sur la RaspberryPi servira d'interface entre l'application web et L'arduino qui sera connecté via une liaison série sur la raspberryPI.&lt;br /&gt;
&lt;br /&gt;
Comme animation de test, nous dessinerons le contour d'une gymnaste avec une couleur et son ballon d'une autre couleur. La gymnaste devra lancer son ballon, réaliser quelques difficultés et récupérer son ballon.&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
Nous utiliserons comme matériels :&lt;br /&gt;
*Deux lasers de différentes couleurs&lt;br /&gt;
*Une paire de galvanomètres à miroir&lt;br /&gt;
*Arduino&lt;br /&gt;
*Raspberry Pi3&lt;br /&gt;
*Alimentation 230V/5V 1A [http://www.miniinthebox.com/fr/dual-usb-eu-prise-murale-5v-2a-voyage-adaptateur-chargeur-d-alimentation-pour-iphone7-6-xiaomi-samsung-et-autre-telephone-portable_p5410410.html?currency=EUR&amp;amp;litb_from=paid_adwords_shopping&amp;amp;sku=429_6917%7C752_20648&amp;amp;utm_source=google_shopping&amp;amp;utm_medium=cpc&amp;amp;adword_mt=&amp;amp;adword_ct=138705676724&amp;amp;adword_kw=&amp;amp;adword_pos=1o5&amp;amp;adword_pl=&amp;amp;adword_net=g&amp;amp;adword_tar=&amp;amp;adw_src_id=9653316068_661261352_33588296076_aud-79897721311:pla-256966386459&amp;amp;gclid=Cj0KEQiA_KvEBRCtzNil4-KR-LIBEiQAmgekFxxKjJJWBYCJlDZEa3Ke_2_WR0DzGVbz-jaCZHVIBoMaAvld8P8HAQ]&lt;br /&gt;
*Drivers galvanomètres x2&lt;br /&gt;
*Alimentation laser&lt;br /&gt;
*Lunette de sécurité x2 [https://www.amazon.fr/Uvex-S1933X-Eyewear-SCTOrange-Anti-Fog/dp/B000USRG90/ref=sr_1_1?ie=UTF8&amp;amp;qid=1485441383&amp;amp;sr=8-1&amp;amp;keywords=uvex+s1933x]&lt;br /&gt;
*Boitier ABS [http://fr.farnell.com/multicomp/g3118/boitier-abs-240x120x60mm-ip65/dp/1526656]&lt;br /&gt;
*DAC 4 canaux, avec interface I²C [https://www.adafruit.com/products/1083]&lt;br /&gt;
*Connecteur C14 [http://www.conrad.fr/ce/fr/product/715001/Connecteur-secteur-C14-Embase-male-verticale-715001-Nombre-de-poles-2-PE-10-A-noir-1-pcs/?ref=detview1&amp;amp;rt=detview1&amp;amp;rb=1]&lt;br /&gt;
*Câble secteur&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Logiciel :&lt;br /&gt;
&lt;br /&gt;
*Serveur web : Apache2, HTML5, PHP5, CSS&lt;br /&gt;
*Base de donnée : MySQL&lt;br /&gt;
*Serveur WebSocket : JQuerry, websocket&lt;br /&gt;
*Arduino : IDE Arduino&lt;br /&gt;
&lt;br /&gt;
===Calendrier prévisionnel===&lt;br /&gt;
&lt;br /&gt;
====Liste des tâches à effectuer====&lt;br /&gt;
Les différentes tâches à effectuer sont :&lt;br /&gt;
*Partie préliminaire : étude de fonctionnement des galvanomètres&lt;br /&gt;
**Déterminer comment est effectuée la commande des galvanomètres (protocole, tension...)&lt;br /&gt;
**Effectuer des tests avec l'Arduino ou la Raspberry Pi&lt;br /&gt;
**Effectuer des tests avec une LED à la place du laser &lt;br /&gt;
*Partie projection&lt;br /&gt;
**Fixer les lasers&lt;br /&gt;
**Aligner les lasers et les galvanomètres&lt;br /&gt;
**Créer le système d'alimentation&lt;br /&gt;
**Création d'un boitier&lt;br /&gt;
*Partie système embarqué&lt;br /&gt;
**Asservissement des galvanomètres avec l'Arduino&lt;br /&gt;
**Système électronique de commande en courant pour les galvanomètres&lt;br /&gt;
*Interface Web&lt;br /&gt;
**Installation et configuration Apache2&lt;br /&gt;
**Création d'une interface graphique simple&lt;br /&gt;
**Implémentation d'algorithmes de traitement d'image&lt;br /&gt;
**Mise en forme avec des CSS&lt;br /&gt;
**Sytème d'authentification avec mot de passe&lt;br /&gt;
**Utilisation d'une base de données pour enregistrer toutes les images déjà utilisés afin de les réutiliser&lt;br /&gt;
*Serveur Web Socket&lt;br /&gt;
**Récupération des données de l'interface web&lt;br /&gt;
**Mise en place de la liaison série avec l'Arduino&lt;br /&gt;
&lt;br /&gt;
====Calendrier====&lt;br /&gt;
Répartition du temps consacré au projet (240h) :&lt;br /&gt;
*Partie projection : 80h&lt;br /&gt;
*Partie système embarqué : 40h&lt;br /&gt;
*Partie interface web et websocket: 120h&lt;br /&gt;
&lt;br /&gt;
==Feuille d'heures==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!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&lt;br /&gt;
|-&lt;br /&gt;
| Définition cahier des charges &lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 14&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|38&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Finalisation du cahier des charges avec les responsables&lt;br /&gt;
&lt;br /&gt;
*Acquisition de matériels :&lt;br /&gt;
**Projecteur Laser&lt;br /&gt;
**Galvanomètres&lt;br /&gt;
**Alimentation des galvanomètres&lt;br /&gt;
&lt;br /&gt;
*Listage du matériels à acquérir :&lt;br /&gt;
**Lunettes de sécurité&lt;br /&gt;
**DAC&lt;br /&gt;
**Alimentation 230V/5V 1A&lt;br /&gt;
** Boitier ABS &lt;br /&gt;
**...&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
*Obtention de l'arduino et de la raspberryPI&lt;br /&gt;
&lt;br /&gt;
*Démontage du projecteur laser&lt;br /&gt;
**Deux lasers de classe 3b (vert et rouge)&lt;br /&gt;
**Circuit d'alimentation des deux lasers&lt;br /&gt;
&lt;br /&gt;
*Initialisation du port série de la raspberryPI&lt;br /&gt;
**Modification du fichier ''config.txt'' dans la partition boot&lt;br /&gt;
**Ajout d'une ligne autorisant la communication série ('''enable_uart=1''')&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
*Installation du serveur apache sur la raspberryPI&lt;br /&gt;
**Modification du fichier ''/etc/network/interfaces'' (Static, Address, Netmask, Gateway)&lt;br /&gt;
**Modification du fichier ''/etc/resolv.conf'' (Adresse du serveur)&lt;br /&gt;
**Utilisation d'un proxy pour la récupération outils de programmation (Apache2, Php5)&lt;br /&gt;
&lt;br /&gt;
*Mise en place du point d’accès wifi de la raspberryPI&lt;br /&gt;
**Récupération des logiciels nécessaires (dnsmasq, hostapd)&lt;br /&gt;
**Mise en place d'une adresse IP statique pour le point d'accès par l'intermédiaire du fichier ''/etc/dhcpcd.conf''&lt;br /&gt;
**Désactivation de la négociation automatique de bail dans le fichier ''/etc/network/interfaces''&lt;br /&gt;
**Configuration du logiciel hostapd ''/etc/hostapd/hostapd.conf''&lt;br /&gt;
**Activation du démarrage automatique du point d'accès ''/etc/default/hostapd''&lt;br /&gt;
**Configuration du serveur DNS par ''/etc/dnsmasq.conf''&lt;br /&gt;
&lt;br /&gt;
*Instauration de la page d'accueil de l'interface web à l'adresse ''192.168.3.1''&lt;br /&gt;
**Téléversement de fichiers images sur la page web et affichage de celle-ci&lt;br /&gt;
**Voyant de confirmation du bon fonctionnement du serveur web&lt;br /&gt;
&lt;br /&gt;
*Développement du serveur websocket&lt;br /&gt;
&lt;br /&gt;
Le développement du serveur websocket, initialement prévu en C (il était prévu de reprendre les sources utilisées l'année précédente dans le cadre des projet IMA3 SC), a finalement été réalisé en JAVA pour plusieurs raisons.&lt;br /&gt;
Premièrement, un seul programme met en œuvre le serveur websocket, les divers traitements d'image, ainsi que les contrôles des galvanomètres (par l'intermédiaire des DAC) via la liaison I²C de la Raspberry Pi. Le langage JAVA fournit nativement des bibliothèques d'objets pour manipuler assez simplement des images, il existe également des librairies pour contrôler le port GPIO de la Raspberry et il était également intéressant de travailler avec un langage de plus haut niveau que le C.&lt;br /&gt;
En outre, la totale portabilité de ce langage nous permet de travailler sur n'importe quelle machine et ensuite transférer notre programme sur la Raspberry Pi et l’exécuter sans même repasser par une phase de compilation. Et finalement, c'est le langage que nous étudions actuellement en cours de programmation orientée objet, ce qui permet de nous perfectionner.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Serveur WebSocket====&lt;br /&gt;
&lt;br /&gt;
N'ayant pas trouvé d'API WebSocket en Java satisfaisante (qui ne nécessitent pas l'installation et la configuration de nombreux outils additionnels), j'ai estimé plus commode et plus formateur de développer notre propre serveur WebSocket en se basant sur les librairies sockets de Java avec l'aide d'une documentation assez exhaustive [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers].&lt;br /&gt;
&lt;br /&gt;
Les WebSockets désignent à la fois un protocole réseau qui étend le protocole TCP ainsi qu'une API du World Wide Web. Nous nous en servons afin d'établir une communication asynchrone et bidirectionnelle entre un navigateur web et le serveur, notamment pour envoyer l'image à projeter. L’implémentation du serveur repose sur plusieurs étapes.&lt;br /&gt;
&lt;br /&gt;
1) Connexion d'un client &lt;br /&gt;
&lt;br /&gt;
2) Handshake : permet de faire le lien entre le protocole HTTP et WS. Le client envoie une requête HTTP demandant un upgrade de la connexion en protocole WS et le serveur répond en configurant la connexion (détail dans la documentation [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers]).&lt;br /&gt;
&lt;br /&gt;
3) Réception et décodage des messages : le serveurs reçoit des trames brutes, on extrait donc la taille du message ainsi que le message. De plus, les données son encodées (cryptage XOR) par un masque qui doit également être extrait.&lt;br /&gt;
&lt;br /&gt;
4) Fermeture de la communication.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le serveur supporte le multi-client il est donc nécessaire qu'il effectue ces étapes en &amp;quot;parallèle&amp;quot;. Nous utilisons donc les threads ou fils d’exécution. Un thread est donc responsable d'attendre qu'un nouveau client se connecte et effectue le &amp;quot;handshake&amp;quot;, il crée ensuite un thread associé à ce client afin d'établir un canal de communication. Il y a donc au moins un thread par client. Par la suite il faudra également implémenter une déconnexion automatique d'un client notamment après un timeout.&lt;br /&gt;
&lt;br /&gt;
Exemple d’exécution du serveur avec deux clients qui se connectent et envoient un message : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testServeur.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Les clients sont des navigateurs web. Pour les tests nous avons repris les exemples utilisés dans le cadre das projets IMA3 SC avec le titre de la page HTML qui se colore en vert lorsque le client est connecté, et un champ de saisie pour envoyer des messages au serveur : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testClient.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 4===&lt;br /&gt;
&lt;br /&gt;
*Mise en place d’algorithmes de traitement d'image&lt;br /&gt;
&lt;br /&gt;
====Détection de contour====&lt;br /&gt;
&lt;br /&gt;
L'objectif de notre projet est de pouvoir projeter n'importe quelle image envoyé grâce à l'application web. Pour cela nous allons tracer à une vitesse élevée les contours de l'image sur par exemple un mur grâce au laser. Il est donc nécessaire de détecter les contours de l'image grâce à plusieurs traitements.&lt;br /&gt;
&lt;br /&gt;
=====Conversion en niveau de gris=====&lt;br /&gt;
&lt;br /&gt;
Une des étapes préliminaires pour effectuer la détection de contour est de convertir l'image couleur en niveau de gris. Pour cela l'algorithme est simple : il suffit pour chaque pixel de l'image d'effectuer la moyenne des composantes rouge, verte, bleu de chaque pixel. En effet, si l'on considère une image matricielle (l'image est considérée comme un tableau à deux dimensions avec chaque case qui contient la couleur du pixel), chaque pixel contient les composantes RGB codées sur un octet. La couleur gris correspond aux composantes RGB égales. Le niveau de gris est donc codé de 0 à 255, avec 0 donnant du noir et 255 du blanc. &lt;br /&gt;
&lt;br /&gt;
Voici le résultat obtenu : [[Fichier:testGrayScale.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Filtre de Prewit et Sobel=====&lt;br /&gt;
&lt;br /&gt;
Un contour est défini par un changement brutal d'intensité lumineuse, il s'agit donc de détecter selon plusieurs directions (au moins 2) ces changements. Il existe de nombreuses techniques afin de détecter les contours d'une image (gradient, Laplacien). L'une des techniques avec un rapport efficacité/temps d'exécution correct repose sur les algorithmes de Prewit ou Sobel. L'algorithme repose sur la convolution de matrices.&lt;br /&gt;
Cela consiste à appliquer sur chaque pixel de l'image la matrice de Prewit définie comme &lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L_x = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; ainsi que sa transposée : &amp;lt;math&amp;gt;&lt;br /&gt;
L_y = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; -1 &amp;amp; -1 \\&lt;br /&gt;
 0 &amp;amp; 0 &amp;amp; 0 \\&lt;br /&gt;
+1 &amp;amp; +1 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Convoluer ces deux filtres sur l'image permet de détecter respectivement les contours verticaux et horizontaux.&lt;br /&gt;
&lt;br /&gt;
D'après wikipedia [https://fr.wikipedia.org/wiki/D%C3%A9tection_de_contours], on obtient de meilleurs résultats en appliquant un filtre triangulaire, on introduit donc la matrice de Sobel :&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-2 &amp;amp; 0 &amp;amp; +2 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
On obtient le résultat suivant : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testOutline1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Pré-traitement : Flou Gaussien=====&lt;br /&gt;
&lt;br /&gt;
Afin de réduire significativement le nombre de contours, il est nécessaire d'effectuer un pré-traitement avant la détection de contours. On utilise généralement un flou gaussien afin de réduire les transitions lumineuses et ainsi réduire le nombre de contours. L’algorithme de flou gaussien repose également sur la convolution de matrices sauf qu'ici la matrice filtre est générée grâce à une fonction gaussienne paramétrée par '''Sigma''' qui va directement impacter le niveau de flou. Plus la matrice de filtrage est grande plus la qualité du résultat est meilleure, mais le temps d’exécution devient également plus grand.&lt;br /&gt;
&lt;br /&gt;
Voici la fonction de génération du filtre : &amp;lt;math&amp;gt;G(x,y) = \frac{1}{{2\pi \sigma^2}} e^{-\frac{x^2 + y^2}{2 \sigma^2}}&amp;lt;/math&amp;gt; où x et y correspondent aux indices de la cellule de la matrice.&lt;br /&gt;
&lt;br /&gt;
On obtient ce résultat :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testGaussianBlur.png]]&lt;br /&gt;
&lt;br /&gt;
On note un bien meilleur résultat. Cependant on remarque que les composantes horizontales ne sont pas correctement détectées il subsiste un problème avec le filtrage vertical que je n'ai pas réussi à identifier. De plus, il s'agit par sa suite d'éliminer les contours parasites ainsi que d'affiner le trait pour n'avoir plus qu'un pixel d'épaisseur.&lt;br /&gt;
&lt;br /&gt;
=====Post-traitement : Algorithme de Canny=====&lt;br /&gt;
&lt;br /&gt;
Afin d'obtenir un résultat exploitable il est nécessaire d'appliquer encore quelques traitements. Pour cela nous utilisons l’algorithme de Canny qui repose que celui de Sobel mais qui ajoute un algorithme de seuillage par hysteresis qui permet de retirer les contours secondaires et de ne garder que les contours connexes dans une seuil haut et un seuil bas définis. En outre, cette algorithme affine également le trait obtenu. Pour cet algorithme nous avons directement trouvé des sources libres de droits [http://www.tomgibara.com/computer-vision/canny-edge-detector] qui donne des résultats très corrects.&lt;br /&gt;
&lt;br /&gt;
Par exemple :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ou encore : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny2.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 5===&lt;br /&gt;
&lt;br /&gt;
*Établissement d'un protocole de transfert d'image basé sur les WebSockets&lt;br /&gt;
**Envoie d'un requête &amp;quot;send&amp;quot; par le client dans une trame websocket texte&lt;br /&gt;
**Réponse serveur 'Y' si aucun autre client tente d'envoyer une image simultanément, 'N' sinon&lt;br /&gt;
**Si et seulement si le client reçoit 'Y' il débute le transfert en envoyant la largeur et la longueur de l'image sur 4 octets, puis les données de l'image soit 4 valeurs pour chaque pixels (r,g,b,alpha)&lt;br /&gt;
**Le serveur renvoie 'D' une fois le transfert achevé (à l'avenir, le serveur renverra l'image après filtrage).&lt;br /&gt;
**A tout moment, le serveur peut renvoyer 'E' si une erreur est survenue (ex : paquets perdus, nombre incorrects de données)&lt;br /&gt;
*Ajout du support des logs au niveau serveur&lt;br /&gt;
**Impression sur la sortie standard des messages&lt;br /&gt;
**Formatage en fonction de la sévérité du log (info, warning, error...)&lt;br /&gt;
**Incrustation de la date et heure&lt;br /&gt;
**Possibilité de redirection dans une fichier, avec configuration (écriture à la suite d'un fichier existant, écrasement...)&lt;br /&gt;
**Le tout dans une classe Java flexible et réutilisable pour d'autres projets&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 6===&lt;br /&gt;
&lt;br /&gt;
*Installation de la librairie Java Pi4j sur la raspberry pi qui permet le contrôle des GPIO de celle-ci et notamment le port I²C (basé sur WiringPi)&lt;br /&gt;
*Amélioration coté serveur websocket&lt;br /&gt;
**Gestion de message plus longs (maximum des trames websockets soit 2^63 octets)&lt;br /&gt;
**Différenciation, à la réception de messages, des trames textes ou binaires des trames de contrôle comme les requête ping, pong ou de fermeture de connexion &lt;br /&gt;
**Ajout d'un mode de debug de trames &lt;br /&gt;
&lt;br /&gt;
===Semaine 7===&lt;br /&gt;
&lt;br /&gt;
*Améliorations du serveur WebSocket&lt;br /&gt;
**Gestion de la fragmentation TCP&lt;br /&gt;
**Gestion de la fragmentation WebSocket&lt;br /&gt;
**Gestion des requêtes ping envoyés par le client en renvoyant une trames de contrôle pong afin de maintenir la connexion&lt;br /&gt;
**Gestion des déconnexion de clients afin d'optimiser le serveur&lt;br /&gt;
**Amélioration de l'émission de messages en augmentant la taille maximale pouvant être émise (2^63 octets)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A ce stade du développement, le client et le serveur sont opérationnels et peuvent s'échanger des messages ainsi que des images que le serveur traite pour extraire les contours.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 8===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Montage projecteur&lt;br /&gt;
**Intégralité des composants fixés par vis dans le boîtier ABS&lt;br /&gt;
**Fusion des alimentations&lt;br /&gt;
**Présence d'une led témoin de mise en tension&lt;br /&gt;
**Position laser réglable grâce à une vis&lt;br /&gt;
**Présence d'un switch à bascule pour allumer et éteindre le laser&lt;br /&gt;
**Isolation et vérification des composants&lt;br /&gt;
**Tests empiriques de température et de fonctionnement des lasers et galvanomètres&lt;br /&gt;
&lt;br /&gt;
Le montage boîtier est donc terminé et s’alimente en 230V par intermédiaire d'un câble secteur avec connecteur C14. Le résultat s'avère plutôt compact. Les quelques tests de températures ont montrés que malgré le manque d'espace la température globale du boîtier ne dépasse pas les 50°C pendant plus d'une heure de fonctionnement. L'intégralité des connexions sont isolées avec de la gaine thermodynamique et les zones &amp;quot;sensibles&amp;quot; sont correctement vérifiés ainsi que protégées avec de la matière isolante.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:proj1.jpg|500px|thumb|left|Boîtier après perçage]] [[Fichier:proj2.jpg|500px|thumb|center|Boîtier finalisé]] [[Fichier:proj3.jpg|500px|thumb|right|Projecteur en fonctionnement]]&lt;br /&gt;
&lt;br /&gt;
*Page web et serveur WebSocket&lt;br /&gt;
**Ajout d'un bouton &amp;quot;reboot&amp;quot; et &amp;quot;shutdown&amp;quot; qui permettent respectivement de redémarrer et d'éteindre la Raspberry directement à partir de la page web&lt;br /&gt;
&lt;br /&gt;
===Semaine 9===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 10===&lt;br /&gt;
&lt;br /&gt;
==A faire==&lt;br /&gt;
&lt;br /&gt;
MAJ 26 mars &lt;br /&gt;
&lt;br /&gt;
*Client websocket et page web&lt;br /&gt;
**Mise en page CSS&lt;br /&gt;
**Ajout canvas pour prévisualisation image projeté&lt;br /&gt;
**Ajout &amp;quot;slider&amp;quot; pour régler niveau du flou Gaussien DOUBLE&lt;br /&gt;
**Ajout slider pour de finir amplitude de la projection&lt;br /&gt;
**Afficher statut de connexion&lt;br /&gt;
**Ajout message de confirmation quand le serveur quitte ou relance&lt;br /&gt;
**Ajout boutons &amp;quot;projeter&amp;quot; &amp;quot;centrer&amp;quot; &amp;quot;eteindre&amp;quot;&lt;br /&gt;
**Gestion de plusieurs images avec délai&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Serveur WebSocket&lt;br /&gt;
**Ajout fonctionnalité envoi image de prévisualisation&lt;br /&gt;
&lt;br /&gt;
*RaspberryPi&lt;br /&gt;
**Utilisation d'un serveur bind9 pour éviter de taper IP&lt;br /&gt;
&lt;br /&gt;
*Détection de contours&lt;br /&gt;
**Implémentation algorithme de tri de la plus courte disance&lt;br /&gt;
&lt;br /&gt;
*Commande galvanomêtre&lt;br /&gt;
**Utilisation API I²C&lt;br /&gt;
**Fonction de transfert position-&amp;gt;angle-&amp;gt;tension&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;br /&gt;
&lt;br /&gt;
==Bibliographie==&lt;br /&gt;
&lt;br /&gt;
http://www.ebay.com/itm/20KPPS-30KPPS-laser-scanning-galvo-scanner-ILDA-Closed-Loop-max-30kpps-for-laser-/261517002270?hash=item3ce3a0c61e&lt;br /&gt;
&lt;br /&gt;
https://icn.fenelonlille.org/mediawiki/index.php/Projet_ICN_commun_2016/2017&lt;br /&gt;
&lt;br /&gt;
https://www.g33k-zone.org/post/2016/05/11/Configurer-le-Raspberry-Pi-en-point-d-acc%C3%A8s-Wifi&lt;br /&gt;
&lt;br /&gt;
http://stackoverflow.com/questions/22087076/how-to-make-a-simple-image-upload-using-javascript-html&lt;br /&gt;
&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_a_WebSocket_server_in_Java&lt;br /&gt;
&lt;br /&gt;
export http_proxy=http://proxy.polytech-lille.fr:3128&lt;/div&gt;</summary>
		<author><name>Mtrimbur</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=40826</id>
		<title>IMA4 2016/2017 P39</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=40826"/>
				<updated>2017-03-27T17:59:11Z</updated>
		
		<summary type="html">&lt;p&gt;Mtrimbur : /* Semaine 8 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
===Contexte===&lt;br /&gt;
&lt;br /&gt;
Le laser est une technologie largement utilisé de nos jours dans de diverses applications. En effet, on retrouve cette technologie dans le domaine médical notamment pour la chirurgie oculaire ou encore dans industrie avec la découpe laser ou la soudure au laser.&lt;br /&gt;
&lt;br /&gt;
Le laser est une émission de photons produit par excitation d'un milieu amplificateur (ex : CO2), le rayonnement produit est unidirectionnel et monochromatique. Ce sont ces propriétés que nous allons exploiter afin réaliser un projecteur laser qui mis en mouvement est capable de dessiner des formes sur une surface à l'instar de systèmes existants utilisés pour des effets lumineux lors de festivités.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
L'objectif du projet est de créer un système de projection laser à plusieurs couleurs (au minimum deux) avec une application web pour programmer les formes à dessiner afin d'agrémenter des compétitions de gymnastique rythmique.&lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
Le projet consiste à réaliser avec des lasers des figures géométriques par l'intermédiaire d'un système galvanométrique. &lt;br /&gt;
&lt;br /&gt;
Notre premier travail sera de concevoir la partie projection. Pour cela, nous devrons aligner les lasers et les galvanomètres. En effet, ces derniers posséderont des miroirs à l'extrémité, ainsi les miroirs changeront d'inclinaison suivant le courant traversant les galvanomètres (similaire à l'image ci-contre). Il nous faudra également créer un système d'alimentation qui à partir d'une même source (réseau 230 V) sera capable d'alimenter les lasers et les galvanomètres ainsi qu'une Arduino et une Raspberry Pi.&lt;br /&gt;
[[File:Scanhead.jpeg|thumb]]&lt;br /&gt;
&lt;br /&gt;
Ensuite nous nous intéresserons à l'utilisation d'un système embarqué pour contrôler les galvanomètres et donc dessiner avec les lasers sur un plan 2D. En effet, le laser restera toujours fixe, seuls les galvanomètres, et donc les miroirs bougeront. Les galvanomètres étant contrôlés en courant il faudra réaliser une interface électronique pour convertir une commande en tension en commande de courant. La commande en tension sera assuré par une carte Arduino. Nous n'utiliserons qu'une seule paire de galvanomètres pour les deux laser. Il faudra donc multiplexer les deux faisceaux. La programmation des formes à effectuer, se fera par l'intermédiaire d'une application web PHP hébergée sur une RaspberryPi qui permettra de récupérer une image, d'y appliquer divers traitements et filtres afin d'en extraire les contours, et de calculer les commandes pour positionner les galvanomètres. Un serveur WebSocket également hébergé sur la RaspberryPi servira d'interface entre l'application web et L'arduino qui sera connecté via une liaison série sur la raspberryPI.&lt;br /&gt;
&lt;br /&gt;
Comme animation de test, nous dessinerons le contour d'une gymnaste avec une couleur et son ballon d'une autre couleur. La gymnaste devra lancer son ballon, réaliser quelques difficultés et récupérer son ballon.&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
Nous utiliserons comme matériels :&lt;br /&gt;
*Deux lasers de différentes couleurs&lt;br /&gt;
*Une paire de galvanomètres à miroir&lt;br /&gt;
*Arduino&lt;br /&gt;
*Raspberry Pi3&lt;br /&gt;
*Alimentation 230V/5V 1A [http://www.miniinthebox.com/fr/dual-usb-eu-prise-murale-5v-2a-voyage-adaptateur-chargeur-d-alimentation-pour-iphone7-6-xiaomi-samsung-et-autre-telephone-portable_p5410410.html?currency=EUR&amp;amp;litb_from=paid_adwords_shopping&amp;amp;sku=429_6917%7C752_20648&amp;amp;utm_source=google_shopping&amp;amp;utm_medium=cpc&amp;amp;adword_mt=&amp;amp;adword_ct=138705676724&amp;amp;adword_kw=&amp;amp;adword_pos=1o5&amp;amp;adword_pl=&amp;amp;adword_net=g&amp;amp;adword_tar=&amp;amp;adw_src_id=9653316068_661261352_33588296076_aud-79897721311:pla-256966386459&amp;amp;gclid=Cj0KEQiA_KvEBRCtzNil4-KR-LIBEiQAmgekFxxKjJJWBYCJlDZEa3Ke_2_WR0DzGVbz-jaCZHVIBoMaAvld8P8HAQ]&lt;br /&gt;
*Drivers galvanomètres x2&lt;br /&gt;
*Alimentation laser&lt;br /&gt;
*Lunette de sécurité x2 [https://www.amazon.fr/Uvex-S1933X-Eyewear-SCTOrange-Anti-Fog/dp/B000USRG90/ref=sr_1_1?ie=UTF8&amp;amp;qid=1485441383&amp;amp;sr=8-1&amp;amp;keywords=uvex+s1933x]&lt;br /&gt;
*Boitier ABS [http://fr.farnell.com/multicomp/g3118/boitier-abs-240x120x60mm-ip65/dp/1526656]&lt;br /&gt;
*DAC 4 canaux, avec interface I²C [https://www.adafruit.com/products/1083]&lt;br /&gt;
*Connecteur C14 [http://www.conrad.fr/ce/fr/product/715001/Connecteur-secteur-C14-Embase-male-verticale-715001-Nombre-de-poles-2-PE-10-A-noir-1-pcs/?ref=detview1&amp;amp;rt=detview1&amp;amp;rb=1]&lt;br /&gt;
*Câble secteur&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Logiciel :&lt;br /&gt;
&lt;br /&gt;
*Serveur web : Apache2, HTML5, PHP5, CSS&lt;br /&gt;
*Base de donnée : MySQL&lt;br /&gt;
*Serveur WebSocket : JQuerry, websocket&lt;br /&gt;
*Arduino : IDE Arduino&lt;br /&gt;
&lt;br /&gt;
===Calendrier prévisionnel===&lt;br /&gt;
&lt;br /&gt;
====Liste des tâches à effectuer====&lt;br /&gt;
Les différentes tâches à effectuer sont :&lt;br /&gt;
*Partie préliminaire : étude de fonctionnement des galvanomètres&lt;br /&gt;
**Déterminer comment est effectuée la commande des galvanomètres (protocole, tension...)&lt;br /&gt;
**Effectuer des tests avec l'Arduino ou la Raspberry Pi&lt;br /&gt;
**Effectuer des tests avec une LED à la place du laser &lt;br /&gt;
*Partie projection&lt;br /&gt;
**Fixer les lasers&lt;br /&gt;
**Aligner les lasers et les galvanomètres&lt;br /&gt;
**Créer le système d'alimentation&lt;br /&gt;
**Création d'un boitier&lt;br /&gt;
*Partie système embarqué&lt;br /&gt;
**Asservissement des galvanomètres avec l'Arduino&lt;br /&gt;
**Système électronique de commande en courant pour les galvanomètres&lt;br /&gt;
*Interface Web&lt;br /&gt;
**Installation et configuration Apache2&lt;br /&gt;
**Création d'une interface graphique simple&lt;br /&gt;
**Implémentation d'algorithmes de traitement d'image&lt;br /&gt;
**Mise en forme avec des CSS&lt;br /&gt;
**Sytème d'authentification avec mot de passe&lt;br /&gt;
**Utilisation d'une base de données pour enregistrer toutes les images déjà utilisés afin de les réutiliser&lt;br /&gt;
*Serveur Web Socket&lt;br /&gt;
**Récupération des données de l'interface web&lt;br /&gt;
**Mise en place de la liaison série avec l'Arduino&lt;br /&gt;
&lt;br /&gt;
====Calendrier====&lt;br /&gt;
Répartition du temps consacré au projet (240h) :&lt;br /&gt;
*Partie projection : 80h&lt;br /&gt;
*Partie système embarqué : 40h&lt;br /&gt;
*Partie interface web et websocket: 120h&lt;br /&gt;
&lt;br /&gt;
==Feuille d'heures==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!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&lt;br /&gt;
|-&lt;br /&gt;
| Définition cahier des charges &lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 14&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|38&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Finalisation du cahier des charges avec les responsables&lt;br /&gt;
&lt;br /&gt;
*Acquisition de matériels :&lt;br /&gt;
**Projecteur Laser&lt;br /&gt;
**Galvanomètres&lt;br /&gt;
**Alimentation des galvanomètres&lt;br /&gt;
&lt;br /&gt;
*Listage du matériels à acquérir :&lt;br /&gt;
**Lunettes de sécurité&lt;br /&gt;
**DAC&lt;br /&gt;
**Alimentation 230V/5V 1A&lt;br /&gt;
** Boitier ABS &lt;br /&gt;
**...&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
*Obtention de l'arduino et de la raspberryPI&lt;br /&gt;
&lt;br /&gt;
*Démontage du projecteur laser&lt;br /&gt;
**Deux lasers de classe 3b (vert et rouge)&lt;br /&gt;
**Circuit d'alimentation des deux lasers&lt;br /&gt;
&lt;br /&gt;
*Initialisation du port série de la raspberryPI&lt;br /&gt;
**Modification du fichier ''config.txt'' dans la partition boot&lt;br /&gt;
**Ajout d'une ligne autorisant la communication série ('''enable_uart=1''')&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
*Installation du serveur apache sur la raspberryPI&lt;br /&gt;
**Modification du fichier ''/etc/network/interfaces'' (Static, Address, Netmask, Gateway)&lt;br /&gt;
**Modification du fichier ''/etc/resolv.conf'' (Adresse du serveur)&lt;br /&gt;
**Utilisation d'un proxy pour la récupération outils de programmation (Apache2, Php5)&lt;br /&gt;
&lt;br /&gt;
*Mise en place du point d’accès wifi de la raspberryPI&lt;br /&gt;
**Récupération des logiciels nécessaires (dnsmasq, hostapd)&lt;br /&gt;
**Mise en place d'une adresse IP statique pour le point d'accès par l'intermédiaire du fichier ''/etc/dhcpcd.conf''&lt;br /&gt;
**Désactivation de la négociation automatique de bail dans le fichier ''/etc/network/interfaces''&lt;br /&gt;
**Configuration du logiciel hostapd ''/etc/hostapd/hostapd.conf''&lt;br /&gt;
**Activation du démarrage automatique du point d'accès ''/etc/default/hostapd''&lt;br /&gt;
**Configuration du serveur DNS par ''/etc/dnsmasq.conf''&lt;br /&gt;
&lt;br /&gt;
*Instauration de la page d'accueil de l'interface web à l'adresse ''192.168.3.1''&lt;br /&gt;
**Téléversement de fichiers images sur la page web et affichage de celle-ci&lt;br /&gt;
**Voyant de confirmation du bon fonctionnement du serveur web&lt;br /&gt;
&lt;br /&gt;
*Développement du serveur websocket&lt;br /&gt;
&lt;br /&gt;
Le développement du serveur websocket, initialement prévu en C (il était prévu de reprendre les sources utilisées l'année précédente dans le cadre des projet IMA3 SC), a finalement été réalisé en JAVA pour plusieurs raisons.&lt;br /&gt;
Premièrement, un seul programme met en œuvre le serveur websocket, les divers traitements d'image, ainsi que les contrôles des galvanomètres (par l'intermédiaire des DAC) via la liaison I²C de la Raspberry Pi. Le langage JAVA fournit nativement des bibliothèques d'objets pour manipuler assez simplement des images, il existe également des librairies pour contrôler le port GPIO de la Raspberry et il était également intéressant de travailler avec un langage de plus haut niveau que le C.&lt;br /&gt;
En outre, la totale portabilité de ce langage nous permet de travailler sur n'importe quelle machine et ensuite transférer notre programme sur la Raspberry Pi et l’exécuter sans même repasser par une phase de compilation. Et finalement, c'est le langage que nous étudions actuellement en cours de programmation orientée objet, ce qui permet de nous perfectionner.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Serveur WebSocket====&lt;br /&gt;
&lt;br /&gt;
N'ayant pas trouvé d'API WebSocket en Java satisfaisante (qui ne nécessitent pas l'installation et la configuration de nombreux outils additionnels), j'ai estimé plus commode et plus formateur de développer notre propre serveur WebSocket en se basant sur les librairies sockets de Java avec l'aide d'une documentation assez exhaustive [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers].&lt;br /&gt;
&lt;br /&gt;
Les WebSockets désignent à la fois un protocole réseau qui étend le protocole TCP ainsi qu'une API du World Wide Web. Nous nous en servons afin d'établir une communication asynchrone et bidirectionnelle entre un navigateur web et le serveur, notamment pour envoyer l'image à projeter. L’implémentation du serveur repose sur plusieurs étapes.&lt;br /&gt;
&lt;br /&gt;
1) Connexion d'un client &lt;br /&gt;
&lt;br /&gt;
2) Handshake : permet de faire le lien entre le protocole HTTP et WS. Le client envoie une requête HTTP demandant un upgrade de la connexion en protocole WS et le serveur répond en configurant la connexion (détail dans la documentation [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers]).&lt;br /&gt;
&lt;br /&gt;
3) Réception et décodage des messages : le serveurs reçoit des trames brutes, on extrait donc la taille du message ainsi que le message. De plus, les données son encodées (cryptage XOR) par un masque qui doit également être extrait.&lt;br /&gt;
&lt;br /&gt;
4) Fermeture de la communication.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le serveur supporte le multi-client il est donc nécessaire qu'il effectue ces étapes en &amp;quot;parallèle&amp;quot;. Nous utilisons donc les threads ou fils d’exécution. Un thread est donc responsable d'attendre qu'un nouveau client se connecte et effectue le &amp;quot;handshake&amp;quot;, il crée ensuite un thread associé à ce client afin d'établir un canal de communication. Il y a donc au moins un thread par client. Par la suite il faudra également implémenter une déconnexion automatique d'un client notamment après un timeout.&lt;br /&gt;
&lt;br /&gt;
Exemple d’exécution du serveur avec deux clients qui se connectent et envoient un message : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testServeur.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Les clients sont des navigateurs web. Pour les tests nous avons repris les exemples utilisés dans le cadre das projets IMA3 SC avec le titre de la page HTML qui se colore en vert lorsque le client est connecté, et un champ de saisie pour envoyer des messages au serveur : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testClient.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 4===&lt;br /&gt;
&lt;br /&gt;
*Mise en place d’algorithmes de traitement d'image&lt;br /&gt;
&lt;br /&gt;
====Détection de contour====&lt;br /&gt;
&lt;br /&gt;
L'objectif de notre projet est de pouvoir projeter n'importe quelle image envoyé grâce à l'application web. Pour cela nous allons tracer à une vitesse élevée les contours de l'image sur par exemple un mur grâce au laser. Il est donc nécessaire de détecter les contours de l'image grâce à plusieurs traitements.&lt;br /&gt;
&lt;br /&gt;
=====Conversion en niveau de gris=====&lt;br /&gt;
&lt;br /&gt;
Une des étapes préliminaires pour effectuer la détection de contour est de convertir l'image couleur en niveau de gris. Pour cela l'algorithme est simple : il suffit pour chaque pixel de l'image d'effectuer la moyenne des composantes rouge, verte, bleu de chaque pixel. En effet, si l'on considère une image matricielle (l'image est considérée comme un tableau à deux dimensions avec chaque case qui contient la couleur du pixel), chaque pixel contient les composantes RGB codées sur un octet. La couleur gris correspond aux composantes RGB égales. Le niveau de gris est donc codé de 0 à 255, avec 0 donnant du noir et 255 du blanc. &lt;br /&gt;
&lt;br /&gt;
Voici le résultat obtenu : [[Fichier:testGrayScale.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Filtre de Prewit et Sobel=====&lt;br /&gt;
&lt;br /&gt;
Un contour est défini par un changement brutal d'intensité lumineuse, il s'agit donc de détecter selon plusieurs directions (au moins 2) ces changements. Il existe de nombreuses techniques afin de détecter les contours d'une image (gradient, Laplacien). L'une des techniques avec un rapport efficacité/temps d'exécution correct repose sur les algorithmes de Prewit ou Sobel. L'algorithme repose sur la convolution de matrices.&lt;br /&gt;
Cela consiste à appliquer sur chaque pixel de l'image la matrice de Prewit définie comme &lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L_x = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; ainsi que sa transposée : &amp;lt;math&amp;gt;&lt;br /&gt;
L_y = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; -1 &amp;amp; -1 \\&lt;br /&gt;
 0 &amp;amp; 0 &amp;amp; 0 \\&lt;br /&gt;
+1 &amp;amp; +1 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Convoluer ces deux filtres sur l'image permet de détecter respectivement les contours verticaux et horizontaux.&lt;br /&gt;
&lt;br /&gt;
D'après wikipedia [https://fr.wikipedia.org/wiki/D%C3%A9tection_de_contours], on obtient de meilleurs résultats en appliquant un filtre triangulaire, on introduit donc la matrice de Sobel :&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-2 &amp;amp; 0 &amp;amp; +2 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
On obtient le résultat suivant : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testOutline1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Pré-traitement : Flou Gaussien=====&lt;br /&gt;
&lt;br /&gt;
Afin de réduire significativement le nombre de contours, il est nécessaire d'effectuer un pré-traitement avant la détection de contours. On utilise généralement un flou gaussien afin de réduire les transitions lumineuses et ainsi réduire le nombre de contours. L’algorithme de flou gaussien repose également sur la convolution de matrices sauf qu'ici la matrice filtre est générée grâce à une fonction gaussienne paramétrée par '''Sigma''' qui va directement impacter le niveau de flou. Plus la matrice de filtrage est grande plus la qualité du résultat est meilleure, mais le temps d’exécution devient également plus grand.&lt;br /&gt;
&lt;br /&gt;
Voici la fonction de génération du filtre : &amp;lt;math&amp;gt;G(x,y) = \frac{1}{{2\pi \sigma^2}} e^{-\frac{x^2 + y^2}{2 \sigma^2}}&amp;lt;/math&amp;gt; où x et y correspondent aux indices de la cellule de la matrice.&lt;br /&gt;
&lt;br /&gt;
On obtient ce résultat :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testGaussianBlur.png]]&lt;br /&gt;
&lt;br /&gt;
On note un bien meilleur résultat. Cependant on remarque que les composantes horizontales ne sont pas correctement détectées il subsiste un problème avec le filtrage vertical que je n'ai pas réussi à identifier. De plus, il s'agit par sa suite d'éliminer les contours parasites ainsi que d'affiner le trait pour n'avoir plus qu'un pixel d'épaisseur.&lt;br /&gt;
&lt;br /&gt;
=====Post-traitement : Algorithme de Canny=====&lt;br /&gt;
&lt;br /&gt;
Afin d'obtenir un résultat exploitable il est nécessaire d'appliquer encore quelques traitements. Pour cela nous utilisons l’algorithme de Canny qui repose que celui de Sobel mais qui ajoute un algorithme de seuillage par hysteresis qui permet de retirer les contours secondaires et de ne garder que les contours connexes dans une seuil haut et un seuil bas définis. En outre, cette algorithme affine également le trait obtenu. Pour cet algorithme nous avons directement trouvé des sources libres de droits [http://www.tomgibara.com/computer-vision/canny-edge-detector] qui donne des résultats très corrects.&lt;br /&gt;
&lt;br /&gt;
Par exemple :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ou encore : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny2.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 5===&lt;br /&gt;
&lt;br /&gt;
*Établissement d'un protocole de transfert d'image basé sur les WebSockets&lt;br /&gt;
**Envoie d'un requête &amp;quot;send&amp;quot; par le client dans une trame websocket texte&lt;br /&gt;
**Réponse serveur 'Y' si aucun autre client tente d'envoyer une image simultanément, 'N' sinon&lt;br /&gt;
**Si et seulement si le client reçoit 'Y' il débute le transfert en envoyant la largeur et la longueur de l'image sur 4 octets, puis les données de l'image soit 4 valeurs pour chaque pixels (r,g,b,alpha)&lt;br /&gt;
**Le serveur renvoie 'D' une fois le transfert achevé (à l'avenir, le serveur renverra l'image après filtrage).&lt;br /&gt;
**A tout moment, le serveur peut renvoyer 'E' si une erreur est survenue (ex : paquets perdus, nombre incorrects de données)&lt;br /&gt;
*Ajout du support des logs au niveau serveur&lt;br /&gt;
**Impression sur la sortie standard des messages&lt;br /&gt;
**Formatage en fonction de la sévérité du log (info, warning, error...)&lt;br /&gt;
**Incrustation de la date et heure&lt;br /&gt;
**Possibilité de redirection dans une fichier, avec configuration (écriture à la suite d'un fichier existant, écrasement...)&lt;br /&gt;
**Le tout dans une classe Java flexible et réutilisable pour d'autres projets&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 6===&lt;br /&gt;
&lt;br /&gt;
*Installation de la librairie Java Pi4j sur la raspberry pi qui permet le contrôle des GPIO de celle-ci et notamment le port I²C (basé sur WiringPi)&lt;br /&gt;
*Amélioration coté serveur websocket&lt;br /&gt;
**Gestion de message plus longs (maximum des trames websockets soit 2^63 octets)&lt;br /&gt;
**Différenciation, à la réception de messages, des trames textes ou binaires des trames de contrôle comme les requête ping, pong ou de fermeture de connexion &lt;br /&gt;
**Ajout d'un mode de debug de trames &lt;br /&gt;
&lt;br /&gt;
===Semaine 7===&lt;br /&gt;
&lt;br /&gt;
*Améliorations du serveur WebSocket&lt;br /&gt;
**Gestion de la fragmentation TCP&lt;br /&gt;
**Gestion de la fragmentation WebSocket&lt;br /&gt;
**Gestion des requêtes ping envoyés par le client en renvoyant une trames de contrôle pong afin de maintenir la connexion&lt;br /&gt;
**Gestion des déconnexion de clients afin d'optimiser le serveur&lt;br /&gt;
**Amélioration de l'émission de messages en augmentant la taille maximale pouvant être émise (2^63 octets)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A ce stade du développement, le client et le serveur sont opérationnels et peuvent s'échanger des messages ainsi que des images que le serveur traite pour extraire les contours.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 8===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Montage projecteur&lt;br /&gt;
**Intégralité des composants fixés par vis dans le boîtier ABS&lt;br /&gt;
**Fusion des alimentations&lt;br /&gt;
**Présence d'une led témoin de mise en tension&lt;br /&gt;
**Position laser réglable grâce à une vis&lt;br /&gt;
**Présence d'un switch à bascule pour allumer et éteindre le laser&lt;br /&gt;
**Isolation et vérification des composants&lt;br /&gt;
**Tests empiriques de température et de fonctionnement des lasers et galvanomètres&lt;br /&gt;
&lt;br /&gt;
Le montage boîtier est donc terminé et s’alimente en 230V par intermédiaire d'un câble secteur avec connecteur C14. Le résultat s'avère plutôt compact. Les quelques tests de températures ont montrés que malgré le manque d'espace la température globale du boîtier ne dépasse pas les 50°C pendant plus d'une heure de fonctionnement. L'intégralité des connexions sont isolées avec de la gaine thermodynamique et les zones &amp;quot;sensibles&amp;quot; sont correctement vérifiés ainsi que protégées avec de la matière isolante.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:proj1.jpg|600px|thumb|left|Boîtier après perçage]] [[Fichier:proj2.jpg|600px|thumb|center|Boîtier finalisé]] [[Fichier:proj3.jpg|600px|thumb|right|Projecteur en fonctionnement]]&lt;br /&gt;
&lt;br /&gt;
*Page web et serveur WebSocket&lt;br /&gt;
**Ajout d'un bouton &amp;quot;reboot&amp;quot; et &amp;quot;shutdown&amp;quot; qui permettent respectivement de redémarrer et d'éteindre la Raspberry directement à partir de la page web&lt;br /&gt;
&lt;br /&gt;
===Semaine 9===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 10===&lt;br /&gt;
&lt;br /&gt;
==A faire==&lt;br /&gt;
&lt;br /&gt;
MAJ 26 mars &lt;br /&gt;
&lt;br /&gt;
*Client websocket et page web&lt;br /&gt;
**Mise en page CSS&lt;br /&gt;
**Ajout canvas pour prévisualisation image projeté&lt;br /&gt;
**Ajout &amp;quot;slider&amp;quot; pour régler niveau du flou Gaussien DOUBLE&lt;br /&gt;
**Ajout slider pour de finir amplitude de la projection&lt;br /&gt;
**Afficher statut de connexion&lt;br /&gt;
**Ajout message de confirmation quand le serveur quitte ou relance&lt;br /&gt;
**Ajout boutons &amp;quot;projeter&amp;quot; &amp;quot;centrer&amp;quot; &amp;quot;eteindre&amp;quot;&lt;br /&gt;
**Gestion de plusieurs images avec délai&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Serveur WebSocket&lt;br /&gt;
**Ajout fonctionnalité envoi image de prévisualisation&lt;br /&gt;
&lt;br /&gt;
*RaspberryPi&lt;br /&gt;
**Utilisation d'un serveur bind9 pour éviter de taper IP&lt;br /&gt;
&lt;br /&gt;
*Détection de contours&lt;br /&gt;
**Implémentation algorithme de tri de la plus courte disance&lt;br /&gt;
&lt;br /&gt;
*Commande galvanomêtre&lt;br /&gt;
**Utilisation API I²C&lt;br /&gt;
**Fonction de transfert position-&amp;gt;angle-&amp;gt;tension&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;br /&gt;
&lt;br /&gt;
==Bibliographie==&lt;br /&gt;
&lt;br /&gt;
http://www.ebay.com/itm/20KPPS-30KPPS-laser-scanning-galvo-scanner-ILDA-Closed-Loop-max-30kpps-for-laser-/261517002270?hash=item3ce3a0c61e&lt;br /&gt;
&lt;br /&gt;
https://icn.fenelonlille.org/mediawiki/index.php/Projet_ICN_commun_2016/2017&lt;br /&gt;
&lt;br /&gt;
https://www.g33k-zone.org/post/2016/05/11/Configurer-le-Raspberry-Pi-en-point-d-acc%C3%A8s-Wifi&lt;br /&gt;
&lt;br /&gt;
http://stackoverflow.com/questions/22087076/how-to-make-a-simple-image-upload-using-javascript-html&lt;br /&gt;
&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_a_WebSocket_server_in_Java&lt;br /&gt;
&lt;br /&gt;
export http_proxy=http://proxy.polytech-lille.fr:3128&lt;/div&gt;</summary>
		<author><name>Mtrimbur</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=Fichier:Proj3.jpg&amp;diff=40825</id>
		<title>Fichier:Proj3.jpg</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=Fichier:Proj3.jpg&amp;diff=40825"/>
				<updated>2017-03-27T17:57:26Z</updated>
		
		<summary type="html">&lt;p&gt;Mtrimbur : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Mtrimbur</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=40824</id>
		<title>IMA4 2016/2017 P39</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=40824"/>
				<updated>2017-03-27T17:57:03Z</updated>
		
		<summary type="html">&lt;p&gt;Mtrimbur : /* Semaine 8 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
===Contexte===&lt;br /&gt;
&lt;br /&gt;
Le laser est une technologie largement utilisé de nos jours dans de diverses applications. En effet, on retrouve cette technologie dans le domaine médical notamment pour la chirurgie oculaire ou encore dans industrie avec la découpe laser ou la soudure au laser.&lt;br /&gt;
&lt;br /&gt;
Le laser est une émission de photons produit par excitation d'un milieu amplificateur (ex : CO2), le rayonnement produit est unidirectionnel et monochromatique. Ce sont ces propriétés que nous allons exploiter afin réaliser un projecteur laser qui mis en mouvement est capable de dessiner des formes sur une surface à l'instar de systèmes existants utilisés pour des effets lumineux lors de festivités.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
L'objectif du projet est de créer un système de projection laser à plusieurs couleurs (au minimum deux) avec une application web pour programmer les formes à dessiner afin d'agrémenter des compétitions de gymnastique rythmique.&lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
Le projet consiste à réaliser avec des lasers des figures géométriques par l'intermédiaire d'un système galvanométrique. &lt;br /&gt;
&lt;br /&gt;
Notre premier travail sera de concevoir la partie projection. Pour cela, nous devrons aligner les lasers et les galvanomètres. En effet, ces derniers posséderont des miroirs à l'extrémité, ainsi les miroirs changeront d'inclinaison suivant le courant traversant les galvanomètres (similaire à l'image ci-contre). Il nous faudra également créer un système d'alimentation qui à partir d'une même source (réseau 230 V) sera capable d'alimenter les lasers et les galvanomètres ainsi qu'une Arduino et une Raspberry Pi.&lt;br /&gt;
[[File:Scanhead.jpeg|thumb]]&lt;br /&gt;
&lt;br /&gt;
Ensuite nous nous intéresserons à l'utilisation d'un système embarqué pour contrôler les galvanomètres et donc dessiner avec les lasers sur un plan 2D. En effet, le laser restera toujours fixe, seuls les galvanomètres, et donc les miroirs bougeront. Les galvanomètres étant contrôlés en courant il faudra réaliser une interface électronique pour convertir une commande en tension en commande de courant. La commande en tension sera assuré par une carte Arduino. Nous n'utiliserons qu'une seule paire de galvanomètres pour les deux laser. Il faudra donc multiplexer les deux faisceaux. La programmation des formes à effectuer, se fera par l'intermédiaire d'une application web PHP hébergée sur une RaspberryPi qui permettra de récupérer une image, d'y appliquer divers traitements et filtres afin d'en extraire les contours, et de calculer les commandes pour positionner les galvanomètres. Un serveur WebSocket également hébergé sur la RaspberryPi servira d'interface entre l'application web et L'arduino qui sera connecté via une liaison série sur la raspberryPI.&lt;br /&gt;
&lt;br /&gt;
Comme animation de test, nous dessinerons le contour d'une gymnaste avec une couleur et son ballon d'une autre couleur. La gymnaste devra lancer son ballon, réaliser quelques difficultés et récupérer son ballon.&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
Nous utiliserons comme matériels :&lt;br /&gt;
*Deux lasers de différentes couleurs&lt;br /&gt;
*Une paire de galvanomètres à miroir&lt;br /&gt;
*Arduino&lt;br /&gt;
*Raspberry Pi3&lt;br /&gt;
*Alimentation 230V/5V 1A [http://www.miniinthebox.com/fr/dual-usb-eu-prise-murale-5v-2a-voyage-adaptateur-chargeur-d-alimentation-pour-iphone7-6-xiaomi-samsung-et-autre-telephone-portable_p5410410.html?currency=EUR&amp;amp;litb_from=paid_adwords_shopping&amp;amp;sku=429_6917%7C752_20648&amp;amp;utm_source=google_shopping&amp;amp;utm_medium=cpc&amp;amp;adword_mt=&amp;amp;adword_ct=138705676724&amp;amp;adword_kw=&amp;amp;adword_pos=1o5&amp;amp;adword_pl=&amp;amp;adword_net=g&amp;amp;adword_tar=&amp;amp;adw_src_id=9653316068_661261352_33588296076_aud-79897721311:pla-256966386459&amp;amp;gclid=Cj0KEQiA_KvEBRCtzNil4-KR-LIBEiQAmgekFxxKjJJWBYCJlDZEa3Ke_2_WR0DzGVbz-jaCZHVIBoMaAvld8P8HAQ]&lt;br /&gt;
*Drivers galvanomètres x2&lt;br /&gt;
*Alimentation laser&lt;br /&gt;
*Lunette de sécurité x2 [https://www.amazon.fr/Uvex-S1933X-Eyewear-SCTOrange-Anti-Fog/dp/B000USRG90/ref=sr_1_1?ie=UTF8&amp;amp;qid=1485441383&amp;amp;sr=8-1&amp;amp;keywords=uvex+s1933x]&lt;br /&gt;
*Boitier ABS [http://fr.farnell.com/multicomp/g3118/boitier-abs-240x120x60mm-ip65/dp/1526656]&lt;br /&gt;
*DAC 4 canaux, avec interface I²C [https://www.adafruit.com/products/1083]&lt;br /&gt;
*Connecteur C14 [http://www.conrad.fr/ce/fr/product/715001/Connecteur-secteur-C14-Embase-male-verticale-715001-Nombre-de-poles-2-PE-10-A-noir-1-pcs/?ref=detview1&amp;amp;rt=detview1&amp;amp;rb=1]&lt;br /&gt;
*Câble secteur&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Logiciel :&lt;br /&gt;
&lt;br /&gt;
*Serveur web : Apache2, HTML5, PHP5, CSS&lt;br /&gt;
*Base de donnée : MySQL&lt;br /&gt;
*Serveur WebSocket : JQuerry, websocket&lt;br /&gt;
*Arduino : IDE Arduino&lt;br /&gt;
&lt;br /&gt;
===Calendrier prévisionnel===&lt;br /&gt;
&lt;br /&gt;
====Liste des tâches à effectuer====&lt;br /&gt;
Les différentes tâches à effectuer sont :&lt;br /&gt;
*Partie préliminaire : étude de fonctionnement des galvanomètres&lt;br /&gt;
**Déterminer comment est effectuée la commande des galvanomètres (protocole, tension...)&lt;br /&gt;
**Effectuer des tests avec l'Arduino ou la Raspberry Pi&lt;br /&gt;
**Effectuer des tests avec une LED à la place du laser &lt;br /&gt;
*Partie projection&lt;br /&gt;
**Fixer les lasers&lt;br /&gt;
**Aligner les lasers et les galvanomètres&lt;br /&gt;
**Créer le système d'alimentation&lt;br /&gt;
**Création d'un boitier&lt;br /&gt;
*Partie système embarqué&lt;br /&gt;
**Asservissement des galvanomètres avec l'Arduino&lt;br /&gt;
**Système électronique de commande en courant pour les galvanomètres&lt;br /&gt;
*Interface Web&lt;br /&gt;
**Installation et configuration Apache2&lt;br /&gt;
**Création d'une interface graphique simple&lt;br /&gt;
**Implémentation d'algorithmes de traitement d'image&lt;br /&gt;
**Mise en forme avec des CSS&lt;br /&gt;
**Sytème d'authentification avec mot de passe&lt;br /&gt;
**Utilisation d'une base de données pour enregistrer toutes les images déjà utilisés afin de les réutiliser&lt;br /&gt;
*Serveur Web Socket&lt;br /&gt;
**Récupération des données de l'interface web&lt;br /&gt;
**Mise en place de la liaison série avec l'Arduino&lt;br /&gt;
&lt;br /&gt;
====Calendrier====&lt;br /&gt;
Répartition du temps consacré au projet (240h) :&lt;br /&gt;
*Partie projection : 80h&lt;br /&gt;
*Partie système embarqué : 40h&lt;br /&gt;
*Partie interface web et websocket: 120h&lt;br /&gt;
&lt;br /&gt;
==Feuille d'heures==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!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&lt;br /&gt;
|-&lt;br /&gt;
| Définition cahier des charges &lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 14&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|38&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Finalisation du cahier des charges avec les responsables&lt;br /&gt;
&lt;br /&gt;
*Acquisition de matériels :&lt;br /&gt;
**Projecteur Laser&lt;br /&gt;
**Galvanomètres&lt;br /&gt;
**Alimentation des galvanomètres&lt;br /&gt;
&lt;br /&gt;
*Listage du matériels à acquérir :&lt;br /&gt;
**Lunettes de sécurité&lt;br /&gt;
**DAC&lt;br /&gt;
**Alimentation 230V/5V 1A&lt;br /&gt;
** Boitier ABS &lt;br /&gt;
**...&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
*Obtention de l'arduino et de la raspberryPI&lt;br /&gt;
&lt;br /&gt;
*Démontage du projecteur laser&lt;br /&gt;
**Deux lasers de classe 3b (vert et rouge)&lt;br /&gt;
**Circuit d'alimentation des deux lasers&lt;br /&gt;
&lt;br /&gt;
*Initialisation du port série de la raspberryPI&lt;br /&gt;
**Modification du fichier ''config.txt'' dans la partition boot&lt;br /&gt;
**Ajout d'une ligne autorisant la communication série ('''enable_uart=1''')&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
*Installation du serveur apache sur la raspberryPI&lt;br /&gt;
**Modification du fichier ''/etc/network/interfaces'' (Static, Address, Netmask, Gateway)&lt;br /&gt;
**Modification du fichier ''/etc/resolv.conf'' (Adresse du serveur)&lt;br /&gt;
**Utilisation d'un proxy pour la récupération outils de programmation (Apache2, Php5)&lt;br /&gt;
&lt;br /&gt;
*Mise en place du point d’accès wifi de la raspberryPI&lt;br /&gt;
**Récupération des logiciels nécessaires (dnsmasq, hostapd)&lt;br /&gt;
**Mise en place d'une adresse IP statique pour le point d'accès par l'intermédiaire du fichier ''/etc/dhcpcd.conf''&lt;br /&gt;
**Désactivation de la négociation automatique de bail dans le fichier ''/etc/network/interfaces''&lt;br /&gt;
**Configuration du logiciel hostapd ''/etc/hostapd/hostapd.conf''&lt;br /&gt;
**Activation du démarrage automatique du point d'accès ''/etc/default/hostapd''&lt;br /&gt;
**Configuration du serveur DNS par ''/etc/dnsmasq.conf''&lt;br /&gt;
&lt;br /&gt;
*Instauration de la page d'accueil de l'interface web à l'adresse ''192.168.3.1''&lt;br /&gt;
**Téléversement de fichiers images sur la page web et affichage de celle-ci&lt;br /&gt;
**Voyant de confirmation du bon fonctionnement du serveur web&lt;br /&gt;
&lt;br /&gt;
*Développement du serveur websocket&lt;br /&gt;
&lt;br /&gt;
Le développement du serveur websocket, initialement prévu en C (il était prévu de reprendre les sources utilisées l'année précédente dans le cadre des projet IMA3 SC), a finalement été réalisé en JAVA pour plusieurs raisons.&lt;br /&gt;
Premièrement, un seul programme met en œuvre le serveur websocket, les divers traitements d'image, ainsi que les contrôles des galvanomètres (par l'intermédiaire des DAC) via la liaison I²C de la Raspberry Pi. Le langage JAVA fournit nativement des bibliothèques d'objets pour manipuler assez simplement des images, il existe également des librairies pour contrôler le port GPIO de la Raspberry et il était également intéressant de travailler avec un langage de plus haut niveau que le C.&lt;br /&gt;
En outre, la totale portabilité de ce langage nous permet de travailler sur n'importe quelle machine et ensuite transférer notre programme sur la Raspberry Pi et l’exécuter sans même repasser par une phase de compilation. Et finalement, c'est le langage que nous étudions actuellement en cours de programmation orientée objet, ce qui permet de nous perfectionner.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Serveur WebSocket====&lt;br /&gt;
&lt;br /&gt;
N'ayant pas trouvé d'API WebSocket en Java satisfaisante (qui ne nécessitent pas l'installation et la configuration de nombreux outils additionnels), j'ai estimé plus commode et plus formateur de développer notre propre serveur WebSocket en se basant sur les librairies sockets de Java avec l'aide d'une documentation assez exhaustive [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers].&lt;br /&gt;
&lt;br /&gt;
Les WebSockets désignent à la fois un protocole réseau qui étend le protocole TCP ainsi qu'une API du World Wide Web. Nous nous en servons afin d'établir une communication asynchrone et bidirectionnelle entre un navigateur web et le serveur, notamment pour envoyer l'image à projeter. L’implémentation du serveur repose sur plusieurs étapes.&lt;br /&gt;
&lt;br /&gt;
1) Connexion d'un client &lt;br /&gt;
&lt;br /&gt;
2) Handshake : permet de faire le lien entre le protocole HTTP et WS. Le client envoie une requête HTTP demandant un upgrade de la connexion en protocole WS et le serveur répond en configurant la connexion (détail dans la documentation [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers]).&lt;br /&gt;
&lt;br /&gt;
3) Réception et décodage des messages : le serveurs reçoit des trames brutes, on extrait donc la taille du message ainsi que le message. De plus, les données son encodées (cryptage XOR) par un masque qui doit également être extrait.&lt;br /&gt;
&lt;br /&gt;
4) Fermeture de la communication.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le serveur supporte le multi-client il est donc nécessaire qu'il effectue ces étapes en &amp;quot;parallèle&amp;quot;. Nous utilisons donc les threads ou fils d’exécution. Un thread est donc responsable d'attendre qu'un nouveau client se connecte et effectue le &amp;quot;handshake&amp;quot;, il crée ensuite un thread associé à ce client afin d'établir un canal de communication. Il y a donc au moins un thread par client. Par la suite il faudra également implémenter une déconnexion automatique d'un client notamment après un timeout.&lt;br /&gt;
&lt;br /&gt;
Exemple d’exécution du serveur avec deux clients qui se connectent et envoient un message : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testServeur.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Les clients sont des navigateurs web. Pour les tests nous avons repris les exemples utilisés dans le cadre das projets IMA3 SC avec le titre de la page HTML qui se colore en vert lorsque le client est connecté, et un champ de saisie pour envoyer des messages au serveur : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testClient.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 4===&lt;br /&gt;
&lt;br /&gt;
*Mise en place d’algorithmes de traitement d'image&lt;br /&gt;
&lt;br /&gt;
====Détection de contour====&lt;br /&gt;
&lt;br /&gt;
L'objectif de notre projet est de pouvoir projeter n'importe quelle image envoyé grâce à l'application web. Pour cela nous allons tracer à une vitesse élevée les contours de l'image sur par exemple un mur grâce au laser. Il est donc nécessaire de détecter les contours de l'image grâce à plusieurs traitements.&lt;br /&gt;
&lt;br /&gt;
=====Conversion en niveau de gris=====&lt;br /&gt;
&lt;br /&gt;
Une des étapes préliminaires pour effectuer la détection de contour est de convertir l'image couleur en niveau de gris. Pour cela l'algorithme est simple : il suffit pour chaque pixel de l'image d'effectuer la moyenne des composantes rouge, verte, bleu de chaque pixel. En effet, si l'on considère une image matricielle (l'image est considérée comme un tableau à deux dimensions avec chaque case qui contient la couleur du pixel), chaque pixel contient les composantes RGB codées sur un octet. La couleur gris correspond aux composantes RGB égales. Le niveau de gris est donc codé de 0 à 255, avec 0 donnant du noir et 255 du blanc. &lt;br /&gt;
&lt;br /&gt;
Voici le résultat obtenu : [[Fichier:testGrayScale.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Filtre de Prewit et Sobel=====&lt;br /&gt;
&lt;br /&gt;
Un contour est défini par un changement brutal d'intensité lumineuse, il s'agit donc de détecter selon plusieurs directions (au moins 2) ces changements. Il existe de nombreuses techniques afin de détecter les contours d'une image (gradient, Laplacien). L'une des techniques avec un rapport efficacité/temps d'exécution correct repose sur les algorithmes de Prewit ou Sobel. L'algorithme repose sur la convolution de matrices.&lt;br /&gt;
Cela consiste à appliquer sur chaque pixel de l'image la matrice de Prewit définie comme &lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L_x = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; ainsi que sa transposée : &amp;lt;math&amp;gt;&lt;br /&gt;
L_y = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; -1 &amp;amp; -1 \\&lt;br /&gt;
 0 &amp;amp; 0 &amp;amp; 0 \\&lt;br /&gt;
+1 &amp;amp; +1 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Convoluer ces deux filtres sur l'image permet de détecter respectivement les contours verticaux et horizontaux.&lt;br /&gt;
&lt;br /&gt;
D'après wikipedia [https://fr.wikipedia.org/wiki/D%C3%A9tection_de_contours], on obtient de meilleurs résultats en appliquant un filtre triangulaire, on introduit donc la matrice de Sobel :&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-2 &amp;amp; 0 &amp;amp; +2 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
On obtient le résultat suivant : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testOutline1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Pré-traitement : Flou Gaussien=====&lt;br /&gt;
&lt;br /&gt;
Afin de réduire significativement le nombre de contours, il est nécessaire d'effectuer un pré-traitement avant la détection de contours. On utilise généralement un flou gaussien afin de réduire les transitions lumineuses et ainsi réduire le nombre de contours. L’algorithme de flou gaussien repose également sur la convolution de matrices sauf qu'ici la matrice filtre est générée grâce à une fonction gaussienne paramétrée par '''Sigma''' qui va directement impacter le niveau de flou. Plus la matrice de filtrage est grande plus la qualité du résultat est meilleure, mais le temps d’exécution devient également plus grand.&lt;br /&gt;
&lt;br /&gt;
Voici la fonction de génération du filtre : &amp;lt;math&amp;gt;G(x,y) = \frac{1}{{2\pi \sigma^2}} e^{-\frac{x^2 + y^2}{2 \sigma^2}}&amp;lt;/math&amp;gt; où x et y correspondent aux indices de la cellule de la matrice.&lt;br /&gt;
&lt;br /&gt;
On obtient ce résultat :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testGaussianBlur.png]]&lt;br /&gt;
&lt;br /&gt;
On note un bien meilleur résultat. Cependant on remarque que les composantes horizontales ne sont pas correctement détectées il subsiste un problème avec le filtrage vertical que je n'ai pas réussi à identifier. De plus, il s'agit par sa suite d'éliminer les contours parasites ainsi que d'affiner le trait pour n'avoir plus qu'un pixel d'épaisseur.&lt;br /&gt;
&lt;br /&gt;
=====Post-traitement : Algorithme de Canny=====&lt;br /&gt;
&lt;br /&gt;
Afin d'obtenir un résultat exploitable il est nécessaire d'appliquer encore quelques traitements. Pour cela nous utilisons l’algorithme de Canny qui repose que celui de Sobel mais qui ajoute un algorithme de seuillage par hysteresis qui permet de retirer les contours secondaires et de ne garder que les contours connexes dans une seuil haut et un seuil bas définis. En outre, cette algorithme affine également le trait obtenu. Pour cet algorithme nous avons directement trouvé des sources libres de droits [http://www.tomgibara.com/computer-vision/canny-edge-detector] qui donne des résultats très corrects.&lt;br /&gt;
&lt;br /&gt;
Par exemple :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ou encore : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny2.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 5===&lt;br /&gt;
&lt;br /&gt;
*Établissement d'un protocole de transfert d'image basé sur les WebSockets&lt;br /&gt;
**Envoie d'un requête &amp;quot;send&amp;quot; par le client dans une trame websocket texte&lt;br /&gt;
**Réponse serveur 'Y' si aucun autre client tente d'envoyer une image simultanément, 'N' sinon&lt;br /&gt;
**Si et seulement si le client reçoit 'Y' il débute le transfert en envoyant la largeur et la longueur de l'image sur 4 octets, puis les données de l'image soit 4 valeurs pour chaque pixels (r,g,b,alpha)&lt;br /&gt;
**Le serveur renvoie 'D' une fois le transfert achevé (à l'avenir, le serveur renverra l'image après filtrage).&lt;br /&gt;
**A tout moment, le serveur peut renvoyer 'E' si une erreur est survenue (ex : paquets perdus, nombre incorrects de données)&lt;br /&gt;
*Ajout du support des logs au niveau serveur&lt;br /&gt;
**Impression sur la sortie standard des messages&lt;br /&gt;
**Formatage en fonction de la sévérité du log (info, warning, error...)&lt;br /&gt;
**Incrustation de la date et heure&lt;br /&gt;
**Possibilité de redirection dans une fichier, avec configuration (écriture à la suite d'un fichier existant, écrasement...)&lt;br /&gt;
**Le tout dans une classe Java flexible et réutilisable pour d'autres projets&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 6===&lt;br /&gt;
&lt;br /&gt;
*Installation de la librairie Java Pi4j sur la raspberry pi qui permet le contrôle des GPIO de celle-ci et notamment le port I²C (basé sur WiringPi)&lt;br /&gt;
*Amélioration coté serveur websocket&lt;br /&gt;
**Gestion de message plus longs (maximum des trames websockets soit 2^63 octets)&lt;br /&gt;
**Différenciation, à la réception de messages, des trames textes ou binaires des trames de contrôle comme les requête ping, pong ou de fermeture de connexion &lt;br /&gt;
**Ajout d'un mode de debug de trames &lt;br /&gt;
&lt;br /&gt;
===Semaine 7===&lt;br /&gt;
&lt;br /&gt;
*Améliorations du serveur WebSocket&lt;br /&gt;
**Gestion de la fragmentation TCP&lt;br /&gt;
**Gestion de la fragmentation WebSocket&lt;br /&gt;
**Gestion des requêtes ping envoyés par le client en renvoyant une trames de contrôle pong afin de maintenir la connexion&lt;br /&gt;
**Gestion des déconnexion de clients afin d'optimiser le serveur&lt;br /&gt;
**Amélioration de l'émission de messages en augmentant la taille maximale pouvant être émise (2^63 octets)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A ce stade du développement, le client et le serveur sont opérationnels et peuvent s'échanger des messages ainsi que des images que le serveur traite pour extraire les contours.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 8===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Montage projecteur&lt;br /&gt;
**Intégralité des composants fixés par vis dans le boîtier ABS&lt;br /&gt;
**Fusion des alimentations&lt;br /&gt;
**Présence d'une led témoin de mise en tension&lt;br /&gt;
**Position laser réglable grâce à une vis&lt;br /&gt;
**Présence d'un switch à bascule pour allumer et éteindre le laser&lt;br /&gt;
**Isolation et vérification des composants&lt;br /&gt;
**Tests empiriques de température et de fonctionnement des lasers et galvanomètres&lt;br /&gt;
&lt;br /&gt;
Le montage boîtier est donc terminé et s’alimente en 230V par intermédiaire d'un câble secteur avec connecteur C14. Le résultat s'avère plutôt compact. Les quelques tests de températures ont montrés que malgré le manque d'espace la température globale du boîtier ne dépasse pas les 50°C pendant plus d'une heure de fonctionnement. L'intégralité des connexions sont isolées avec de la gaine thermodynamique et les zones &amp;quot;sensibles&amp;quot; sont correctement vérifiés ainsi que protégées avec de la matière isolante.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:proj1.jpg|800px|thumb|left|Boîtier après perçage]] [[Fichier:proj2.jpg|800px|thumb|center|Boîtier finalisé]] [[Fichier:proj3.jpg|800px|thumb|left|Projecteur en fonctionnement]]&lt;br /&gt;
&lt;br /&gt;
*Page web et serveur WebSocket&lt;br /&gt;
**Ajout d'un bouton &amp;quot;reboot&amp;quot; et &amp;quot;shutdown&amp;quot; qui permettent respectivement de redémarrer et d'éteindre la Raspberry directement à partir de la page web&lt;br /&gt;
&lt;br /&gt;
===Semaine 9===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 10===&lt;br /&gt;
&lt;br /&gt;
==A faire==&lt;br /&gt;
&lt;br /&gt;
MAJ 26 mars &lt;br /&gt;
&lt;br /&gt;
*Client websocket et page web&lt;br /&gt;
**Mise en page CSS&lt;br /&gt;
**Ajout canvas pour prévisualisation image projeté&lt;br /&gt;
**Ajout &amp;quot;slider&amp;quot; pour régler niveau du flou Gaussien DOUBLE&lt;br /&gt;
**Ajout slider pour de finir amplitude de la projection&lt;br /&gt;
**Afficher statut de connexion&lt;br /&gt;
**Ajout message de confirmation quand le serveur quitte ou relance&lt;br /&gt;
**Ajout boutons &amp;quot;projeter&amp;quot; &amp;quot;centrer&amp;quot; &amp;quot;eteindre&amp;quot;&lt;br /&gt;
**Gestion de plusieurs images avec délai&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Serveur WebSocket&lt;br /&gt;
**Ajout fonctionnalité envoi image de prévisualisation&lt;br /&gt;
&lt;br /&gt;
*RaspberryPi&lt;br /&gt;
**Utilisation d'un serveur bind9 pour éviter de taper IP&lt;br /&gt;
&lt;br /&gt;
*Détection de contours&lt;br /&gt;
**Implémentation algorithme de tri de la plus courte disance&lt;br /&gt;
&lt;br /&gt;
*Commande galvanomêtre&lt;br /&gt;
**Utilisation API I²C&lt;br /&gt;
**Fonction de transfert position-&amp;gt;angle-&amp;gt;tension&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;br /&gt;
&lt;br /&gt;
==Bibliographie==&lt;br /&gt;
&lt;br /&gt;
http://www.ebay.com/itm/20KPPS-30KPPS-laser-scanning-galvo-scanner-ILDA-Closed-Loop-max-30kpps-for-laser-/261517002270?hash=item3ce3a0c61e&lt;br /&gt;
&lt;br /&gt;
https://icn.fenelonlille.org/mediawiki/index.php/Projet_ICN_commun_2016/2017&lt;br /&gt;
&lt;br /&gt;
https://www.g33k-zone.org/post/2016/05/11/Configurer-le-Raspberry-Pi-en-point-d-acc%C3%A8s-Wifi&lt;br /&gt;
&lt;br /&gt;
http://stackoverflow.com/questions/22087076/how-to-make-a-simple-image-upload-using-javascript-html&lt;br /&gt;
&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_a_WebSocket_server_in_Java&lt;br /&gt;
&lt;br /&gt;
export http_proxy=http://proxy.polytech-lille.fr:3128&lt;/div&gt;</summary>
		<author><name>Mtrimbur</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=40823</id>
		<title>IMA4 2016/2017 P39</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=40823"/>
				<updated>2017-03-27T17:55:35Z</updated>
		
		<summary type="html">&lt;p&gt;Mtrimbur : /* Semaine 8 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
===Contexte===&lt;br /&gt;
&lt;br /&gt;
Le laser est une technologie largement utilisé de nos jours dans de diverses applications. En effet, on retrouve cette technologie dans le domaine médical notamment pour la chirurgie oculaire ou encore dans industrie avec la découpe laser ou la soudure au laser.&lt;br /&gt;
&lt;br /&gt;
Le laser est une émission de photons produit par excitation d'un milieu amplificateur (ex : CO2), le rayonnement produit est unidirectionnel et monochromatique. Ce sont ces propriétés que nous allons exploiter afin réaliser un projecteur laser qui mis en mouvement est capable de dessiner des formes sur une surface à l'instar de systèmes existants utilisés pour des effets lumineux lors de festivités.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
L'objectif du projet est de créer un système de projection laser à plusieurs couleurs (au minimum deux) avec une application web pour programmer les formes à dessiner afin d'agrémenter des compétitions de gymnastique rythmique.&lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
Le projet consiste à réaliser avec des lasers des figures géométriques par l'intermédiaire d'un système galvanométrique. &lt;br /&gt;
&lt;br /&gt;
Notre premier travail sera de concevoir la partie projection. Pour cela, nous devrons aligner les lasers et les galvanomètres. En effet, ces derniers posséderont des miroirs à l'extrémité, ainsi les miroirs changeront d'inclinaison suivant le courant traversant les galvanomètres (similaire à l'image ci-contre). Il nous faudra également créer un système d'alimentation qui à partir d'une même source (réseau 230 V) sera capable d'alimenter les lasers et les galvanomètres ainsi qu'une Arduino et une Raspberry Pi.&lt;br /&gt;
[[File:Scanhead.jpeg|thumb]]&lt;br /&gt;
&lt;br /&gt;
Ensuite nous nous intéresserons à l'utilisation d'un système embarqué pour contrôler les galvanomètres et donc dessiner avec les lasers sur un plan 2D. En effet, le laser restera toujours fixe, seuls les galvanomètres, et donc les miroirs bougeront. Les galvanomètres étant contrôlés en courant il faudra réaliser une interface électronique pour convertir une commande en tension en commande de courant. La commande en tension sera assuré par une carte Arduino. Nous n'utiliserons qu'une seule paire de galvanomètres pour les deux laser. Il faudra donc multiplexer les deux faisceaux. La programmation des formes à effectuer, se fera par l'intermédiaire d'une application web PHP hébergée sur une RaspberryPi qui permettra de récupérer une image, d'y appliquer divers traitements et filtres afin d'en extraire les contours, et de calculer les commandes pour positionner les galvanomètres. Un serveur WebSocket également hébergé sur la RaspberryPi servira d'interface entre l'application web et L'arduino qui sera connecté via une liaison série sur la raspberryPI.&lt;br /&gt;
&lt;br /&gt;
Comme animation de test, nous dessinerons le contour d'une gymnaste avec une couleur et son ballon d'une autre couleur. La gymnaste devra lancer son ballon, réaliser quelques difficultés et récupérer son ballon.&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
Nous utiliserons comme matériels :&lt;br /&gt;
*Deux lasers de différentes couleurs&lt;br /&gt;
*Une paire de galvanomètres à miroir&lt;br /&gt;
*Arduino&lt;br /&gt;
*Raspberry Pi3&lt;br /&gt;
*Alimentation 230V/5V 1A [http://www.miniinthebox.com/fr/dual-usb-eu-prise-murale-5v-2a-voyage-adaptateur-chargeur-d-alimentation-pour-iphone7-6-xiaomi-samsung-et-autre-telephone-portable_p5410410.html?currency=EUR&amp;amp;litb_from=paid_adwords_shopping&amp;amp;sku=429_6917%7C752_20648&amp;amp;utm_source=google_shopping&amp;amp;utm_medium=cpc&amp;amp;adword_mt=&amp;amp;adword_ct=138705676724&amp;amp;adword_kw=&amp;amp;adword_pos=1o5&amp;amp;adword_pl=&amp;amp;adword_net=g&amp;amp;adword_tar=&amp;amp;adw_src_id=9653316068_661261352_33588296076_aud-79897721311:pla-256966386459&amp;amp;gclid=Cj0KEQiA_KvEBRCtzNil4-KR-LIBEiQAmgekFxxKjJJWBYCJlDZEa3Ke_2_WR0DzGVbz-jaCZHVIBoMaAvld8P8HAQ]&lt;br /&gt;
*Drivers galvanomètres x2&lt;br /&gt;
*Alimentation laser&lt;br /&gt;
*Lunette de sécurité x2 [https://www.amazon.fr/Uvex-S1933X-Eyewear-SCTOrange-Anti-Fog/dp/B000USRG90/ref=sr_1_1?ie=UTF8&amp;amp;qid=1485441383&amp;amp;sr=8-1&amp;amp;keywords=uvex+s1933x]&lt;br /&gt;
*Boitier ABS [http://fr.farnell.com/multicomp/g3118/boitier-abs-240x120x60mm-ip65/dp/1526656]&lt;br /&gt;
*DAC 4 canaux, avec interface I²C [https://www.adafruit.com/products/1083]&lt;br /&gt;
*Connecteur C14 [http://www.conrad.fr/ce/fr/product/715001/Connecteur-secteur-C14-Embase-male-verticale-715001-Nombre-de-poles-2-PE-10-A-noir-1-pcs/?ref=detview1&amp;amp;rt=detview1&amp;amp;rb=1]&lt;br /&gt;
*Câble secteur&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Logiciel :&lt;br /&gt;
&lt;br /&gt;
*Serveur web : Apache2, HTML5, PHP5, CSS&lt;br /&gt;
*Base de donnée : MySQL&lt;br /&gt;
*Serveur WebSocket : JQuerry, websocket&lt;br /&gt;
*Arduino : IDE Arduino&lt;br /&gt;
&lt;br /&gt;
===Calendrier prévisionnel===&lt;br /&gt;
&lt;br /&gt;
====Liste des tâches à effectuer====&lt;br /&gt;
Les différentes tâches à effectuer sont :&lt;br /&gt;
*Partie préliminaire : étude de fonctionnement des galvanomètres&lt;br /&gt;
**Déterminer comment est effectuée la commande des galvanomètres (protocole, tension...)&lt;br /&gt;
**Effectuer des tests avec l'Arduino ou la Raspberry Pi&lt;br /&gt;
**Effectuer des tests avec une LED à la place du laser &lt;br /&gt;
*Partie projection&lt;br /&gt;
**Fixer les lasers&lt;br /&gt;
**Aligner les lasers et les galvanomètres&lt;br /&gt;
**Créer le système d'alimentation&lt;br /&gt;
**Création d'un boitier&lt;br /&gt;
*Partie système embarqué&lt;br /&gt;
**Asservissement des galvanomètres avec l'Arduino&lt;br /&gt;
**Système électronique de commande en courant pour les galvanomètres&lt;br /&gt;
*Interface Web&lt;br /&gt;
**Installation et configuration Apache2&lt;br /&gt;
**Création d'une interface graphique simple&lt;br /&gt;
**Implémentation d'algorithmes de traitement d'image&lt;br /&gt;
**Mise en forme avec des CSS&lt;br /&gt;
**Sytème d'authentification avec mot de passe&lt;br /&gt;
**Utilisation d'une base de données pour enregistrer toutes les images déjà utilisés afin de les réutiliser&lt;br /&gt;
*Serveur Web Socket&lt;br /&gt;
**Récupération des données de l'interface web&lt;br /&gt;
**Mise en place de la liaison série avec l'Arduino&lt;br /&gt;
&lt;br /&gt;
====Calendrier====&lt;br /&gt;
Répartition du temps consacré au projet (240h) :&lt;br /&gt;
*Partie projection : 80h&lt;br /&gt;
*Partie système embarqué : 40h&lt;br /&gt;
*Partie interface web et websocket: 120h&lt;br /&gt;
&lt;br /&gt;
==Feuille d'heures==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!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&lt;br /&gt;
|-&lt;br /&gt;
| Définition cahier des charges &lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 14&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|38&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Finalisation du cahier des charges avec les responsables&lt;br /&gt;
&lt;br /&gt;
*Acquisition de matériels :&lt;br /&gt;
**Projecteur Laser&lt;br /&gt;
**Galvanomètres&lt;br /&gt;
**Alimentation des galvanomètres&lt;br /&gt;
&lt;br /&gt;
*Listage du matériels à acquérir :&lt;br /&gt;
**Lunettes de sécurité&lt;br /&gt;
**DAC&lt;br /&gt;
**Alimentation 230V/5V 1A&lt;br /&gt;
** Boitier ABS &lt;br /&gt;
**...&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
*Obtention de l'arduino et de la raspberryPI&lt;br /&gt;
&lt;br /&gt;
*Démontage du projecteur laser&lt;br /&gt;
**Deux lasers de classe 3b (vert et rouge)&lt;br /&gt;
**Circuit d'alimentation des deux lasers&lt;br /&gt;
&lt;br /&gt;
*Initialisation du port série de la raspberryPI&lt;br /&gt;
**Modification du fichier ''config.txt'' dans la partition boot&lt;br /&gt;
**Ajout d'une ligne autorisant la communication série ('''enable_uart=1''')&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
*Installation du serveur apache sur la raspberryPI&lt;br /&gt;
**Modification du fichier ''/etc/network/interfaces'' (Static, Address, Netmask, Gateway)&lt;br /&gt;
**Modification du fichier ''/etc/resolv.conf'' (Adresse du serveur)&lt;br /&gt;
**Utilisation d'un proxy pour la récupération outils de programmation (Apache2, Php5)&lt;br /&gt;
&lt;br /&gt;
*Mise en place du point d’accès wifi de la raspberryPI&lt;br /&gt;
**Récupération des logiciels nécessaires (dnsmasq, hostapd)&lt;br /&gt;
**Mise en place d'une adresse IP statique pour le point d'accès par l'intermédiaire du fichier ''/etc/dhcpcd.conf''&lt;br /&gt;
**Désactivation de la négociation automatique de bail dans le fichier ''/etc/network/interfaces''&lt;br /&gt;
**Configuration du logiciel hostapd ''/etc/hostapd/hostapd.conf''&lt;br /&gt;
**Activation du démarrage automatique du point d'accès ''/etc/default/hostapd''&lt;br /&gt;
**Configuration du serveur DNS par ''/etc/dnsmasq.conf''&lt;br /&gt;
&lt;br /&gt;
*Instauration de la page d'accueil de l'interface web à l'adresse ''192.168.3.1''&lt;br /&gt;
**Téléversement de fichiers images sur la page web et affichage de celle-ci&lt;br /&gt;
**Voyant de confirmation du bon fonctionnement du serveur web&lt;br /&gt;
&lt;br /&gt;
*Développement du serveur websocket&lt;br /&gt;
&lt;br /&gt;
Le développement du serveur websocket, initialement prévu en C (il était prévu de reprendre les sources utilisées l'année précédente dans le cadre des projet IMA3 SC), a finalement été réalisé en JAVA pour plusieurs raisons.&lt;br /&gt;
Premièrement, un seul programme met en œuvre le serveur websocket, les divers traitements d'image, ainsi que les contrôles des galvanomètres (par l'intermédiaire des DAC) via la liaison I²C de la Raspberry Pi. Le langage JAVA fournit nativement des bibliothèques d'objets pour manipuler assez simplement des images, il existe également des librairies pour contrôler le port GPIO de la Raspberry et il était également intéressant de travailler avec un langage de plus haut niveau que le C.&lt;br /&gt;
En outre, la totale portabilité de ce langage nous permet de travailler sur n'importe quelle machine et ensuite transférer notre programme sur la Raspberry Pi et l’exécuter sans même repasser par une phase de compilation. Et finalement, c'est le langage que nous étudions actuellement en cours de programmation orientée objet, ce qui permet de nous perfectionner.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Serveur WebSocket====&lt;br /&gt;
&lt;br /&gt;
N'ayant pas trouvé d'API WebSocket en Java satisfaisante (qui ne nécessitent pas l'installation et la configuration de nombreux outils additionnels), j'ai estimé plus commode et plus formateur de développer notre propre serveur WebSocket en se basant sur les librairies sockets de Java avec l'aide d'une documentation assez exhaustive [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers].&lt;br /&gt;
&lt;br /&gt;
Les WebSockets désignent à la fois un protocole réseau qui étend le protocole TCP ainsi qu'une API du World Wide Web. Nous nous en servons afin d'établir une communication asynchrone et bidirectionnelle entre un navigateur web et le serveur, notamment pour envoyer l'image à projeter. L’implémentation du serveur repose sur plusieurs étapes.&lt;br /&gt;
&lt;br /&gt;
1) Connexion d'un client &lt;br /&gt;
&lt;br /&gt;
2) Handshake : permet de faire le lien entre le protocole HTTP et WS. Le client envoie une requête HTTP demandant un upgrade de la connexion en protocole WS et le serveur répond en configurant la connexion (détail dans la documentation [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers]).&lt;br /&gt;
&lt;br /&gt;
3) Réception et décodage des messages : le serveurs reçoit des trames brutes, on extrait donc la taille du message ainsi que le message. De plus, les données son encodées (cryptage XOR) par un masque qui doit également être extrait.&lt;br /&gt;
&lt;br /&gt;
4) Fermeture de la communication.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le serveur supporte le multi-client il est donc nécessaire qu'il effectue ces étapes en &amp;quot;parallèle&amp;quot;. Nous utilisons donc les threads ou fils d’exécution. Un thread est donc responsable d'attendre qu'un nouveau client se connecte et effectue le &amp;quot;handshake&amp;quot;, il crée ensuite un thread associé à ce client afin d'établir un canal de communication. Il y a donc au moins un thread par client. Par la suite il faudra également implémenter une déconnexion automatique d'un client notamment après un timeout.&lt;br /&gt;
&lt;br /&gt;
Exemple d’exécution du serveur avec deux clients qui se connectent et envoient un message : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testServeur.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Les clients sont des navigateurs web. Pour les tests nous avons repris les exemples utilisés dans le cadre das projets IMA3 SC avec le titre de la page HTML qui se colore en vert lorsque le client est connecté, et un champ de saisie pour envoyer des messages au serveur : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testClient.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 4===&lt;br /&gt;
&lt;br /&gt;
*Mise en place d’algorithmes de traitement d'image&lt;br /&gt;
&lt;br /&gt;
====Détection de contour====&lt;br /&gt;
&lt;br /&gt;
L'objectif de notre projet est de pouvoir projeter n'importe quelle image envoyé grâce à l'application web. Pour cela nous allons tracer à une vitesse élevée les contours de l'image sur par exemple un mur grâce au laser. Il est donc nécessaire de détecter les contours de l'image grâce à plusieurs traitements.&lt;br /&gt;
&lt;br /&gt;
=====Conversion en niveau de gris=====&lt;br /&gt;
&lt;br /&gt;
Une des étapes préliminaires pour effectuer la détection de contour est de convertir l'image couleur en niveau de gris. Pour cela l'algorithme est simple : il suffit pour chaque pixel de l'image d'effectuer la moyenne des composantes rouge, verte, bleu de chaque pixel. En effet, si l'on considère une image matricielle (l'image est considérée comme un tableau à deux dimensions avec chaque case qui contient la couleur du pixel), chaque pixel contient les composantes RGB codées sur un octet. La couleur gris correspond aux composantes RGB égales. Le niveau de gris est donc codé de 0 à 255, avec 0 donnant du noir et 255 du blanc. &lt;br /&gt;
&lt;br /&gt;
Voici le résultat obtenu : [[Fichier:testGrayScale.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Filtre de Prewit et Sobel=====&lt;br /&gt;
&lt;br /&gt;
Un contour est défini par un changement brutal d'intensité lumineuse, il s'agit donc de détecter selon plusieurs directions (au moins 2) ces changements. Il existe de nombreuses techniques afin de détecter les contours d'une image (gradient, Laplacien). L'une des techniques avec un rapport efficacité/temps d'exécution correct repose sur les algorithmes de Prewit ou Sobel. L'algorithme repose sur la convolution de matrices.&lt;br /&gt;
Cela consiste à appliquer sur chaque pixel de l'image la matrice de Prewit définie comme &lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L_x = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; ainsi que sa transposée : &amp;lt;math&amp;gt;&lt;br /&gt;
L_y = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; -1 &amp;amp; -1 \\&lt;br /&gt;
 0 &amp;amp; 0 &amp;amp; 0 \\&lt;br /&gt;
+1 &amp;amp; +1 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Convoluer ces deux filtres sur l'image permet de détecter respectivement les contours verticaux et horizontaux.&lt;br /&gt;
&lt;br /&gt;
D'après wikipedia [https://fr.wikipedia.org/wiki/D%C3%A9tection_de_contours], on obtient de meilleurs résultats en appliquant un filtre triangulaire, on introduit donc la matrice de Sobel :&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-2 &amp;amp; 0 &amp;amp; +2 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
On obtient le résultat suivant : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testOutline1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Pré-traitement : Flou Gaussien=====&lt;br /&gt;
&lt;br /&gt;
Afin de réduire significativement le nombre de contours, il est nécessaire d'effectuer un pré-traitement avant la détection de contours. On utilise généralement un flou gaussien afin de réduire les transitions lumineuses et ainsi réduire le nombre de contours. L’algorithme de flou gaussien repose également sur la convolution de matrices sauf qu'ici la matrice filtre est générée grâce à une fonction gaussienne paramétrée par '''Sigma''' qui va directement impacter le niveau de flou. Plus la matrice de filtrage est grande plus la qualité du résultat est meilleure, mais le temps d’exécution devient également plus grand.&lt;br /&gt;
&lt;br /&gt;
Voici la fonction de génération du filtre : &amp;lt;math&amp;gt;G(x,y) = \frac{1}{{2\pi \sigma^2}} e^{-\frac{x^2 + y^2}{2 \sigma^2}}&amp;lt;/math&amp;gt; où x et y correspondent aux indices de la cellule de la matrice.&lt;br /&gt;
&lt;br /&gt;
On obtient ce résultat :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testGaussianBlur.png]]&lt;br /&gt;
&lt;br /&gt;
On note un bien meilleur résultat. Cependant on remarque que les composantes horizontales ne sont pas correctement détectées il subsiste un problème avec le filtrage vertical que je n'ai pas réussi à identifier. De plus, il s'agit par sa suite d'éliminer les contours parasites ainsi que d'affiner le trait pour n'avoir plus qu'un pixel d'épaisseur.&lt;br /&gt;
&lt;br /&gt;
=====Post-traitement : Algorithme de Canny=====&lt;br /&gt;
&lt;br /&gt;
Afin d'obtenir un résultat exploitable il est nécessaire d'appliquer encore quelques traitements. Pour cela nous utilisons l’algorithme de Canny qui repose que celui de Sobel mais qui ajoute un algorithme de seuillage par hysteresis qui permet de retirer les contours secondaires et de ne garder que les contours connexes dans une seuil haut et un seuil bas définis. En outre, cette algorithme affine également le trait obtenu. Pour cet algorithme nous avons directement trouvé des sources libres de droits [http://www.tomgibara.com/computer-vision/canny-edge-detector] qui donne des résultats très corrects.&lt;br /&gt;
&lt;br /&gt;
Par exemple :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ou encore : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny2.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 5===&lt;br /&gt;
&lt;br /&gt;
*Établissement d'un protocole de transfert d'image basé sur les WebSockets&lt;br /&gt;
**Envoie d'un requête &amp;quot;send&amp;quot; par le client dans une trame websocket texte&lt;br /&gt;
**Réponse serveur 'Y' si aucun autre client tente d'envoyer une image simultanément, 'N' sinon&lt;br /&gt;
**Si et seulement si le client reçoit 'Y' il débute le transfert en envoyant la largeur et la longueur de l'image sur 4 octets, puis les données de l'image soit 4 valeurs pour chaque pixels (r,g,b,alpha)&lt;br /&gt;
**Le serveur renvoie 'D' une fois le transfert achevé (à l'avenir, le serveur renverra l'image après filtrage).&lt;br /&gt;
**A tout moment, le serveur peut renvoyer 'E' si une erreur est survenue (ex : paquets perdus, nombre incorrects de données)&lt;br /&gt;
*Ajout du support des logs au niveau serveur&lt;br /&gt;
**Impression sur la sortie standard des messages&lt;br /&gt;
**Formatage en fonction de la sévérité du log (info, warning, error...)&lt;br /&gt;
**Incrustation de la date et heure&lt;br /&gt;
**Possibilité de redirection dans une fichier, avec configuration (écriture à la suite d'un fichier existant, écrasement...)&lt;br /&gt;
**Le tout dans une classe Java flexible et réutilisable pour d'autres projets&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 6===&lt;br /&gt;
&lt;br /&gt;
*Installation de la librairie Java Pi4j sur la raspberry pi qui permet le contrôle des GPIO de celle-ci et notamment le port I²C (basé sur WiringPi)&lt;br /&gt;
*Amélioration coté serveur websocket&lt;br /&gt;
**Gestion de message plus longs (maximum des trames websockets soit 2^63 octets)&lt;br /&gt;
**Différenciation, à la réception de messages, des trames textes ou binaires des trames de contrôle comme les requête ping, pong ou de fermeture de connexion &lt;br /&gt;
**Ajout d'un mode de debug de trames &lt;br /&gt;
&lt;br /&gt;
===Semaine 7===&lt;br /&gt;
&lt;br /&gt;
*Améliorations du serveur WebSocket&lt;br /&gt;
**Gestion de la fragmentation TCP&lt;br /&gt;
**Gestion de la fragmentation WebSocket&lt;br /&gt;
**Gestion des requêtes ping envoyés par le client en renvoyant une trames de contrôle pong afin de maintenir la connexion&lt;br /&gt;
**Gestion des déconnexion de clients afin d'optimiser le serveur&lt;br /&gt;
**Amélioration de l'émission de messages en augmentant la taille maximale pouvant être émise (2^63 octets)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A ce stade du développement, le client et le serveur sont opérationnels et peuvent s'échanger des messages ainsi que des images que le serveur traite pour extraire les contours.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 8===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Montage projecteur&lt;br /&gt;
**Intégralité des composants fixés par vis dans le boîtier ABS&lt;br /&gt;
**Fusion des alimentations&lt;br /&gt;
**Présence d'une led témoin de mise en tension&lt;br /&gt;
**Position laser réglable grâce à une vis&lt;br /&gt;
**Présence d'un switch à bascule pour allumer et éteindre le laser&lt;br /&gt;
**Isolation et vérification des composants&lt;br /&gt;
**Tests empiriques de température et de fonctionnement des lasers et galvanomètres&lt;br /&gt;
&lt;br /&gt;
Le montage boîtier est donc terminé et s’alimente en 230V par intermédiaire d'un câble secteur avec connecteur C14. Le résultat s'avère plutôt compact. Les quelques tests de températures ont montrés que malgré le manque d'espace la température globale du boîtier ne dépasse pas les 50°C pendant plus d'une heure de fonctionnement. L'intégralité des connexions sont isolées avec de la gaine thermodynamique et les zones &amp;quot;sensibles&amp;quot; sont correctement vérifiés ainsi que protégées avec de la matière isolante.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:proj1.jpg|400px|thumb|left|Boîtier après perçage]]] [[Fichier:proj2.jpg|400px|thumb|center|Boîtier finalisé]] [[Fichier:proj3.jpg|400px|thumb|left|Projecteur en fonctionnement]]&lt;br /&gt;
&lt;br /&gt;
*Page web et serveur WebSocket&lt;br /&gt;
**Ajout d'un bouton &amp;quot;reboot&amp;quot; et &amp;quot;shutdown&amp;quot; qui permettent respectivement de redémarrer et d'éteindre la Raspberry directement à partir de la page web&lt;br /&gt;
&lt;br /&gt;
===Semaine 9===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 10===&lt;br /&gt;
&lt;br /&gt;
==A faire==&lt;br /&gt;
&lt;br /&gt;
MAJ 26 mars &lt;br /&gt;
&lt;br /&gt;
*Client websocket et page web&lt;br /&gt;
**Mise en page CSS&lt;br /&gt;
**Ajout canvas pour prévisualisation image projeté&lt;br /&gt;
**Ajout &amp;quot;slider&amp;quot; pour régler niveau du flou Gaussien DOUBLE&lt;br /&gt;
**Ajout slider pour de finir amplitude de la projection&lt;br /&gt;
**Afficher statut de connexion&lt;br /&gt;
**Ajout message de confirmation quand le serveur quitte ou relance&lt;br /&gt;
**Ajout boutons &amp;quot;projeter&amp;quot; &amp;quot;centrer&amp;quot; &amp;quot;eteindre&amp;quot;&lt;br /&gt;
**Gestion de plusieurs images avec délai&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Serveur WebSocket&lt;br /&gt;
**Ajout fonctionnalité envoi image de prévisualisation&lt;br /&gt;
&lt;br /&gt;
*RaspberryPi&lt;br /&gt;
**Utilisation d'un serveur bind9 pour éviter de taper IP&lt;br /&gt;
&lt;br /&gt;
*Détection de contours&lt;br /&gt;
**Implémentation algorithme de tri de la plus courte disance&lt;br /&gt;
&lt;br /&gt;
*Commande galvanomêtre&lt;br /&gt;
**Utilisation API I²C&lt;br /&gt;
**Fonction de transfert position-&amp;gt;angle-&amp;gt;tension&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;br /&gt;
&lt;br /&gt;
==Bibliographie==&lt;br /&gt;
&lt;br /&gt;
http://www.ebay.com/itm/20KPPS-30KPPS-laser-scanning-galvo-scanner-ILDA-Closed-Loop-max-30kpps-for-laser-/261517002270?hash=item3ce3a0c61e&lt;br /&gt;
&lt;br /&gt;
https://icn.fenelonlille.org/mediawiki/index.php/Projet_ICN_commun_2016/2017&lt;br /&gt;
&lt;br /&gt;
https://www.g33k-zone.org/post/2016/05/11/Configurer-le-Raspberry-Pi-en-point-d-acc%C3%A8s-Wifi&lt;br /&gt;
&lt;br /&gt;
http://stackoverflow.com/questions/22087076/how-to-make-a-simple-image-upload-using-javascript-html&lt;br /&gt;
&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_a_WebSocket_server_in_Java&lt;br /&gt;
&lt;br /&gt;
export http_proxy=http://proxy.polytech-lille.fr:3128&lt;/div&gt;</summary>
		<author><name>Mtrimbur</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=Fichier:Proj2.jpg&amp;diff=40822</id>
		<title>Fichier:Proj2.jpg</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=Fichier:Proj2.jpg&amp;diff=40822"/>
				<updated>2017-03-27T17:53:48Z</updated>
		
		<summary type="html">&lt;p&gt;Mtrimbur : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Mtrimbur</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=Fichier:Proj1.jpg&amp;diff=40821</id>
		<title>Fichier:Proj1.jpg</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=Fichier:Proj1.jpg&amp;diff=40821"/>
				<updated>2017-03-27T17:52:34Z</updated>
		
		<summary type="html">&lt;p&gt;Mtrimbur : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Mtrimbur</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=40820</id>
		<title>IMA4 2016/2017 P39</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=40820"/>
				<updated>2017-03-27T17:52:14Z</updated>
		
		<summary type="html">&lt;p&gt;Mtrimbur : /* Semaine 8 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
===Contexte===&lt;br /&gt;
&lt;br /&gt;
Le laser est une technologie largement utilisé de nos jours dans de diverses applications. En effet, on retrouve cette technologie dans le domaine médical notamment pour la chirurgie oculaire ou encore dans industrie avec la découpe laser ou la soudure au laser.&lt;br /&gt;
&lt;br /&gt;
Le laser est une émission de photons produit par excitation d'un milieu amplificateur (ex : CO2), le rayonnement produit est unidirectionnel et monochromatique. Ce sont ces propriétés que nous allons exploiter afin réaliser un projecteur laser qui mis en mouvement est capable de dessiner des formes sur une surface à l'instar de systèmes existants utilisés pour des effets lumineux lors de festivités.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
L'objectif du projet est de créer un système de projection laser à plusieurs couleurs (au minimum deux) avec une application web pour programmer les formes à dessiner afin d'agrémenter des compétitions de gymnastique rythmique.&lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
Le projet consiste à réaliser avec des lasers des figures géométriques par l'intermédiaire d'un système galvanométrique. &lt;br /&gt;
&lt;br /&gt;
Notre premier travail sera de concevoir la partie projection. Pour cela, nous devrons aligner les lasers et les galvanomètres. En effet, ces derniers posséderont des miroirs à l'extrémité, ainsi les miroirs changeront d'inclinaison suivant le courant traversant les galvanomètres (similaire à l'image ci-contre). Il nous faudra également créer un système d'alimentation qui à partir d'une même source (réseau 230 V) sera capable d'alimenter les lasers et les galvanomètres ainsi qu'une Arduino et une Raspberry Pi.&lt;br /&gt;
[[File:Scanhead.jpeg|thumb]]&lt;br /&gt;
&lt;br /&gt;
Ensuite nous nous intéresserons à l'utilisation d'un système embarqué pour contrôler les galvanomètres et donc dessiner avec les lasers sur un plan 2D. En effet, le laser restera toujours fixe, seuls les galvanomètres, et donc les miroirs bougeront. Les galvanomètres étant contrôlés en courant il faudra réaliser une interface électronique pour convertir une commande en tension en commande de courant. La commande en tension sera assuré par une carte Arduino. Nous n'utiliserons qu'une seule paire de galvanomètres pour les deux laser. Il faudra donc multiplexer les deux faisceaux. La programmation des formes à effectuer, se fera par l'intermédiaire d'une application web PHP hébergée sur une RaspberryPi qui permettra de récupérer une image, d'y appliquer divers traitements et filtres afin d'en extraire les contours, et de calculer les commandes pour positionner les galvanomètres. Un serveur WebSocket également hébergé sur la RaspberryPi servira d'interface entre l'application web et L'arduino qui sera connecté via une liaison série sur la raspberryPI.&lt;br /&gt;
&lt;br /&gt;
Comme animation de test, nous dessinerons le contour d'une gymnaste avec une couleur et son ballon d'une autre couleur. La gymnaste devra lancer son ballon, réaliser quelques difficultés et récupérer son ballon.&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
Nous utiliserons comme matériels :&lt;br /&gt;
*Deux lasers de différentes couleurs&lt;br /&gt;
*Une paire de galvanomètres à miroir&lt;br /&gt;
*Arduino&lt;br /&gt;
*Raspberry Pi3&lt;br /&gt;
*Alimentation 230V/5V 1A [http://www.miniinthebox.com/fr/dual-usb-eu-prise-murale-5v-2a-voyage-adaptateur-chargeur-d-alimentation-pour-iphone7-6-xiaomi-samsung-et-autre-telephone-portable_p5410410.html?currency=EUR&amp;amp;litb_from=paid_adwords_shopping&amp;amp;sku=429_6917%7C752_20648&amp;amp;utm_source=google_shopping&amp;amp;utm_medium=cpc&amp;amp;adword_mt=&amp;amp;adword_ct=138705676724&amp;amp;adword_kw=&amp;amp;adword_pos=1o5&amp;amp;adword_pl=&amp;amp;adword_net=g&amp;amp;adword_tar=&amp;amp;adw_src_id=9653316068_661261352_33588296076_aud-79897721311:pla-256966386459&amp;amp;gclid=Cj0KEQiA_KvEBRCtzNil4-KR-LIBEiQAmgekFxxKjJJWBYCJlDZEa3Ke_2_WR0DzGVbz-jaCZHVIBoMaAvld8P8HAQ]&lt;br /&gt;
*Drivers galvanomètres x2&lt;br /&gt;
*Alimentation laser&lt;br /&gt;
*Lunette de sécurité x2 [https://www.amazon.fr/Uvex-S1933X-Eyewear-SCTOrange-Anti-Fog/dp/B000USRG90/ref=sr_1_1?ie=UTF8&amp;amp;qid=1485441383&amp;amp;sr=8-1&amp;amp;keywords=uvex+s1933x]&lt;br /&gt;
*Boitier ABS [http://fr.farnell.com/multicomp/g3118/boitier-abs-240x120x60mm-ip65/dp/1526656]&lt;br /&gt;
*DAC 4 canaux, avec interface I²C [https://www.adafruit.com/products/1083]&lt;br /&gt;
*Connecteur C14 [http://www.conrad.fr/ce/fr/product/715001/Connecteur-secteur-C14-Embase-male-verticale-715001-Nombre-de-poles-2-PE-10-A-noir-1-pcs/?ref=detview1&amp;amp;rt=detview1&amp;amp;rb=1]&lt;br /&gt;
*Câble secteur&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Logiciel :&lt;br /&gt;
&lt;br /&gt;
*Serveur web : Apache2, HTML5, PHP5, CSS&lt;br /&gt;
*Base de donnée : MySQL&lt;br /&gt;
*Serveur WebSocket : JQuerry, websocket&lt;br /&gt;
*Arduino : IDE Arduino&lt;br /&gt;
&lt;br /&gt;
===Calendrier prévisionnel===&lt;br /&gt;
&lt;br /&gt;
====Liste des tâches à effectuer====&lt;br /&gt;
Les différentes tâches à effectuer sont :&lt;br /&gt;
*Partie préliminaire : étude de fonctionnement des galvanomètres&lt;br /&gt;
**Déterminer comment est effectuée la commande des galvanomètres (protocole, tension...)&lt;br /&gt;
**Effectuer des tests avec l'Arduino ou la Raspberry Pi&lt;br /&gt;
**Effectuer des tests avec une LED à la place du laser &lt;br /&gt;
*Partie projection&lt;br /&gt;
**Fixer les lasers&lt;br /&gt;
**Aligner les lasers et les galvanomètres&lt;br /&gt;
**Créer le système d'alimentation&lt;br /&gt;
**Création d'un boitier&lt;br /&gt;
*Partie système embarqué&lt;br /&gt;
**Asservissement des galvanomètres avec l'Arduino&lt;br /&gt;
**Système électronique de commande en courant pour les galvanomètres&lt;br /&gt;
*Interface Web&lt;br /&gt;
**Installation et configuration Apache2&lt;br /&gt;
**Création d'une interface graphique simple&lt;br /&gt;
**Implémentation d'algorithmes de traitement d'image&lt;br /&gt;
**Mise en forme avec des CSS&lt;br /&gt;
**Sytème d'authentification avec mot de passe&lt;br /&gt;
**Utilisation d'une base de données pour enregistrer toutes les images déjà utilisés afin de les réutiliser&lt;br /&gt;
*Serveur Web Socket&lt;br /&gt;
**Récupération des données de l'interface web&lt;br /&gt;
**Mise en place de la liaison série avec l'Arduino&lt;br /&gt;
&lt;br /&gt;
====Calendrier====&lt;br /&gt;
Répartition du temps consacré au projet (240h) :&lt;br /&gt;
*Partie projection : 80h&lt;br /&gt;
*Partie système embarqué : 40h&lt;br /&gt;
*Partie interface web et websocket: 120h&lt;br /&gt;
&lt;br /&gt;
==Feuille d'heures==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!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&lt;br /&gt;
|-&lt;br /&gt;
| Définition cahier des charges &lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 14&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|38&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Finalisation du cahier des charges avec les responsables&lt;br /&gt;
&lt;br /&gt;
*Acquisition de matériels :&lt;br /&gt;
**Projecteur Laser&lt;br /&gt;
**Galvanomètres&lt;br /&gt;
**Alimentation des galvanomètres&lt;br /&gt;
&lt;br /&gt;
*Listage du matériels à acquérir :&lt;br /&gt;
**Lunettes de sécurité&lt;br /&gt;
**DAC&lt;br /&gt;
**Alimentation 230V/5V 1A&lt;br /&gt;
** Boitier ABS &lt;br /&gt;
**...&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
*Obtention de l'arduino et de la raspberryPI&lt;br /&gt;
&lt;br /&gt;
*Démontage du projecteur laser&lt;br /&gt;
**Deux lasers de classe 3b (vert et rouge)&lt;br /&gt;
**Circuit d'alimentation des deux lasers&lt;br /&gt;
&lt;br /&gt;
*Initialisation du port série de la raspberryPI&lt;br /&gt;
**Modification du fichier ''config.txt'' dans la partition boot&lt;br /&gt;
**Ajout d'une ligne autorisant la communication série ('''enable_uart=1''')&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
*Installation du serveur apache sur la raspberryPI&lt;br /&gt;
**Modification du fichier ''/etc/network/interfaces'' (Static, Address, Netmask, Gateway)&lt;br /&gt;
**Modification du fichier ''/etc/resolv.conf'' (Adresse du serveur)&lt;br /&gt;
**Utilisation d'un proxy pour la récupération outils de programmation (Apache2, Php5)&lt;br /&gt;
&lt;br /&gt;
*Mise en place du point d’accès wifi de la raspberryPI&lt;br /&gt;
**Récupération des logiciels nécessaires (dnsmasq, hostapd)&lt;br /&gt;
**Mise en place d'une adresse IP statique pour le point d'accès par l'intermédiaire du fichier ''/etc/dhcpcd.conf''&lt;br /&gt;
**Désactivation de la négociation automatique de bail dans le fichier ''/etc/network/interfaces''&lt;br /&gt;
**Configuration du logiciel hostapd ''/etc/hostapd/hostapd.conf''&lt;br /&gt;
**Activation du démarrage automatique du point d'accès ''/etc/default/hostapd''&lt;br /&gt;
**Configuration du serveur DNS par ''/etc/dnsmasq.conf''&lt;br /&gt;
&lt;br /&gt;
*Instauration de la page d'accueil de l'interface web à l'adresse ''192.168.3.1''&lt;br /&gt;
**Téléversement de fichiers images sur la page web et affichage de celle-ci&lt;br /&gt;
**Voyant de confirmation du bon fonctionnement du serveur web&lt;br /&gt;
&lt;br /&gt;
*Développement du serveur websocket&lt;br /&gt;
&lt;br /&gt;
Le développement du serveur websocket, initialement prévu en C (il était prévu de reprendre les sources utilisées l'année précédente dans le cadre des projet IMA3 SC), a finalement été réalisé en JAVA pour plusieurs raisons.&lt;br /&gt;
Premièrement, un seul programme met en œuvre le serveur websocket, les divers traitements d'image, ainsi que les contrôles des galvanomètres (par l'intermédiaire des DAC) via la liaison I²C de la Raspberry Pi. Le langage JAVA fournit nativement des bibliothèques d'objets pour manipuler assez simplement des images, il existe également des librairies pour contrôler le port GPIO de la Raspberry et il était également intéressant de travailler avec un langage de plus haut niveau que le C.&lt;br /&gt;
En outre, la totale portabilité de ce langage nous permet de travailler sur n'importe quelle machine et ensuite transférer notre programme sur la Raspberry Pi et l’exécuter sans même repasser par une phase de compilation. Et finalement, c'est le langage que nous étudions actuellement en cours de programmation orientée objet, ce qui permet de nous perfectionner.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Serveur WebSocket====&lt;br /&gt;
&lt;br /&gt;
N'ayant pas trouvé d'API WebSocket en Java satisfaisante (qui ne nécessitent pas l'installation et la configuration de nombreux outils additionnels), j'ai estimé plus commode et plus formateur de développer notre propre serveur WebSocket en se basant sur les librairies sockets de Java avec l'aide d'une documentation assez exhaustive [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers].&lt;br /&gt;
&lt;br /&gt;
Les WebSockets désignent à la fois un protocole réseau qui étend le protocole TCP ainsi qu'une API du World Wide Web. Nous nous en servons afin d'établir une communication asynchrone et bidirectionnelle entre un navigateur web et le serveur, notamment pour envoyer l'image à projeter. L’implémentation du serveur repose sur plusieurs étapes.&lt;br /&gt;
&lt;br /&gt;
1) Connexion d'un client &lt;br /&gt;
&lt;br /&gt;
2) Handshake : permet de faire le lien entre le protocole HTTP et WS. Le client envoie une requête HTTP demandant un upgrade de la connexion en protocole WS et le serveur répond en configurant la connexion (détail dans la documentation [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers]).&lt;br /&gt;
&lt;br /&gt;
3) Réception et décodage des messages : le serveurs reçoit des trames brutes, on extrait donc la taille du message ainsi que le message. De plus, les données son encodées (cryptage XOR) par un masque qui doit également être extrait.&lt;br /&gt;
&lt;br /&gt;
4) Fermeture de la communication.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le serveur supporte le multi-client il est donc nécessaire qu'il effectue ces étapes en &amp;quot;parallèle&amp;quot;. Nous utilisons donc les threads ou fils d’exécution. Un thread est donc responsable d'attendre qu'un nouveau client se connecte et effectue le &amp;quot;handshake&amp;quot;, il crée ensuite un thread associé à ce client afin d'établir un canal de communication. Il y a donc au moins un thread par client. Par la suite il faudra également implémenter une déconnexion automatique d'un client notamment après un timeout.&lt;br /&gt;
&lt;br /&gt;
Exemple d’exécution du serveur avec deux clients qui se connectent et envoient un message : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testServeur.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Les clients sont des navigateurs web. Pour les tests nous avons repris les exemples utilisés dans le cadre das projets IMA3 SC avec le titre de la page HTML qui se colore en vert lorsque le client est connecté, et un champ de saisie pour envoyer des messages au serveur : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testClient.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 4===&lt;br /&gt;
&lt;br /&gt;
*Mise en place d’algorithmes de traitement d'image&lt;br /&gt;
&lt;br /&gt;
====Détection de contour====&lt;br /&gt;
&lt;br /&gt;
L'objectif de notre projet est de pouvoir projeter n'importe quelle image envoyé grâce à l'application web. Pour cela nous allons tracer à une vitesse élevée les contours de l'image sur par exemple un mur grâce au laser. Il est donc nécessaire de détecter les contours de l'image grâce à plusieurs traitements.&lt;br /&gt;
&lt;br /&gt;
=====Conversion en niveau de gris=====&lt;br /&gt;
&lt;br /&gt;
Une des étapes préliminaires pour effectuer la détection de contour est de convertir l'image couleur en niveau de gris. Pour cela l'algorithme est simple : il suffit pour chaque pixel de l'image d'effectuer la moyenne des composantes rouge, verte, bleu de chaque pixel. En effet, si l'on considère une image matricielle (l'image est considérée comme un tableau à deux dimensions avec chaque case qui contient la couleur du pixel), chaque pixel contient les composantes RGB codées sur un octet. La couleur gris correspond aux composantes RGB égales. Le niveau de gris est donc codé de 0 à 255, avec 0 donnant du noir et 255 du blanc. &lt;br /&gt;
&lt;br /&gt;
Voici le résultat obtenu : [[Fichier:testGrayScale.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Filtre de Prewit et Sobel=====&lt;br /&gt;
&lt;br /&gt;
Un contour est défini par un changement brutal d'intensité lumineuse, il s'agit donc de détecter selon plusieurs directions (au moins 2) ces changements. Il existe de nombreuses techniques afin de détecter les contours d'une image (gradient, Laplacien). L'une des techniques avec un rapport efficacité/temps d'exécution correct repose sur les algorithmes de Prewit ou Sobel. L'algorithme repose sur la convolution de matrices.&lt;br /&gt;
Cela consiste à appliquer sur chaque pixel de l'image la matrice de Prewit définie comme &lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L_x = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; ainsi que sa transposée : &amp;lt;math&amp;gt;&lt;br /&gt;
L_y = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; -1 &amp;amp; -1 \\&lt;br /&gt;
 0 &amp;amp; 0 &amp;amp; 0 \\&lt;br /&gt;
+1 &amp;amp; +1 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Convoluer ces deux filtres sur l'image permet de détecter respectivement les contours verticaux et horizontaux.&lt;br /&gt;
&lt;br /&gt;
D'après wikipedia [https://fr.wikipedia.org/wiki/D%C3%A9tection_de_contours], on obtient de meilleurs résultats en appliquant un filtre triangulaire, on introduit donc la matrice de Sobel :&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-2 &amp;amp; 0 &amp;amp; +2 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
On obtient le résultat suivant : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testOutline1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Pré-traitement : Flou Gaussien=====&lt;br /&gt;
&lt;br /&gt;
Afin de réduire significativement le nombre de contours, il est nécessaire d'effectuer un pré-traitement avant la détection de contours. On utilise généralement un flou gaussien afin de réduire les transitions lumineuses et ainsi réduire le nombre de contours. L’algorithme de flou gaussien repose également sur la convolution de matrices sauf qu'ici la matrice filtre est générée grâce à une fonction gaussienne paramétrée par '''Sigma''' qui va directement impacter le niveau de flou. Plus la matrice de filtrage est grande plus la qualité du résultat est meilleure, mais le temps d’exécution devient également plus grand.&lt;br /&gt;
&lt;br /&gt;
Voici la fonction de génération du filtre : &amp;lt;math&amp;gt;G(x,y) = \frac{1}{{2\pi \sigma^2}} e^{-\frac{x^2 + y^2}{2 \sigma^2}}&amp;lt;/math&amp;gt; où x et y correspondent aux indices de la cellule de la matrice.&lt;br /&gt;
&lt;br /&gt;
On obtient ce résultat :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testGaussianBlur.png]]&lt;br /&gt;
&lt;br /&gt;
On note un bien meilleur résultat. Cependant on remarque que les composantes horizontales ne sont pas correctement détectées il subsiste un problème avec le filtrage vertical que je n'ai pas réussi à identifier. De plus, il s'agit par sa suite d'éliminer les contours parasites ainsi que d'affiner le trait pour n'avoir plus qu'un pixel d'épaisseur.&lt;br /&gt;
&lt;br /&gt;
=====Post-traitement : Algorithme de Canny=====&lt;br /&gt;
&lt;br /&gt;
Afin d'obtenir un résultat exploitable il est nécessaire d'appliquer encore quelques traitements. Pour cela nous utilisons l’algorithme de Canny qui repose que celui de Sobel mais qui ajoute un algorithme de seuillage par hysteresis qui permet de retirer les contours secondaires et de ne garder que les contours connexes dans une seuil haut et un seuil bas définis. En outre, cette algorithme affine également le trait obtenu. Pour cet algorithme nous avons directement trouvé des sources libres de droits [http://www.tomgibara.com/computer-vision/canny-edge-detector] qui donne des résultats très corrects.&lt;br /&gt;
&lt;br /&gt;
Par exemple :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ou encore : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny2.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 5===&lt;br /&gt;
&lt;br /&gt;
*Établissement d'un protocole de transfert d'image basé sur les WebSockets&lt;br /&gt;
**Envoie d'un requête &amp;quot;send&amp;quot; par le client dans une trame websocket texte&lt;br /&gt;
**Réponse serveur 'Y' si aucun autre client tente d'envoyer une image simultanément, 'N' sinon&lt;br /&gt;
**Si et seulement si le client reçoit 'Y' il débute le transfert en envoyant la largeur et la longueur de l'image sur 4 octets, puis les données de l'image soit 4 valeurs pour chaque pixels (r,g,b,alpha)&lt;br /&gt;
**Le serveur renvoie 'D' une fois le transfert achevé (à l'avenir, le serveur renverra l'image après filtrage).&lt;br /&gt;
**A tout moment, le serveur peut renvoyer 'E' si une erreur est survenue (ex : paquets perdus, nombre incorrects de données)&lt;br /&gt;
*Ajout du support des logs au niveau serveur&lt;br /&gt;
**Impression sur la sortie standard des messages&lt;br /&gt;
**Formatage en fonction de la sévérité du log (info, warning, error...)&lt;br /&gt;
**Incrustation de la date et heure&lt;br /&gt;
**Possibilité de redirection dans une fichier, avec configuration (écriture à la suite d'un fichier existant, écrasement...)&lt;br /&gt;
**Le tout dans une classe Java flexible et réutilisable pour d'autres projets&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 6===&lt;br /&gt;
&lt;br /&gt;
*Installation de la librairie Java Pi4j sur la raspberry pi qui permet le contrôle des GPIO de celle-ci et notamment le port I²C (basé sur WiringPi)&lt;br /&gt;
*Amélioration coté serveur websocket&lt;br /&gt;
**Gestion de message plus longs (maximum des trames websockets soit 2^63 octets)&lt;br /&gt;
**Différenciation, à la réception de messages, des trames textes ou binaires des trames de contrôle comme les requête ping, pong ou de fermeture de connexion &lt;br /&gt;
**Ajout d'un mode de debug de trames &lt;br /&gt;
&lt;br /&gt;
===Semaine 7===&lt;br /&gt;
&lt;br /&gt;
*Améliorations du serveur WebSocket&lt;br /&gt;
**Gestion de la fragmentation TCP&lt;br /&gt;
**Gestion de la fragmentation WebSocket&lt;br /&gt;
**Gestion des requêtes ping envoyés par le client en renvoyant une trames de contrôle pong afin de maintenir la connexion&lt;br /&gt;
**Gestion des déconnexion de clients afin d'optimiser le serveur&lt;br /&gt;
**Amélioration de l'émission de messages en augmentant la taille maximale pouvant être émise (2^63 octets)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A ce stade du développement, le client et le serveur sont opérationnels et peuvent s'échanger des messages ainsi que des images que le serveur traite pour extraire les contours.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 8===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Montage projecteur&lt;br /&gt;
**Intégralité des composants fixés par vis dans le boîtier ABS&lt;br /&gt;
**Fusion des alimentations&lt;br /&gt;
**Présence d'une led témoin de mise en tension&lt;br /&gt;
**Position laser réglable grâce à une vis&lt;br /&gt;
**Présence d'un switch à bascule pour allumer et éteindre le laser&lt;br /&gt;
**Isolation et vérification des composants&lt;br /&gt;
**Tests empiriques de température et de fonctionnement des lasers et galvanomètres&lt;br /&gt;
&lt;br /&gt;
Le montage boîtier est donc terminé et s’alimente en 230V par intermédiaire d'un câble secteur avec connecteur C14. Le résultat s'avère plutôt compact. Les quelques tests de températures ont montrés que malgré le manque d'espace la température globale du boîtier ne dépasse pas les 50°C pendant plus d'une heure de fonctionnement. L'intégralité des connexions sont isolées avec de la gaine thermodynamique et les zones &amp;quot;sensibles&amp;quot; sont correctement vérifiés ainsi que protégées avec de la matière isolante.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:proj1.jpg]] [[Fichier:proj2.jpg]] [[Fichier:proj3.jpg]]&lt;br /&gt;
&lt;br /&gt;
*Page web et serveur WebSocket&lt;br /&gt;
**Ajout d'un bouton &amp;quot;reboot&amp;quot; et &amp;quot;shutdown&amp;quot; qui permettent respectivement de redémarrer et d'éteindre la Raspberry directement à partir de la page web&lt;br /&gt;
&lt;br /&gt;
===Semaine 9===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 10===&lt;br /&gt;
&lt;br /&gt;
==A faire==&lt;br /&gt;
&lt;br /&gt;
MAJ 26 mars &lt;br /&gt;
&lt;br /&gt;
*Client websocket et page web&lt;br /&gt;
**Mise en page CSS&lt;br /&gt;
**Ajout canvas pour prévisualisation image projeté&lt;br /&gt;
**Ajout &amp;quot;slider&amp;quot; pour régler niveau du flou Gaussien DOUBLE&lt;br /&gt;
**Ajout slider pour de finir amplitude de la projection&lt;br /&gt;
**Afficher statut de connexion&lt;br /&gt;
**Ajout message de confirmation quand le serveur quitte ou relance&lt;br /&gt;
**Ajout boutons &amp;quot;projeter&amp;quot; &amp;quot;centrer&amp;quot; &amp;quot;eteindre&amp;quot;&lt;br /&gt;
**Gestion de plusieurs images avec délai&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Serveur WebSocket&lt;br /&gt;
**Ajout fonctionnalité envoi image de prévisualisation&lt;br /&gt;
&lt;br /&gt;
*RaspberryPi&lt;br /&gt;
**Utilisation d'un serveur bind9 pour éviter de taper IP&lt;br /&gt;
&lt;br /&gt;
*Détection de contours&lt;br /&gt;
**Implémentation algorithme de tri de la plus courte disance&lt;br /&gt;
&lt;br /&gt;
*Commande galvanomêtre&lt;br /&gt;
**Utilisation API I²C&lt;br /&gt;
**Fonction de transfert position-&amp;gt;angle-&amp;gt;tension&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;br /&gt;
&lt;br /&gt;
==Bibliographie==&lt;br /&gt;
&lt;br /&gt;
http://www.ebay.com/itm/20KPPS-30KPPS-laser-scanning-galvo-scanner-ILDA-Closed-Loop-max-30kpps-for-laser-/261517002270?hash=item3ce3a0c61e&lt;br /&gt;
&lt;br /&gt;
https://icn.fenelonlille.org/mediawiki/index.php/Projet_ICN_commun_2016/2017&lt;br /&gt;
&lt;br /&gt;
https://www.g33k-zone.org/post/2016/05/11/Configurer-le-Raspberry-Pi-en-point-d-acc%C3%A8s-Wifi&lt;br /&gt;
&lt;br /&gt;
http://stackoverflow.com/questions/22087076/how-to-make-a-simple-image-upload-using-javascript-html&lt;br /&gt;
&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_a_WebSocket_server_in_Java&lt;br /&gt;
&lt;br /&gt;
export http_proxy=http://proxy.polytech-lille.fr:3128&lt;/div&gt;</summary>
		<author><name>Mtrimbur</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=40818</id>
		<title>IMA4 2016/2017 P39</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=40818"/>
				<updated>2017-03-27T17:36:58Z</updated>
		
		<summary type="html">&lt;p&gt;Mtrimbur : /* Avancement du Projet */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
===Contexte===&lt;br /&gt;
&lt;br /&gt;
Le laser est une technologie largement utilisé de nos jours dans de diverses applications. En effet, on retrouve cette technologie dans le domaine médical notamment pour la chirurgie oculaire ou encore dans industrie avec la découpe laser ou la soudure au laser.&lt;br /&gt;
&lt;br /&gt;
Le laser est une émission de photons produit par excitation d'un milieu amplificateur (ex : CO2), le rayonnement produit est unidirectionnel et monochromatique. Ce sont ces propriétés que nous allons exploiter afin réaliser un projecteur laser qui mis en mouvement est capable de dessiner des formes sur une surface à l'instar de systèmes existants utilisés pour des effets lumineux lors de festivités.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
L'objectif du projet est de créer un système de projection laser à plusieurs couleurs (au minimum deux) avec une application web pour programmer les formes à dessiner afin d'agrémenter des compétitions de gymnastique rythmique.&lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
Le projet consiste à réaliser avec des lasers des figures géométriques par l'intermédiaire d'un système galvanométrique. &lt;br /&gt;
&lt;br /&gt;
Notre premier travail sera de concevoir la partie projection. Pour cela, nous devrons aligner les lasers et les galvanomètres. En effet, ces derniers posséderont des miroirs à l'extrémité, ainsi les miroirs changeront d'inclinaison suivant le courant traversant les galvanomètres (similaire à l'image ci-contre). Il nous faudra également créer un système d'alimentation qui à partir d'une même source (réseau 230 V) sera capable d'alimenter les lasers et les galvanomètres ainsi qu'une Arduino et une Raspberry Pi.&lt;br /&gt;
[[File:Scanhead.jpeg|thumb]]&lt;br /&gt;
&lt;br /&gt;
Ensuite nous nous intéresserons à l'utilisation d'un système embarqué pour contrôler les galvanomètres et donc dessiner avec les lasers sur un plan 2D. En effet, le laser restera toujours fixe, seuls les galvanomètres, et donc les miroirs bougeront. Les galvanomètres étant contrôlés en courant il faudra réaliser une interface électronique pour convertir une commande en tension en commande de courant. La commande en tension sera assuré par une carte Arduino. Nous n'utiliserons qu'une seule paire de galvanomètres pour les deux laser. Il faudra donc multiplexer les deux faisceaux. La programmation des formes à effectuer, se fera par l'intermédiaire d'une application web PHP hébergée sur une RaspberryPi qui permettra de récupérer une image, d'y appliquer divers traitements et filtres afin d'en extraire les contours, et de calculer les commandes pour positionner les galvanomètres. Un serveur WebSocket également hébergé sur la RaspberryPi servira d'interface entre l'application web et L'arduino qui sera connecté via une liaison série sur la raspberryPI.&lt;br /&gt;
&lt;br /&gt;
Comme animation de test, nous dessinerons le contour d'une gymnaste avec une couleur et son ballon d'une autre couleur. La gymnaste devra lancer son ballon, réaliser quelques difficultés et récupérer son ballon.&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
Nous utiliserons comme matériels :&lt;br /&gt;
*Deux lasers de différentes couleurs&lt;br /&gt;
*Une paire de galvanomètres à miroir&lt;br /&gt;
*Arduino&lt;br /&gt;
*Raspberry Pi3&lt;br /&gt;
*Alimentation 230V/5V 1A [http://www.miniinthebox.com/fr/dual-usb-eu-prise-murale-5v-2a-voyage-adaptateur-chargeur-d-alimentation-pour-iphone7-6-xiaomi-samsung-et-autre-telephone-portable_p5410410.html?currency=EUR&amp;amp;litb_from=paid_adwords_shopping&amp;amp;sku=429_6917%7C752_20648&amp;amp;utm_source=google_shopping&amp;amp;utm_medium=cpc&amp;amp;adword_mt=&amp;amp;adword_ct=138705676724&amp;amp;adword_kw=&amp;amp;adword_pos=1o5&amp;amp;adword_pl=&amp;amp;adword_net=g&amp;amp;adword_tar=&amp;amp;adw_src_id=9653316068_661261352_33588296076_aud-79897721311:pla-256966386459&amp;amp;gclid=Cj0KEQiA_KvEBRCtzNil4-KR-LIBEiQAmgekFxxKjJJWBYCJlDZEa3Ke_2_WR0DzGVbz-jaCZHVIBoMaAvld8P8HAQ]&lt;br /&gt;
*Drivers galvanomètres x2&lt;br /&gt;
*Alimentation laser&lt;br /&gt;
*Lunette de sécurité x2 [https://www.amazon.fr/Uvex-S1933X-Eyewear-SCTOrange-Anti-Fog/dp/B000USRG90/ref=sr_1_1?ie=UTF8&amp;amp;qid=1485441383&amp;amp;sr=8-1&amp;amp;keywords=uvex+s1933x]&lt;br /&gt;
*Boitier ABS [http://fr.farnell.com/multicomp/g3118/boitier-abs-240x120x60mm-ip65/dp/1526656]&lt;br /&gt;
*DAC 4 canaux, avec interface I²C [https://www.adafruit.com/products/1083]&lt;br /&gt;
*Connecteur C14 [http://www.conrad.fr/ce/fr/product/715001/Connecteur-secteur-C14-Embase-male-verticale-715001-Nombre-de-poles-2-PE-10-A-noir-1-pcs/?ref=detview1&amp;amp;rt=detview1&amp;amp;rb=1]&lt;br /&gt;
*Câble secteur&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Logiciel :&lt;br /&gt;
&lt;br /&gt;
*Serveur web : Apache2, HTML5, PHP5, CSS&lt;br /&gt;
*Base de donnée : MySQL&lt;br /&gt;
*Serveur WebSocket : JQuerry, websocket&lt;br /&gt;
*Arduino : IDE Arduino&lt;br /&gt;
&lt;br /&gt;
===Calendrier prévisionnel===&lt;br /&gt;
&lt;br /&gt;
====Liste des tâches à effectuer====&lt;br /&gt;
Les différentes tâches à effectuer sont :&lt;br /&gt;
*Partie préliminaire : étude de fonctionnement des galvanomètres&lt;br /&gt;
**Déterminer comment est effectuée la commande des galvanomètres (protocole, tension...)&lt;br /&gt;
**Effectuer des tests avec l'Arduino ou la Raspberry Pi&lt;br /&gt;
**Effectuer des tests avec une LED à la place du laser &lt;br /&gt;
*Partie projection&lt;br /&gt;
**Fixer les lasers&lt;br /&gt;
**Aligner les lasers et les galvanomètres&lt;br /&gt;
**Créer le système d'alimentation&lt;br /&gt;
**Création d'un boitier&lt;br /&gt;
*Partie système embarqué&lt;br /&gt;
**Asservissement des galvanomètres avec l'Arduino&lt;br /&gt;
**Système électronique de commande en courant pour les galvanomètres&lt;br /&gt;
*Interface Web&lt;br /&gt;
**Installation et configuration Apache2&lt;br /&gt;
**Création d'une interface graphique simple&lt;br /&gt;
**Implémentation d'algorithmes de traitement d'image&lt;br /&gt;
**Mise en forme avec des CSS&lt;br /&gt;
**Sytème d'authentification avec mot de passe&lt;br /&gt;
**Utilisation d'une base de données pour enregistrer toutes les images déjà utilisés afin de les réutiliser&lt;br /&gt;
*Serveur Web Socket&lt;br /&gt;
**Récupération des données de l'interface web&lt;br /&gt;
**Mise en place de la liaison série avec l'Arduino&lt;br /&gt;
&lt;br /&gt;
====Calendrier====&lt;br /&gt;
Répartition du temps consacré au projet (240h) :&lt;br /&gt;
*Partie projection : 80h&lt;br /&gt;
*Partie système embarqué : 40h&lt;br /&gt;
*Partie interface web et websocket: 120h&lt;br /&gt;
&lt;br /&gt;
==Feuille d'heures==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!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&lt;br /&gt;
|-&lt;br /&gt;
| Définition cahier des charges &lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 14&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|38&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Finalisation du cahier des charges avec les responsables&lt;br /&gt;
&lt;br /&gt;
*Acquisition de matériels :&lt;br /&gt;
**Projecteur Laser&lt;br /&gt;
**Galvanomètres&lt;br /&gt;
**Alimentation des galvanomètres&lt;br /&gt;
&lt;br /&gt;
*Listage du matériels à acquérir :&lt;br /&gt;
**Lunettes de sécurité&lt;br /&gt;
**DAC&lt;br /&gt;
**Alimentation 230V/5V 1A&lt;br /&gt;
** Boitier ABS &lt;br /&gt;
**...&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
*Obtention de l'arduino et de la raspberryPI&lt;br /&gt;
&lt;br /&gt;
*Démontage du projecteur laser&lt;br /&gt;
**Deux lasers de classe 3b (vert et rouge)&lt;br /&gt;
**Circuit d'alimentation des deux lasers&lt;br /&gt;
&lt;br /&gt;
*Initialisation du port série de la raspberryPI&lt;br /&gt;
**Modification du fichier ''config.txt'' dans la partition boot&lt;br /&gt;
**Ajout d'une ligne autorisant la communication série ('''enable_uart=1''')&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
*Installation du serveur apache sur la raspberryPI&lt;br /&gt;
**Modification du fichier ''/etc/network/interfaces'' (Static, Address, Netmask, Gateway)&lt;br /&gt;
**Modification du fichier ''/etc/resolv.conf'' (Adresse du serveur)&lt;br /&gt;
**Utilisation d'un proxy pour la récupération outils de programmation (Apache2, Php5)&lt;br /&gt;
&lt;br /&gt;
*Mise en place du point d’accès wifi de la raspberryPI&lt;br /&gt;
**Récupération des logiciels nécessaires (dnsmasq, hostapd)&lt;br /&gt;
**Mise en place d'une adresse IP statique pour le point d'accès par l'intermédiaire du fichier ''/etc/dhcpcd.conf''&lt;br /&gt;
**Désactivation de la négociation automatique de bail dans le fichier ''/etc/network/interfaces''&lt;br /&gt;
**Configuration du logiciel hostapd ''/etc/hostapd/hostapd.conf''&lt;br /&gt;
**Activation du démarrage automatique du point d'accès ''/etc/default/hostapd''&lt;br /&gt;
**Configuration du serveur DNS par ''/etc/dnsmasq.conf''&lt;br /&gt;
&lt;br /&gt;
*Instauration de la page d'accueil de l'interface web à l'adresse ''192.168.3.1''&lt;br /&gt;
**Téléversement de fichiers images sur la page web et affichage de celle-ci&lt;br /&gt;
**Voyant de confirmation du bon fonctionnement du serveur web&lt;br /&gt;
&lt;br /&gt;
*Développement du serveur websocket&lt;br /&gt;
&lt;br /&gt;
Le développement du serveur websocket, initialement prévu en C (il était prévu de reprendre les sources utilisées l'année précédente dans le cadre des projet IMA3 SC), a finalement été réalisé en JAVA pour plusieurs raisons.&lt;br /&gt;
Premièrement, un seul programme met en œuvre le serveur websocket, les divers traitements d'image, ainsi que les contrôles des galvanomètres (par l'intermédiaire des DAC) via la liaison I²C de la Raspberry Pi. Le langage JAVA fournit nativement des bibliothèques d'objets pour manipuler assez simplement des images, il existe également des librairies pour contrôler le port GPIO de la Raspberry et il était également intéressant de travailler avec un langage de plus haut niveau que le C.&lt;br /&gt;
En outre, la totale portabilité de ce langage nous permet de travailler sur n'importe quelle machine et ensuite transférer notre programme sur la Raspberry Pi et l’exécuter sans même repasser par une phase de compilation. Et finalement, c'est le langage que nous étudions actuellement en cours de programmation orientée objet, ce qui permet de nous perfectionner.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Serveur WebSocket====&lt;br /&gt;
&lt;br /&gt;
N'ayant pas trouvé d'API WebSocket en Java satisfaisante (qui ne nécessitent pas l'installation et la configuration de nombreux outils additionnels), j'ai estimé plus commode et plus formateur de développer notre propre serveur WebSocket en se basant sur les librairies sockets de Java avec l'aide d'une documentation assez exhaustive [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers].&lt;br /&gt;
&lt;br /&gt;
Les WebSockets désignent à la fois un protocole réseau qui étend le protocole TCP ainsi qu'une API du World Wide Web. Nous nous en servons afin d'établir une communication asynchrone et bidirectionnelle entre un navigateur web et le serveur, notamment pour envoyer l'image à projeter. L’implémentation du serveur repose sur plusieurs étapes.&lt;br /&gt;
&lt;br /&gt;
1) Connexion d'un client &lt;br /&gt;
&lt;br /&gt;
2) Handshake : permet de faire le lien entre le protocole HTTP et WS. Le client envoie une requête HTTP demandant un upgrade de la connexion en protocole WS et le serveur répond en configurant la connexion (détail dans la documentation [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers]).&lt;br /&gt;
&lt;br /&gt;
3) Réception et décodage des messages : le serveurs reçoit des trames brutes, on extrait donc la taille du message ainsi que le message. De plus, les données son encodées (cryptage XOR) par un masque qui doit également être extrait.&lt;br /&gt;
&lt;br /&gt;
4) Fermeture de la communication.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le serveur supporte le multi-client il est donc nécessaire qu'il effectue ces étapes en &amp;quot;parallèle&amp;quot;. Nous utilisons donc les threads ou fils d’exécution. Un thread est donc responsable d'attendre qu'un nouveau client se connecte et effectue le &amp;quot;handshake&amp;quot;, il crée ensuite un thread associé à ce client afin d'établir un canal de communication. Il y a donc au moins un thread par client. Par la suite il faudra également implémenter une déconnexion automatique d'un client notamment après un timeout.&lt;br /&gt;
&lt;br /&gt;
Exemple d’exécution du serveur avec deux clients qui se connectent et envoient un message : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testServeur.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Les clients sont des navigateurs web. Pour les tests nous avons repris les exemples utilisés dans le cadre das projets IMA3 SC avec le titre de la page HTML qui se colore en vert lorsque le client est connecté, et un champ de saisie pour envoyer des messages au serveur : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testClient.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 4===&lt;br /&gt;
&lt;br /&gt;
*Mise en place d’algorithmes de traitement d'image&lt;br /&gt;
&lt;br /&gt;
====Détection de contour====&lt;br /&gt;
&lt;br /&gt;
L'objectif de notre projet est de pouvoir projeter n'importe quelle image envoyé grâce à l'application web. Pour cela nous allons tracer à une vitesse élevée les contours de l'image sur par exemple un mur grâce au laser. Il est donc nécessaire de détecter les contours de l'image grâce à plusieurs traitements.&lt;br /&gt;
&lt;br /&gt;
=====Conversion en niveau de gris=====&lt;br /&gt;
&lt;br /&gt;
Une des étapes préliminaires pour effectuer la détection de contour est de convertir l'image couleur en niveau de gris. Pour cela l'algorithme est simple : il suffit pour chaque pixel de l'image d'effectuer la moyenne des composantes rouge, verte, bleu de chaque pixel. En effet, si l'on considère une image matricielle (l'image est considérée comme un tableau à deux dimensions avec chaque case qui contient la couleur du pixel), chaque pixel contient les composantes RGB codées sur un octet. La couleur gris correspond aux composantes RGB égales. Le niveau de gris est donc codé de 0 à 255, avec 0 donnant du noir et 255 du blanc. &lt;br /&gt;
&lt;br /&gt;
Voici le résultat obtenu : [[Fichier:testGrayScale.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Filtre de Prewit et Sobel=====&lt;br /&gt;
&lt;br /&gt;
Un contour est défini par un changement brutal d'intensité lumineuse, il s'agit donc de détecter selon plusieurs directions (au moins 2) ces changements. Il existe de nombreuses techniques afin de détecter les contours d'une image (gradient, Laplacien). L'une des techniques avec un rapport efficacité/temps d'exécution correct repose sur les algorithmes de Prewit ou Sobel. L'algorithme repose sur la convolution de matrices.&lt;br /&gt;
Cela consiste à appliquer sur chaque pixel de l'image la matrice de Prewit définie comme &lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L_x = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; ainsi que sa transposée : &amp;lt;math&amp;gt;&lt;br /&gt;
L_y = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; -1 &amp;amp; -1 \\&lt;br /&gt;
 0 &amp;amp; 0 &amp;amp; 0 \\&lt;br /&gt;
+1 &amp;amp; +1 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Convoluer ces deux filtres sur l'image permet de détecter respectivement les contours verticaux et horizontaux.&lt;br /&gt;
&lt;br /&gt;
D'après wikipedia [https://fr.wikipedia.org/wiki/D%C3%A9tection_de_contours], on obtient de meilleurs résultats en appliquant un filtre triangulaire, on introduit donc la matrice de Sobel :&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-2 &amp;amp; 0 &amp;amp; +2 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
On obtient le résultat suivant : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testOutline1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Pré-traitement : Flou Gaussien=====&lt;br /&gt;
&lt;br /&gt;
Afin de réduire significativement le nombre de contours, il est nécessaire d'effectuer un pré-traitement avant la détection de contours. On utilise généralement un flou gaussien afin de réduire les transitions lumineuses et ainsi réduire le nombre de contours. L’algorithme de flou gaussien repose également sur la convolution de matrices sauf qu'ici la matrice filtre est générée grâce à une fonction gaussienne paramétrée par '''Sigma''' qui va directement impacter le niveau de flou. Plus la matrice de filtrage est grande plus la qualité du résultat est meilleure, mais le temps d’exécution devient également plus grand.&lt;br /&gt;
&lt;br /&gt;
Voici la fonction de génération du filtre : &amp;lt;math&amp;gt;G(x,y) = \frac{1}{{2\pi \sigma^2}} e^{-\frac{x^2 + y^2}{2 \sigma^2}}&amp;lt;/math&amp;gt; où x et y correspondent aux indices de la cellule de la matrice.&lt;br /&gt;
&lt;br /&gt;
On obtient ce résultat :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testGaussianBlur.png]]&lt;br /&gt;
&lt;br /&gt;
On note un bien meilleur résultat. Cependant on remarque que les composantes horizontales ne sont pas correctement détectées il subsiste un problème avec le filtrage vertical que je n'ai pas réussi à identifier. De plus, il s'agit par sa suite d'éliminer les contours parasites ainsi que d'affiner le trait pour n'avoir plus qu'un pixel d'épaisseur.&lt;br /&gt;
&lt;br /&gt;
=====Post-traitement : Algorithme de Canny=====&lt;br /&gt;
&lt;br /&gt;
Afin d'obtenir un résultat exploitable il est nécessaire d'appliquer encore quelques traitements. Pour cela nous utilisons l’algorithme de Canny qui repose que celui de Sobel mais qui ajoute un algorithme de seuillage par hysteresis qui permet de retirer les contours secondaires et de ne garder que les contours connexes dans une seuil haut et un seuil bas définis. En outre, cette algorithme affine également le trait obtenu. Pour cet algorithme nous avons directement trouvé des sources libres de droits [http://www.tomgibara.com/computer-vision/canny-edge-detector] qui donne des résultats très corrects.&lt;br /&gt;
&lt;br /&gt;
Par exemple :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ou encore : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny2.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 5===&lt;br /&gt;
&lt;br /&gt;
*Établissement d'un protocole de transfert d'image basé sur les WebSockets&lt;br /&gt;
**Envoie d'un requête &amp;quot;send&amp;quot; par le client dans une trame websocket texte&lt;br /&gt;
**Réponse serveur 'Y' si aucun autre client tente d'envoyer une image simultanément, 'N' sinon&lt;br /&gt;
**Si et seulement si le client reçoit 'Y' il débute le transfert en envoyant la largeur et la longueur de l'image sur 4 octets, puis les données de l'image soit 4 valeurs pour chaque pixels (r,g,b,alpha)&lt;br /&gt;
**Le serveur renvoie 'D' une fois le transfert achevé (à l'avenir, le serveur renverra l'image après filtrage).&lt;br /&gt;
**A tout moment, le serveur peut renvoyer 'E' si une erreur est survenue (ex : paquets perdus, nombre incorrects de données)&lt;br /&gt;
*Ajout du support des logs au niveau serveur&lt;br /&gt;
**Impression sur la sortie standard des messages&lt;br /&gt;
**Formatage en fonction de la sévérité du log (info, warning, error...)&lt;br /&gt;
**Incrustation de la date et heure&lt;br /&gt;
**Possibilité de redirection dans une fichier, avec configuration (écriture à la suite d'un fichier existant, écrasement...)&lt;br /&gt;
**Le tout dans une classe Java flexible et réutilisable pour d'autres projets&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 6===&lt;br /&gt;
&lt;br /&gt;
*Installation de la librairie Java Pi4j sur la raspberry pi qui permet le contrôle des GPIO de celle-ci et notamment le port I²C (basé sur WiringPi)&lt;br /&gt;
*Amélioration coté serveur websocket&lt;br /&gt;
**Gestion de message plus longs (maximum des trames websockets soit 2^63 octets)&lt;br /&gt;
**Différenciation, à la réception de messages, des trames textes ou binaires des trames de contrôle comme les requête ping, pong ou de fermeture de connexion &lt;br /&gt;
**Ajout d'un mode de debug de trames &lt;br /&gt;
&lt;br /&gt;
===Semaine 7===&lt;br /&gt;
&lt;br /&gt;
*Améliorations du serveur WebSocket&lt;br /&gt;
**Gestion de la fragmentation TCP&lt;br /&gt;
**Gestion de la fragmentation WebSocket&lt;br /&gt;
**Gestion des requêtes ping envoyés par le client en renvoyant une trames de contrôle pong afin de maintenir la connexion&lt;br /&gt;
**Gestion des déconnexion de clients afin d'optimiser le serveur&lt;br /&gt;
**Amélioration de l'émission de messages en augmentant la taille maximale pouvant être émise (2^63 octets)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A ce stade du développement, le client et le serveur sont opérationnels et peuvent s'échanger des messages ainsi que des images que le serveur traite pour extraire les contours.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 8===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Montage projecteur&lt;br /&gt;
**Intégralité des composants fixés par vis dans le boîtier ABS&lt;br /&gt;
**Fusion des alimentations&lt;br /&gt;
**Présence d'une led témoin de mise en tension&lt;br /&gt;
**Position laser réglable grâce à une vis&lt;br /&gt;
**Présence d'un switch à bascule pour allumer et éteindre le laser&lt;br /&gt;
**Isolation et vérification des composants&lt;br /&gt;
**Tests empiriques de température et de fonctionnement des lasers et galvanomètres&lt;br /&gt;
&lt;br /&gt;
Le montage boîtier est donc terminé et s’alimente en 230V par intermédiaire d'un câble secteur avec connecteur C14. Le résultat s'avère plutôt compact. Les quelques tests de températures ont montrés que malgré le manque d'espace la température globale du boîtier ne dépasse pas les 50°C pendant plus d'une heure de fonctionnement. L'intégralité des connexions sont isolées avec de la gaine thermodynamique et les zones &amp;quot;sensibles&amp;quot; sont correctement vérifiés ainsi que protégées avec de la matière isolante.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Page web et serveur WebSocket&lt;br /&gt;
**Ajout d'un bouton &amp;quot;reboot&amp;quot; et &amp;quot;shutdown&amp;quot; qui permettent respectivement de redémarrer et d'éteindre la Raspberry directement à partir de la page web&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 9===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 10===&lt;br /&gt;
&lt;br /&gt;
==A faire==&lt;br /&gt;
&lt;br /&gt;
MAJ 26 mars &lt;br /&gt;
&lt;br /&gt;
*Client websocket et page web&lt;br /&gt;
**Mise en page CSS&lt;br /&gt;
**Ajout canvas pour prévisualisation image projeté&lt;br /&gt;
**Ajout &amp;quot;slider&amp;quot; pour régler niveau du flou Gaussien DOUBLE&lt;br /&gt;
**Ajout slider pour de finir amplitude de la projection&lt;br /&gt;
**Afficher statut de connexion&lt;br /&gt;
**Ajout message de confirmation quand le serveur quitte ou relance&lt;br /&gt;
**Ajout boutons &amp;quot;projeter&amp;quot; &amp;quot;centrer&amp;quot; &amp;quot;eteindre&amp;quot;&lt;br /&gt;
**Gestion de plusieurs images avec délai&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Serveur WebSocket&lt;br /&gt;
**Ajout fonctionnalité envoi image de prévisualisation&lt;br /&gt;
&lt;br /&gt;
*RaspberryPi&lt;br /&gt;
**Utilisation d'un serveur bind9 pour éviter de taper IP&lt;br /&gt;
&lt;br /&gt;
*Détection de contours&lt;br /&gt;
**Implémentation algorithme de tri de la plus courte disance&lt;br /&gt;
&lt;br /&gt;
*Commande galvanomêtre&lt;br /&gt;
**Utilisation API I²C&lt;br /&gt;
**Fonction de transfert position-&amp;gt;angle-&amp;gt;tension&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;br /&gt;
&lt;br /&gt;
==Bibliographie==&lt;br /&gt;
&lt;br /&gt;
http://www.ebay.com/itm/20KPPS-30KPPS-laser-scanning-galvo-scanner-ILDA-Closed-Loop-max-30kpps-for-laser-/261517002270?hash=item3ce3a0c61e&lt;br /&gt;
&lt;br /&gt;
https://icn.fenelonlille.org/mediawiki/index.php/Projet_ICN_commun_2016/2017&lt;br /&gt;
&lt;br /&gt;
https://www.g33k-zone.org/post/2016/05/11/Configurer-le-Raspberry-Pi-en-point-d-acc%C3%A8s-Wifi&lt;br /&gt;
&lt;br /&gt;
http://stackoverflow.com/questions/22087076/how-to-make-a-simple-image-upload-using-javascript-html&lt;br /&gt;
&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_a_WebSocket_server_in_Java&lt;br /&gt;
&lt;br /&gt;
export http_proxy=http://proxy.polytech-lille.fr:3128&lt;/div&gt;</summary>
		<author><name>Mtrimbur</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=40816</id>
		<title>IMA4 2016/2017 P39</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=40816"/>
				<updated>2017-03-27T17:34:50Z</updated>
		
		<summary type="html">&lt;p&gt;Mtrimbur : /* Semaine 8 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
===Contexte===&lt;br /&gt;
&lt;br /&gt;
Le laser est une technologie largement utilisé de nos jours dans de diverses applications. En effet, on retrouve cette technologie dans le domaine médical notamment pour la chirurgie oculaire ou encore dans industrie avec la découpe laser ou la soudure au laser.&lt;br /&gt;
&lt;br /&gt;
Le laser est une émission de photons produit par excitation d'un milieu amplificateur (ex : CO2), le rayonnement produit est unidirectionnel et monochromatique. Ce sont ces propriétés que nous allons exploiter afin réaliser un projecteur laser qui mis en mouvement est capable de dessiner des formes sur une surface à l'instar de systèmes existants utilisés pour des effets lumineux lors de festivités.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
L'objectif du projet est de créer un système de projection laser à plusieurs couleurs (au minimum deux) avec une application web pour programmer les formes à dessiner afin d'agrémenter des compétitions de gymnastique rythmique.&lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
Le projet consiste à réaliser avec des lasers des figures géométriques par l'intermédiaire d'un système galvanométrique. &lt;br /&gt;
&lt;br /&gt;
Notre premier travail sera de concevoir la partie projection. Pour cela, nous devrons aligner les lasers et les galvanomètres. En effet, ces derniers posséderont des miroirs à l'extrémité, ainsi les miroirs changeront d'inclinaison suivant le courant traversant les galvanomètres (similaire à l'image ci-contre). Il nous faudra également créer un système d'alimentation qui à partir d'une même source (réseau 230 V) sera capable d'alimenter les lasers et les galvanomètres ainsi qu'une Arduino et une Raspberry Pi.&lt;br /&gt;
[[File:Scanhead.jpeg|thumb]]&lt;br /&gt;
&lt;br /&gt;
Ensuite nous nous intéresserons à l'utilisation d'un système embarqué pour contrôler les galvanomètres et donc dessiner avec les lasers sur un plan 2D. En effet, le laser restera toujours fixe, seuls les galvanomètres, et donc les miroirs bougeront. Les galvanomètres étant contrôlés en courant il faudra réaliser une interface électronique pour convertir une commande en tension en commande de courant. La commande en tension sera assuré par une carte Arduino. Nous n'utiliserons qu'une seule paire de galvanomètres pour les deux laser. Il faudra donc multiplexer les deux faisceaux. La programmation des formes à effectuer, se fera par l'intermédiaire d'une application web PHP hébergée sur une RaspberryPi qui permettra de récupérer une image, d'y appliquer divers traitements et filtres afin d'en extraire les contours, et de calculer les commandes pour positionner les galvanomètres. Un serveur WebSocket également hébergé sur la RaspberryPi servira d'interface entre l'application web et L'arduino qui sera connecté via une liaison série sur la raspberryPI.&lt;br /&gt;
&lt;br /&gt;
Comme animation de test, nous dessinerons le contour d'une gymnaste avec une couleur et son ballon d'une autre couleur. La gymnaste devra lancer son ballon, réaliser quelques difficultés et récupérer son ballon.&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
Nous utiliserons comme matériels :&lt;br /&gt;
*Deux lasers de différentes couleurs&lt;br /&gt;
*Une paire de galvanomètres à miroir&lt;br /&gt;
*Arduino&lt;br /&gt;
*Raspberry Pi3&lt;br /&gt;
*Alimentation 230V/5V 1A [http://www.miniinthebox.com/fr/dual-usb-eu-prise-murale-5v-2a-voyage-adaptateur-chargeur-d-alimentation-pour-iphone7-6-xiaomi-samsung-et-autre-telephone-portable_p5410410.html?currency=EUR&amp;amp;litb_from=paid_adwords_shopping&amp;amp;sku=429_6917%7C752_20648&amp;amp;utm_source=google_shopping&amp;amp;utm_medium=cpc&amp;amp;adword_mt=&amp;amp;adword_ct=138705676724&amp;amp;adword_kw=&amp;amp;adword_pos=1o5&amp;amp;adword_pl=&amp;amp;adword_net=g&amp;amp;adword_tar=&amp;amp;adw_src_id=9653316068_661261352_33588296076_aud-79897721311:pla-256966386459&amp;amp;gclid=Cj0KEQiA_KvEBRCtzNil4-KR-LIBEiQAmgekFxxKjJJWBYCJlDZEa3Ke_2_WR0DzGVbz-jaCZHVIBoMaAvld8P8HAQ]&lt;br /&gt;
*Drivers galvanomètres x2&lt;br /&gt;
*Alimentation laser&lt;br /&gt;
*Lunette de sécurité x2 [https://www.amazon.fr/Uvex-S1933X-Eyewear-SCTOrange-Anti-Fog/dp/B000USRG90/ref=sr_1_1?ie=UTF8&amp;amp;qid=1485441383&amp;amp;sr=8-1&amp;amp;keywords=uvex+s1933x]&lt;br /&gt;
*Boitier ABS [http://fr.farnell.com/multicomp/g3118/boitier-abs-240x120x60mm-ip65/dp/1526656]&lt;br /&gt;
*DAC 4 canaux, avec interface I²C [https://www.adafruit.com/products/1083]&lt;br /&gt;
*Connecteur C14 [http://www.conrad.fr/ce/fr/product/715001/Connecteur-secteur-C14-Embase-male-verticale-715001-Nombre-de-poles-2-PE-10-A-noir-1-pcs/?ref=detview1&amp;amp;rt=detview1&amp;amp;rb=1]&lt;br /&gt;
*Câble secteur&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Logiciel :&lt;br /&gt;
&lt;br /&gt;
*Serveur web : Apache2, HTML5, PHP5, CSS&lt;br /&gt;
*Base de donnée : MySQL&lt;br /&gt;
*Serveur WebSocket : JQuerry, websocket&lt;br /&gt;
*Arduino : IDE Arduino&lt;br /&gt;
&lt;br /&gt;
===Calendrier prévisionnel===&lt;br /&gt;
&lt;br /&gt;
====Liste des tâches à effectuer====&lt;br /&gt;
Les différentes tâches à effectuer sont :&lt;br /&gt;
*Partie préliminaire : étude de fonctionnement des galvanomètres&lt;br /&gt;
**Déterminer comment est effectuée la commande des galvanomètres (protocole, tension...)&lt;br /&gt;
**Effectuer des tests avec l'Arduino ou la Raspberry Pi&lt;br /&gt;
**Effectuer des tests avec une LED à la place du laser &lt;br /&gt;
*Partie projection&lt;br /&gt;
**Fixer les lasers&lt;br /&gt;
**Aligner les lasers et les galvanomètres&lt;br /&gt;
**Créer le système d'alimentation&lt;br /&gt;
**Création d'un boitier&lt;br /&gt;
*Partie système embarqué&lt;br /&gt;
**Asservissement des galvanomètres avec l'Arduino&lt;br /&gt;
**Système électronique de commande en courant pour les galvanomètres&lt;br /&gt;
*Interface Web&lt;br /&gt;
**Installation et configuration Apache2&lt;br /&gt;
**Création d'une interface graphique simple&lt;br /&gt;
**Implémentation d'algorithmes de traitement d'image&lt;br /&gt;
**Mise en forme avec des CSS&lt;br /&gt;
**Sytème d'authentification avec mot de passe&lt;br /&gt;
**Utilisation d'une base de données pour enregistrer toutes les images déjà utilisés afin de les réutiliser&lt;br /&gt;
*Serveur Web Socket&lt;br /&gt;
**Récupération des données de l'interface web&lt;br /&gt;
**Mise en place de la liaison série avec l'Arduino&lt;br /&gt;
&lt;br /&gt;
====Calendrier====&lt;br /&gt;
Répartition du temps consacré au projet (240h) :&lt;br /&gt;
*Partie projection : 80h&lt;br /&gt;
*Partie système embarqué : 40h&lt;br /&gt;
*Partie interface web et websocket: 120h&lt;br /&gt;
&lt;br /&gt;
==Feuille d'heures==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!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&lt;br /&gt;
|-&lt;br /&gt;
| Définition cahier des charges &lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 14&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|38&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Finalisation du cahier des charges avec les responsables&lt;br /&gt;
&lt;br /&gt;
*Acquisition de matériels :&lt;br /&gt;
**Projecteur Laser&lt;br /&gt;
**Galvanomètres&lt;br /&gt;
**Alimentation des galvanomètres&lt;br /&gt;
&lt;br /&gt;
*Listage du matériels à acquérir :&lt;br /&gt;
**Lunettes de sécurité&lt;br /&gt;
**DAC&lt;br /&gt;
**Alimentation 230V/5V 1A&lt;br /&gt;
** Boitier ABS &lt;br /&gt;
**...&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
*Obtention de l'arduino et de la raspberryPI&lt;br /&gt;
&lt;br /&gt;
*Démontage du projecteur laser&lt;br /&gt;
**Deux lasers de classe 3b (vert et rouge)&lt;br /&gt;
**Circuit d'alimentation des deux lasers&lt;br /&gt;
&lt;br /&gt;
*Initialisation du port série de la raspberryPI&lt;br /&gt;
**Modification du fichier ''config.txt'' dans la partition boot&lt;br /&gt;
**Ajout d'une ligne autorisant la communication série ('''enable_uart=1''')&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
*Installation du serveur apache sur la raspberryPI&lt;br /&gt;
**Modification du fichier ''/etc/network/interfaces'' (Static, Address, Netmask, Gateway)&lt;br /&gt;
**Modification du fichier ''/etc/resolv.conf'' (Adresse du serveur)&lt;br /&gt;
**Utilisation d'un proxy pour la récupération outils de programmation (Apache2, Php5)&lt;br /&gt;
&lt;br /&gt;
*Mise en place du point d’accès wifi de la raspberryPI&lt;br /&gt;
**Récupération des logiciels nécessaires (dnsmasq, hostapd)&lt;br /&gt;
**Mise en place d'une adresse IP statique pour le point d'accès par l'intermédiaire du fichier ''/etc/dhcpcd.conf''&lt;br /&gt;
**Désactivation de la négociation automatique de bail dans le fichier ''/etc/network/interfaces''&lt;br /&gt;
**Configuration du logiciel hostapd ''/etc/hostapd/hostapd.conf''&lt;br /&gt;
**Activation du démarrage automatique du point d'accès ''/etc/default/hostapd''&lt;br /&gt;
**Configuration du serveur DNS par ''/etc/dnsmasq.conf''&lt;br /&gt;
&lt;br /&gt;
*Instauration de la page d'accueil de l'interface web à l'adresse ''192.168.3.1''&lt;br /&gt;
**Téléversement de fichiers images sur la page web et affichage de celle-ci&lt;br /&gt;
**Voyant de confirmation du bon fonctionnement du serveur web&lt;br /&gt;
&lt;br /&gt;
*Développement du serveur websocket&lt;br /&gt;
&lt;br /&gt;
Le développement du serveur websocket, initialement prévu en C (il était prévu de reprendre les sources utilisées l'année précédente dans le cadre des projet IMA3 SC), a finalement été réalisé en JAVA pour plusieurs raisons.&lt;br /&gt;
Premièrement, un seul programme met en œuvre le serveur websocket, les divers traitements d'image, ainsi que les contrôles des galvanomètres (par l'intermédiaire des DAC) via la liaison I²C de la Raspberry Pi. Le langage JAVA fournit nativement des bibliothèques d'objets pour manipuler assez simplement des images, il existe également des librairies pour contrôler le port GPIO de la Raspberry et il était également intéressant de travailler avec un langage de plus haut niveau que le C.&lt;br /&gt;
En outre, la totale portabilité de ce langage nous permet de travailler sur n'importe quelle machine et ensuite transférer notre programme sur la Raspberry Pi et l’exécuter sans même repasser par une phase de compilation. Et finalement, c'est le langage que nous étudions actuellement en cours de programmation orientée objet, ce qui permet de nous perfectionner.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Serveur WebSocket====&lt;br /&gt;
&lt;br /&gt;
N'ayant pas trouvé d'API WebSocket en Java satisfaisante (qui ne nécessitent pas l'installation et la configuration de nombreux outils additionnels), j'ai estimé plus commode et plus formateur de développer notre propre serveur WebSocket en se basant sur les librairies sockets de Java avec l'aide d'une documentation assez exhaustive [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers].&lt;br /&gt;
&lt;br /&gt;
Les WebSockets désignent à la fois un protocole réseau qui étend le protocole TCP ainsi qu'une API du World Wide Web. Nous nous en servons afin d'établir une communication asynchrone et bidirectionnelle entre un navigateur web et le serveur, notamment pour envoyer l'image à projeter. L’implémentation du serveur repose sur plusieurs étapes.&lt;br /&gt;
&lt;br /&gt;
1) Connexion d'un client &lt;br /&gt;
&lt;br /&gt;
2) Handshake : permet de faire le lien entre le protocole HTTP et WS. Le client envoie une requête HTTP demandant un upgrade de la connexion en protocole WS et le serveur répond en configurant la connexion (détail dans la documentation [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers]).&lt;br /&gt;
&lt;br /&gt;
3) Réception et décodage des messages : le serveurs reçoit des trames brutes, on extrait donc la taille du message ainsi que le message. De plus, les données son encodées (cryptage XOR) par un masque qui doit également être extrait.&lt;br /&gt;
&lt;br /&gt;
4) Fermeture de la communication.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le serveur supporte le multi-client il est donc nécessaire qu'il effectue ces étapes en &amp;quot;parallèle&amp;quot;. Nous utilisons donc les threads ou fils d’exécution. Un thread est donc responsable d'attendre qu'un nouveau client se connecte et effectue le &amp;quot;handshake&amp;quot;, il crée ensuite un thread associé à ce client afin d'établir un canal de communication. Il y a donc au moins un thread par client. Par la suite il faudra également implémenter une déconnexion automatique d'un client notamment après un timeout.&lt;br /&gt;
&lt;br /&gt;
Exemple d’exécution du serveur avec deux clients qui se connectent et envoient un message : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testServeur.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Les clients sont des navigateurs web. Pour les tests nous avons repris les exemples utilisés dans le cadre das projets IMA3 SC avec le titre de la page HTML qui se colore en vert lorsque le client est connecté, et un champ de saisie pour envoyer des messages au serveur : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testClient.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 4===&lt;br /&gt;
&lt;br /&gt;
*Mise en place d’algorithmes de traitement d'image&lt;br /&gt;
&lt;br /&gt;
====Détection de contour====&lt;br /&gt;
&lt;br /&gt;
L'objectif de notre projet est de pouvoir projeter n'importe quelle image envoyé grâce à l'application web. Pour cela nous allons tracer à une vitesse élevée les contours de l'image sur par exemple un mur grâce au laser. Il est donc nécessaire de détecter les contours de l'image grâce à plusieurs traitements.&lt;br /&gt;
&lt;br /&gt;
=====Conversion en niveau de gris=====&lt;br /&gt;
&lt;br /&gt;
Une des étapes préliminaires pour effectuer la détection de contour est de convertir l'image couleur en niveau de gris. Pour cela l'algorithme est simple : il suffit pour chaque pixel de l'image d'effectuer la moyenne des composantes rouge, verte, bleu de chaque pixel. En effet, si l'on considère une image matricielle (l'image est considérée comme un tableau à deux dimensions avec chaque case qui contient la couleur du pixel), chaque pixel contient les composantes RGB codées sur un octet. La couleur gris correspond aux composantes RGB égales. Le niveau de gris est donc codé de 0 à 255, avec 0 donnant du noir et 255 du blanc. &lt;br /&gt;
&lt;br /&gt;
Voici le résultat obtenu : [[Fichier:testGrayScale.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Filtre de Prewit et Sobel=====&lt;br /&gt;
&lt;br /&gt;
Un contour est défini par un changement brutal d'intensité lumineuse, il s'agit donc de détecter selon plusieurs directions (au moins 2) ces changements. Il existe de nombreuses techniques afin de détecter les contours d'une image (gradient, Laplacien). L'une des techniques avec un rapport efficacité/temps d'exécution correct repose sur les algorithmes de Prewit ou Sobel. L'algorithme repose sur la convolution de matrices.&lt;br /&gt;
Cela consiste à appliquer sur chaque pixel de l'image la matrice de Prewit définie comme &lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L_x = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; ainsi que sa transposée : &amp;lt;math&amp;gt;&lt;br /&gt;
L_y = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; -1 &amp;amp; -1 \\&lt;br /&gt;
 0 &amp;amp; 0 &amp;amp; 0 \\&lt;br /&gt;
+1 &amp;amp; +1 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Convoluer ces deux filtres sur l'image permet de détecter respectivement les contours verticaux et horizontaux.&lt;br /&gt;
&lt;br /&gt;
D'après wikipedia [https://fr.wikipedia.org/wiki/D%C3%A9tection_de_contours], on obtient de meilleurs résultats en appliquant un filtre triangulaire, on introduit donc la matrice de Sobel :&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-2 &amp;amp; 0 &amp;amp; +2 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
On obtient le résultat suivant : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testOutline1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Pré-traitement : Flou Gaussien=====&lt;br /&gt;
&lt;br /&gt;
Afin de réduire significativement le nombre de contours, il est nécessaire d'effectuer un pré-traitement avant la détection de contours. On utilise généralement un flou gaussien afin de réduire les transitions lumineuses et ainsi réduire le nombre de contours. L’algorithme de flou gaussien repose également sur la convolution de matrices sauf qu'ici la matrice filtre est générée grâce à une fonction gaussienne paramétrée par '''Sigma''' qui va directement impacter le niveau de flou. Plus la matrice de filtrage est grande plus la qualité du résultat est meilleure, mais le temps d’exécution devient également plus grand.&lt;br /&gt;
&lt;br /&gt;
Voici la fonction de génération du filtre : &amp;lt;math&amp;gt;G(x,y) = \frac{1}{{2\pi \sigma^2}} e^{-\frac{x^2 + y^2}{2 \sigma^2}}&amp;lt;/math&amp;gt; où x et y correspondent aux indices de la cellule de la matrice.&lt;br /&gt;
&lt;br /&gt;
On obtient ce résultat :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testGaussianBlur.png]]&lt;br /&gt;
&lt;br /&gt;
On note un bien meilleur résultat. Cependant on remarque que les composantes horizontales ne sont pas correctement détectées il subsiste un problème avec le filtrage vertical que je n'ai pas réussi à identifier. De plus, il s'agit par sa suite d'éliminer les contours parasites ainsi que d'affiner le trait pour n'avoir plus qu'un pixel d'épaisseur.&lt;br /&gt;
&lt;br /&gt;
=====Post-traitement : Algorithme de Canny=====&lt;br /&gt;
&lt;br /&gt;
Afin d'obtenir un résultat exploitable il est nécessaire d'appliquer encore quelques traitements. Pour cela nous utilisons l’algorithme de Canny qui repose que celui de Sobel mais qui ajoute un algorithme de seuillage par hysteresis qui permet de retirer les contours secondaires et de ne garder que les contours connexes dans une seuil haut et un seuil bas définis. En outre, cette algorithme affine également le trait obtenu. Pour cet algorithme nous avons directement trouvé des sources libres de droits [http://www.tomgibara.com/computer-vision/canny-edge-detector] qui donne des résultats très corrects.&lt;br /&gt;
&lt;br /&gt;
Par exemple :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ou encore : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny2.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 5===&lt;br /&gt;
&lt;br /&gt;
*Établissement d'un protocole de transfert d'image basé sur les WebSockets&lt;br /&gt;
**Envoie d'un requête &amp;quot;send&amp;quot; par le client dans une trame websocket texte&lt;br /&gt;
**Réponse serveur 'Y' si aucun autre client tente d'envoyer une image simultanément, 'N' sinon&lt;br /&gt;
**Si et seulement si le client reçoit 'Y' il débute le transfert en envoyant la largeur et la longueur de l'image sur 4 octets, puis les données de l'image soit 4 valeurs pour chaque pixels (r,g,b,alpha)&lt;br /&gt;
**Le serveur renvoie 'D' une fois le transfert achevé (à l'avenir, le serveur renverra l'image après filtrage).&lt;br /&gt;
**A tout moment, le serveur peut renvoyer 'E' si une erreur est survenue (ex : paquets perdus, nombre incorrects de données)&lt;br /&gt;
*Ajout du support des logs au niveau serveur&lt;br /&gt;
**Impression sur la sortie standard des messages&lt;br /&gt;
**Formatage en fonction de la sévérité du log (info, warning, error...)&lt;br /&gt;
**Incrustation de la date et heure&lt;br /&gt;
**Possibilité de redirection dans une fichier, avec configuration (écriture à la suite d'un fichier existant, écrasement...)&lt;br /&gt;
**Le tout dans une classe Java flexible et réutilisable pour d'autres projets&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 6===&lt;br /&gt;
&lt;br /&gt;
*Installation de la librairie Java Pi4j sur la raspberry pi qui permet le contrôle des GPIO de celle-ci et notamment le port I²C (basé sur WiringPi)&lt;br /&gt;
*Amélioration coté serveur websocket&lt;br /&gt;
**Gestion de message plus longs (maximum des trames websockets soit 2^63 octets)&lt;br /&gt;
**Différenciation, à la réception de messages, des trames textes ou binaires des trames de contrôle comme les requête ping, pong ou de fermeture de connexion &lt;br /&gt;
**Ajout d'un mode de debug de trames &lt;br /&gt;
&lt;br /&gt;
===Semaine 7===&lt;br /&gt;
&lt;br /&gt;
*Améliorations du serveur WebSocket&lt;br /&gt;
**Gestion de la fragmentation TCP&lt;br /&gt;
**Gestion de la fragmentation WebSocket&lt;br /&gt;
**Gestion des requêtes ping envoyés par le client en renvoyant une trames de contrôle pong afin de maintenir la connexion&lt;br /&gt;
**Gestion des déconnexion de clients afin d'optimiser le serveur&lt;br /&gt;
**Amélioration de l'émission de messages en augmentant la taille maximale pouvant être émise (2^63 octets)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A ce stade du développement, le client et le serveur sont opérationnels et peuvent s'échanger des messages ainsi que des images que le serveur traite pour extraire les contours.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 8===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Montage projecteur&lt;br /&gt;
**Intégralité des composants fixés par vis dans le boîtier ABS&lt;br /&gt;
**Fusion des alimentations&lt;br /&gt;
**Présence d'une led témoin de mise en tension&lt;br /&gt;
**Position laser réglable grâce à une vis&lt;br /&gt;
**Présence d'un switch à bascule pour allumer et éteindre le laser&lt;br /&gt;
**Isolation et vérification des composants&lt;br /&gt;
**Tests empiriques de température et de fonctionnement des lasers et galvanomètres&lt;br /&gt;
&lt;br /&gt;
Le montage boîtier est donc terminé et s’alimente en 230V par intermédiaire d'un câble secteur avec connecteur C14. Le résultat s'avère plutôt compact. Les quelques tests de températures ont montrés que malgré le manque d'espace la température globale du boîtier ne dépasse pas les 50°C pendant plus d'une heure de fonctionnement. L'intégralité des connexions sont isolées avec de la gaine thermodynamique et les zones &amp;quot;sensibles&amp;quot; sont correctement vérifiés ainsi que protégées avec de la matière isolante.&lt;br /&gt;
&lt;br /&gt;
*Page web et serveur WebSocket&lt;br /&gt;
**Ajout d'un bouton &amp;quot;reboot&amp;quot; et &amp;quot;shutdown&amp;quot; qui permettent respectivement de redémarrer et d'éteindre la Raspberry directement à partir de la page web&lt;br /&gt;
&lt;br /&gt;
===Semaine 9===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 10===&lt;br /&gt;
&lt;br /&gt;
==A faire==&lt;br /&gt;
&lt;br /&gt;
MAJ 26 mars &lt;br /&gt;
&lt;br /&gt;
*Client websocket et page web&lt;br /&gt;
**Mise en page CSS&lt;br /&gt;
**Ajout canvas pour prévisualisation image projeté&lt;br /&gt;
**Ajout &amp;quot;slider&amp;quot; pour régler niveau du flou Gaussien DOUBLE&lt;br /&gt;
**Ajout slider pour de finir amplitude de la projection&lt;br /&gt;
**Afficher statut de connexion&lt;br /&gt;
**Ajout message de confirmation quand le serveur quitte ou relance&lt;br /&gt;
**Ajout boutons &amp;quot;projeter&amp;quot; &amp;quot;centrer&amp;quot; &amp;quot;eteindre&amp;quot;&lt;br /&gt;
**Gestion de plusieurs images avec délai&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Serveur WebSocket&lt;br /&gt;
**Ajout fonctionnalité envoi image de prévisualisation&lt;br /&gt;
&lt;br /&gt;
*RaspberryPi&lt;br /&gt;
**Utilisation d'un serveur bind9 pour éviter de taper IP&lt;br /&gt;
&lt;br /&gt;
*Détection de contours&lt;br /&gt;
**Implémentation algorithme de tri de la plus courte disance&lt;br /&gt;
&lt;br /&gt;
*Commande galvanomêtre&lt;br /&gt;
**Utilisation API I²C&lt;br /&gt;
**Fonction de transfert position-&amp;gt;angle-&amp;gt;tension&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;br /&gt;
&lt;br /&gt;
==Bibliographie==&lt;br /&gt;
&lt;br /&gt;
http://www.ebay.com/itm/20KPPS-30KPPS-laser-scanning-galvo-scanner-ILDA-Closed-Loop-max-30kpps-for-laser-/261517002270?hash=item3ce3a0c61e&lt;br /&gt;
&lt;br /&gt;
https://icn.fenelonlille.org/mediawiki/index.php/Projet_ICN_commun_2016/2017&lt;br /&gt;
&lt;br /&gt;
https://www.g33k-zone.org/post/2016/05/11/Configurer-le-Raspberry-Pi-en-point-d-acc%C3%A8s-Wifi&lt;br /&gt;
&lt;br /&gt;
http://stackoverflow.com/questions/22087076/how-to-make-a-simple-image-upload-using-javascript-html&lt;br /&gt;
&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_a_WebSocket_server_in_Java&lt;br /&gt;
&lt;br /&gt;
export http_proxy=http://proxy.polytech-lille.fr:3128&lt;/div&gt;</summary>
		<author><name>Mtrimbur</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=40815</id>
		<title>IMA4 2016/2017 P39</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=40815"/>
				<updated>2017-03-27T17:21:12Z</updated>
		
		<summary type="html">&lt;p&gt;Mtrimbur : /* Avancement du Projet */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
===Contexte===&lt;br /&gt;
&lt;br /&gt;
Le laser est une technologie largement utilisé de nos jours dans de diverses applications. En effet, on retrouve cette technologie dans le domaine médical notamment pour la chirurgie oculaire ou encore dans industrie avec la découpe laser ou la soudure au laser.&lt;br /&gt;
&lt;br /&gt;
Le laser est une émission de photons produit par excitation d'un milieu amplificateur (ex : CO2), le rayonnement produit est unidirectionnel et monochromatique. Ce sont ces propriétés que nous allons exploiter afin réaliser un projecteur laser qui mis en mouvement est capable de dessiner des formes sur une surface à l'instar de systèmes existants utilisés pour des effets lumineux lors de festivités.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
L'objectif du projet est de créer un système de projection laser à plusieurs couleurs (au minimum deux) avec une application web pour programmer les formes à dessiner afin d'agrémenter des compétitions de gymnastique rythmique.&lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
Le projet consiste à réaliser avec des lasers des figures géométriques par l'intermédiaire d'un système galvanométrique. &lt;br /&gt;
&lt;br /&gt;
Notre premier travail sera de concevoir la partie projection. Pour cela, nous devrons aligner les lasers et les galvanomètres. En effet, ces derniers posséderont des miroirs à l'extrémité, ainsi les miroirs changeront d'inclinaison suivant le courant traversant les galvanomètres (similaire à l'image ci-contre). Il nous faudra également créer un système d'alimentation qui à partir d'une même source (réseau 230 V) sera capable d'alimenter les lasers et les galvanomètres ainsi qu'une Arduino et une Raspberry Pi.&lt;br /&gt;
[[File:Scanhead.jpeg|thumb]]&lt;br /&gt;
&lt;br /&gt;
Ensuite nous nous intéresserons à l'utilisation d'un système embarqué pour contrôler les galvanomètres et donc dessiner avec les lasers sur un plan 2D. En effet, le laser restera toujours fixe, seuls les galvanomètres, et donc les miroirs bougeront. Les galvanomètres étant contrôlés en courant il faudra réaliser une interface électronique pour convertir une commande en tension en commande de courant. La commande en tension sera assuré par une carte Arduino. Nous n'utiliserons qu'une seule paire de galvanomètres pour les deux laser. Il faudra donc multiplexer les deux faisceaux. La programmation des formes à effectuer, se fera par l'intermédiaire d'une application web PHP hébergée sur une RaspberryPi qui permettra de récupérer une image, d'y appliquer divers traitements et filtres afin d'en extraire les contours, et de calculer les commandes pour positionner les galvanomètres. Un serveur WebSocket également hébergé sur la RaspberryPi servira d'interface entre l'application web et L'arduino qui sera connecté via une liaison série sur la raspberryPI.&lt;br /&gt;
&lt;br /&gt;
Comme animation de test, nous dessinerons le contour d'une gymnaste avec une couleur et son ballon d'une autre couleur. La gymnaste devra lancer son ballon, réaliser quelques difficultés et récupérer son ballon.&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
Nous utiliserons comme matériels :&lt;br /&gt;
*Deux lasers de différentes couleurs&lt;br /&gt;
*Une paire de galvanomètres à miroir&lt;br /&gt;
*Arduino&lt;br /&gt;
*Raspberry Pi3&lt;br /&gt;
*Alimentation 230V/5V 1A [http://www.miniinthebox.com/fr/dual-usb-eu-prise-murale-5v-2a-voyage-adaptateur-chargeur-d-alimentation-pour-iphone7-6-xiaomi-samsung-et-autre-telephone-portable_p5410410.html?currency=EUR&amp;amp;litb_from=paid_adwords_shopping&amp;amp;sku=429_6917%7C752_20648&amp;amp;utm_source=google_shopping&amp;amp;utm_medium=cpc&amp;amp;adword_mt=&amp;amp;adword_ct=138705676724&amp;amp;adword_kw=&amp;amp;adword_pos=1o5&amp;amp;adword_pl=&amp;amp;adword_net=g&amp;amp;adword_tar=&amp;amp;adw_src_id=9653316068_661261352_33588296076_aud-79897721311:pla-256966386459&amp;amp;gclid=Cj0KEQiA_KvEBRCtzNil4-KR-LIBEiQAmgekFxxKjJJWBYCJlDZEa3Ke_2_WR0DzGVbz-jaCZHVIBoMaAvld8P8HAQ]&lt;br /&gt;
*Drivers galvanomètres x2&lt;br /&gt;
*Alimentation laser&lt;br /&gt;
*Lunette de sécurité x2 [https://www.amazon.fr/Uvex-S1933X-Eyewear-SCTOrange-Anti-Fog/dp/B000USRG90/ref=sr_1_1?ie=UTF8&amp;amp;qid=1485441383&amp;amp;sr=8-1&amp;amp;keywords=uvex+s1933x]&lt;br /&gt;
*Boitier ABS [http://fr.farnell.com/multicomp/g3118/boitier-abs-240x120x60mm-ip65/dp/1526656]&lt;br /&gt;
*DAC 4 canaux, avec interface I²C [https://www.adafruit.com/products/1083]&lt;br /&gt;
*Connecteur C14 [http://www.conrad.fr/ce/fr/product/715001/Connecteur-secteur-C14-Embase-male-verticale-715001-Nombre-de-poles-2-PE-10-A-noir-1-pcs/?ref=detview1&amp;amp;rt=detview1&amp;amp;rb=1]&lt;br /&gt;
*Câble secteur&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Logiciel :&lt;br /&gt;
&lt;br /&gt;
*Serveur web : Apache2, HTML5, PHP5, CSS&lt;br /&gt;
*Base de donnée : MySQL&lt;br /&gt;
*Serveur WebSocket : JQuerry, websocket&lt;br /&gt;
*Arduino : IDE Arduino&lt;br /&gt;
&lt;br /&gt;
===Calendrier prévisionnel===&lt;br /&gt;
&lt;br /&gt;
====Liste des tâches à effectuer====&lt;br /&gt;
Les différentes tâches à effectuer sont :&lt;br /&gt;
*Partie préliminaire : étude de fonctionnement des galvanomètres&lt;br /&gt;
**Déterminer comment est effectuée la commande des galvanomètres (protocole, tension...)&lt;br /&gt;
**Effectuer des tests avec l'Arduino ou la Raspberry Pi&lt;br /&gt;
**Effectuer des tests avec une LED à la place du laser &lt;br /&gt;
*Partie projection&lt;br /&gt;
**Fixer les lasers&lt;br /&gt;
**Aligner les lasers et les galvanomètres&lt;br /&gt;
**Créer le système d'alimentation&lt;br /&gt;
**Création d'un boitier&lt;br /&gt;
*Partie système embarqué&lt;br /&gt;
**Asservissement des galvanomètres avec l'Arduino&lt;br /&gt;
**Système électronique de commande en courant pour les galvanomètres&lt;br /&gt;
*Interface Web&lt;br /&gt;
**Installation et configuration Apache2&lt;br /&gt;
**Création d'une interface graphique simple&lt;br /&gt;
**Implémentation d'algorithmes de traitement d'image&lt;br /&gt;
**Mise en forme avec des CSS&lt;br /&gt;
**Sytème d'authentification avec mot de passe&lt;br /&gt;
**Utilisation d'une base de données pour enregistrer toutes les images déjà utilisés afin de les réutiliser&lt;br /&gt;
*Serveur Web Socket&lt;br /&gt;
**Récupération des données de l'interface web&lt;br /&gt;
**Mise en place de la liaison série avec l'Arduino&lt;br /&gt;
&lt;br /&gt;
====Calendrier====&lt;br /&gt;
Répartition du temps consacré au projet (240h) :&lt;br /&gt;
*Partie projection : 80h&lt;br /&gt;
*Partie système embarqué : 40h&lt;br /&gt;
*Partie interface web et websocket: 120h&lt;br /&gt;
&lt;br /&gt;
==Feuille d'heures==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!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&lt;br /&gt;
|-&lt;br /&gt;
| Définition cahier des charges &lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 14&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|38&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Finalisation du cahier des charges avec les responsables&lt;br /&gt;
&lt;br /&gt;
*Acquisition de matériels :&lt;br /&gt;
**Projecteur Laser&lt;br /&gt;
**Galvanomètres&lt;br /&gt;
**Alimentation des galvanomètres&lt;br /&gt;
&lt;br /&gt;
*Listage du matériels à acquérir :&lt;br /&gt;
**Lunettes de sécurité&lt;br /&gt;
**DAC&lt;br /&gt;
**Alimentation 230V/5V 1A&lt;br /&gt;
** Boitier ABS &lt;br /&gt;
**...&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
*Obtention de l'arduino et de la raspberryPI&lt;br /&gt;
&lt;br /&gt;
*Démontage du projecteur laser&lt;br /&gt;
**Deux lasers de classe 3b (vert et rouge)&lt;br /&gt;
**Circuit d'alimentation des deux lasers&lt;br /&gt;
&lt;br /&gt;
*Initialisation du port série de la raspberryPI&lt;br /&gt;
**Modification du fichier ''config.txt'' dans la partition boot&lt;br /&gt;
**Ajout d'une ligne autorisant la communication série ('''enable_uart=1''')&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
*Installation du serveur apache sur la raspberryPI&lt;br /&gt;
**Modification du fichier ''/etc/network/interfaces'' (Static, Address, Netmask, Gateway)&lt;br /&gt;
**Modification du fichier ''/etc/resolv.conf'' (Adresse du serveur)&lt;br /&gt;
**Utilisation d'un proxy pour la récupération outils de programmation (Apache2, Php5)&lt;br /&gt;
&lt;br /&gt;
*Mise en place du point d’accès wifi de la raspberryPI&lt;br /&gt;
**Récupération des logiciels nécessaires (dnsmasq, hostapd)&lt;br /&gt;
**Mise en place d'une adresse IP statique pour le point d'accès par l'intermédiaire du fichier ''/etc/dhcpcd.conf''&lt;br /&gt;
**Désactivation de la négociation automatique de bail dans le fichier ''/etc/network/interfaces''&lt;br /&gt;
**Configuration du logiciel hostapd ''/etc/hostapd/hostapd.conf''&lt;br /&gt;
**Activation du démarrage automatique du point d'accès ''/etc/default/hostapd''&lt;br /&gt;
**Configuration du serveur DNS par ''/etc/dnsmasq.conf''&lt;br /&gt;
&lt;br /&gt;
*Instauration de la page d'accueil de l'interface web à l'adresse ''192.168.3.1''&lt;br /&gt;
**Téléversement de fichiers images sur la page web et affichage de celle-ci&lt;br /&gt;
**Voyant de confirmation du bon fonctionnement du serveur web&lt;br /&gt;
&lt;br /&gt;
*Développement du serveur websocket&lt;br /&gt;
&lt;br /&gt;
Le développement du serveur websocket, initialement prévu en C (il était prévu de reprendre les sources utilisées l'année précédente dans le cadre des projet IMA3 SC), a finalement été réalisé en JAVA pour plusieurs raisons.&lt;br /&gt;
Premièrement, un seul programme met en œuvre le serveur websocket, les divers traitements d'image, ainsi que les contrôles des galvanomètres (par l'intermédiaire des DAC) via la liaison I²C de la Raspberry Pi. Le langage JAVA fournit nativement des bibliothèques d'objets pour manipuler assez simplement des images, il existe également des librairies pour contrôler le port GPIO de la Raspberry et il était également intéressant de travailler avec un langage de plus haut niveau que le C.&lt;br /&gt;
En outre, la totale portabilité de ce langage nous permet de travailler sur n'importe quelle machine et ensuite transférer notre programme sur la Raspberry Pi et l’exécuter sans même repasser par une phase de compilation. Et finalement, c'est le langage que nous étudions actuellement en cours de programmation orientée objet, ce qui permet de nous perfectionner.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Serveur WebSocket====&lt;br /&gt;
&lt;br /&gt;
N'ayant pas trouvé d'API WebSocket en Java satisfaisante (qui ne nécessitent pas l'installation et la configuration de nombreux outils additionnels), j'ai estimé plus commode et plus formateur de développer notre propre serveur WebSocket en se basant sur les librairies sockets de Java avec l'aide d'une documentation assez exhaustive [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers].&lt;br /&gt;
&lt;br /&gt;
Les WebSockets désignent à la fois un protocole réseau qui étend le protocole TCP ainsi qu'une API du World Wide Web. Nous nous en servons afin d'établir une communication asynchrone et bidirectionnelle entre un navigateur web et le serveur, notamment pour envoyer l'image à projeter. L’implémentation du serveur repose sur plusieurs étapes.&lt;br /&gt;
&lt;br /&gt;
1) Connexion d'un client &lt;br /&gt;
&lt;br /&gt;
2) Handshake : permet de faire le lien entre le protocole HTTP et WS. Le client envoie une requête HTTP demandant un upgrade de la connexion en protocole WS et le serveur répond en configurant la connexion (détail dans la documentation [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers]).&lt;br /&gt;
&lt;br /&gt;
3) Réception et décodage des messages : le serveurs reçoit des trames brutes, on extrait donc la taille du message ainsi que le message. De plus, les données son encodées (cryptage XOR) par un masque qui doit également être extrait.&lt;br /&gt;
&lt;br /&gt;
4) Fermeture de la communication.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le serveur supporte le multi-client il est donc nécessaire qu'il effectue ces étapes en &amp;quot;parallèle&amp;quot;. Nous utilisons donc les threads ou fils d’exécution. Un thread est donc responsable d'attendre qu'un nouveau client se connecte et effectue le &amp;quot;handshake&amp;quot;, il crée ensuite un thread associé à ce client afin d'établir un canal de communication. Il y a donc au moins un thread par client. Par la suite il faudra également implémenter une déconnexion automatique d'un client notamment après un timeout.&lt;br /&gt;
&lt;br /&gt;
Exemple d’exécution du serveur avec deux clients qui se connectent et envoient un message : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testServeur.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Les clients sont des navigateurs web. Pour les tests nous avons repris les exemples utilisés dans le cadre das projets IMA3 SC avec le titre de la page HTML qui se colore en vert lorsque le client est connecté, et un champ de saisie pour envoyer des messages au serveur : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testClient.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 4===&lt;br /&gt;
&lt;br /&gt;
*Mise en place d’algorithmes de traitement d'image&lt;br /&gt;
&lt;br /&gt;
====Détection de contour====&lt;br /&gt;
&lt;br /&gt;
L'objectif de notre projet est de pouvoir projeter n'importe quelle image envoyé grâce à l'application web. Pour cela nous allons tracer à une vitesse élevée les contours de l'image sur par exemple un mur grâce au laser. Il est donc nécessaire de détecter les contours de l'image grâce à plusieurs traitements.&lt;br /&gt;
&lt;br /&gt;
=====Conversion en niveau de gris=====&lt;br /&gt;
&lt;br /&gt;
Une des étapes préliminaires pour effectuer la détection de contour est de convertir l'image couleur en niveau de gris. Pour cela l'algorithme est simple : il suffit pour chaque pixel de l'image d'effectuer la moyenne des composantes rouge, verte, bleu de chaque pixel. En effet, si l'on considère une image matricielle (l'image est considérée comme un tableau à deux dimensions avec chaque case qui contient la couleur du pixel), chaque pixel contient les composantes RGB codées sur un octet. La couleur gris correspond aux composantes RGB égales. Le niveau de gris est donc codé de 0 à 255, avec 0 donnant du noir et 255 du blanc. &lt;br /&gt;
&lt;br /&gt;
Voici le résultat obtenu : [[Fichier:testGrayScale.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Filtre de Prewit et Sobel=====&lt;br /&gt;
&lt;br /&gt;
Un contour est défini par un changement brutal d'intensité lumineuse, il s'agit donc de détecter selon plusieurs directions (au moins 2) ces changements. Il existe de nombreuses techniques afin de détecter les contours d'une image (gradient, Laplacien). L'une des techniques avec un rapport efficacité/temps d'exécution correct repose sur les algorithmes de Prewit ou Sobel. L'algorithme repose sur la convolution de matrices.&lt;br /&gt;
Cela consiste à appliquer sur chaque pixel de l'image la matrice de Prewit définie comme &lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L_x = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; ainsi que sa transposée : &amp;lt;math&amp;gt;&lt;br /&gt;
L_y = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; -1 &amp;amp; -1 \\&lt;br /&gt;
 0 &amp;amp; 0 &amp;amp; 0 \\&lt;br /&gt;
+1 &amp;amp; +1 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Convoluer ces deux filtres sur l'image permet de détecter respectivement les contours verticaux et horizontaux.&lt;br /&gt;
&lt;br /&gt;
D'après wikipedia [https://fr.wikipedia.org/wiki/D%C3%A9tection_de_contours], on obtient de meilleurs résultats en appliquant un filtre triangulaire, on introduit donc la matrice de Sobel :&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-2 &amp;amp; 0 &amp;amp; +2 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
On obtient le résultat suivant : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testOutline1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Pré-traitement : Flou Gaussien=====&lt;br /&gt;
&lt;br /&gt;
Afin de réduire significativement le nombre de contours, il est nécessaire d'effectuer un pré-traitement avant la détection de contours. On utilise généralement un flou gaussien afin de réduire les transitions lumineuses et ainsi réduire le nombre de contours. L’algorithme de flou gaussien repose également sur la convolution de matrices sauf qu'ici la matrice filtre est générée grâce à une fonction gaussienne paramétrée par '''Sigma''' qui va directement impacter le niveau de flou. Plus la matrice de filtrage est grande plus la qualité du résultat est meilleure, mais le temps d’exécution devient également plus grand.&lt;br /&gt;
&lt;br /&gt;
Voici la fonction de génération du filtre : &amp;lt;math&amp;gt;G(x,y) = \frac{1}{{2\pi \sigma^2}} e^{-\frac{x^2 + y^2}{2 \sigma^2}}&amp;lt;/math&amp;gt; où x et y correspondent aux indices de la cellule de la matrice.&lt;br /&gt;
&lt;br /&gt;
On obtient ce résultat :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testGaussianBlur.png]]&lt;br /&gt;
&lt;br /&gt;
On note un bien meilleur résultat. Cependant on remarque que les composantes horizontales ne sont pas correctement détectées il subsiste un problème avec le filtrage vertical que je n'ai pas réussi à identifier. De plus, il s'agit par sa suite d'éliminer les contours parasites ainsi que d'affiner le trait pour n'avoir plus qu'un pixel d'épaisseur.&lt;br /&gt;
&lt;br /&gt;
=====Post-traitement : Algorithme de Canny=====&lt;br /&gt;
&lt;br /&gt;
Afin d'obtenir un résultat exploitable il est nécessaire d'appliquer encore quelques traitements. Pour cela nous utilisons l’algorithme de Canny qui repose que celui de Sobel mais qui ajoute un algorithme de seuillage par hysteresis qui permet de retirer les contours secondaires et de ne garder que les contours connexes dans une seuil haut et un seuil bas définis. En outre, cette algorithme affine également le trait obtenu. Pour cet algorithme nous avons directement trouvé des sources libres de droits [http://www.tomgibara.com/computer-vision/canny-edge-detector] qui donne des résultats très corrects.&lt;br /&gt;
&lt;br /&gt;
Par exemple :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ou encore : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny2.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 5===&lt;br /&gt;
&lt;br /&gt;
*Établissement d'un protocole de transfert d'image basé sur les WebSockets&lt;br /&gt;
**Envoie d'un requête &amp;quot;send&amp;quot; par le client dans une trame websocket texte&lt;br /&gt;
**Réponse serveur 'Y' si aucun autre client tente d'envoyer une image simultanément, 'N' sinon&lt;br /&gt;
**Si et seulement si le client reçoit 'Y' il débute le transfert en envoyant la largeur et la longueur de l'image sur 4 octets, puis les données de l'image soit 4 valeurs pour chaque pixels (r,g,b,alpha)&lt;br /&gt;
**Le serveur renvoie 'D' une fois le transfert achevé (à l'avenir, le serveur renverra l'image après filtrage).&lt;br /&gt;
**A tout moment, le serveur peut renvoyer 'E' si une erreur est survenue (ex : paquets perdus, nombre incorrects de données)&lt;br /&gt;
*Ajout du support des logs au niveau serveur&lt;br /&gt;
**Impression sur la sortie standard des messages&lt;br /&gt;
**Formatage en fonction de la sévérité du log (info, warning, error...)&lt;br /&gt;
**Incrustation de la date et heure&lt;br /&gt;
**Possibilité de redirection dans une fichier, avec configuration (écriture à la suite d'un fichier existant, écrasement...)&lt;br /&gt;
**Le tout dans une classe Java flexible et réutilisable pour d'autres projets&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 6===&lt;br /&gt;
&lt;br /&gt;
*Installation de la librairie Java Pi4j sur la raspberry pi qui permet le contrôle des GPIO de celle-ci et notamment le port I²C (basé sur WiringPi)&lt;br /&gt;
*Amélioration coté serveur websocket&lt;br /&gt;
**Gestion de message plus longs (maximum des trames websockets soit 2^63 octets)&lt;br /&gt;
**Différenciation, à la réception de messages, des trames textes ou binaires des trames de contrôle comme les requête ping, pong ou de fermeture de connexion &lt;br /&gt;
**Ajout d'un mode de debug de trames &lt;br /&gt;
&lt;br /&gt;
===Semaine 7===&lt;br /&gt;
&lt;br /&gt;
*Améliorations du serveur WebSocket&lt;br /&gt;
**Gestion de la fragmentation TCP&lt;br /&gt;
**Gestion de la fragmentation WebSocket&lt;br /&gt;
**Gestion des requêtes ping envoyés par le client en renvoyant une trames de contrôle pong afin de maintenir la connexion&lt;br /&gt;
**Gestion des déconnexion de clients afin d'optimiser le serveur&lt;br /&gt;
**Amélioration de l'émission de messages en augmentant la taille maximale pouvant être émise (2^63 octets)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A ce stade du développement, le client et le serveur sont opérationnels et peuvent s'échanger des messages ainsi que des images que le serveur traite pour extraire les contours.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 8===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 9===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 10===&lt;br /&gt;
&lt;br /&gt;
==A faire==&lt;br /&gt;
&lt;br /&gt;
MAJ 26 mars &lt;br /&gt;
&lt;br /&gt;
*Client websocket et page web&lt;br /&gt;
**Mise en page CSS&lt;br /&gt;
**Ajout canvas pour prévisualisation image projeté&lt;br /&gt;
**Ajout &amp;quot;slider&amp;quot; pour régler niveau du flou Gaussien DOUBLE&lt;br /&gt;
**Ajout slider pour de finir amplitude de la projection&lt;br /&gt;
**Afficher statut de connexion&lt;br /&gt;
**Ajout message de confirmation quand le serveur quitte ou relance&lt;br /&gt;
**Ajout boutons &amp;quot;projeter&amp;quot; &amp;quot;centrer&amp;quot; &amp;quot;eteindre&amp;quot;&lt;br /&gt;
**Gestion de plusieurs images avec délai&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Serveur WebSocket&lt;br /&gt;
**Ajout fonctionnalité envoi image de prévisualisation&lt;br /&gt;
&lt;br /&gt;
*RaspberryPi&lt;br /&gt;
**Utilisation d'un serveur bind9 pour éviter de taper IP&lt;br /&gt;
&lt;br /&gt;
*Détection de contours&lt;br /&gt;
**Implémentation algorithme de tri de la plus courte disance&lt;br /&gt;
&lt;br /&gt;
*Commande galvanomêtre&lt;br /&gt;
**Utilisation API I²C&lt;br /&gt;
**Fonction de transfert position-&amp;gt;angle-&amp;gt;tension&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;br /&gt;
&lt;br /&gt;
==Bibliographie==&lt;br /&gt;
&lt;br /&gt;
http://www.ebay.com/itm/20KPPS-30KPPS-laser-scanning-galvo-scanner-ILDA-Closed-Loop-max-30kpps-for-laser-/261517002270?hash=item3ce3a0c61e&lt;br /&gt;
&lt;br /&gt;
https://icn.fenelonlille.org/mediawiki/index.php/Projet_ICN_commun_2016/2017&lt;br /&gt;
&lt;br /&gt;
https://www.g33k-zone.org/post/2016/05/11/Configurer-le-Raspberry-Pi-en-point-d-acc%C3%A8s-Wifi&lt;br /&gt;
&lt;br /&gt;
http://stackoverflow.com/questions/22087076/how-to-make-a-simple-image-upload-using-javascript-html&lt;br /&gt;
&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_a_WebSocket_server_in_Java&lt;br /&gt;
&lt;br /&gt;
export http_proxy=http://proxy.polytech-lille.fr:3128&lt;/div&gt;</summary>
		<author><name>Mtrimbur</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=40814</id>
		<title>IMA4 2016/2017 P39</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=40814"/>
				<updated>2017-03-27T17:19:50Z</updated>
		
		<summary type="html">&lt;p&gt;Mtrimbur : /* Avancement du Projet */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
===Contexte===&lt;br /&gt;
&lt;br /&gt;
Le laser est une technologie largement utilisé de nos jours dans de diverses applications. En effet, on retrouve cette technologie dans le domaine médical notamment pour la chirurgie oculaire ou encore dans industrie avec la découpe laser ou la soudure au laser.&lt;br /&gt;
&lt;br /&gt;
Le laser est une émission de photons produit par excitation d'un milieu amplificateur (ex : CO2), le rayonnement produit est unidirectionnel et monochromatique. Ce sont ces propriétés que nous allons exploiter afin réaliser un projecteur laser qui mis en mouvement est capable de dessiner des formes sur une surface à l'instar de systèmes existants utilisés pour des effets lumineux lors de festivités.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
L'objectif du projet est de créer un système de projection laser à plusieurs couleurs (au minimum deux) avec une application web pour programmer les formes à dessiner afin d'agrémenter des compétitions de gymnastique rythmique.&lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
Le projet consiste à réaliser avec des lasers des figures géométriques par l'intermédiaire d'un système galvanométrique. &lt;br /&gt;
&lt;br /&gt;
Notre premier travail sera de concevoir la partie projection. Pour cela, nous devrons aligner les lasers et les galvanomètres. En effet, ces derniers posséderont des miroirs à l'extrémité, ainsi les miroirs changeront d'inclinaison suivant le courant traversant les galvanomètres (similaire à l'image ci-contre). Il nous faudra également créer un système d'alimentation qui à partir d'une même source (réseau 230 V) sera capable d'alimenter les lasers et les galvanomètres ainsi qu'une Arduino et une Raspberry Pi.&lt;br /&gt;
[[File:Scanhead.jpeg|thumb]]&lt;br /&gt;
&lt;br /&gt;
Ensuite nous nous intéresserons à l'utilisation d'un système embarqué pour contrôler les galvanomètres et donc dessiner avec les lasers sur un plan 2D. En effet, le laser restera toujours fixe, seuls les galvanomètres, et donc les miroirs bougeront. Les galvanomètres étant contrôlés en courant il faudra réaliser une interface électronique pour convertir une commande en tension en commande de courant. La commande en tension sera assuré par une carte Arduino. Nous n'utiliserons qu'une seule paire de galvanomètres pour les deux laser. Il faudra donc multiplexer les deux faisceaux. La programmation des formes à effectuer, se fera par l'intermédiaire d'une application web PHP hébergée sur une RaspberryPi qui permettra de récupérer une image, d'y appliquer divers traitements et filtres afin d'en extraire les contours, et de calculer les commandes pour positionner les galvanomètres. Un serveur WebSocket également hébergé sur la RaspberryPi servira d'interface entre l'application web et L'arduino qui sera connecté via une liaison série sur la raspberryPI.&lt;br /&gt;
&lt;br /&gt;
Comme animation de test, nous dessinerons le contour d'une gymnaste avec une couleur et son ballon d'une autre couleur. La gymnaste devra lancer son ballon, réaliser quelques difficultés et récupérer son ballon.&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
Nous utiliserons comme matériels :&lt;br /&gt;
*Deux lasers de différentes couleurs&lt;br /&gt;
*Une paire de galvanomètres à miroir&lt;br /&gt;
*Arduino&lt;br /&gt;
*Raspberry Pi3&lt;br /&gt;
*Alimentation 230V/5V 1A [http://www.miniinthebox.com/fr/dual-usb-eu-prise-murale-5v-2a-voyage-adaptateur-chargeur-d-alimentation-pour-iphone7-6-xiaomi-samsung-et-autre-telephone-portable_p5410410.html?currency=EUR&amp;amp;litb_from=paid_adwords_shopping&amp;amp;sku=429_6917%7C752_20648&amp;amp;utm_source=google_shopping&amp;amp;utm_medium=cpc&amp;amp;adword_mt=&amp;amp;adword_ct=138705676724&amp;amp;adword_kw=&amp;amp;adword_pos=1o5&amp;amp;adword_pl=&amp;amp;adword_net=g&amp;amp;adword_tar=&amp;amp;adw_src_id=9653316068_661261352_33588296076_aud-79897721311:pla-256966386459&amp;amp;gclid=Cj0KEQiA_KvEBRCtzNil4-KR-LIBEiQAmgekFxxKjJJWBYCJlDZEa3Ke_2_WR0DzGVbz-jaCZHVIBoMaAvld8P8HAQ]&lt;br /&gt;
*Drivers galvanomètres x2&lt;br /&gt;
*Alimentation laser&lt;br /&gt;
*Lunette de sécurité x2 [https://www.amazon.fr/Uvex-S1933X-Eyewear-SCTOrange-Anti-Fog/dp/B000USRG90/ref=sr_1_1?ie=UTF8&amp;amp;qid=1485441383&amp;amp;sr=8-1&amp;amp;keywords=uvex+s1933x]&lt;br /&gt;
*Boitier ABS [http://fr.farnell.com/multicomp/g3118/boitier-abs-240x120x60mm-ip65/dp/1526656]&lt;br /&gt;
*DAC 4 canaux, avec interface I²C [https://www.adafruit.com/products/1083]&lt;br /&gt;
*Connecteur C14 [http://www.conrad.fr/ce/fr/product/715001/Connecteur-secteur-C14-Embase-male-verticale-715001-Nombre-de-poles-2-PE-10-A-noir-1-pcs/?ref=detview1&amp;amp;rt=detview1&amp;amp;rb=1]&lt;br /&gt;
*Câble secteur&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Logiciel :&lt;br /&gt;
&lt;br /&gt;
*Serveur web : Apache2, HTML5, PHP5, CSS&lt;br /&gt;
*Base de donnée : MySQL&lt;br /&gt;
*Serveur WebSocket : JQuerry, websocket&lt;br /&gt;
*Arduino : IDE Arduino&lt;br /&gt;
&lt;br /&gt;
===Calendrier prévisionnel===&lt;br /&gt;
&lt;br /&gt;
====Liste des tâches à effectuer====&lt;br /&gt;
Les différentes tâches à effectuer sont :&lt;br /&gt;
*Partie préliminaire : étude de fonctionnement des galvanomètres&lt;br /&gt;
**Déterminer comment est effectuée la commande des galvanomètres (protocole, tension...)&lt;br /&gt;
**Effectuer des tests avec l'Arduino ou la Raspberry Pi&lt;br /&gt;
**Effectuer des tests avec une LED à la place du laser &lt;br /&gt;
*Partie projection&lt;br /&gt;
**Fixer les lasers&lt;br /&gt;
**Aligner les lasers et les galvanomètres&lt;br /&gt;
**Créer le système d'alimentation&lt;br /&gt;
**Création d'un boitier&lt;br /&gt;
*Partie système embarqué&lt;br /&gt;
**Asservissement des galvanomètres avec l'Arduino&lt;br /&gt;
**Système électronique de commande en courant pour les galvanomètres&lt;br /&gt;
*Interface Web&lt;br /&gt;
**Installation et configuration Apache2&lt;br /&gt;
**Création d'une interface graphique simple&lt;br /&gt;
**Implémentation d'algorithmes de traitement d'image&lt;br /&gt;
**Mise en forme avec des CSS&lt;br /&gt;
**Sytème d'authentification avec mot de passe&lt;br /&gt;
**Utilisation d'une base de données pour enregistrer toutes les images déjà utilisés afin de les réutiliser&lt;br /&gt;
*Serveur Web Socket&lt;br /&gt;
**Récupération des données de l'interface web&lt;br /&gt;
**Mise en place de la liaison série avec l'Arduino&lt;br /&gt;
&lt;br /&gt;
====Calendrier====&lt;br /&gt;
Répartition du temps consacré au projet (240h) :&lt;br /&gt;
*Partie projection : 80h&lt;br /&gt;
*Partie système embarqué : 40h&lt;br /&gt;
*Partie interface web et websocket: 120h&lt;br /&gt;
&lt;br /&gt;
==Feuille d'heures==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!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&lt;br /&gt;
|-&lt;br /&gt;
| Définition cahier des charges &lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 14&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|38&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Finalisation du cahier des charges avec les responsables&lt;br /&gt;
&lt;br /&gt;
*Acquisition de matériels :&lt;br /&gt;
**Projecteur Laser&lt;br /&gt;
**Galvanomètres&lt;br /&gt;
**Alimentation des galvanomètres&lt;br /&gt;
&lt;br /&gt;
*Listage du matériels à acquérir :&lt;br /&gt;
**Lunettes de sécurité&lt;br /&gt;
**DAC&lt;br /&gt;
**Alimentation 230V/5V 1A&lt;br /&gt;
** Boitier ABS &lt;br /&gt;
**...&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
*Obtention de l'arduino et de la raspberryPI&lt;br /&gt;
&lt;br /&gt;
*Démontage du projecteur laser&lt;br /&gt;
**Deux lasers de classe 3b (vert et rouge)&lt;br /&gt;
**Circuit d'alimentation des deux lasers&lt;br /&gt;
&lt;br /&gt;
*Initialisation du port série de la raspberryPI&lt;br /&gt;
**Modification du fichier ''config.txt'' dans la partition boot&lt;br /&gt;
**Ajout d'une ligne autorisant la communication série ('''enable_uart=1''')&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
*Installation du serveur apache sur la raspberryPI&lt;br /&gt;
**Modification du fichier ''/etc/network/interfaces'' (Static, Address, Netmask, Gateway)&lt;br /&gt;
**Modification du fichier ''/etc/resolv.conf'' (Adresse du serveur)&lt;br /&gt;
**Utilisation d'un proxy pour la récupération outils de programmation (Apache2, Php5)&lt;br /&gt;
&lt;br /&gt;
*Mise en place du point d’accès wifi de la raspberryPI&lt;br /&gt;
**Récupération des logiciels nécessaires (dnsmasq, hostapd)&lt;br /&gt;
**Mise en place d'une adresse IP statique pour le point d'accès par l'intermédiaire du fichier ''/etc/dhcpcd.conf''&lt;br /&gt;
**Désactivation de la négociation automatique de bail dans le fichier ''/etc/network/interfaces''&lt;br /&gt;
**Configuration du logiciel hostapd ''/etc/hostapd/hostapd.conf''&lt;br /&gt;
**Activation du démarrage automatique du point d'accès ''/etc/default/hostapd''&lt;br /&gt;
**Configuration du serveur DNS par ''/etc/dnsmasq.conf''&lt;br /&gt;
&lt;br /&gt;
*Instauration de la page d'accueil de l'interface web à l'adresse ''192.168.3.1''&lt;br /&gt;
**Téléversement de fichiers images sur la page web et affichage de celle-ci&lt;br /&gt;
**Voyant de confirmation du bon fonctionnement du serveur web&lt;br /&gt;
&lt;br /&gt;
*Développement du serveur websocket&lt;br /&gt;
&lt;br /&gt;
Le développement du serveur websocket, initialement prévu en C (il était prévu de reprendre les sources utilisées l'année précédente dans le cadre des projet IMA3 SC), a finalement été réalisé en JAVA pour plusieurs raisons.&lt;br /&gt;
Premièrement, un seul programme met en œuvre le serveur websocket, les divers traitements d'image, ainsi que les contrôles des galvanomètres (par l'intermédiaire des DAC) via la liaison I²C de la Raspberry Pi. Le langage JAVA fournit nativement des bibliothèques d'objets pour manipuler assez simplement des images, il existe également des librairies pour contrôler le port GPIO de la Raspberry et il était également intéressant de travailler avec un langage de plus haut niveau que le C.&lt;br /&gt;
En outre, la totale portabilité de ce langage nous permet de travailler sur n'importe quelle machine et ensuite transférer notre programme sur la Raspberry Pi et l’exécuter sans même repasser par une phase de compilation. Et finalement, c'est le langage que nous étudions actuellement en cours de programmation orientée objet, ce qui permet de nous perfectionner.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Serveur WebSocket====&lt;br /&gt;
&lt;br /&gt;
N'ayant pas trouvé d'API WebSocket en Java satisfaisante (qui ne nécessitent pas l'installation et la configuration de nombreux outils additionnels), j'ai estimé plus commode et plus formateur de développer notre propre serveur WebSocket en se basant sur les librairies sockets de Java avec l'aide d'une documentation assez exhaustive [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers].&lt;br /&gt;
&lt;br /&gt;
Les WebSockets désignent à la fois un protocole réseau qui étend le protocole TCP ainsi qu'une API du World Wide Web. Nous nous en servons afin d'établir une communication asynchrone et bidirectionnelle entre un navigateur web et le serveur, notamment pour envoyer l'image à projeter. L’implémentation du serveur repose sur plusieurs étapes.&lt;br /&gt;
&lt;br /&gt;
1) Connexion d'un client &lt;br /&gt;
&lt;br /&gt;
2) Handshake : permet de faire le lien entre le protocole HTTP et WS. Le client envoie une requête HTTP demandant un upgrade de la connexion en protocole WS et le serveur répond en configurant la connexion (détail dans la documentation [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers]).&lt;br /&gt;
&lt;br /&gt;
3) Réception et décodage des messages : le serveurs reçoit des trames brutes, on extrait donc la taille du message ainsi que le message. De plus, les données son encodées (cryptage XOR) par un masque qui doit également être extrait.&lt;br /&gt;
&lt;br /&gt;
4) Fermeture de la communication.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le serveur supporte le multi-client il est donc nécessaire qu'il effectue ces étapes en &amp;quot;parallèle&amp;quot;. Nous utilisons donc les threads ou fils d’exécution. Un thread est donc responsable d'attendre qu'un nouveau client se connecte et effectue le &amp;quot;handshake&amp;quot;, il crée ensuite un thread associé à ce client afin d'établir un canal de communication. Il y a donc au moins un thread par client. Par la suite il faudra également implémenter une déconnexion automatique d'un client notamment après un timeout.&lt;br /&gt;
&lt;br /&gt;
Exemple d’exécution du serveur avec deux clients qui se connectent et envoient un message : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testServeur.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Les clients sont des navigateurs web. Pour les tests nous avons repris les exemples utilisés dans le cadre das projets IMA3 SC avec le titre de la page HTML qui se colore en vert lorsque le client est connecté, et un champ de saisie pour envoyer des messages au serveur : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testClient.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 4===&lt;br /&gt;
&lt;br /&gt;
*Mise en place d’algorithmes de traitement d'image&lt;br /&gt;
&lt;br /&gt;
====Détection de contour====&lt;br /&gt;
&lt;br /&gt;
L'objectif de notre projet est de pouvoir projeter n'importe quelle image envoyé grâce à l'application web. Pour cela nous allons tracer à une vitesse élevée les contours de l'image sur par exemple un mur grâce au laser. Il est donc nécessaire de détecter les contours de l'image grâce à plusieurs traitements.&lt;br /&gt;
&lt;br /&gt;
=====Conversion en niveau de gris=====&lt;br /&gt;
&lt;br /&gt;
Une des étapes préliminaires pour effectuer la détection de contour est de convertir l'image couleur en niveau de gris. Pour cela l'algorithme est simple : il suffit pour chaque pixel de l'image d'effectuer la moyenne des composantes rouge, verte, bleu de chaque pixel. En effet, si l'on considère une image matricielle (l'image est considérée comme un tableau à deux dimensions avec chaque case qui contient la couleur du pixel), chaque pixel contient les composantes RGB codées sur un octet. La couleur gris correspond aux composantes RGB égales. Le niveau de gris est donc codé de 0 à 255, avec 0 donnant du noir et 255 du blanc. &lt;br /&gt;
&lt;br /&gt;
Voici le résultat obtenu : [[Fichier:testGrayScale.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Filtre de Prewit et Sobel=====&lt;br /&gt;
&lt;br /&gt;
Un contour est défini par un changement brutal d'intensité lumineuse, il s'agit donc de détecter selon plusieurs directions (au moins 2) ces changements. Il existe de nombreuses techniques afin de détecter les contours d'une image (gradient, Laplacien). L'une des techniques avec un rapport efficacité/temps d'exécution correct repose sur les algorithmes de Prewit ou Sobel. L'algorithme repose sur la convolution de matrices.&lt;br /&gt;
Cela consiste à appliquer sur chaque pixel de l'image la matrice de Prewit définie comme &lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L_x = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; ainsi que sa transposée : &amp;lt;math&amp;gt;&lt;br /&gt;
L_y = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; -1 &amp;amp; -1 \\&lt;br /&gt;
 0 &amp;amp; 0 &amp;amp; 0 \\&lt;br /&gt;
+1 &amp;amp; +1 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Convoluer ces deux filtres sur l'image permet de détecter respectivement les contours verticaux et horizontaux.&lt;br /&gt;
&lt;br /&gt;
D'après wikipedia [https://fr.wikipedia.org/wiki/D%C3%A9tection_de_contours], on obtient de meilleurs résultats en appliquant un filtre triangulaire, on introduit donc la matrice de Sobel :&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-2 &amp;amp; 0 &amp;amp; +2 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
On obtient le résultat suivant : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testOutline1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Pré-traitement : Flou Gaussien=====&lt;br /&gt;
&lt;br /&gt;
Afin de réduire significativement le nombre de contours, il est nécessaire d'effectuer un pré-traitement avant la détection de contours. On utilise généralement un flou gaussien afin de réduire les transitions lumineuses et ainsi réduire le nombre de contours. L’algorithme de flou gaussien repose également sur la convolution de matrices sauf qu'ici la matrice filtre est générée grâce à une fonction gaussienne paramétrée par '''Sigma''' qui va directement impacter le niveau de flou. Plus la matrice de filtrage est grande plus la qualité du résultat est meilleure, mais le temps d’exécution devient également plus grand.&lt;br /&gt;
&lt;br /&gt;
Voici la fonction de génération du filtre : &amp;lt;math&amp;gt;G(x,y) = \frac{1}{{2\pi \sigma^2}} e^{-\frac{x^2 + y^2}{2 \sigma^2}}&amp;lt;/math&amp;gt; où x et y correspondent aux indices de la cellule de la matrice.&lt;br /&gt;
&lt;br /&gt;
On obtient ce résultat :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testGaussianBlur.png]]&lt;br /&gt;
&lt;br /&gt;
On note un bien meilleur résultat. Cependant on remarque que les composantes horizontales ne sont pas correctement détectées il subsiste un problème avec le filtrage vertical que je n'ai pas réussi à identifier. De plus, il s'agit par sa suite d'éliminer les contours parasites ainsi que d'affiner le trait pour n'avoir plus qu'un pixel d'épaisseur.&lt;br /&gt;
&lt;br /&gt;
=====Post-traitement : Algorithme de Canny=====&lt;br /&gt;
&lt;br /&gt;
Afin d'obtenir un résultat exploitable il est nécessaire d'appliquer encore quelques traitements. Pour cela nous utilisons l’algorithme de Canny qui repose que celui de Sobel mais qui ajoute un algorithme de seuillage par hysteresis qui permet de retirer les contours secondaires et de ne garder que les contours connexes dans une seuil haut et un seuil bas définis. En outre, cette algorithme affine également le trait obtenu. Pour cet algorithme nous avons directement trouvé des sources libres de droits [http://www.tomgibara.com/computer-vision/canny-edge-detector] qui donne des résultats très corrects.&lt;br /&gt;
&lt;br /&gt;
Par exemple :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ou encore : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny2.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 5===&lt;br /&gt;
&lt;br /&gt;
*Établissement d'un protocole de transfert d'image basé sur les WebSockets&lt;br /&gt;
**Envoie d'un requête &amp;quot;send&amp;quot; par le client dans une trame websocket texte&lt;br /&gt;
**Réponse serveur 'Y' si aucun autre client tente d'envoyer une image simultanément, 'N' sinon&lt;br /&gt;
**Si et seulement si le client reçoit 'Y' il débute le transfert en envoyant la largeur et la longueur de l'image sur 4 octets, puis les données de l'image soit 4 valeurs pour chaque pixels (r,g,b,alpha)&lt;br /&gt;
**Le serveur renvoie 'D' une fois le transfert achevé (à l'avenir, le serveur renverra l'image après filtrage).&lt;br /&gt;
**A tout moment, le serveur peut renvoyer 'E' si une erreur est survenue (ex : paquets perdus, nombre incorrects de données)&lt;br /&gt;
*Ajout du support des logs au niveau serveur&lt;br /&gt;
**Impression sur la sortie standard des messages&lt;br /&gt;
**Formatage en fonction de la sévérité du log (info, warning, error...)&lt;br /&gt;
**Incrustation de la date et heure&lt;br /&gt;
**Possibilité de redirection dans une fichier, avec configuration (écriture à la suite d'un fichier existant, écrasement...)&lt;br /&gt;
**Le tout dans une classe Java flexible et réutilisable pour d'autres projets&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 6===&lt;br /&gt;
&lt;br /&gt;
*Installation de la librairie Java Pi4j sur la raspberry pi qui permet le contrôle des GPIO de celle-ci et notamment le port I²C (basé sur WiringPi)&lt;br /&gt;
*Amélioration coté serveur websocket&lt;br /&gt;
**Gestion de message plus longs (maximum des trames websockets soit 2^63 octets)&lt;br /&gt;
**Différenciation, à la réception de messages, des trames textes ou binaires des trames de contrôle comme les requête ping, pong ou de fermeture de connexion &lt;br /&gt;
**Ajout d'un mode de debug de trames &lt;br /&gt;
&lt;br /&gt;
===Semaine 7===&lt;br /&gt;
&lt;br /&gt;
*Améliorations du serveur WebSocket&lt;br /&gt;
**Gestion de la fragmentation TCP&lt;br /&gt;
**Gestion de la fragmentation WebSocket&lt;br /&gt;
**Gestion des requêtes ping envoyés par le client en renvoyant une trames de contrôle pong afin de maintenir la connexion&lt;br /&gt;
**Gestion des déconnexion de clients afin d'optimiser le serveur&lt;br /&gt;
**Amélioration de l'émission de messages en augmentant la taille maximale pouvant être émise (2^63 octets)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A ce stade du développement, le client et le serveur sont opérationnels et peuvent s'échanger des messages ainsi que des images que le serveur traite pour extraire les contours.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 7===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 8===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 9===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 10===&lt;br /&gt;
&lt;br /&gt;
==A faire==&lt;br /&gt;
&lt;br /&gt;
MAJ 26 mars &lt;br /&gt;
&lt;br /&gt;
*Client websocket et page web&lt;br /&gt;
**Mise en page CSS&lt;br /&gt;
**Ajout canvas pour prévisualisation image projeté&lt;br /&gt;
**Ajout &amp;quot;slider&amp;quot; pour régler niveau du flou Gaussien DOUBLE&lt;br /&gt;
**Ajout slider pour de finir amplitude de la projection&lt;br /&gt;
**Afficher statut de connexion&lt;br /&gt;
**Ajout message de confirmation quand le serveur quitte ou relance&lt;br /&gt;
**Ajout boutons &amp;quot;projeter&amp;quot; &amp;quot;centrer&amp;quot; &amp;quot;eteindre&amp;quot;&lt;br /&gt;
**Gestion de plusieurs images avec délai&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Serveur WebSocket&lt;br /&gt;
**Ajout fonctionnalité envoi image de prévisualisation&lt;br /&gt;
&lt;br /&gt;
*RaspberryPi&lt;br /&gt;
**Utilisation d'un serveur bind9 pour éviter de taper IP&lt;br /&gt;
&lt;br /&gt;
*Détection de contours&lt;br /&gt;
**Implémentation algorithme de tri de la plus courte disance&lt;br /&gt;
&lt;br /&gt;
*Commande galvanomêtre&lt;br /&gt;
**Utilisation API I²C&lt;br /&gt;
**Fonction de transfert position-&amp;gt;angle-&amp;gt;tension&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;br /&gt;
&lt;br /&gt;
==Bibliographie==&lt;br /&gt;
&lt;br /&gt;
http://www.ebay.com/itm/20KPPS-30KPPS-laser-scanning-galvo-scanner-ILDA-Closed-Loop-max-30kpps-for-laser-/261517002270?hash=item3ce3a0c61e&lt;br /&gt;
&lt;br /&gt;
https://icn.fenelonlille.org/mediawiki/index.php/Projet_ICN_commun_2016/2017&lt;br /&gt;
&lt;br /&gt;
https://www.g33k-zone.org/post/2016/05/11/Configurer-le-Raspberry-Pi-en-point-d-acc%C3%A8s-Wifi&lt;br /&gt;
&lt;br /&gt;
http://stackoverflow.com/questions/22087076/how-to-make-a-simple-image-upload-using-javascript-html&lt;br /&gt;
&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_a_WebSocket_server_in_Java&lt;br /&gt;
&lt;br /&gt;
export http_proxy=http://proxy.polytech-lille.fr:3128&lt;/div&gt;</summary>
		<author><name>Mtrimbur</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=40813</id>
		<title>IMA4 2016/2017 P39</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=40813"/>
				<updated>2017-03-27T17:17:12Z</updated>
		
		<summary type="html">&lt;p&gt;Mtrimbur : /* A faire */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
===Contexte===&lt;br /&gt;
&lt;br /&gt;
Le laser est une technologie largement utilisé de nos jours dans de diverses applications. En effet, on retrouve cette technologie dans le domaine médical notamment pour la chirurgie oculaire ou encore dans industrie avec la découpe laser ou la soudure au laser.&lt;br /&gt;
&lt;br /&gt;
Le laser est une émission de photons produit par excitation d'un milieu amplificateur (ex : CO2), le rayonnement produit est unidirectionnel et monochromatique. Ce sont ces propriétés que nous allons exploiter afin réaliser un projecteur laser qui mis en mouvement est capable de dessiner des formes sur une surface à l'instar de systèmes existants utilisés pour des effets lumineux lors de festivités.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
L'objectif du projet est de créer un système de projection laser à plusieurs couleurs (au minimum deux) avec une application web pour programmer les formes à dessiner afin d'agrémenter des compétitions de gymnastique rythmique.&lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
Le projet consiste à réaliser avec des lasers des figures géométriques par l'intermédiaire d'un système galvanométrique. &lt;br /&gt;
&lt;br /&gt;
Notre premier travail sera de concevoir la partie projection. Pour cela, nous devrons aligner les lasers et les galvanomètres. En effet, ces derniers posséderont des miroirs à l'extrémité, ainsi les miroirs changeront d'inclinaison suivant le courant traversant les galvanomètres (similaire à l'image ci-contre). Il nous faudra également créer un système d'alimentation qui à partir d'une même source (réseau 230 V) sera capable d'alimenter les lasers et les galvanomètres ainsi qu'une Arduino et une Raspberry Pi.&lt;br /&gt;
[[File:Scanhead.jpeg|thumb]]&lt;br /&gt;
&lt;br /&gt;
Ensuite nous nous intéresserons à l'utilisation d'un système embarqué pour contrôler les galvanomètres et donc dessiner avec les lasers sur un plan 2D. En effet, le laser restera toujours fixe, seuls les galvanomètres, et donc les miroirs bougeront. Les galvanomètres étant contrôlés en courant il faudra réaliser une interface électronique pour convertir une commande en tension en commande de courant. La commande en tension sera assuré par une carte Arduino. Nous n'utiliserons qu'une seule paire de galvanomètres pour les deux laser. Il faudra donc multiplexer les deux faisceaux. La programmation des formes à effectuer, se fera par l'intermédiaire d'une application web PHP hébergée sur une RaspberryPi qui permettra de récupérer une image, d'y appliquer divers traitements et filtres afin d'en extraire les contours, et de calculer les commandes pour positionner les galvanomètres. Un serveur WebSocket également hébergé sur la RaspberryPi servira d'interface entre l'application web et L'arduino qui sera connecté via une liaison série sur la raspberryPI.&lt;br /&gt;
&lt;br /&gt;
Comme animation de test, nous dessinerons le contour d'une gymnaste avec une couleur et son ballon d'une autre couleur. La gymnaste devra lancer son ballon, réaliser quelques difficultés et récupérer son ballon.&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
Nous utiliserons comme matériels :&lt;br /&gt;
*Deux lasers de différentes couleurs&lt;br /&gt;
*Une paire de galvanomètres à miroir&lt;br /&gt;
*Arduino&lt;br /&gt;
*Raspberry Pi3&lt;br /&gt;
*Alimentation 230V/5V 1A [http://www.miniinthebox.com/fr/dual-usb-eu-prise-murale-5v-2a-voyage-adaptateur-chargeur-d-alimentation-pour-iphone7-6-xiaomi-samsung-et-autre-telephone-portable_p5410410.html?currency=EUR&amp;amp;litb_from=paid_adwords_shopping&amp;amp;sku=429_6917%7C752_20648&amp;amp;utm_source=google_shopping&amp;amp;utm_medium=cpc&amp;amp;adword_mt=&amp;amp;adword_ct=138705676724&amp;amp;adword_kw=&amp;amp;adword_pos=1o5&amp;amp;adword_pl=&amp;amp;adword_net=g&amp;amp;adword_tar=&amp;amp;adw_src_id=9653316068_661261352_33588296076_aud-79897721311:pla-256966386459&amp;amp;gclid=Cj0KEQiA_KvEBRCtzNil4-KR-LIBEiQAmgekFxxKjJJWBYCJlDZEa3Ke_2_WR0DzGVbz-jaCZHVIBoMaAvld8P8HAQ]&lt;br /&gt;
*Drivers galvanomètres x2&lt;br /&gt;
*Alimentation laser&lt;br /&gt;
*Lunette de sécurité x2 [https://www.amazon.fr/Uvex-S1933X-Eyewear-SCTOrange-Anti-Fog/dp/B000USRG90/ref=sr_1_1?ie=UTF8&amp;amp;qid=1485441383&amp;amp;sr=8-1&amp;amp;keywords=uvex+s1933x]&lt;br /&gt;
*Boitier ABS [http://fr.farnell.com/multicomp/g3118/boitier-abs-240x120x60mm-ip65/dp/1526656]&lt;br /&gt;
*DAC 4 canaux, avec interface I²C [https://www.adafruit.com/products/1083]&lt;br /&gt;
*Connecteur C14 [http://www.conrad.fr/ce/fr/product/715001/Connecteur-secteur-C14-Embase-male-verticale-715001-Nombre-de-poles-2-PE-10-A-noir-1-pcs/?ref=detview1&amp;amp;rt=detview1&amp;amp;rb=1]&lt;br /&gt;
*Câble secteur&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Logiciel :&lt;br /&gt;
&lt;br /&gt;
*Serveur web : Apache2, HTML5, PHP5, CSS&lt;br /&gt;
*Base de donnée : MySQL&lt;br /&gt;
*Serveur WebSocket : JQuerry, websocket&lt;br /&gt;
*Arduino : IDE Arduino&lt;br /&gt;
&lt;br /&gt;
===Calendrier prévisionnel===&lt;br /&gt;
&lt;br /&gt;
====Liste des tâches à effectuer====&lt;br /&gt;
Les différentes tâches à effectuer sont :&lt;br /&gt;
*Partie préliminaire : étude de fonctionnement des galvanomètres&lt;br /&gt;
**Déterminer comment est effectuée la commande des galvanomètres (protocole, tension...)&lt;br /&gt;
**Effectuer des tests avec l'Arduino ou la Raspberry Pi&lt;br /&gt;
**Effectuer des tests avec une LED à la place du laser &lt;br /&gt;
*Partie projection&lt;br /&gt;
**Fixer les lasers&lt;br /&gt;
**Aligner les lasers et les galvanomètres&lt;br /&gt;
**Créer le système d'alimentation&lt;br /&gt;
**Création d'un boitier&lt;br /&gt;
*Partie système embarqué&lt;br /&gt;
**Asservissement des galvanomètres avec l'Arduino&lt;br /&gt;
**Système électronique de commande en courant pour les galvanomètres&lt;br /&gt;
*Interface Web&lt;br /&gt;
**Installation et configuration Apache2&lt;br /&gt;
**Création d'une interface graphique simple&lt;br /&gt;
**Implémentation d'algorithmes de traitement d'image&lt;br /&gt;
**Mise en forme avec des CSS&lt;br /&gt;
**Sytème d'authentification avec mot de passe&lt;br /&gt;
**Utilisation d'une base de données pour enregistrer toutes les images déjà utilisés afin de les réutiliser&lt;br /&gt;
*Serveur Web Socket&lt;br /&gt;
**Récupération des données de l'interface web&lt;br /&gt;
**Mise en place de la liaison série avec l'Arduino&lt;br /&gt;
&lt;br /&gt;
====Calendrier====&lt;br /&gt;
Répartition du temps consacré au projet (240h) :&lt;br /&gt;
*Partie projection : 80h&lt;br /&gt;
*Partie système embarqué : 40h&lt;br /&gt;
*Partie interface web et websocket: 120h&lt;br /&gt;
&lt;br /&gt;
==Feuille d'heures==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!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&lt;br /&gt;
|-&lt;br /&gt;
| Définition cahier des charges &lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 14&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|38&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Finalisation du cahier des charges avec les responsables&lt;br /&gt;
&lt;br /&gt;
*Acquisition de matériels :&lt;br /&gt;
**Projecteur Laser&lt;br /&gt;
**Galvanomètres&lt;br /&gt;
**Alimentation des galvanomètres&lt;br /&gt;
&lt;br /&gt;
*Listage du matériels à acquérir :&lt;br /&gt;
**Lunettes de sécurité&lt;br /&gt;
**DAC&lt;br /&gt;
**Alimentation 230V/5V 1A&lt;br /&gt;
** Boitier ABS &lt;br /&gt;
**...&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
*Obtention de l'arduino et de la raspberryPI&lt;br /&gt;
&lt;br /&gt;
*Démontage du projecteur laser&lt;br /&gt;
**Deux lasers de classe 3b (vert et rouge)&lt;br /&gt;
**Circuit d'alimentation des deux lasers&lt;br /&gt;
&lt;br /&gt;
*Initialisation du port série de la raspberryPI&lt;br /&gt;
**Modification du fichier ''config.txt'' dans la partition boot&lt;br /&gt;
**Ajout d'une ligne autorisant la communication série ('''enable_uart=1''')&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
*Installation du serveur apache sur la raspberryPI&lt;br /&gt;
**Modification du fichier ''/etc/network/interfaces'' (Static, Address, Netmask, Gateway)&lt;br /&gt;
**Modification du fichier ''/etc/resolv.conf'' (Adresse du serveur)&lt;br /&gt;
**Utilisation d'un proxy pour la récupération outils de programmation (Apache2, Php5)&lt;br /&gt;
&lt;br /&gt;
*Mise en place du point d’accès wifi de la raspberryPI&lt;br /&gt;
**Récupération des logiciels nécessaires (dnsmasq, hostapd)&lt;br /&gt;
**Mise en place d'une adresse IP statique pour le point d'accès par l'intermédiaire du fichier ''/etc/dhcpcd.conf''&lt;br /&gt;
**Désactivation de la négociation automatique de bail dans le fichier ''/etc/network/interfaces''&lt;br /&gt;
**Configuration du logiciel hostapd ''/etc/hostapd/hostapd.conf''&lt;br /&gt;
**Activation du démarrage automatique du point d'accès ''/etc/default/hostapd''&lt;br /&gt;
**Configuration du serveur DNS par ''/etc/dnsmasq.conf''&lt;br /&gt;
&lt;br /&gt;
*Instauration de la page d'accueil de l'interface web à l'adresse ''192.168.3.1''&lt;br /&gt;
**Téléversement de fichiers images sur la page web et affichage de celle-ci&lt;br /&gt;
**Voyant de confirmation du bon fonctionnement du serveur web&lt;br /&gt;
&lt;br /&gt;
*Développement du serveur websocket&lt;br /&gt;
&lt;br /&gt;
Le développement du serveur websocket, initialement prévu en C (il était prévu de reprendre les sources utilisées l'année précédente dans le cadre des projet IMA3 SC), a finalement été réalisé en JAVA pour plusieurs raisons.&lt;br /&gt;
Premièrement, un seul programme met en œuvre le serveur websocket, les divers traitements d'image, ainsi que les contrôles des galvanomètres (par l'intermédiaire des DAC) via la liaison I²C de la Raspberry Pi. Le langage JAVA fournit nativement des bibliothèques d'objets pour manipuler assez simplement des images, il existe également des librairies pour contrôler le port GPIO de la Raspberry et il était également intéressant de travailler avec un langage de plus haut niveau que le C.&lt;br /&gt;
En outre, la totale portabilité de ce langage nous permet de travailler sur n'importe quelle machine et ensuite transférer notre programme sur la Raspberry Pi et l’exécuter sans même repasser par une phase de compilation. Et finalement, c'est le langage que nous étudions actuellement en cours de programmation orientée objet, ce qui permet de nous perfectionner.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Serveur WebSocket====&lt;br /&gt;
&lt;br /&gt;
N'ayant pas trouvé d'API WebSocket en Java satisfaisante (qui ne nécessitent pas l'installation et la configuration de nombreux outils additionnels), j'ai estimé plus commode et plus formateur de développer notre propre serveur WebSocket en se basant sur les librairies sockets de Java avec l'aide d'une documentation assez exhaustive [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers].&lt;br /&gt;
&lt;br /&gt;
Les WebSockets désignent à la fois un protocole réseau qui étend le protocole TCP ainsi qu'une API du World Wide Web. Nous nous en servons afin d'établir une communication asynchrone et bidirectionnelle entre un navigateur web et le serveur, notamment pour envoyer l'image à projeter. L’implémentation du serveur repose sur plusieurs étapes.&lt;br /&gt;
&lt;br /&gt;
1) Connexion d'un client &lt;br /&gt;
&lt;br /&gt;
2) Handshake : permet de faire le lien entre le protocole HTTP et WS. Le client envoie une requête HTTP demandant un upgrade de la connexion en protocole WS et le serveur répond en configurant la connexion (détail dans la documentation [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers]).&lt;br /&gt;
&lt;br /&gt;
3) Réception et décodage des messages : le serveurs reçoit des trames brutes, on extrait donc la taille du message ainsi que le message. De plus, les données son encodées (cryptage XOR) par un masque qui doit également être extrait.&lt;br /&gt;
&lt;br /&gt;
4) Fermeture de la communication.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le serveur supporte le multi-client il est donc nécessaire qu'il effectue ces étapes en &amp;quot;parallèle&amp;quot;. Nous utilisons donc les threads ou fils d’exécution. Un thread est donc responsable d'attendre qu'un nouveau client se connecte et effectue le &amp;quot;handshake&amp;quot;, il crée ensuite un thread associé à ce client afin d'établir un canal de communication. Il y a donc au moins un thread par client. Par la suite il faudra également implémenter une déconnexion automatique d'un client notamment après un timeout.&lt;br /&gt;
&lt;br /&gt;
Exemple d’exécution du serveur avec deux clients qui se connectent et envoient un message : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testServeur.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Les clients sont des navigateurs web. Pour les tests nous avons repris les exemples utilisés dans le cadre das projets IMA3 SC avec le titre de la page HTML qui se colore en vert lorsque le client est connecté, et un champ de saisie pour envoyer des messages au serveur : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testClient.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 4===&lt;br /&gt;
&lt;br /&gt;
*Mise en place d’algorithmes de traitement d'image&lt;br /&gt;
&lt;br /&gt;
====Détection de contour====&lt;br /&gt;
&lt;br /&gt;
L'objectif de notre projet est de pouvoir projeter n'importe quelle image envoyé grâce à l'application web. Pour cela nous allons tracer à une vitesse élevée les contours de l'image sur par exemple un mur grâce au laser. Il est donc nécessaire de détecter les contours de l'image grâce à plusieurs traitements.&lt;br /&gt;
&lt;br /&gt;
=====Conversion en niveau de gris=====&lt;br /&gt;
&lt;br /&gt;
Une des étapes préliminaires pour effectuer la détection de contour est de convertir l'image couleur en niveau de gris. Pour cela l'algorithme est simple : il suffit pour chaque pixel de l'image d'effectuer la moyenne des composantes rouge, verte, bleu de chaque pixel. En effet, si l'on considère une image matricielle (l'image est considérée comme un tableau à deux dimensions avec chaque case qui contient la couleur du pixel), chaque pixel contient les composantes RGB codées sur un octet. La couleur gris correspond aux composantes RGB égales. Le niveau de gris est donc codé de 0 à 255, avec 0 donnant du noir et 255 du blanc. &lt;br /&gt;
&lt;br /&gt;
Voici le résultat obtenu : [[Fichier:testGrayScale.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Filtre de Prewit et Sobel=====&lt;br /&gt;
&lt;br /&gt;
Un contour est défini par un changement brutal d'intensité lumineuse, il s'agit donc de détecter selon plusieurs directions (au moins 2) ces changements. Il existe de nombreuses techniques afin de détecter les contours d'une image (gradient, Laplacien). L'une des techniques avec un rapport efficacité/temps d'exécution correct repose sur les algorithmes de Prewit ou Sobel. L'algorithme repose sur la convolution de matrices.&lt;br /&gt;
Cela consiste à appliquer sur chaque pixel de l'image la matrice de Prewit définie comme &lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L_x = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; ainsi que sa transposée : &amp;lt;math&amp;gt;&lt;br /&gt;
L_y = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; -1 &amp;amp; -1 \\&lt;br /&gt;
 0 &amp;amp; 0 &amp;amp; 0 \\&lt;br /&gt;
+1 &amp;amp; +1 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Convoluer ces deux filtres sur l'image permet de détecter respectivement les contours verticaux et horizontaux.&lt;br /&gt;
&lt;br /&gt;
D'après wikipedia [https://fr.wikipedia.org/wiki/D%C3%A9tection_de_contours], on obtient de meilleurs résultats en appliquant un filtre triangulaire, on introduit donc la matrice de Sobel :&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-2 &amp;amp; 0 &amp;amp; +2 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
On obtient le résultat suivant : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testOutline1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Pré-traitement : Flou Gaussien=====&lt;br /&gt;
&lt;br /&gt;
Afin de réduire significativement le nombre de contours, il est nécessaire d'effectuer un pré-traitement avant la détection de contours. On utilise généralement un flou gaussien afin de réduire les transitions lumineuses et ainsi réduire le nombre de contours. L’algorithme de flou gaussien repose également sur la convolution de matrices sauf qu'ici la matrice filtre est générée grâce à une fonction gaussienne paramétrée par '''Sigma''' qui va directement impacter le niveau de flou. Plus la matrice de filtrage est grande plus la qualité du résultat est meilleure, mais le temps d’exécution devient également plus grand.&lt;br /&gt;
&lt;br /&gt;
Voici la fonction de génération du filtre : &amp;lt;math&amp;gt;G(x,y) = \frac{1}{{2\pi \sigma^2}} e^{-\frac{x^2 + y^2}{2 \sigma^2}}&amp;lt;/math&amp;gt; où x et y correspondent aux indices de la cellule de la matrice.&lt;br /&gt;
&lt;br /&gt;
On obtient ce résultat :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testGaussianBlur.png]]&lt;br /&gt;
&lt;br /&gt;
On note un bien meilleur résultat. Cependant on remarque que les composantes horizontales ne sont pas correctement détectées il subsiste un problème avec le filtrage vertical que je n'ai pas réussi à identifier. De plus, il s'agit par sa suite d'éliminer les contours parasites ainsi que d'affiner le trait pour n'avoir plus qu'un pixel d'épaisseur.&lt;br /&gt;
&lt;br /&gt;
=====Post-traitement : Algorithme de Canny=====&lt;br /&gt;
&lt;br /&gt;
Afin d'obtenir un résultat exploitable il est nécessaire d'appliquer encore quelques traitements. Pour cela nous utilisons l’algorithme de Canny qui repose que celui de Sobel mais qui ajoute un algorithme de seuillage par hysteresis qui permet de retirer les contours secondaires et de ne garder que les contours connexes dans une seuil haut et un seuil bas définis. En outre, cette algorithme affine également le trait obtenu. Pour cet algorithme nous avons directement trouvé des sources libres de droits [http://www.tomgibara.com/computer-vision/canny-edge-detector] qui donne des résultats très corrects.&lt;br /&gt;
&lt;br /&gt;
Par exemple :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ou encore : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny2.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 5===&lt;br /&gt;
&lt;br /&gt;
*Établissement d'un protocole de transfert d'image basé sur les WebSockets&lt;br /&gt;
**Envoie d'un requête &amp;quot;send&amp;quot; par le client dans une trame websocket texte&lt;br /&gt;
**Réponse serveur 'Y' si aucun autre client tente d'envoyer une image simultanément, 'N' sinon&lt;br /&gt;
**Si et seulement si le client reçoit 'Y' il débute le transfert en envoyant la largeur et la longueur de l'image sur 4 octets, puis les données de l'image soit 4 valeurs pour chaque pixels (r,g,b,alpha)&lt;br /&gt;
**Le serveur renvoie 'D' une fois le transfert achevé (à l'avenir, le serveur renverra l'image après filtrage).&lt;br /&gt;
**A tout moment, le serveur peut renvoyer 'E' si une erreur est survenue (ex : paquets perdus, nombre incorrects de données)&lt;br /&gt;
*Ajout du support des logs au niveau serveur&lt;br /&gt;
**Impression sur la sortie standard des messages&lt;br /&gt;
**Formatage en fonction de la sévérité du log (info, warning, error...)&lt;br /&gt;
**Incrustation de la date et heure&lt;br /&gt;
**Possibilité de redirection dans une fichier, avec configuration (écriture à la suite d'un fichier existant, écrasement...)&lt;br /&gt;
**Le tout dans une classe Java flexible et réutilisable pour d'autres projets&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 6===&lt;br /&gt;
&lt;br /&gt;
*Installation de la librairie Java Pi4j sur la raspberry pi qui permet le contrôle des GPIO de celle-ci et notamment le port I²C (basé sur WiringPi)&lt;br /&gt;
*Amélioration coté serveur websocket&lt;br /&gt;
**Gestion de message plus longs (maximum des trames websockets soit 2^63 octets)&lt;br /&gt;
**Différenciation, à la réception de messages, des trames textes ou binaires des trames de contrôle comme les requête ping, pong ou de fermeture de connexion &lt;br /&gt;
**Ajout d'un mode de debug de trames &lt;br /&gt;
&lt;br /&gt;
===Semaine 7===&lt;br /&gt;
&lt;br /&gt;
*Améliorations du serveur WebSocket&lt;br /&gt;
**Gestion de la fragmentation TCP&lt;br /&gt;
**Gestion de la fragmentation WebSocket&lt;br /&gt;
**Gestion des requêtes ping envoyés par le client en renvoyant une trames de contrôle pong afin de maintenir la connexion&lt;br /&gt;
**Gestion des déconnexion de clients afin d'optimiser le serveur&lt;br /&gt;
**Amélioration de l'émission de messages en augmentant la taille maximale pouvant être émise (2^63 octets)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A ce stade du développement, le client et le serveur sont opérationnels et peuvent s'échanger des messages ainsi que des images que le serveur traite pour extraire les contours.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==A faire==&lt;br /&gt;
&lt;br /&gt;
MAJ 26 mars &lt;br /&gt;
&lt;br /&gt;
*Client websocket et page web&lt;br /&gt;
**Mise en page CSS&lt;br /&gt;
**Ajout canvas pour prévisualisation image projeté&lt;br /&gt;
**Ajout &amp;quot;slider&amp;quot; pour régler niveau du flou Gaussien DOUBLE&lt;br /&gt;
**Ajout slider pour de finir amplitude de la projection&lt;br /&gt;
**Afficher statut de connexion&lt;br /&gt;
**Ajout message de confirmation quand le serveur quitte ou relance&lt;br /&gt;
**Ajout boutons &amp;quot;projeter&amp;quot; &amp;quot;centrer&amp;quot; &amp;quot;eteindre&amp;quot;&lt;br /&gt;
**Gestion de plusieurs images avec délai&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Serveur WebSocket&lt;br /&gt;
**Ajout fonctionnalité envoi image de prévisualisation&lt;br /&gt;
&lt;br /&gt;
*RaspberryPi&lt;br /&gt;
**Utilisation d'un serveur bind9 pour éviter de taper IP&lt;br /&gt;
&lt;br /&gt;
*Détection de contours&lt;br /&gt;
**Implémentation algorithme de tri de la plus courte disance&lt;br /&gt;
&lt;br /&gt;
*Commande galvanomêtre&lt;br /&gt;
**Utilisation API I²C&lt;br /&gt;
**Fonction de transfert position-&amp;gt;angle-&amp;gt;tension&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;br /&gt;
&lt;br /&gt;
==Bibliographie==&lt;br /&gt;
&lt;br /&gt;
http://www.ebay.com/itm/20KPPS-30KPPS-laser-scanning-galvo-scanner-ILDA-Closed-Loop-max-30kpps-for-laser-/261517002270?hash=item3ce3a0c61e&lt;br /&gt;
&lt;br /&gt;
https://icn.fenelonlille.org/mediawiki/index.php/Projet_ICN_commun_2016/2017&lt;br /&gt;
&lt;br /&gt;
https://www.g33k-zone.org/post/2016/05/11/Configurer-le-Raspberry-Pi-en-point-d-acc%C3%A8s-Wifi&lt;br /&gt;
&lt;br /&gt;
http://stackoverflow.com/questions/22087076/how-to-make-a-simple-image-upload-using-javascript-html&lt;br /&gt;
&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_a_WebSocket_server_in_Java&lt;br /&gt;
&lt;br /&gt;
export http_proxy=http://proxy.polytech-lille.fr:3128&lt;/div&gt;</summary>
		<author><name>Mtrimbur</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=40769</id>
		<title>IMA4 2016/2017 P39</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=40769"/>
				<updated>2017-03-26T09:12:08Z</updated>
		
		<summary type="html">&lt;p&gt;Mtrimbur : /* A faire */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
===Contexte===&lt;br /&gt;
&lt;br /&gt;
Le laser est une technologie largement utilisé de nos jours dans de diverses applications. En effet, on retrouve cette technologie dans le domaine médical notamment pour la chirurgie oculaire ou encore dans industrie avec la découpe laser ou la soudure au laser.&lt;br /&gt;
&lt;br /&gt;
Le laser est une émission de photons produit par excitation d'un milieu amplificateur (ex : CO2), le rayonnement produit est unidirectionnel et monochromatique. Ce sont ces propriétés que nous allons exploiter afin réaliser un projecteur laser qui mis en mouvement est capable de dessiner des formes sur une surface à l'instar de systèmes existants utilisés pour des effets lumineux lors de festivités.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
L'objectif du projet est de créer un système de projection laser à plusieurs couleurs (au minimum deux) avec une application web pour programmer les formes à dessiner afin d'agrémenter des compétitions de gymnastique rythmique.&lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
Le projet consiste à réaliser avec des lasers des figures géométriques par l'intermédiaire d'un système galvanométrique. &lt;br /&gt;
&lt;br /&gt;
Notre premier travail sera de concevoir la partie projection. Pour cela, nous devrons aligner les lasers et les galvanomètres. En effet, ces derniers posséderont des miroirs à l'extrémité, ainsi les miroirs changeront d'inclinaison suivant le courant traversant les galvanomètres (similaire à l'image ci-contre). Il nous faudra également créer un système d'alimentation qui à partir d'une même source (réseau 230 V) sera capable d'alimenter les lasers et les galvanomètres ainsi qu'une Arduino et une Raspberry Pi.&lt;br /&gt;
[[File:Scanhead.jpeg|thumb]]&lt;br /&gt;
&lt;br /&gt;
Ensuite nous nous intéresserons à l'utilisation d'un système embarqué pour contrôler les galvanomètres et donc dessiner avec les lasers sur un plan 2D. En effet, le laser restera toujours fixe, seuls les galvanomètres, et donc les miroirs bougeront. Les galvanomètres étant contrôlés en courant il faudra réaliser une interface électronique pour convertir une commande en tension en commande de courant. La commande en tension sera assuré par une carte Arduino. Nous n'utiliserons qu'une seule paire de galvanomètres pour les deux laser. Il faudra donc multiplexer les deux faisceaux. La programmation des formes à effectuer, se fera par l'intermédiaire d'une application web PHP hébergée sur une RaspberryPi qui permettra de récupérer une image, d'y appliquer divers traitements et filtres afin d'en extraire les contours, et de calculer les commandes pour positionner les galvanomètres. Un serveur WebSocket également hébergé sur la RaspberryPi servira d'interface entre l'application web et L'arduino qui sera connecté via une liaison série sur la raspberryPI.&lt;br /&gt;
&lt;br /&gt;
Comme animation de test, nous dessinerons le contour d'une gymnaste avec une couleur et son ballon d'une autre couleur. La gymnaste devra lancer son ballon, réaliser quelques difficultés et récupérer son ballon.&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
Nous utiliserons comme matériels :&lt;br /&gt;
*Deux lasers de différentes couleurs&lt;br /&gt;
*Une paire de galvanomètres à miroir&lt;br /&gt;
*Arduino&lt;br /&gt;
*Raspberry Pi3&lt;br /&gt;
*Alimentation 230V/5V 1A [http://www.miniinthebox.com/fr/dual-usb-eu-prise-murale-5v-2a-voyage-adaptateur-chargeur-d-alimentation-pour-iphone7-6-xiaomi-samsung-et-autre-telephone-portable_p5410410.html?currency=EUR&amp;amp;litb_from=paid_adwords_shopping&amp;amp;sku=429_6917%7C752_20648&amp;amp;utm_source=google_shopping&amp;amp;utm_medium=cpc&amp;amp;adword_mt=&amp;amp;adword_ct=138705676724&amp;amp;adword_kw=&amp;amp;adword_pos=1o5&amp;amp;adword_pl=&amp;amp;adword_net=g&amp;amp;adword_tar=&amp;amp;adw_src_id=9653316068_661261352_33588296076_aud-79897721311:pla-256966386459&amp;amp;gclid=Cj0KEQiA_KvEBRCtzNil4-KR-LIBEiQAmgekFxxKjJJWBYCJlDZEa3Ke_2_WR0DzGVbz-jaCZHVIBoMaAvld8P8HAQ]&lt;br /&gt;
*Drivers galvanomètres x2&lt;br /&gt;
*Alimentation laser&lt;br /&gt;
*Lunette de sécurité x2 [https://www.amazon.fr/Uvex-S1933X-Eyewear-SCTOrange-Anti-Fog/dp/B000USRG90/ref=sr_1_1?ie=UTF8&amp;amp;qid=1485441383&amp;amp;sr=8-1&amp;amp;keywords=uvex+s1933x]&lt;br /&gt;
*Boitier ABS [http://fr.farnell.com/multicomp/g3118/boitier-abs-240x120x60mm-ip65/dp/1526656]&lt;br /&gt;
*DAC 4 canaux, avec interface I²C [https://www.adafruit.com/products/1083]&lt;br /&gt;
*Connecteur C14 [http://www.conrad.fr/ce/fr/product/715001/Connecteur-secteur-C14-Embase-male-verticale-715001-Nombre-de-poles-2-PE-10-A-noir-1-pcs/?ref=detview1&amp;amp;rt=detview1&amp;amp;rb=1]&lt;br /&gt;
*Câble secteur&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Logiciel :&lt;br /&gt;
&lt;br /&gt;
*Serveur web : Apache2, HTML5, PHP5, CSS&lt;br /&gt;
*Base de donnée : MySQL&lt;br /&gt;
*Serveur WebSocket : JQuerry, websocket&lt;br /&gt;
*Arduino : IDE Arduino&lt;br /&gt;
&lt;br /&gt;
===Calendrier prévisionnel===&lt;br /&gt;
&lt;br /&gt;
====Liste des tâches à effectuer====&lt;br /&gt;
Les différentes tâches à effectuer sont :&lt;br /&gt;
*Partie préliminaire : étude de fonctionnement des galvanomètres&lt;br /&gt;
**Déterminer comment est effectuée la commande des galvanomètres (protocole, tension...)&lt;br /&gt;
**Effectuer des tests avec l'Arduino ou la Raspberry Pi&lt;br /&gt;
**Effectuer des tests avec une LED à la place du laser &lt;br /&gt;
*Partie projection&lt;br /&gt;
**Fixer les lasers&lt;br /&gt;
**Aligner les lasers et les galvanomètres&lt;br /&gt;
**Créer le système d'alimentation&lt;br /&gt;
**Création d'un boitier&lt;br /&gt;
*Partie système embarqué&lt;br /&gt;
**Asservissement des galvanomètres avec l'Arduino&lt;br /&gt;
**Système électronique de commande en courant pour les galvanomètres&lt;br /&gt;
*Interface Web&lt;br /&gt;
**Installation et configuration Apache2&lt;br /&gt;
**Création d'une interface graphique simple&lt;br /&gt;
**Implémentation d'algorithmes de traitement d'image&lt;br /&gt;
**Mise en forme avec des CSS&lt;br /&gt;
**Sytème d'authentification avec mot de passe&lt;br /&gt;
**Utilisation d'une base de données pour enregistrer toutes les images déjà utilisés afin de les réutiliser&lt;br /&gt;
*Serveur Web Socket&lt;br /&gt;
**Récupération des données de l'interface web&lt;br /&gt;
**Mise en place de la liaison série avec l'Arduino&lt;br /&gt;
&lt;br /&gt;
====Calendrier====&lt;br /&gt;
Répartition du temps consacré au projet (240h) :&lt;br /&gt;
*Partie projection : 80h&lt;br /&gt;
*Partie système embarqué : 40h&lt;br /&gt;
*Partie interface web et websocket: 120h&lt;br /&gt;
&lt;br /&gt;
==Feuille d'heures==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!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&lt;br /&gt;
|-&lt;br /&gt;
| Définition cahier des charges &lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 14&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|38&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Finalisation du cahier des charges avec les responsables&lt;br /&gt;
&lt;br /&gt;
*Acquisition de matériels :&lt;br /&gt;
**Projecteur Laser&lt;br /&gt;
**Galvanomètres&lt;br /&gt;
**Alimentation des galvanomètres&lt;br /&gt;
&lt;br /&gt;
*Listage du matériels à acquérir :&lt;br /&gt;
**Lunettes de sécurité&lt;br /&gt;
**DAC&lt;br /&gt;
**Alimentation 230V/5V 1A&lt;br /&gt;
** Boitier ABS &lt;br /&gt;
**...&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
*Obtention de l'arduino et de la raspberryPI&lt;br /&gt;
&lt;br /&gt;
*Démontage du projecteur laser&lt;br /&gt;
**Deux lasers de classe 3b (vert et rouge)&lt;br /&gt;
**Circuit d'alimentation des deux lasers&lt;br /&gt;
&lt;br /&gt;
*Initialisation du port série de la raspberryPI&lt;br /&gt;
**Modification du fichier ''config.txt'' dans la partition boot&lt;br /&gt;
**Ajout d'une ligne autorisant la communication série ('''enable_uart=1''')&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
*Installation du serveur apache sur la raspberryPI&lt;br /&gt;
**Modification du fichier ''/etc/network/interfaces'' (Static, Address, Netmask, Gateway)&lt;br /&gt;
**Modification du fichier ''/etc/resolv.conf'' (Adresse du serveur)&lt;br /&gt;
**Utilisation d'un proxy pour la récupération outils de programmation (Apache2, Php5)&lt;br /&gt;
&lt;br /&gt;
*Mise en place du point d’accès wifi de la raspberryPI&lt;br /&gt;
**Récupération des logiciels nécessaires (dnsmasq, hostapd)&lt;br /&gt;
**Mise en place d'une adresse IP statique pour le point d'accès par l'intermédiaire du fichier ''/etc/dhcpcd.conf''&lt;br /&gt;
**Désactivation de la négociation automatique de bail dans le fichier ''/etc/network/interfaces''&lt;br /&gt;
**Configuration du logiciel hostapd ''/etc/hostapd/hostapd.conf''&lt;br /&gt;
**Activation du démarrage automatique du point d'accès ''/etc/default/hostapd''&lt;br /&gt;
**Configuration du serveur DNS par ''/etc/dnsmasq.conf''&lt;br /&gt;
&lt;br /&gt;
*Instauration de la page d'accueil de l'interface web à l'adresse ''192.168.3.1''&lt;br /&gt;
**Téléversement de fichiers images sur la page web et affichage de celle-ci&lt;br /&gt;
**Voyant de confirmation du bon fonctionnement du serveur web&lt;br /&gt;
&lt;br /&gt;
*Développement du serveur websocket&lt;br /&gt;
&lt;br /&gt;
Le développement du serveur websocket, initialement prévu en C (il était prévu de reprendre les sources utilisées l'année précédente dans le cadre des projet IMA3 SC), a finalement été réalisé en JAVA pour plusieurs raisons.&lt;br /&gt;
Premièrement, un seul programme met en œuvre le serveur websocket, les divers traitements d'image, ainsi que les contrôles des galvanomètres (par l'intermédiaire des DAC) via la liaison I²C de la Raspberry Pi. Le langage JAVA fournit nativement des bibliothèques d'objets pour manipuler assez simplement des images, il existe également des librairies pour contrôler le port GPIO de la Raspberry et il était également intéressant de travailler avec un langage de plus haut niveau que le C.&lt;br /&gt;
En outre, la totale portabilité de ce langage nous permet de travailler sur n'importe quelle machine et ensuite transférer notre programme sur la Raspberry Pi et l’exécuter sans même repasser par une phase de compilation. Et finalement, c'est le langage que nous étudions actuellement en cours de programmation orientée objet, ce qui permet de nous perfectionner.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Serveur WebSocket====&lt;br /&gt;
&lt;br /&gt;
N'ayant pas trouvé d'API WebSocket en Java satisfaisante (qui ne nécessitent pas l'installation et la configuration de nombreux outils additionnels), j'ai estimé plus commode et plus formateur de développer notre propre serveur WebSocket en se basant sur les librairies sockets de Java avec l'aide d'une documentation assez exhaustive [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers].&lt;br /&gt;
&lt;br /&gt;
Les WebSockets désignent à la fois un protocole réseau qui étend le protocole TCP ainsi qu'une API du World Wide Web. Nous nous en servons afin d'établir une communication asynchrone et bidirectionnelle entre un navigateur web et le serveur, notamment pour envoyer l'image à projeter. L’implémentation du serveur repose sur plusieurs étapes.&lt;br /&gt;
&lt;br /&gt;
1) Connexion d'un client &lt;br /&gt;
&lt;br /&gt;
2) Handshake : permet de faire le lien entre le protocole HTTP et WS. Le client envoie une requête HTTP demandant un upgrade de la connexion en protocole WS et le serveur répond en configurant la connexion (détail dans la documentation [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers]).&lt;br /&gt;
&lt;br /&gt;
3) Réception et décodage des messages : le serveurs reçoit des trames brutes, on extrait donc la taille du message ainsi que le message. De plus, les données son encodées (cryptage XOR) par un masque qui doit également être extrait.&lt;br /&gt;
&lt;br /&gt;
4) Fermeture de la communication.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le serveur supporte le multi-client il est donc nécessaire qu'il effectue ces étapes en &amp;quot;parallèle&amp;quot;. Nous utilisons donc les threads ou fils d’exécution. Un thread est donc responsable d'attendre qu'un nouveau client se connecte et effectue le &amp;quot;handshake&amp;quot;, il crée ensuite un thread associé à ce client afin d'établir un canal de communication. Il y a donc au moins un thread par client. Par la suite il faudra également implémenter une déconnexion automatique d'un client notamment après un timeout.&lt;br /&gt;
&lt;br /&gt;
Exemple d’exécution du serveur avec deux clients qui se connectent et envoient un message : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testServeur.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Les clients sont des navigateurs web. Pour les tests nous avons repris les exemples utilisés dans le cadre das projets IMA3 SC avec le titre de la page HTML qui se colore en vert lorsque le client est connecté, et un champ de saisie pour envoyer des messages au serveur : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testClient.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 4===&lt;br /&gt;
&lt;br /&gt;
*Mise en place d’algorithmes de traitement d'image&lt;br /&gt;
&lt;br /&gt;
====Détection de contour====&lt;br /&gt;
&lt;br /&gt;
L'objectif de notre projet est de pouvoir projeter n'importe quelle image envoyé grâce à l'application web. Pour cela nous allons tracer à une vitesse élevée les contours de l'image sur par exemple un mur grâce au laser. Il est donc nécessaire de détecter les contours de l'image grâce à plusieurs traitements.&lt;br /&gt;
&lt;br /&gt;
=====Conversion en niveau de gris=====&lt;br /&gt;
&lt;br /&gt;
Une des étapes préliminaires pour effectuer la détection de contour est de convertir l'image couleur en niveau de gris. Pour cela l'algorithme est simple : il suffit pour chaque pixel de l'image d'effectuer la moyenne des composantes rouge, verte, bleu de chaque pixel. En effet, si l'on considère une image matricielle (l'image est considérée comme un tableau à deux dimensions avec chaque case qui contient la couleur du pixel), chaque pixel contient les composantes RGB codées sur un octet. La couleur gris correspond aux composantes RGB égales. Le niveau de gris est donc codé de 0 à 255, avec 0 donnant du noir et 255 du blanc. &lt;br /&gt;
&lt;br /&gt;
Voici le résultat obtenu : [[Fichier:testGrayScale.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Filtre de Prewit et Sobel=====&lt;br /&gt;
&lt;br /&gt;
Un contour est défini par un changement brutal d'intensité lumineuse, il s'agit donc de détecter selon plusieurs directions (au moins 2) ces changements. Il existe de nombreuses techniques afin de détecter les contours d'une image (gradient, Laplacien). L'une des techniques avec un rapport efficacité/temps d'exécution correct repose sur les algorithmes de Prewit ou Sobel. L'algorithme repose sur la convolution de matrices.&lt;br /&gt;
Cela consiste à appliquer sur chaque pixel de l'image la matrice de Prewit définie comme &lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L_x = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; ainsi que sa transposée : &amp;lt;math&amp;gt;&lt;br /&gt;
L_y = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; -1 &amp;amp; -1 \\&lt;br /&gt;
 0 &amp;amp; 0 &amp;amp; 0 \\&lt;br /&gt;
+1 &amp;amp; +1 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Convoluer ces deux filtres sur l'image permet de détecter respectivement les contours verticaux et horizontaux.&lt;br /&gt;
&lt;br /&gt;
D'après wikipedia [https://fr.wikipedia.org/wiki/D%C3%A9tection_de_contours], on obtient de meilleurs résultats en appliquant un filtre triangulaire, on introduit donc la matrice de Sobel :&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-2 &amp;amp; 0 &amp;amp; +2 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
On obtient le résultat suivant : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testOutline1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Pré-traitement : Flou Gaussien=====&lt;br /&gt;
&lt;br /&gt;
Afin de réduire significativement le nombre de contours, il est nécessaire d'effectuer un pré-traitement avant la détection de contours. On utilise généralement un flou gaussien afin de réduire les transitions lumineuses et ainsi réduire le nombre de contours. L’algorithme de flou gaussien repose également sur la convolution de matrices sauf qu'ici la matrice filtre est générée grâce à une fonction gaussienne paramétrée par '''Sigma''' qui va directement impacter le niveau de flou. Plus la matrice de filtrage est grande plus la qualité du résultat est meilleure, mais le temps d’exécution devient également plus grand.&lt;br /&gt;
&lt;br /&gt;
Voici la fonction de génération du filtre : &amp;lt;math&amp;gt;G(x,y) = \frac{1}{{2\pi \sigma^2}} e^{-\frac{x^2 + y^2}{2 \sigma^2}}&amp;lt;/math&amp;gt; où x et y correspondent aux indices de la cellule de la matrice.&lt;br /&gt;
&lt;br /&gt;
On obtient ce résultat :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testGaussianBlur.png]]&lt;br /&gt;
&lt;br /&gt;
On note un bien meilleur résultat. Cependant on remarque que les composantes horizontales ne sont pas correctement détectées il subsiste un problème avec le filtrage vertical que je n'ai pas réussi à identifier. De plus, il s'agit par sa suite d'éliminer les contours parasites ainsi que d'affiner le trait pour n'avoir plus qu'un pixel d'épaisseur.&lt;br /&gt;
&lt;br /&gt;
=====Post-traitement : Algorithme de Canny=====&lt;br /&gt;
&lt;br /&gt;
Afin d'obtenir un résultat exploitable il est nécessaire d'appliquer encore quelques traitements. Pour cela nous utilisons l’algorithme de Canny qui repose que celui de Sobel mais qui ajoute un algorithme de seuillage par hysteresis qui permet de retirer les contours secondaires et de ne garder que les contours connexes dans une seuil haut et un seuil bas définis. En outre, cette algorithme affine également le trait obtenu. Pour cet algorithme nous avons directement trouvé des sources libres de droits [http://www.tomgibara.com/computer-vision/canny-edge-detector] qui donne des résultats très corrects.&lt;br /&gt;
&lt;br /&gt;
Par exemple :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ou encore : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny2.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 5===&lt;br /&gt;
&lt;br /&gt;
*Établissement d'un protocole de transfert d'image basé sur les WebSockets&lt;br /&gt;
**Envoie d'un requête &amp;quot;send&amp;quot; par le client dans une trame websocket texte&lt;br /&gt;
**Réponse serveur 'Y' si aucun autre client tente d'envoyer une image simultanément, 'N' sinon&lt;br /&gt;
**Si et seulement si le client reçoit 'Y' il débute le transfert en envoyant la largeur et la longueur de l'image sur 4 octets, puis les données de l'image soit 4 valeurs pour chaque pixels (r,g,b,alpha)&lt;br /&gt;
**Le serveur renvoie 'D' une fois le transfert achevé (à l'avenir, le serveur renverra l'image après filtrage).&lt;br /&gt;
**A tout moment, le serveur peut renvoyer 'E' si une erreur est survenue (ex : paquets perdus, nombre incorrects de données)&lt;br /&gt;
*Ajout du support des logs au niveau serveur&lt;br /&gt;
**Impression sur la sortie standard des messages&lt;br /&gt;
**Formatage en fonction de la sévérité du log (info, warning, error...)&lt;br /&gt;
**Incrustation de la date et heure&lt;br /&gt;
**Possibilité de redirection dans une fichier, avec configuration (écriture à la suite d'un fichier existant, écrasement...)&lt;br /&gt;
**Le tout dans une classe Java flexible et réutilisable pour d'autres projets&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 6===&lt;br /&gt;
&lt;br /&gt;
*Installation de la librairie Java Pi4j sur la raspberry pi qui permet le contrôle des GPIO de celle-ci et notamment le port I²C (basé sur WiringPi)&lt;br /&gt;
*Amélioration coté serveur websocket&lt;br /&gt;
**Gestion de message plus longs (maximum des trames websockets soit 2^63 octets)&lt;br /&gt;
**Différenciation, à la réception de messages, des trames textes ou binaires des trames de contrôle comme les requête ping, pong ou de fermeture de connexion &lt;br /&gt;
**Ajout d'un mode de debug de trames &lt;br /&gt;
&lt;br /&gt;
===Semaine 7===&lt;br /&gt;
&lt;br /&gt;
*Améliorations du serveur WebSocket&lt;br /&gt;
**Gestion de la fragmentation TCP&lt;br /&gt;
**Gestion de la fragmentation WebSocket&lt;br /&gt;
**Gestion des requêtes ping envoyés par le client en renvoyant une trames de contrôle pong afin de maintenir la connexion&lt;br /&gt;
**Gestion des déconnexion de clients afin d'optimiser le serveur&lt;br /&gt;
**Amélioration de l'émission de messages en augmentant la taille maximale pouvant être émise (2^63 octets)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A ce stade du développement, le client et le serveur sont opérationnels et peuvent s'échanger des messages ainsi que des images que le serveur traite pour extraire les contours.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==A faire==&lt;br /&gt;
&lt;br /&gt;
MAJ 26 mars &lt;br /&gt;
&lt;br /&gt;
*Client websocket et page web&lt;br /&gt;
**Mise en page CSS&lt;br /&gt;
**Ajout canvas pour prévisualisation image projeté&lt;br /&gt;
**Ajout &amp;quot;slider&amp;quot; pour régler niveau du flou Gaussien (double)&lt;br /&gt;
**Ajout message pop up en cas d'erreurs&lt;br /&gt;
**Ajout message de confirmation quand le serveur quitte ou relance&lt;br /&gt;
**Ajout boutons &amp;quot;projeter&amp;quot; &amp;quot;centrer&amp;quot; &amp;quot;eteindre&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Serveur WebSocket&lt;br /&gt;
**Ajout fonctionnalité envoi image de prévisualisation&lt;br /&gt;
&lt;br /&gt;
*RaspberryPi&lt;br /&gt;
**Utilisation d'un serveur bind9 pour éviter de taper IP&lt;br /&gt;
&lt;br /&gt;
*Détection de contours&lt;br /&gt;
**Implémentation algorithme de tri de la plus courte disance&lt;br /&gt;
&lt;br /&gt;
*Commande galvanomêtre&lt;br /&gt;
**Utilisation API I²C&lt;br /&gt;
**Fonction de transfert position-&amp;gt;angle-&amp;gt;tension&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;br /&gt;
&lt;br /&gt;
==Bibliographie==&lt;br /&gt;
&lt;br /&gt;
http://www.ebay.com/itm/20KPPS-30KPPS-laser-scanning-galvo-scanner-ILDA-Closed-Loop-max-30kpps-for-laser-/261517002270?hash=item3ce3a0c61e&lt;br /&gt;
&lt;br /&gt;
https://icn.fenelonlille.org/mediawiki/index.php/Projet_ICN_commun_2016/2017&lt;br /&gt;
&lt;br /&gt;
https://www.g33k-zone.org/post/2016/05/11/Configurer-le-Raspberry-Pi-en-point-d-acc%C3%A8s-Wifi&lt;br /&gt;
&lt;br /&gt;
http://stackoverflow.com/questions/22087076/how-to-make-a-simple-image-upload-using-javascript-html&lt;br /&gt;
&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_a_WebSocket_server_in_Java&lt;br /&gt;
&lt;br /&gt;
export http_proxy=http://proxy.polytech-lille.fr:3128&lt;/div&gt;</summary>
		<author><name>Mtrimbur</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=40489</id>
		<title>IMA4 2016/2017 P39</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=40489"/>
				<updated>2017-03-17T16:48:35Z</updated>
		
		<summary type="html">&lt;p&gt;Mtrimbur : /* A faire */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
===Contexte===&lt;br /&gt;
&lt;br /&gt;
Le laser est une technologie largement utilisé de nos jours dans de diverses applications. En effet, on retrouve cette technologie dans le domaine médical notamment pour la chirurgie oculaire ou encore dans industrie avec la découpe laser ou la soudure au laser.&lt;br /&gt;
&lt;br /&gt;
Le laser est une émission de photons produit par excitation d'un milieu amplificateur (ex : CO2), le rayonnement produit est unidirectionnel et monochromatique. Ce sont ces propriétés que nous allons exploiter afin réaliser un projecteur laser qui mis en mouvement est capable de dessiner des formes sur une surface à l'instar de systèmes existants utilisés pour des effets lumineux lors de festivités.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
L'objectif du projet est de créer un système de projection laser à plusieurs couleurs (au minimum deux) avec une application web pour programmer les formes à dessiner afin d'agrémenter des compétitions de gymnastique rythmique.&lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
Le projet consiste à réaliser avec des lasers des figures géométriques par l'intermédiaire d'un système galvanométrique. &lt;br /&gt;
&lt;br /&gt;
Notre premier travail sera de concevoir la partie projection. Pour cela, nous devrons aligner les lasers et les galvanomètres. En effet, ces derniers posséderont des miroirs à l'extrémité, ainsi les miroirs changeront d'inclinaison suivant le courant traversant les galvanomètres (similaire à l'image ci-contre). Il nous faudra également créer un système d'alimentation qui à partir d'une même source (réseau 230 V) sera capable d'alimenter les lasers et les galvanomètres ainsi qu'une Arduino et une Raspberry Pi.&lt;br /&gt;
[[File:Scanhead.jpeg|thumb]]&lt;br /&gt;
&lt;br /&gt;
Ensuite nous nous intéresserons à l'utilisation d'un système embarqué pour contrôler les galvanomètres et donc dessiner avec les lasers sur un plan 2D. En effet, le laser restera toujours fixe, seuls les galvanomètres, et donc les miroirs bougeront. Les galvanomètres étant contrôlés en courant il faudra réaliser une interface électronique pour convertir une commande en tension en commande de courant. La commande en tension sera assuré par une carte Arduino. Nous n'utiliserons qu'une seule paire de galvanomètres pour les deux laser. Il faudra donc multiplexer les deux faisceaux. La programmation des formes à effectuer, se fera par l'intermédiaire d'une application web PHP hébergée sur une RaspberryPi qui permettra de récupérer une image, d'y appliquer divers traitements et filtres afin d'en extraire les contours, et de calculer les commandes pour positionner les galvanomètres. Un serveur WebSocket également hébergé sur la RaspberryPi servira d'interface entre l'application web et L'arduino qui sera connecté via une liaison série sur la raspberryPI.&lt;br /&gt;
&lt;br /&gt;
Comme animation de test, nous dessinerons le contour d'une gymnaste avec une couleur et son ballon d'une autre couleur. La gymnaste devra lancer son ballon, réaliser quelques difficultés et récupérer son ballon.&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
Nous utiliserons comme matériels :&lt;br /&gt;
*Deux lasers de différentes couleurs&lt;br /&gt;
*Une paire de galvanomètres à miroir&lt;br /&gt;
*Arduino&lt;br /&gt;
*Raspberry Pi3&lt;br /&gt;
*Alimentation 230V/5V 1A [http://www.miniinthebox.com/fr/dual-usb-eu-prise-murale-5v-2a-voyage-adaptateur-chargeur-d-alimentation-pour-iphone7-6-xiaomi-samsung-et-autre-telephone-portable_p5410410.html?currency=EUR&amp;amp;litb_from=paid_adwords_shopping&amp;amp;sku=429_6917%7C752_20648&amp;amp;utm_source=google_shopping&amp;amp;utm_medium=cpc&amp;amp;adword_mt=&amp;amp;adword_ct=138705676724&amp;amp;adword_kw=&amp;amp;adword_pos=1o5&amp;amp;adword_pl=&amp;amp;adword_net=g&amp;amp;adword_tar=&amp;amp;adw_src_id=9653316068_661261352_33588296076_aud-79897721311:pla-256966386459&amp;amp;gclid=Cj0KEQiA_KvEBRCtzNil4-KR-LIBEiQAmgekFxxKjJJWBYCJlDZEa3Ke_2_WR0DzGVbz-jaCZHVIBoMaAvld8P8HAQ]&lt;br /&gt;
*Drivers galvanomètres x2&lt;br /&gt;
*Alimentation laser&lt;br /&gt;
*Lunette de sécurité x2 [https://www.amazon.fr/Uvex-S1933X-Eyewear-SCTOrange-Anti-Fog/dp/B000USRG90/ref=sr_1_1?ie=UTF8&amp;amp;qid=1485441383&amp;amp;sr=8-1&amp;amp;keywords=uvex+s1933x]&lt;br /&gt;
*Boitier ABS [http://fr.farnell.com/multicomp/g3118/boitier-abs-240x120x60mm-ip65/dp/1526656]&lt;br /&gt;
*DAC 4 canaux, avec interface I²C [https://www.adafruit.com/products/1083]&lt;br /&gt;
*Connecteur C14 [http://www.conrad.fr/ce/fr/product/715001/Connecteur-secteur-C14-Embase-male-verticale-715001-Nombre-de-poles-2-PE-10-A-noir-1-pcs/?ref=detview1&amp;amp;rt=detview1&amp;amp;rb=1]&lt;br /&gt;
*Câble secteur&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Logiciel :&lt;br /&gt;
&lt;br /&gt;
*Serveur web : Apache2, HTML5, PHP5, CSS&lt;br /&gt;
*Base de donnée : MySQL&lt;br /&gt;
*Serveur WebSocket : JQuerry, websocket&lt;br /&gt;
*Arduino : IDE Arduino&lt;br /&gt;
&lt;br /&gt;
===Calendrier prévisionnel===&lt;br /&gt;
&lt;br /&gt;
====Liste des tâches à effectuer====&lt;br /&gt;
Les différentes tâches à effectuer sont :&lt;br /&gt;
*Partie préliminaire : étude de fonctionnement des galvanomètres&lt;br /&gt;
**Déterminer comment est effectuée la commande des galvanomètres (protocole, tension...)&lt;br /&gt;
**Effectuer des tests avec l'Arduino ou la Raspberry Pi&lt;br /&gt;
**Effectuer des tests avec une LED à la place du laser &lt;br /&gt;
*Partie projection&lt;br /&gt;
**Fixer les lasers&lt;br /&gt;
**Aligner les lasers et les galvanomètres&lt;br /&gt;
**Créer le système d'alimentation&lt;br /&gt;
**Création d'un boitier&lt;br /&gt;
*Partie système embarqué&lt;br /&gt;
**Asservissement des galvanomètres avec l'Arduino&lt;br /&gt;
**Système électronique de commande en courant pour les galvanomètres&lt;br /&gt;
*Interface Web&lt;br /&gt;
**Installation et configuration Apache2&lt;br /&gt;
**Création d'une interface graphique simple&lt;br /&gt;
**Implémentation d'algorithmes de traitement d'image&lt;br /&gt;
**Mise en forme avec des CSS&lt;br /&gt;
**Sytème d'authentification avec mot de passe&lt;br /&gt;
**Utilisation d'une base de données pour enregistrer toutes les images déjà utilisés afin de les réutiliser&lt;br /&gt;
*Serveur Web Socket&lt;br /&gt;
**Récupération des données de l'interface web&lt;br /&gt;
**Mise en place de la liaison série avec l'Arduino&lt;br /&gt;
&lt;br /&gt;
====Calendrier====&lt;br /&gt;
Répartition du temps consacré au projet (240h) :&lt;br /&gt;
*Partie projection : 80h&lt;br /&gt;
*Partie système embarqué : 40h&lt;br /&gt;
*Partie interface web et websocket: 120h&lt;br /&gt;
&lt;br /&gt;
==Feuille d'heures==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!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&lt;br /&gt;
|-&lt;br /&gt;
| Définition cahier des charges &lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 14&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|38&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Finalisation du cahier des charges avec les responsables&lt;br /&gt;
&lt;br /&gt;
*Acquisition de matériels :&lt;br /&gt;
**Projecteur Laser&lt;br /&gt;
**Galvanomètres&lt;br /&gt;
**Alimentation des galvanomètres&lt;br /&gt;
&lt;br /&gt;
*Listage du matériels à acquérir :&lt;br /&gt;
**Lunettes de sécurité&lt;br /&gt;
**DAC&lt;br /&gt;
**Alimentation 230V/5V 1A&lt;br /&gt;
** Boitier ABS &lt;br /&gt;
**...&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
*Obtention de l'arduino et de la raspberryPI&lt;br /&gt;
&lt;br /&gt;
*Démontage du projecteur laser&lt;br /&gt;
**Deux lasers de classe 3b (vert et rouge)&lt;br /&gt;
**Circuit d'alimentation des deux lasers&lt;br /&gt;
&lt;br /&gt;
*Initialisation du port série de la raspberryPI&lt;br /&gt;
**Modification du fichier ''config.txt'' dans la partition boot&lt;br /&gt;
**Ajout d'une ligne autorisant la communication série ('''enable_uart=1''')&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
*Installation du serveur apache sur la raspberryPI&lt;br /&gt;
**Modification du fichier ''/etc/network/interfaces'' (Static, Address, Netmask, Gateway)&lt;br /&gt;
**Modification du fichier ''/etc/resolv.conf'' (Adresse du serveur)&lt;br /&gt;
**Utilisation d'un proxy pour la récupération outils de programmation (Apache2, Php5)&lt;br /&gt;
&lt;br /&gt;
*Mise en place du point d’accès wifi de la raspberryPI&lt;br /&gt;
**Récupération des logiciels nécessaires (dnsmasq, hostapd)&lt;br /&gt;
**Mise en place d'une adresse IP statique pour le point d'accès par l'intermédiaire du fichier ''/etc/dhcpcd.conf''&lt;br /&gt;
**Désactivation de la négociation automatique de bail dans le fichier ''/etc/network/interfaces''&lt;br /&gt;
**Configuration du logiciel hostapd ''/etc/hostapd/hostapd.conf''&lt;br /&gt;
**Activation du démarrage automatique du point d'accès ''/etc/default/hostapd''&lt;br /&gt;
**Configuration du serveur DNS par ''/etc/dnsmasq.conf''&lt;br /&gt;
&lt;br /&gt;
*Instauration de la page d'accueil de l'interface web à l'adresse ''192.168.3.1''&lt;br /&gt;
**Téléversement de fichiers images sur la page web et affichage de celle-ci&lt;br /&gt;
**Voyant de confirmation du bon fonctionnement du serveur web&lt;br /&gt;
&lt;br /&gt;
*Développement du serveur websocket&lt;br /&gt;
&lt;br /&gt;
Le développement du serveur websocket, initialement prévu en C (il était prévu de reprendre les sources utilisées l'année précédente dans le cadre des projet IMA3 SC), a finalement été réalisé en JAVA pour plusieurs raisons.&lt;br /&gt;
Premièrement, un seul programme met en œuvre le serveur websocket, les divers traitements d'image, ainsi que les contrôles des galvanomètres (par l'intermédiaire des DAC) via la liaison I²C de la Raspberry Pi. Le langage JAVA fournit nativement des bibliothèques d'objets pour manipuler assez simplement des images, il existe également des librairies pour contrôler le port GPIO de la Raspberry et il était également intéressant de travailler avec un langage de plus haut niveau que le C.&lt;br /&gt;
En outre, la totale portabilité de ce langage nous permet de travailler sur n'importe quelle machine et ensuite transférer notre programme sur la Raspberry Pi et l’exécuter sans même repasser par une phase de compilation. Et finalement, c'est le langage que nous étudions actuellement en cours de programmation orientée objet, ce qui permet de nous perfectionner.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Serveur WebSocket====&lt;br /&gt;
&lt;br /&gt;
N'ayant pas trouvé d'API WebSocket en Java satisfaisante (qui ne nécessitent pas l'installation et la configuration de nombreux outils additionnels), j'ai estimé plus commode et plus formateur de développer notre propre serveur WebSocket en se basant sur les librairies sockets de Java avec l'aide d'une documentation assez exhaustive [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers].&lt;br /&gt;
&lt;br /&gt;
Les WebSockets désignent à la fois un protocole réseau qui étend le protocole TCP ainsi qu'une API du World Wide Web. Nous nous en servons afin d'établir une communication asynchrone et bidirectionnelle entre un navigateur web et le serveur, notamment pour envoyer l'image à projeter. L’implémentation du serveur repose sur plusieurs étapes.&lt;br /&gt;
&lt;br /&gt;
1) Connexion d'un client &lt;br /&gt;
&lt;br /&gt;
2) Handshake : permet de faire le lien entre le protocole HTTP et WS. Le client envoie une requête HTTP demandant un upgrade de la connexion en protocole WS et le serveur répond en configurant la connexion (détail dans la documentation [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers]).&lt;br /&gt;
&lt;br /&gt;
3) Réception et décodage des messages : le serveurs reçoit des trames brutes, on extrait donc la taille du message ainsi que le message. De plus, les données son encodées (cryptage XOR) par un masque qui doit également être extrait.&lt;br /&gt;
&lt;br /&gt;
4) Fermeture de la communication.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le serveur supporte le multi-client il est donc nécessaire qu'il effectue ces étapes en &amp;quot;parallèle&amp;quot;. Nous utilisons donc les threads ou fils d’exécution. Un thread est donc responsable d'attendre qu'un nouveau client se connecte et effectue le &amp;quot;handshake&amp;quot;, il crée ensuite un thread associé à ce client afin d'établir un canal de communication. Il y a donc au moins un thread par client. Par la suite il faudra également implémenter une déconnexion automatique d'un client notamment après un timeout.&lt;br /&gt;
&lt;br /&gt;
Exemple d’exécution du serveur avec deux clients qui se connectent et envoient un message : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testServeur.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Les clients sont des navigateurs web. Pour les tests nous avons repris les exemples utilisés dans le cadre das projets IMA3 SC avec le titre de la page HTML qui se colore en vert lorsque le client est connecté, et un champ de saisie pour envoyer des messages au serveur : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testClient.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 4===&lt;br /&gt;
&lt;br /&gt;
*Mise en place d’algorithmes de traitement d'image&lt;br /&gt;
&lt;br /&gt;
====Détection de contour====&lt;br /&gt;
&lt;br /&gt;
L'objectif de notre projet est de pouvoir projeter n'importe quelle image envoyé grâce à l'application web. Pour cela nous allons tracer à une vitesse élevée les contours de l'image sur par exemple un mur grâce au laser. Il est donc nécessaire de détecter les contours de l'image grâce à plusieurs traitements.&lt;br /&gt;
&lt;br /&gt;
=====Conversion en niveau de gris=====&lt;br /&gt;
&lt;br /&gt;
Une des étapes préliminaires pour effectuer la détection de contour est de convertir l'image couleur en niveau de gris. Pour cela l'algorithme est simple : il suffit pour chaque pixel de l'image d'effectuer la moyenne des composantes rouge, verte, bleu de chaque pixel. En effet, si l'on considère une image matricielle (l'image est considérée comme un tableau à deux dimensions avec chaque case qui contient la couleur du pixel), chaque pixel contient les composantes RGB codées sur un octet. La couleur gris correspond aux composantes RGB égales. Le niveau de gris est donc codé de 0 à 255, avec 0 donnant du noir et 255 du blanc. &lt;br /&gt;
&lt;br /&gt;
Voici le résultat obtenu : [[Fichier:testGrayScale.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Filtre de Prewit et Sobel=====&lt;br /&gt;
&lt;br /&gt;
Un contour est défini par un changement brutal d'intensité lumineuse, il s'agit donc de détecter selon plusieurs directions (au moins 2) ces changements. Il existe de nombreuses techniques afin de détecter les contours d'une image (gradient, Laplacien). L'une des techniques avec un rapport efficacité/temps d'exécution correct repose sur les algorithmes de Prewit ou Sobel. L'algorithme repose sur la convolution de matrices.&lt;br /&gt;
Cela consiste à appliquer sur chaque pixel de l'image la matrice de Prewit définie comme &lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L_x = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; ainsi que sa transposée : &amp;lt;math&amp;gt;&lt;br /&gt;
L_y = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; -1 &amp;amp; -1 \\&lt;br /&gt;
 0 &amp;amp; 0 &amp;amp; 0 \\&lt;br /&gt;
+1 &amp;amp; +1 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Convoluer ces deux filtres sur l'image permet de détecter respectivement les contours verticaux et horizontaux.&lt;br /&gt;
&lt;br /&gt;
D'après wikipedia [https://fr.wikipedia.org/wiki/D%C3%A9tection_de_contours], on obtient de meilleurs résultats en appliquant un filtre triangulaire, on introduit donc la matrice de Sobel :&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-2 &amp;amp; 0 &amp;amp; +2 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
On obtient le résultat suivant : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testOutline1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Pré-traitement : Flou Gaussien=====&lt;br /&gt;
&lt;br /&gt;
Afin de réduire significativement le nombre de contours, il est nécessaire d'effectuer un pré-traitement avant la détection de contours. On utilise généralement un flou gaussien afin de réduire les transitions lumineuses et ainsi réduire le nombre de contours. L’algorithme de flou gaussien repose également sur la convolution de matrices sauf qu'ici la matrice filtre est générée grâce à une fonction gaussienne paramétrée par '''Sigma''' qui va directement impacter le niveau de flou. Plus la matrice de filtrage est grande plus la qualité du résultat est meilleure, mais le temps d’exécution devient également plus grand.&lt;br /&gt;
&lt;br /&gt;
Voici la fonction de génération du filtre : &amp;lt;math&amp;gt;G(x,y) = \frac{1}{{2\pi \sigma^2}} e^{-\frac{x^2 + y^2}{2 \sigma^2}}&amp;lt;/math&amp;gt; où x et y correspondent aux indices de la cellule de la matrice.&lt;br /&gt;
&lt;br /&gt;
On obtient ce résultat :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testGaussianBlur.png]]&lt;br /&gt;
&lt;br /&gt;
On note un bien meilleur résultat. Cependant on remarque que les composantes horizontales ne sont pas correctement détectées il subsiste un problème avec le filtrage vertical que je n'ai pas réussi à identifier. De plus, il s'agit par sa suite d'éliminer les contours parasites ainsi que d'affiner le trait pour n'avoir plus qu'un pixel d'épaisseur.&lt;br /&gt;
&lt;br /&gt;
=====Post-traitement : Algorithme de Canny=====&lt;br /&gt;
&lt;br /&gt;
Afin d'obtenir un résultat exploitable il est nécessaire d'appliquer encore quelques traitements. Pour cela nous utilisons l’algorithme de Canny qui repose que celui de Sobel mais qui ajoute un algorithme de seuillage par hysteresis qui permet de retirer les contours secondaires et de ne garder que les contours connexes dans une seuil haut et un seuil bas définis. En outre, cette algorithme affine également le trait obtenu. Pour cet algorithme nous avons directement trouvé des sources libres de droits [http://www.tomgibara.com/computer-vision/canny-edge-detector] qui donne des résultats très corrects.&lt;br /&gt;
&lt;br /&gt;
Par exemple :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ou encore : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny2.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 5===&lt;br /&gt;
&lt;br /&gt;
*Établissement d'un protocole de transfert d'image basé sur les WebSockets&lt;br /&gt;
**Envoie d'un requête &amp;quot;send&amp;quot; par le client dans une trame websocket texte&lt;br /&gt;
**Réponse serveur 'Y' si aucun autre client tente d'envoyer une image simultanément, 'N' sinon&lt;br /&gt;
**Si et seulement si le client reçoit 'Y' il débute le transfert en envoyant la largeur et la longueur de l'image sur 4 octets, puis les données de l'image soit 4 valeurs pour chaque pixels (r,g,b,alpha)&lt;br /&gt;
**Le serveur renvoie 'D' une fois le transfert achevé (à l'avenir, le serveur renverra l'image après filtrage).&lt;br /&gt;
**A tout moment, le serveur peut renvoyer 'E' si une erreur est survenue (ex : paquets perdus, nombre incorrects de données)&lt;br /&gt;
*Ajout du support des logs au niveau serveur&lt;br /&gt;
**Impression sur la sortie standard des messages&lt;br /&gt;
**Formatage en fonction de la sévérité du log (info, warning, error...)&lt;br /&gt;
**Incrustation de la date et heure&lt;br /&gt;
**Possibilité de redirection dans une fichier, avec configuration (écriture à la suite d'un fichier existant, écrasement...)&lt;br /&gt;
**Le tout dans une classe Java flexible et réutilisable pour d'autres projets&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 6===&lt;br /&gt;
&lt;br /&gt;
*Installation de la librairie Java Pi4j sur la raspberry pi qui permet le contrôle des GPIO de celle-ci et notamment le port I²C (basé sur WiringPi)&lt;br /&gt;
*Amélioration coté serveur websocket&lt;br /&gt;
**Gestion de message plus longs (maximum des trames websockets soit 2^63 octets)&lt;br /&gt;
**Différenciation, à la réception de messages, des trames textes ou binaires des trames de contrôle comme les requête ping, pong ou de fermeture de connexion &lt;br /&gt;
**Ajout d'un mode de debug de trames &lt;br /&gt;
&lt;br /&gt;
===Semaine 7===&lt;br /&gt;
&lt;br /&gt;
*Améliorations du serveur WebSocket&lt;br /&gt;
**Gestion de la fragmentation TCP&lt;br /&gt;
**Gestion de la fragmentation WebSocket&lt;br /&gt;
**Gestion des requêtes ping envoyés par le client en renvoyant une trames de contrôle pong afin de maintenir la connexion&lt;br /&gt;
**Gestion des déconnexion de clients afin d'optimiser le serveur&lt;br /&gt;
**Amélioration de l'émission de messages en augmentant la taille maximale pouvant être émise (2^63 octets)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A ce stade du développement, le client et le serveur sont opérationnels et peuvent s'échanger des messages ainsi que des images que le serveur traite pour extraire les contours.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==A faire==&lt;br /&gt;
&lt;br /&gt;
MAJ 17 mars &lt;br /&gt;
&lt;br /&gt;
*Client websocket et page web&lt;br /&gt;
**Mise en page CSS&lt;br /&gt;
**Ajout bouton reboot serveur&lt;br /&gt;
**Ajout bouton shutdown serveur&lt;br /&gt;
**Ajout canvas pour prévisualisation image projeté&lt;br /&gt;
**Ajout &amp;quot;slider&amp;quot; pour régler niveau du flou Gaussien&lt;br /&gt;
**Ajout message pop up en cas d'erreurs&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Serveur WebSocket&lt;br /&gt;
**Ajout fonctionnalité envoi image de prévisualisation&lt;br /&gt;
&lt;br /&gt;
*RaspberryPi&lt;br /&gt;
**Utilisation d'un serveur bind9 pour éviter de taper IP&lt;br /&gt;
&lt;br /&gt;
*Détection de contours&lt;br /&gt;
**Implémentation algorithme de tri de la plus courte disance&lt;br /&gt;
&lt;br /&gt;
*Réalisation matérielle projecteur&lt;br /&gt;
**Assemblage galva+laser+DAC+alim&lt;br /&gt;
**Fusion des alims&lt;br /&gt;
&lt;br /&gt;
*Commande galvanomêtre&lt;br /&gt;
**Utilisation API I²C&lt;br /&gt;
**Fonction de transfert position-&amp;gt;angle-&amp;gt;tension&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;br /&gt;
&lt;br /&gt;
==Bibliographie==&lt;br /&gt;
&lt;br /&gt;
http://www.ebay.com/itm/20KPPS-30KPPS-laser-scanning-galvo-scanner-ILDA-Closed-Loop-max-30kpps-for-laser-/261517002270?hash=item3ce3a0c61e&lt;br /&gt;
&lt;br /&gt;
https://icn.fenelonlille.org/mediawiki/index.php/Projet_ICN_commun_2016/2017&lt;br /&gt;
&lt;br /&gt;
https://www.g33k-zone.org/post/2016/05/11/Configurer-le-Raspberry-Pi-en-point-d-acc%C3%A8s-Wifi&lt;br /&gt;
&lt;br /&gt;
http://stackoverflow.com/questions/22087076/how-to-make-a-simple-image-upload-using-javascript-html&lt;br /&gt;
&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_a_WebSocket_server_in_Java&lt;br /&gt;
&lt;br /&gt;
export http_proxy=http://proxy.polytech-lille.fr:3128&lt;/div&gt;</summary>
		<author><name>Mtrimbur</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=40488</id>
		<title>IMA4 2016/2017 P39</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=40488"/>
				<updated>2017-03-17T16:32:59Z</updated>
		
		<summary type="html">&lt;p&gt;Mtrimbur : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
===Contexte===&lt;br /&gt;
&lt;br /&gt;
Le laser est une technologie largement utilisé de nos jours dans de diverses applications. En effet, on retrouve cette technologie dans le domaine médical notamment pour la chirurgie oculaire ou encore dans industrie avec la découpe laser ou la soudure au laser.&lt;br /&gt;
&lt;br /&gt;
Le laser est une émission de photons produit par excitation d'un milieu amplificateur (ex : CO2), le rayonnement produit est unidirectionnel et monochromatique. Ce sont ces propriétés que nous allons exploiter afin réaliser un projecteur laser qui mis en mouvement est capable de dessiner des formes sur une surface à l'instar de systèmes existants utilisés pour des effets lumineux lors de festivités.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
L'objectif du projet est de créer un système de projection laser à plusieurs couleurs (au minimum deux) avec une application web pour programmer les formes à dessiner afin d'agrémenter des compétitions de gymnastique rythmique.&lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
Le projet consiste à réaliser avec des lasers des figures géométriques par l'intermédiaire d'un système galvanométrique. &lt;br /&gt;
&lt;br /&gt;
Notre premier travail sera de concevoir la partie projection. Pour cela, nous devrons aligner les lasers et les galvanomètres. En effet, ces derniers posséderont des miroirs à l'extrémité, ainsi les miroirs changeront d'inclinaison suivant le courant traversant les galvanomètres (similaire à l'image ci-contre). Il nous faudra également créer un système d'alimentation qui à partir d'une même source (réseau 230 V) sera capable d'alimenter les lasers et les galvanomètres ainsi qu'une Arduino et une Raspberry Pi.&lt;br /&gt;
[[File:Scanhead.jpeg|thumb]]&lt;br /&gt;
&lt;br /&gt;
Ensuite nous nous intéresserons à l'utilisation d'un système embarqué pour contrôler les galvanomètres et donc dessiner avec les lasers sur un plan 2D. En effet, le laser restera toujours fixe, seuls les galvanomètres, et donc les miroirs bougeront. Les galvanomètres étant contrôlés en courant il faudra réaliser une interface électronique pour convertir une commande en tension en commande de courant. La commande en tension sera assuré par une carte Arduino. Nous n'utiliserons qu'une seule paire de galvanomètres pour les deux laser. Il faudra donc multiplexer les deux faisceaux. La programmation des formes à effectuer, se fera par l'intermédiaire d'une application web PHP hébergée sur une RaspberryPi qui permettra de récupérer une image, d'y appliquer divers traitements et filtres afin d'en extraire les contours, et de calculer les commandes pour positionner les galvanomètres. Un serveur WebSocket également hébergé sur la RaspberryPi servira d'interface entre l'application web et L'arduino qui sera connecté via une liaison série sur la raspberryPI.&lt;br /&gt;
&lt;br /&gt;
Comme animation de test, nous dessinerons le contour d'une gymnaste avec une couleur et son ballon d'une autre couleur. La gymnaste devra lancer son ballon, réaliser quelques difficultés et récupérer son ballon.&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
Nous utiliserons comme matériels :&lt;br /&gt;
*Deux lasers de différentes couleurs&lt;br /&gt;
*Une paire de galvanomètres à miroir&lt;br /&gt;
*Arduino&lt;br /&gt;
*Raspberry Pi3&lt;br /&gt;
*Alimentation 230V/5V 1A [http://www.miniinthebox.com/fr/dual-usb-eu-prise-murale-5v-2a-voyage-adaptateur-chargeur-d-alimentation-pour-iphone7-6-xiaomi-samsung-et-autre-telephone-portable_p5410410.html?currency=EUR&amp;amp;litb_from=paid_adwords_shopping&amp;amp;sku=429_6917%7C752_20648&amp;amp;utm_source=google_shopping&amp;amp;utm_medium=cpc&amp;amp;adword_mt=&amp;amp;adword_ct=138705676724&amp;amp;adword_kw=&amp;amp;adword_pos=1o5&amp;amp;adword_pl=&amp;amp;adword_net=g&amp;amp;adword_tar=&amp;amp;adw_src_id=9653316068_661261352_33588296076_aud-79897721311:pla-256966386459&amp;amp;gclid=Cj0KEQiA_KvEBRCtzNil4-KR-LIBEiQAmgekFxxKjJJWBYCJlDZEa3Ke_2_WR0DzGVbz-jaCZHVIBoMaAvld8P8HAQ]&lt;br /&gt;
*Drivers galvanomètres x2&lt;br /&gt;
*Alimentation laser&lt;br /&gt;
*Lunette de sécurité x2 [https://www.amazon.fr/Uvex-S1933X-Eyewear-SCTOrange-Anti-Fog/dp/B000USRG90/ref=sr_1_1?ie=UTF8&amp;amp;qid=1485441383&amp;amp;sr=8-1&amp;amp;keywords=uvex+s1933x]&lt;br /&gt;
*Boitier ABS [http://fr.farnell.com/multicomp/g3118/boitier-abs-240x120x60mm-ip65/dp/1526656]&lt;br /&gt;
*DAC 4 canaux, avec interface I²C [https://www.adafruit.com/products/1083]&lt;br /&gt;
*Connecteur C14 [http://www.conrad.fr/ce/fr/product/715001/Connecteur-secteur-C14-Embase-male-verticale-715001-Nombre-de-poles-2-PE-10-A-noir-1-pcs/?ref=detview1&amp;amp;rt=detview1&amp;amp;rb=1]&lt;br /&gt;
*Câble secteur&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Logiciel :&lt;br /&gt;
&lt;br /&gt;
*Serveur web : Apache2, HTML5, PHP5, CSS&lt;br /&gt;
*Base de donnée : MySQL&lt;br /&gt;
*Serveur WebSocket : JQuerry, websocket&lt;br /&gt;
*Arduino : IDE Arduino&lt;br /&gt;
&lt;br /&gt;
===Calendrier prévisionnel===&lt;br /&gt;
&lt;br /&gt;
====Liste des tâches à effectuer====&lt;br /&gt;
Les différentes tâches à effectuer sont :&lt;br /&gt;
*Partie préliminaire : étude de fonctionnement des galvanomètres&lt;br /&gt;
**Déterminer comment est effectuée la commande des galvanomètres (protocole, tension...)&lt;br /&gt;
**Effectuer des tests avec l'Arduino ou la Raspberry Pi&lt;br /&gt;
**Effectuer des tests avec une LED à la place du laser &lt;br /&gt;
*Partie projection&lt;br /&gt;
**Fixer les lasers&lt;br /&gt;
**Aligner les lasers et les galvanomètres&lt;br /&gt;
**Créer le système d'alimentation&lt;br /&gt;
**Création d'un boitier&lt;br /&gt;
*Partie système embarqué&lt;br /&gt;
**Asservissement des galvanomètres avec l'Arduino&lt;br /&gt;
**Système électronique de commande en courant pour les galvanomètres&lt;br /&gt;
*Interface Web&lt;br /&gt;
**Installation et configuration Apache2&lt;br /&gt;
**Création d'une interface graphique simple&lt;br /&gt;
**Implémentation d'algorithmes de traitement d'image&lt;br /&gt;
**Mise en forme avec des CSS&lt;br /&gt;
**Sytème d'authentification avec mot de passe&lt;br /&gt;
**Utilisation d'une base de données pour enregistrer toutes les images déjà utilisés afin de les réutiliser&lt;br /&gt;
*Serveur Web Socket&lt;br /&gt;
**Récupération des données de l'interface web&lt;br /&gt;
**Mise en place de la liaison série avec l'Arduino&lt;br /&gt;
&lt;br /&gt;
====Calendrier====&lt;br /&gt;
Répartition du temps consacré au projet (240h) :&lt;br /&gt;
*Partie projection : 80h&lt;br /&gt;
*Partie système embarqué : 40h&lt;br /&gt;
*Partie interface web et websocket: 120h&lt;br /&gt;
&lt;br /&gt;
==Feuille d'heures==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!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&lt;br /&gt;
|-&lt;br /&gt;
| Définition cahier des charges &lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 14&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|38&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Finalisation du cahier des charges avec les responsables&lt;br /&gt;
&lt;br /&gt;
*Acquisition de matériels :&lt;br /&gt;
**Projecteur Laser&lt;br /&gt;
**Galvanomètres&lt;br /&gt;
**Alimentation des galvanomètres&lt;br /&gt;
&lt;br /&gt;
*Listage du matériels à acquérir :&lt;br /&gt;
**Lunettes de sécurité&lt;br /&gt;
**DAC&lt;br /&gt;
**Alimentation 230V/5V 1A&lt;br /&gt;
** Boitier ABS &lt;br /&gt;
**...&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
*Obtention de l'arduino et de la raspberryPI&lt;br /&gt;
&lt;br /&gt;
*Démontage du projecteur laser&lt;br /&gt;
**Deux lasers de classe 3b (vert et rouge)&lt;br /&gt;
**Circuit d'alimentation des deux lasers&lt;br /&gt;
&lt;br /&gt;
*Initialisation du port série de la raspberryPI&lt;br /&gt;
**Modification du fichier ''config.txt'' dans la partition boot&lt;br /&gt;
**Ajout d'une ligne autorisant la communication série ('''enable_uart=1''')&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
*Installation du serveur apache sur la raspberryPI&lt;br /&gt;
**Modification du fichier ''/etc/network/interfaces'' (Static, Address, Netmask, Gateway)&lt;br /&gt;
**Modification du fichier ''/etc/resolv.conf'' (Adresse du serveur)&lt;br /&gt;
**Utilisation d'un proxy pour la récupération outils de programmation (Apache2, Php5)&lt;br /&gt;
&lt;br /&gt;
*Mise en place du point d’accès wifi de la raspberryPI&lt;br /&gt;
**Récupération des logiciels nécessaires (dnsmasq, hostapd)&lt;br /&gt;
**Mise en place d'une adresse IP statique pour le point d'accès par l'intermédiaire du fichier ''/etc/dhcpcd.conf''&lt;br /&gt;
**Désactivation de la négociation automatique de bail dans le fichier ''/etc/network/interfaces''&lt;br /&gt;
**Configuration du logiciel hostapd ''/etc/hostapd/hostapd.conf''&lt;br /&gt;
**Activation du démarrage automatique du point d'accès ''/etc/default/hostapd''&lt;br /&gt;
**Configuration du serveur DNS par ''/etc/dnsmasq.conf''&lt;br /&gt;
&lt;br /&gt;
*Instauration de la page d'accueil de l'interface web à l'adresse ''192.168.3.1''&lt;br /&gt;
**Téléversement de fichiers images sur la page web et affichage de celle-ci&lt;br /&gt;
**Voyant de confirmation du bon fonctionnement du serveur web&lt;br /&gt;
&lt;br /&gt;
*Développement du serveur websocket&lt;br /&gt;
&lt;br /&gt;
Le développement du serveur websocket, initialement prévu en C (il était prévu de reprendre les sources utilisées l'année précédente dans le cadre des projet IMA3 SC), a finalement été réalisé en JAVA pour plusieurs raisons.&lt;br /&gt;
Premièrement, un seul programme met en œuvre le serveur websocket, les divers traitements d'image, ainsi que les contrôles des galvanomètres (par l'intermédiaire des DAC) via la liaison I²C de la Raspberry Pi. Le langage JAVA fournit nativement des bibliothèques d'objets pour manipuler assez simplement des images, il existe également des librairies pour contrôler le port GPIO de la Raspberry et il était également intéressant de travailler avec un langage de plus haut niveau que le C.&lt;br /&gt;
En outre, la totale portabilité de ce langage nous permet de travailler sur n'importe quelle machine et ensuite transférer notre programme sur la Raspberry Pi et l’exécuter sans même repasser par une phase de compilation. Et finalement, c'est le langage que nous étudions actuellement en cours de programmation orientée objet, ce qui permet de nous perfectionner.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Serveur WebSocket====&lt;br /&gt;
&lt;br /&gt;
N'ayant pas trouvé d'API WebSocket en Java satisfaisante (qui ne nécessitent pas l'installation et la configuration de nombreux outils additionnels), j'ai estimé plus commode et plus formateur de développer notre propre serveur WebSocket en se basant sur les librairies sockets de Java avec l'aide d'une documentation assez exhaustive [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers].&lt;br /&gt;
&lt;br /&gt;
Les WebSockets désignent à la fois un protocole réseau qui étend le protocole TCP ainsi qu'une API du World Wide Web. Nous nous en servons afin d'établir une communication asynchrone et bidirectionnelle entre un navigateur web et le serveur, notamment pour envoyer l'image à projeter. L’implémentation du serveur repose sur plusieurs étapes.&lt;br /&gt;
&lt;br /&gt;
1) Connexion d'un client &lt;br /&gt;
&lt;br /&gt;
2) Handshake : permet de faire le lien entre le protocole HTTP et WS. Le client envoie une requête HTTP demandant un upgrade de la connexion en protocole WS et le serveur répond en configurant la connexion (détail dans la documentation [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers]).&lt;br /&gt;
&lt;br /&gt;
3) Réception et décodage des messages : le serveurs reçoit des trames brutes, on extrait donc la taille du message ainsi que le message. De plus, les données son encodées (cryptage XOR) par un masque qui doit également être extrait.&lt;br /&gt;
&lt;br /&gt;
4) Fermeture de la communication.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le serveur supporte le multi-client il est donc nécessaire qu'il effectue ces étapes en &amp;quot;parallèle&amp;quot;. Nous utilisons donc les threads ou fils d’exécution. Un thread est donc responsable d'attendre qu'un nouveau client se connecte et effectue le &amp;quot;handshake&amp;quot;, il crée ensuite un thread associé à ce client afin d'établir un canal de communication. Il y a donc au moins un thread par client. Par la suite il faudra également implémenter une déconnexion automatique d'un client notamment après un timeout.&lt;br /&gt;
&lt;br /&gt;
Exemple d’exécution du serveur avec deux clients qui se connectent et envoient un message : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testServeur.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Les clients sont des navigateurs web. Pour les tests nous avons repris les exemples utilisés dans le cadre das projets IMA3 SC avec le titre de la page HTML qui se colore en vert lorsque le client est connecté, et un champ de saisie pour envoyer des messages au serveur : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testClient.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 4===&lt;br /&gt;
&lt;br /&gt;
*Mise en place d’algorithmes de traitement d'image&lt;br /&gt;
&lt;br /&gt;
====Détection de contour====&lt;br /&gt;
&lt;br /&gt;
L'objectif de notre projet est de pouvoir projeter n'importe quelle image envoyé grâce à l'application web. Pour cela nous allons tracer à une vitesse élevée les contours de l'image sur par exemple un mur grâce au laser. Il est donc nécessaire de détecter les contours de l'image grâce à plusieurs traitements.&lt;br /&gt;
&lt;br /&gt;
=====Conversion en niveau de gris=====&lt;br /&gt;
&lt;br /&gt;
Une des étapes préliminaires pour effectuer la détection de contour est de convertir l'image couleur en niveau de gris. Pour cela l'algorithme est simple : il suffit pour chaque pixel de l'image d'effectuer la moyenne des composantes rouge, verte, bleu de chaque pixel. En effet, si l'on considère une image matricielle (l'image est considérée comme un tableau à deux dimensions avec chaque case qui contient la couleur du pixel), chaque pixel contient les composantes RGB codées sur un octet. La couleur gris correspond aux composantes RGB égales. Le niveau de gris est donc codé de 0 à 255, avec 0 donnant du noir et 255 du blanc. &lt;br /&gt;
&lt;br /&gt;
Voici le résultat obtenu : [[Fichier:testGrayScale.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Filtre de Prewit et Sobel=====&lt;br /&gt;
&lt;br /&gt;
Un contour est défini par un changement brutal d'intensité lumineuse, il s'agit donc de détecter selon plusieurs directions (au moins 2) ces changements. Il existe de nombreuses techniques afin de détecter les contours d'une image (gradient, Laplacien). L'une des techniques avec un rapport efficacité/temps d'exécution correct repose sur les algorithmes de Prewit ou Sobel. L'algorithme repose sur la convolution de matrices.&lt;br /&gt;
Cela consiste à appliquer sur chaque pixel de l'image la matrice de Prewit définie comme &lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L_x = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; ainsi que sa transposée : &amp;lt;math&amp;gt;&lt;br /&gt;
L_y = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; -1 &amp;amp; -1 \\&lt;br /&gt;
 0 &amp;amp; 0 &amp;amp; 0 \\&lt;br /&gt;
+1 &amp;amp; +1 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Convoluer ces deux filtres sur l'image permet de détecter respectivement les contours verticaux et horizontaux.&lt;br /&gt;
&lt;br /&gt;
D'après wikipedia [https://fr.wikipedia.org/wiki/D%C3%A9tection_de_contours], on obtient de meilleurs résultats en appliquant un filtre triangulaire, on introduit donc la matrice de Sobel :&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-2 &amp;amp; 0 &amp;amp; +2 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
On obtient le résultat suivant : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testOutline1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Pré-traitement : Flou Gaussien=====&lt;br /&gt;
&lt;br /&gt;
Afin de réduire significativement le nombre de contours, il est nécessaire d'effectuer un pré-traitement avant la détection de contours. On utilise généralement un flou gaussien afin de réduire les transitions lumineuses et ainsi réduire le nombre de contours. L’algorithme de flou gaussien repose également sur la convolution de matrices sauf qu'ici la matrice filtre est générée grâce à une fonction gaussienne paramétrée par '''Sigma''' qui va directement impacter le niveau de flou. Plus la matrice de filtrage est grande plus la qualité du résultat est meilleure, mais le temps d’exécution devient également plus grand.&lt;br /&gt;
&lt;br /&gt;
Voici la fonction de génération du filtre : &amp;lt;math&amp;gt;G(x,y) = \frac{1}{{2\pi \sigma^2}} e^{-\frac{x^2 + y^2}{2 \sigma^2}}&amp;lt;/math&amp;gt; où x et y correspondent aux indices de la cellule de la matrice.&lt;br /&gt;
&lt;br /&gt;
On obtient ce résultat :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testGaussianBlur.png]]&lt;br /&gt;
&lt;br /&gt;
On note un bien meilleur résultat. Cependant on remarque que les composantes horizontales ne sont pas correctement détectées il subsiste un problème avec le filtrage vertical que je n'ai pas réussi à identifier. De plus, il s'agit par sa suite d'éliminer les contours parasites ainsi que d'affiner le trait pour n'avoir plus qu'un pixel d'épaisseur.&lt;br /&gt;
&lt;br /&gt;
=====Post-traitement : Algorithme de Canny=====&lt;br /&gt;
&lt;br /&gt;
Afin d'obtenir un résultat exploitable il est nécessaire d'appliquer encore quelques traitements. Pour cela nous utilisons l’algorithme de Canny qui repose que celui de Sobel mais qui ajoute un algorithme de seuillage par hysteresis qui permet de retirer les contours secondaires et de ne garder que les contours connexes dans une seuil haut et un seuil bas définis. En outre, cette algorithme affine également le trait obtenu. Pour cet algorithme nous avons directement trouvé des sources libres de droits [http://www.tomgibara.com/computer-vision/canny-edge-detector] qui donne des résultats très corrects.&lt;br /&gt;
&lt;br /&gt;
Par exemple :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ou encore : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny2.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 5===&lt;br /&gt;
&lt;br /&gt;
*Établissement d'un protocole de transfert d'image basé sur les WebSockets&lt;br /&gt;
**Envoie d'un requête &amp;quot;send&amp;quot; par le client dans une trame websocket texte&lt;br /&gt;
**Réponse serveur 'Y' si aucun autre client tente d'envoyer une image simultanément, 'N' sinon&lt;br /&gt;
**Si et seulement si le client reçoit 'Y' il débute le transfert en envoyant la largeur et la longueur de l'image sur 4 octets, puis les données de l'image soit 4 valeurs pour chaque pixels (r,g,b,alpha)&lt;br /&gt;
**Le serveur renvoie 'D' une fois le transfert achevé (à l'avenir, le serveur renverra l'image après filtrage).&lt;br /&gt;
**A tout moment, le serveur peut renvoyer 'E' si une erreur est survenue (ex : paquets perdus, nombre incorrects de données)&lt;br /&gt;
*Ajout du support des logs au niveau serveur&lt;br /&gt;
**Impression sur la sortie standard des messages&lt;br /&gt;
**Formatage en fonction de la sévérité du log (info, warning, error...)&lt;br /&gt;
**Incrustation de la date et heure&lt;br /&gt;
**Possibilité de redirection dans une fichier, avec configuration (écriture à la suite d'un fichier existant, écrasement...)&lt;br /&gt;
**Le tout dans une classe Java flexible et réutilisable pour d'autres projets&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 6===&lt;br /&gt;
&lt;br /&gt;
*Installation de la librairie Java Pi4j sur la raspberry pi qui permet le contrôle des GPIO de celle-ci et notamment le port I²C (basé sur WiringPi)&lt;br /&gt;
*Amélioration coté serveur websocket&lt;br /&gt;
**Gestion de message plus longs (maximum des trames websockets soit 2^63 octets)&lt;br /&gt;
**Différenciation, à la réception de messages, des trames textes ou binaires des trames de contrôle comme les requête ping, pong ou de fermeture de connexion &lt;br /&gt;
**Ajout d'un mode de debug de trames &lt;br /&gt;
&lt;br /&gt;
===Semaine 7===&lt;br /&gt;
&lt;br /&gt;
*Améliorations du serveur WebSocket&lt;br /&gt;
**Gestion de la fragmentation TCP&lt;br /&gt;
**Gestion de la fragmentation WebSocket&lt;br /&gt;
**Gestion des requêtes ping envoyés par le client en renvoyant une trames de contrôle pong afin de maintenir la connexion&lt;br /&gt;
**Gestion des déconnexion de clients afin d'optimiser le serveur&lt;br /&gt;
**Amélioration de l'émission de messages en augmentant la taille maximale pouvant être émise (2^63 octets)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A ce stade du développement, le client et le serveur sont opérationnels et peuvent s'échanger des messages ainsi que des images que le serveur traite pour extraire les contours.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==A faire==&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;br /&gt;
&lt;br /&gt;
==Bibliographie==&lt;br /&gt;
&lt;br /&gt;
http://www.ebay.com/itm/20KPPS-30KPPS-laser-scanning-galvo-scanner-ILDA-Closed-Loop-max-30kpps-for-laser-/261517002270?hash=item3ce3a0c61e&lt;br /&gt;
&lt;br /&gt;
https://icn.fenelonlille.org/mediawiki/index.php/Projet_ICN_commun_2016/2017&lt;br /&gt;
&lt;br /&gt;
https://www.g33k-zone.org/post/2016/05/11/Configurer-le-Raspberry-Pi-en-point-d-acc%C3%A8s-Wifi&lt;br /&gt;
&lt;br /&gt;
http://stackoverflow.com/questions/22087076/how-to-make-a-simple-image-upload-using-javascript-html&lt;br /&gt;
&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_a_WebSocket_server_in_Java&lt;br /&gt;
&lt;br /&gt;
export http_proxy=http://proxy.polytech-lille.fr:3128&lt;/div&gt;</summary>
		<author><name>Mtrimbur</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=40487</id>
		<title>IMA4 2016/2017 P39</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=40487"/>
				<updated>2017-03-17T16:26:34Z</updated>
		
		<summary type="html">&lt;p&gt;Mtrimbur : /* Avancement du Projet */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
===Contexte===&lt;br /&gt;
&lt;br /&gt;
Le laser est une technologie largement utilisé de nos jours dans de diverses applications. En effet, on retrouve cette technologie dans le domaine médical notamment pour la chirurgie oculaire ou encore dans industrie avec la découpe laser ou la soudure au laser.&lt;br /&gt;
&lt;br /&gt;
Le laser est une émission de photons produit par excitation d'un milieu amplificateur (ex : CO2), le rayonnement produit est unidirectionnel et monochromatique. Ce sont ces propriétés que nous allons exploiter afin réaliser un projecteur laser qui mis en mouvement est capable de dessiner des formes sur une surface à l'instar de systèmes existants utilisés pour des effets lumineux lors de festivités.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
L'objectif du projet est de créer un système de projection laser à plusieurs couleurs (au minimum deux) avec une application web pour programmer les formes à dessiner afin d'agrémenter des compétitions de gymnastique rythmique.&lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
Le projet consiste à réaliser avec des lasers des figures géométriques par l'intermédiaire d'un système galvanométrique. &lt;br /&gt;
&lt;br /&gt;
Notre premier travail sera de concevoir la partie projection. Pour cela, nous devrons aligner les lasers et les galvanomètres. En effet, ces derniers posséderont des miroirs à l'extrémité, ainsi les miroirs changeront d'inclinaison suivant le courant traversant les galvanomètres (similaire à l'image ci-contre). Il nous faudra également créer un système d'alimentation qui à partir d'une même source (réseau 230 V) sera capable d'alimenter les lasers et les galvanomètres ainsi qu'une Arduino et une Raspberry Pi.&lt;br /&gt;
[[File:Scanhead.jpeg|thumb]]&lt;br /&gt;
&lt;br /&gt;
Ensuite nous nous intéresserons à l'utilisation d'un système embarqué pour contrôler les galvanomètres et donc dessiner avec les lasers sur un plan 2D. En effet, le laser restera toujours fixe, seuls les galvanomètres, et donc les miroirs bougeront. Les galvanomètres étant contrôlés en courant il faudra réaliser une interface électronique pour convertir une commande en tension en commande de courant. La commande en tension sera assuré par une carte Arduino. Nous n'utiliserons qu'une seule paire de galvanomètres pour les deux laser. Il faudra donc multiplexer les deux faisceaux. La programmation des formes à effectuer, se fera par l'intermédiaire d'une application web PHP hébergée sur une RaspberryPi qui permettra de récupérer une image, d'y appliquer divers traitements et filtres afin d'en extraire les contours, et de calculer les commandes pour positionner les galvanomètres. Un serveur WebSocket également hébergé sur la RaspberryPi servira d'interface entre l'application web et L'arduino qui sera connecté via une liaison série sur la raspberryPI.&lt;br /&gt;
&lt;br /&gt;
Comme animation de test, nous dessinerons le contour d'une gymnaste avec une couleur et son ballon d'une autre couleur. La gymnaste devra lancer son ballon, réaliser quelques difficultés et récupérer son ballon.&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
Nous utiliserons comme matériels :&lt;br /&gt;
*Deux lasers de différentes couleurs&lt;br /&gt;
*Une paire de galvanomètres à miroir&lt;br /&gt;
*Arduino&lt;br /&gt;
*Raspberry Pi3&lt;br /&gt;
*Alimentation 230V/5V 1A [http://www.miniinthebox.com/fr/dual-usb-eu-prise-murale-5v-2a-voyage-adaptateur-chargeur-d-alimentation-pour-iphone7-6-xiaomi-samsung-et-autre-telephone-portable_p5410410.html?currency=EUR&amp;amp;litb_from=paid_adwords_shopping&amp;amp;sku=429_6917%7C752_20648&amp;amp;utm_source=google_shopping&amp;amp;utm_medium=cpc&amp;amp;adword_mt=&amp;amp;adword_ct=138705676724&amp;amp;adword_kw=&amp;amp;adword_pos=1o5&amp;amp;adword_pl=&amp;amp;adword_net=g&amp;amp;adword_tar=&amp;amp;adw_src_id=9653316068_661261352_33588296076_aud-79897721311:pla-256966386459&amp;amp;gclid=Cj0KEQiA_KvEBRCtzNil4-KR-LIBEiQAmgekFxxKjJJWBYCJlDZEa3Ke_2_WR0DzGVbz-jaCZHVIBoMaAvld8P8HAQ]&lt;br /&gt;
*Drivers galvanomètres x2&lt;br /&gt;
*Alimentation laser&lt;br /&gt;
*Lunette de sécurité x2 [https://www.amazon.fr/Uvex-S1933X-Eyewear-SCTOrange-Anti-Fog/dp/B000USRG90/ref=sr_1_1?ie=UTF8&amp;amp;qid=1485441383&amp;amp;sr=8-1&amp;amp;keywords=uvex+s1933x]&lt;br /&gt;
*Boitier ABS [http://fr.farnell.com/multicomp/g3118/boitier-abs-240x120x60mm-ip65/dp/1526656]&lt;br /&gt;
*DAC 4 canaux, avec interface I²C [https://www.adafruit.com/products/1083]&lt;br /&gt;
*Connecteur C14 [http://www.conrad.fr/ce/fr/product/715001/Connecteur-secteur-C14-Embase-male-verticale-715001-Nombre-de-poles-2-PE-10-A-noir-1-pcs/?ref=detview1&amp;amp;rt=detview1&amp;amp;rb=1]&lt;br /&gt;
*Câble secteur&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Logiciel :&lt;br /&gt;
&lt;br /&gt;
*Serveur web : Apache2, HTML5, PHP5, CSS&lt;br /&gt;
*Base de donnée : MySQL&lt;br /&gt;
*Serveur WebSocket : JQuerry, websocket&lt;br /&gt;
*Arduino : IDE Arduino&lt;br /&gt;
&lt;br /&gt;
===Calendrier prévisionnel===&lt;br /&gt;
&lt;br /&gt;
====Liste des tâches à effectuer====&lt;br /&gt;
Les différentes tâches à effectuer sont :&lt;br /&gt;
*Partie préliminaire : étude de fonctionnement des galvanomètres&lt;br /&gt;
**Déterminer comment est effectuée la commande des galvanomètres (protocole, tension...)&lt;br /&gt;
**Effectuer des tests avec l'Arduino ou la Raspberry Pi&lt;br /&gt;
**Effectuer des tests avec une LED à la place du laser &lt;br /&gt;
*Partie projection&lt;br /&gt;
**Fixer les lasers&lt;br /&gt;
**Aligner les lasers et les galvanomètres&lt;br /&gt;
**Créer le système d'alimentation&lt;br /&gt;
**Création d'un boitier&lt;br /&gt;
*Partie système embarqué&lt;br /&gt;
**Asservissement des galvanomètres avec l'Arduino&lt;br /&gt;
**Système électronique de commande en courant pour les galvanomètres&lt;br /&gt;
*Interface Web&lt;br /&gt;
**Installation et configuration Apache2&lt;br /&gt;
**Création d'une interface graphique simple&lt;br /&gt;
**Implémentation d'algorithmes de traitement d'image&lt;br /&gt;
**Mise en forme avec des CSS&lt;br /&gt;
**Sytème d'authentification avec mot de passe&lt;br /&gt;
**Utilisation d'une base de données pour enregistrer toutes les images déjà utilisés afin de les réutiliser&lt;br /&gt;
*Serveur Web Socket&lt;br /&gt;
**Récupération des données de l'interface web&lt;br /&gt;
**Mise en place de la liaison série avec l'Arduino&lt;br /&gt;
&lt;br /&gt;
====Calendrier====&lt;br /&gt;
Répartition du temps consacré au projet (240h) :&lt;br /&gt;
*Partie projection : 80h&lt;br /&gt;
*Partie système embarqué : 40h&lt;br /&gt;
*Partie interface web et websocket: 120h&lt;br /&gt;
&lt;br /&gt;
==Feuille d'heures==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!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&lt;br /&gt;
|-&lt;br /&gt;
| Définition cahier des charges &lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 14&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|38&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Finalisation du cahier des charges avec les responsables&lt;br /&gt;
&lt;br /&gt;
*Acquisition de matériels :&lt;br /&gt;
**Projecteur Laser&lt;br /&gt;
**Galvanomètres&lt;br /&gt;
**Alimentation des galvanomètres&lt;br /&gt;
&lt;br /&gt;
*Listage du matériels à acquérir :&lt;br /&gt;
**Lunettes de sécurité&lt;br /&gt;
**DAC&lt;br /&gt;
**Alimentation 230V/5V 1A&lt;br /&gt;
** Boitier ABS &lt;br /&gt;
**...&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
*Obtention de l'arduino et de la raspberryPI&lt;br /&gt;
&lt;br /&gt;
*Démontage du projecteur laser&lt;br /&gt;
**Deux lasers de classe 3b (vert et rouge)&lt;br /&gt;
**Circuit d'alimentation des deux lasers&lt;br /&gt;
&lt;br /&gt;
*Initialisation du port série de la raspberryPI&lt;br /&gt;
**Modification du fichier ''config.txt'' dans la partition boot&lt;br /&gt;
**Ajout d'une ligne autorisant la communication série ('''enable_uart=1''')&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
*Installation du serveur apache sur la raspberryPI&lt;br /&gt;
**Modification du fichier ''/etc/network/interfaces'' (Static, Address, Netmask, Gateway)&lt;br /&gt;
**Modification du fichier ''/etc/resolv.conf'' (Adresse du serveur)&lt;br /&gt;
**Utilisation d'un proxy pour la récupération outils de programmation (Apache2, Php5)&lt;br /&gt;
&lt;br /&gt;
*Mise en place du point d’accès wifi de la raspberryPI&lt;br /&gt;
**Récupération des logiciels nécessaires (dnsmasq, hostapd)&lt;br /&gt;
**Mise en place d'une adresse IP statique pour le point d'accès par l'intermédiaire du fichier ''/etc/dhcpcd.conf''&lt;br /&gt;
**Désactivation de la négociation automatique de bail dans le fichier ''/etc/network/interfaces''&lt;br /&gt;
**Configuration du logiciel hostapd ''/etc/hostapd/hostapd.conf''&lt;br /&gt;
**Activation du démarrage automatique du point d'accès ''/etc/default/hostapd''&lt;br /&gt;
**Configuration du serveur DNS par ''/etc/dnsmasq.conf''&lt;br /&gt;
&lt;br /&gt;
*Instauration de la page d'accueil de l'interface web à l'adresse ''192.168.3.1''&lt;br /&gt;
**Téléversement de fichiers images sur la page web et affichage de celle-ci&lt;br /&gt;
**Voyant de confirmation du bon fonctionnement du serveur web&lt;br /&gt;
&lt;br /&gt;
*Développement du serveur websocket&lt;br /&gt;
&lt;br /&gt;
Le développement du serveur websocket, initialement prévu en C (il était prévu de reprendre les sources utilisées l'année précédente dans le cadre des projet IMA3 SC), a finalement été réalisé en JAVA pour plusieurs raisons.&lt;br /&gt;
Premièrement, un seul programme met en œuvre le serveur websocket, les divers traitements d'image, ainsi que les contrôles des galvanomètres (par l'intermédiaire des DAC) via la liaison I²C de la Raspberry Pi. Le langage JAVA fournit nativement des bibliothèques d'objets pour manipuler assez simplement des images, il existe également des librairies pour contrôler le port GPIO de la Raspberry et il était également intéressant de travailler avec un langage de plus haut niveau que le C.&lt;br /&gt;
En outre, la totale portabilité de ce langage nous permet de travailler sur n'importe quelle machine et ensuite transférer notre programme sur la Raspberry Pi et l’exécuter sans même repasser par une phase de compilation. Et finalement, c'est le langage que nous étudions actuellement en cours de programmation orientée objet, ce qui permet de nous perfectionner.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Serveur WebSocket====&lt;br /&gt;
&lt;br /&gt;
N'ayant pas trouvé d'API WebSocket en Java satisfaisante (qui ne nécessitent pas l'installation et la configuration de nombreux outils additionnels), j'ai estimé plus commode et plus formateur de développer notre propre serveur WebSocket en se basant sur les librairies sockets de Java avec l'aide d'une documentation assez exhaustive [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers].&lt;br /&gt;
&lt;br /&gt;
Les WebSockets désignent à la fois un protocole réseau qui étend le protocole TCP ainsi qu'une API du World Wide Web. Nous nous en servons afin d'établir une communication asynchrone et bidirectionnelle entre un navigateur web et le serveur, notamment pour envoyer l'image à projeter. L’implémentation du serveur repose sur plusieurs étapes.&lt;br /&gt;
&lt;br /&gt;
1) Connexion d'un client &lt;br /&gt;
&lt;br /&gt;
2) Handshake : permet de faire le lien entre le protocole HTTP et WS. Le client envoie une requête HTTP demandant un upgrade de la connexion en protocole WS et le serveur répond en configurant la connexion (détail dans la documentation [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers]).&lt;br /&gt;
&lt;br /&gt;
3) Réception et décodage des messages : le serveurs reçoit des trames brutes, on extrait donc la taille du message ainsi que le message. De plus, les données son encodées (cryptage XOR) par un masque qui doit également être extrait.&lt;br /&gt;
&lt;br /&gt;
4) Fermeture de la communication.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le serveur supporte le multi-client il est donc nécessaire qu'il effectue ces étapes en &amp;quot;parallèle&amp;quot;. Nous utilisons donc les threads ou fils d’exécution. Un thread est donc responsable d'attendre qu'un nouveau client se connecte et effectue le &amp;quot;handshake&amp;quot;, il crée ensuite un thread associé à ce client afin d'établir un canal de communication. Il y a donc au moins un thread par client. Par la suite il faudra également implémenter une déconnexion automatique d'un client notamment après un timeout.&lt;br /&gt;
&lt;br /&gt;
Exemple d’exécution du serveur avec deux clients qui se connectent et envoient un message : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testServeur.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Les clients sont des navigateurs web. Pour les tests nous avons repris les exemples utilisés dans le cadre das projets IMA3 SC avec le titre de la page HTML qui se colore en vert lorsque le client est connecté, et un champ de saisie pour envoyer des messages au serveur : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testClient.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 4===&lt;br /&gt;
&lt;br /&gt;
*Mise en place d’algorithmes de traitement d'image&lt;br /&gt;
&lt;br /&gt;
====Détection de contour====&lt;br /&gt;
&lt;br /&gt;
L'objectif de notre projet est de pouvoir projeter n'importe quelle image envoyé grâce à l'application web. Pour cela nous allons tracer à une vitesse élevée les contours de l'image sur par exemple un mur grâce au laser. Il est donc nécessaire de détecter les contours de l'image grâce à plusieurs traitements.&lt;br /&gt;
&lt;br /&gt;
=====Conversion en niveau de gris=====&lt;br /&gt;
&lt;br /&gt;
Une des étapes préliminaires pour effectuer la détection de contour est de convertir l'image couleur en niveau de gris. Pour cela l'algorithme est simple : il suffit pour chaque pixel de l'image d'effectuer la moyenne des composantes rouge, verte, bleu de chaque pixel. En effet, si l'on considère une image matricielle (l'image est considérée comme un tableau à deux dimensions avec chaque case qui contient la couleur du pixel), chaque pixel contient les composantes RGB codées sur un octet. La couleur gris correspond aux composantes RGB égales. Le niveau de gris est donc codé de 0 à 255, avec 0 donnant du noir et 255 du blanc. &lt;br /&gt;
&lt;br /&gt;
Voici le résultat obtenu : [[Fichier:testGrayScale.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Filtre de Prewit et Sobel=====&lt;br /&gt;
&lt;br /&gt;
Un contour est défini par un changement brutal d'intensité lumineuse, il s'agit donc de détecter selon plusieurs directions (au moins 2) ces changements. Il existe de nombreuses techniques afin de détecter les contours d'une image (gradient, Laplacien). L'une des techniques avec un rapport efficacité/temps d'exécution correct repose sur les algorithmes de Prewit ou Sobel. L'algorithme repose sur la convolution de matrices.&lt;br /&gt;
Cela consiste à appliquer sur chaque pixel de l'image la matrice de Prewit définie comme &lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L_x = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; ainsi que sa transposée : &amp;lt;math&amp;gt;&lt;br /&gt;
L_y = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; -1 &amp;amp; -1 \\&lt;br /&gt;
 0 &amp;amp; 0 &amp;amp; 0 \\&lt;br /&gt;
+1 &amp;amp; +1 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Convoluer ces deux filtres sur l'image permet de détecter respectivement les contours verticaux et horizontaux.&lt;br /&gt;
&lt;br /&gt;
D'après wikipedia [https://fr.wikipedia.org/wiki/D%C3%A9tection_de_contours], on obtient de meilleurs résultats en appliquant un filtre triangulaire, on introduit donc la matrice de Sobel :&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-2 &amp;amp; 0 &amp;amp; +2 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
On obtient le résultat suivant : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testOutline1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Pré-traitement : Flou Gaussien=====&lt;br /&gt;
&lt;br /&gt;
Afin de réduire significativement le nombre de contours, il est nécessaire d'effectuer un pré-traitement avant la détection de contours. On utilise généralement un flou gaussien afin de réduire les transitions lumineuses et ainsi réduire le nombre de contours. L’algorithme de flou gaussien repose également sur la convolution de matrices sauf qu'ici la matrice filtre est générée grâce à une fonction gaussienne paramétrée par '''Sigma''' qui va directement impacter le niveau de flou. Plus la matrice de filtrage est grande plus la qualité du résultat est meilleure, mais le temps d’exécution devient également plus grand.&lt;br /&gt;
&lt;br /&gt;
Voici la fonction de génération du filtre : &amp;lt;math&amp;gt;G(x,y) = \frac{1}{{2\pi \sigma^2}} e^{-\frac{x^2 + y^2}{2 \sigma^2}}&amp;lt;/math&amp;gt; où x et y correspondent aux indices de la cellule de la matrice.&lt;br /&gt;
&lt;br /&gt;
On obtient ce résultat :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testGaussianBlur.png]]&lt;br /&gt;
&lt;br /&gt;
On note un bien meilleur résultat. Cependant on remarque que les composantes horizontales ne sont pas correctement détectées il subsiste un problème avec le filtrage vertical que je n'ai pas réussi à identifier. De plus, il s'agit par sa suite d'éliminer les contours parasites ainsi que d'affiner le trait pour n'avoir plus qu'un pixel d'épaisseur.&lt;br /&gt;
&lt;br /&gt;
=====Post-traitement : Algorithme de Canny=====&lt;br /&gt;
&lt;br /&gt;
Afin d'obtenir un résultat exploitable il est nécessaire d'appliquer encore quelques traitements. Pour cela nous utilisons l’algorithme de Canny qui repose que celui de Sobel mais qui ajoute un algorithme de seuillage par hysteresis qui permet de retirer les contours secondaires et de ne garder que les contours connexes dans une seuil haut et un seuil bas définis. En outre, cette algorithme affine également le trait obtenu. Pour cet algorithme nous avons directement trouvé des sources libres de droits [http://www.tomgibara.com/computer-vision/canny-edge-detector] qui donne des résultats très corrects.&lt;br /&gt;
&lt;br /&gt;
Par exemple :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ou encore : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny2.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 5===&lt;br /&gt;
&lt;br /&gt;
*Établissement d'un protocole de transfert d'image basé sur les WebSockets&lt;br /&gt;
**Envoie d'un requête &amp;quot;send&amp;quot; par le client dans une trame websocket texte&lt;br /&gt;
**Réponse serveur 'Y' si aucun autre client tente d'envoyer une image simultanément, 'N' sinon&lt;br /&gt;
**Si et seulement si le client reçoit 'Y' il débute le transfert en envoyant la largeur et la longueur de l'image sur 4 octets, puis les données de l'image soit 4 valeurs pour chaque pixels (r,g,b,alpha)&lt;br /&gt;
**Le serveur renvoie 'D' une fois le transfert achevé (à l'avenir, le serveur renverra l'image après filtrage).&lt;br /&gt;
**A tout moment, le serveur peut renvoyer 'E' si une erreur est survenue (ex : paquets perdus, nombre incorrects de données)&lt;br /&gt;
*Ajout du support des logs au niveau serveur&lt;br /&gt;
**Impression sur la sortie standard des messages&lt;br /&gt;
**Formatage en fonction de la sévérité du log (info, warning, error...)&lt;br /&gt;
**Incrustation de la date et heure&lt;br /&gt;
**Possibilité de redirection dans une fichier, avec configuration (écriture à la suite d'un fichier existant, écrasement...)&lt;br /&gt;
**Le tout dans une classe Java flexible et réutilisable pour d'autres projets&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Semaine 6===&lt;br /&gt;
&lt;br /&gt;
*Installation de la librairie Java Pi4j sur la raspberry pi qui permet le contrôle des GPIO de celle-ci et notamment le port I²C (basé sur WiringPi)&lt;br /&gt;
*Amélioration coté serveur websocket&lt;br /&gt;
**Gestion de message plus longs (maximum des trames websockets soit 2^63 octets)&lt;br /&gt;
**Différenciation, à la réception de messages, des trames textes ou binaires des trames de contrôle comme les requête ping, pong ou de fermeture de connexion &lt;br /&gt;
**Ajout d'un mode de debug de trames &lt;br /&gt;
&lt;br /&gt;
===Semaine 7===&lt;br /&gt;
&lt;br /&gt;
*Améliorations du serveur WebSocket&lt;br /&gt;
**Gestion de la fragmentation TCP&lt;br /&gt;
**Gestion de la fragmentation WebSocket&lt;br /&gt;
**Gestion des requêtes ping envoyés par le client en renvoyant une trames de contrôle pong afin de maintenir la connexion&lt;br /&gt;
**Gestion des déconnexion de clients afin d'optimiser le serveur&lt;br /&gt;
**Amélioration de l'émission de messages en augmentant la taille maximale pouvant être émise (2^63 octets)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A ce stade du développement, le client et le serveur sont opérationnels et peuvent s'échanger des messages ainsi que des images que le serveur traite pour extraire les contours.&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;br /&gt;
&lt;br /&gt;
==Bibliographie==&lt;br /&gt;
&lt;br /&gt;
http://www.ebay.com/itm/20KPPS-30KPPS-laser-scanning-galvo-scanner-ILDA-Closed-Loop-max-30kpps-for-laser-/261517002270?hash=item3ce3a0c61e&lt;br /&gt;
&lt;br /&gt;
https://icn.fenelonlille.org/mediawiki/index.php/Projet_ICN_commun_2016/2017&lt;br /&gt;
&lt;br /&gt;
https://www.g33k-zone.org/post/2016/05/11/Configurer-le-Raspberry-Pi-en-point-d-acc%C3%A8s-Wifi&lt;br /&gt;
&lt;br /&gt;
http://stackoverflow.com/questions/22087076/how-to-make-a-simple-image-upload-using-javascript-html&lt;br /&gt;
&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_a_WebSocket_server_in_Java&lt;br /&gt;
&lt;br /&gt;
export http_proxy=http://proxy.polytech-lille.fr:3128&lt;/div&gt;</summary>
		<author><name>Mtrimbur</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=39468</id>
		<title>IMA4 2016/2017 P39</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=39468"/>
				<updated>2017-02-22T17:51:36Z</updated>
		
		<summary type="html">&lt;p&gt;Mtrimbur : /* Pré-traitement : Flou Gaussien */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
===Contexte===&lt;br /&gt;
&lt;br /&gt;
Le laser est une technologie largement utilisé de nos jours dans de diverses applications. En effet, on retrouve cette technologie dans le domaine médical notamment pour la chirurgie oculaire ou encore dans industrie avec la découpe laser ou la soudure au laser.&lt;br /&gt;
&lt;br /&gt;
Le laser est une émission de photons produit par excitation d'un milieu amplificateur (ex : CO2), le rayonnement produit est unidirectionnel et monochromatique. Ce sont ces propriétés que nous allons exploiter afin réaliser un projecteur laser qui mis en mouvement est capable de dessiner des formes sur une surface à l'instar de systèmes existants utilisés pour des effets lumineux lors de festivités.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
L'objectif du projet est de créer un système de projection laser à plusieurs couleurs (au minimum deux) avec une application web pour programmer les formes à dessiner afin d'agrémenter des compétitions de gymnastique rythmique.&lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
Le projet consiste à réaliser avec des lasers des figures géométriques par l'intermédiaire d'un système galvanométrique. &lt;br /&gt;
&lt;br /&gt;
Notre premier travail sera de concevoir la partie projection. Pour cela, nous devrons aligner les lasers et les galvanomètres. En effet, ces derniers posséderont des miroirs à l'extrémité, ainsi les miroirs changeront d'inclinaison suivant le courant traversant les galvanomètres (similaire à l'image ci-contre). Il nous faudra également créer un système d'alimentation qui à partir d'une même source (réseau 230 V) sera capable d'alimenter les lasers et les galvanomètres ainsi qu'une Arduino et une Raspberry Pi.&lt;br /&gt;
[[File:Scanhead.jpeg|thumb]]&lt;br /&gt;
&lt;br /&gt;
Ensuite nous nous intéresserons à l'utilisation d'un système embarqué pour contrôler les galvanomètres et donc dessiner avec les lasers sur un plan 2D. En effet, le laser restera toujours fixe, seuls les galvanomètres, et donc les miroirs bougeront. Les galvanomètres étant contrôlés en courant il faudra réaliser une interface électronique pour convertir une commande en tension en commande de courant. La commande en tension sera assuré par une carte Arduino. Nous n'utiliserons qu'une seule paire de galvanomètres pour les deux laser. Il faudra donc multiplexer les deux faisceaux. La programmation des formes à effectuer, se fera par l'intermédiaire d'une application web PHP hébergée sur une RaspberryPi qui permettra de récupérer une image, d'y appliquer divers traitements et filtres afin d'en extraire les contours, et de calculer les commandes pour positionner les galvanomètres. Un serveur WebSocket également hébergé sur la RaspberryPi servira d'interface entre l'application web et L'arduino qui sera connecté via une liaison série sur la raspberryPI.&lt;br /&gt;
&lt;br /&gt;
Comme animation de test, nous dessinerons le contour d'une gymnaste avec une couleur et son ballon d'une autre couleur. La gymnaste devra lancer son ballon, réaliser quelques difficultés et récupérer son ballon.&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
Nous utiliserons comme matériels :&lt;br /&gt;
*Deux lasers de différentes couleurs&lt;br /&gt;
*Une paire de galvanomètres à miroir&lt;br /&gt;
*Arduino&lt;br /&gt;
*Raspberry Pi3&lt;br /&gt;
*Alimentation 230V/5V 1A [http://www.miniinthebox.com/fr/dual-usb-eu-prise-murale-5v-2a-voyage-adaptateur-chargeur-d-alimentation-pour-iphone7-6-xiaomi-samsung-et-autre-telephone-portable_p5410410.html?currency=EUR&amp;amp;litb_from=paid_adwords_shopping&amp;amp;sku=429_6917%7C752_20648&amp;amp;utm_source=google_shopping&amp;amp;utm_medium=cpc&amp;amp;adword_mt=&amp;amp;adword_ct=138705676724&amp;amp;adword_kw=&amp;amp;adword_pos=1o5&amp;amp;adword_pl=&amp;amp;adword_net=g&amp;amp;adword_tar=&amp;amp;adw_src_id=9653316068_661261352_33588296076_aud-79897721311:pla-256966386459&amp;amp;gclid=Cj0KEQiA_KvEBRCtzNil4-KR-LIBEiQAmgekFxxKjJJWBYCJlDZEa3Ke_2_WR0DzGVbz-jaCZHVIBoMaAvld8P8HAQ]&lt;br /&gt;
*Drivers galvanomètres x2&lt;br /&gt;
*Alimentation laser&lt;br /&gt;
*Lunette de sécurité x2 [https://www.amazon.fr/Uvex-S1933X-Eyewear-SCTOrange-Anti-Fog/dp/B000USRG90/ref=sr_1_1?ie=UTF8&amp;amp;qid=1485441383&amp;amp;sr=8-1&amp;amp;keywords=uvex+s1933x]&lt;br /&gt;
*Boitier ABS [http://fr.farnell.com/multicomp/g3118/boitier-abs-240x120x60mm-ip65/dp/1526656]&lt;br /&gt;
*DAC 4 canaux, avec interface I²C [https://www.adafruit.com/products/1083]&lt;br /&gt;
*Connecteur C14 [http://www.conrad.fr/ce/fr/product/715001/Connecteur-secteur-C14-Embase-male-verticale-715001-Nombre-de-poles-2-PE-10-A-noir-1-pcs/?ref=detview1&amp;amp;rt=detview1&amp;amp;rb=1]&lt;br /&gt;
*Câble secteur&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Logiciel :&lt;br /&gt;
&lt;br /&gt;
*Serveur web : Apache2, HTML5, PHP5, CSS&lt;br /&gt;
*Base de donnée : MySQL&lt;br /&gt;
*Serveur WebSocket : JQuerry, websocket&lt;br /&gt;
*Arduino : IDE Arduino&lt;br /&gt;
&lt;br /&gt;
===Calendrier prévisionnel===&lt;br /&gt;
&lt;br /&gt;
====Liste des tâches à effectuer====&lt;br /&gt;
Les différentes tâches à effectuer sont :&lt;br /&gt;
*Partie préliminaire : étude de fonctionnement des galvanomètres&lt;br /&gt;
**Déterminer comment est effectuée la commande des galvanomètres (protocole, tension...)&lt;br /&gt;
**Effectuer des tests avec l'Arduino ou la Raspberry Pi&lt;br /&gt;
**Effectuer des tests avec une LED à la place du laser &lt;br /&gt;
*Partie projection&lt;br /&gt;
**Fixer les lasers&lt;br /&gt;
**Aligner les lasers et les galvanomètres&lt;br /&gt;
**Créer le système d'alimentation&lt;br /&gt;
**Création d'un boitier&lt;br /&gt;
*Partie système embarqué&lt;br /&gt;
**Asservissement des galvanomètres avec l'Arduino&lt;br /&gt;
**Système électronique de commande en courant pour les galvanomètres&lt;br /&gt;
*Interface Web&lt;br /&gt;
**Installation et configuration Apache2&lt;br /&gt;
**Création d'une interface graphique simple&lt;br /&gt;
**Implémentation d'algorithmes de traitement d'image&lt;br /&gt;
**Mise en forme avec des CSS&lt;br /&gt;
**Sytème d'authentification avec mot de passe&lt;br /&gt;
**Utilisation d'une base de données pour enregistrer toutes les images déjà utilisés afin de les réutiliser&lt;br /&gt;
*Serveur Web Socket&lt;br /&gt;
**Récupération des données de l'interface web&lt;br /&gt;
**Mise en place de la liaison série avec l'Arduino&lt;br /&gt;
&lt;br /&gt;
====Calendrier====&lt;br /&gt;
Répartition du temps consacré au projet (240h) :&lt;br /&gt;
*Partie projection : 80h&lt;br /&gt;
*Partie système embarqué : 40h&lt;br /&gt;
*Partie interface web et websocket: 120h&lt;br /&gt;
&lt;br /&gt;
==Feuille d'heures==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!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&lt;br /&gt;
|-&lt;br /&gt;
| Définition cahier des charges &lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 14&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|38&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Finalisation du cahier des charges avec les responsables&lt;br /&gt;
&lt;br /&gt;
*Acquisition de matériels :&lt;br /&gt;
**Projecteur Laser&lt;br /&gt;
**Galvanomètres&lt;br /&gt;
**Alimentation des galvanomètres&lt;br /&gt;
&lt;br /&gt;
*Listage du matériels à acquérir :&lt;br /&gt;
**Lunettes de sécurité&lt;br /&gt;
**DAC&lt;br /&gt;
**Alimentation 230V/5V 1A&lt;br /&gt;
** Boitier ABS &lt;br /&gt;
**...&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
*Obtention de l'arduino et de la raspberryPI&lt;br /&gt;
&lt;br /&gt;
*Démontage du projecteur laser&lt;br /&gt;
**Deux lasers de classe 3b (vert et rouge)&lt;br /&gt;
**Circuit d'alimentation des deux lasers&lt;br /&gt;
&lt;br /&gt;
*Initialisation du port série de la raspberryPI&lt;br /&gt;
**Modification du fichier ''config.txt'' dans la partition boot&lt;br /&gt;
**Ajout d'une ligne autorisant la communication série ('''enable_uart=1''')&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
*Installation du serveur apache sur la raspberryPI&lt;br /&gt;
**Modification du fichier ''/etc/network/interfaces'' (Static, Address, Netmask, Gateway)&lt;br /&gt;
**Modification du fichier ''/etc/resolv.conf'' (Adresse du serveur)&lt;br /&gt;
**Utilisation d'un proxy pour la récupération outils de programmation (Apache2, Php5)&lt;br /&gt;
&lt;br /&gt;
*Mise en place du point d’accès wifi de la raspberryPI&lt;br /&gt;
**Récupération des logiciels nécessaires (dnsmasq, hostapd)&lt;br /&gt;
**Mise en place d'une adresse IP statique pour le point d'accès par l'intermédiaire du fichier ''/etc/dhcpcd.conf''&lt;br /&gt;
**Désactivation de la négociation automatique de bail dans le fichier ''/etc/network/interfaces''&lt;br /&gt;
**Configuration du logiciel hostapd ''/etc/hostapd/hostapd.conf''&lt;br /&gt;
**Activation du démarrage automatique du point d'accès ''/etc/default/hostapd''&lt;br /&gt;
**Configuration du serveur DNS par ''/etc/dnsmasq.conf''&lt;br /&gt;
&lt;br /&gt;
*Instauration de la page d'accueil de l'interface web à l'adresse ''192.168.3.1''&lt;br /&gt;
**Téléversement de fichiers images sur la page web et affichage de celle-ci&lt;br /&gt;
**Voyant de confirmation du bon fonctionnement du serveur web&lt;br /&gt;
&lt;br /&gt;
*Développement du serveur websocket&lt;br /&gt;
&lt;br /&gt;
Le développement du serveur websocket, initialement prévu en C (il était prévu de reprendre les sources utilisées l'année précédente dans le cadre des projet IMA3 SC), a finalement été réalisé en JAVA pour plusieurs raisons.&lt;br /&gt;
Premièrement, un seul programme met en œuvre le serveur websocket, les divers traitements d'image, ainsi que les contrôles des galvanomètres (par l'intermédiaire des DAC) via la liaison I²C de la Raspberry Pi. Le langage JAVA fournit nativement des bibliothèques d'objets pour manipuler assez simplement des images, il existe également des librairies pour contrôler le port GPIO de la Raspberry et il était également intéressant de travailler avec un langage de plus haut niveau que le C.&lt;br /&gt;
En outre, la totale portabilité de ce langage nous permet de travailler sur n'importe quelle machine et ensuite transférer notre programme sur la Raspberry Pi et l’exécuter sans même repasser par une phase de compilation. Et finalement, c'est le langage que nous étudions actuellement en cours de programmation orientée objet, ce qui permet de nous perfectionner.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Serveur WebSocket====&lt;br /&gt;
&lt;br /&gt;
N'ayant pas trouvé d'API WebSocket en Java satisfaisante (qui ne nécessitent pas l'installation et la configuration de nombreux outils additionnels), j'ai estimé plus commode et plus formateur de développer notre propre serveur WebSocket en se basant sur les librairies sockets de Java avec l'aide d'une documentation assez exhaustive [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers].&lt;br /&gt;
&lt;br /&gt;
Les WebSockets désignent à la fois un protocole réseau qui étend le protocole TCP ainsi qu'une API du World Wide Web. Nous nous en servons afin d'établir une communication asynchrone et bidirectionnelle entre un navigateur web et le serveur, notamment pour envoyer l'image à projeter. L’implémentation du serveur repose sur plusieurs étapes.&lt;br /&gt;
&lt;br /&gt;
1) Connexion d'un client &lt;br /&gt;
&lt;br /&gt;
2) Handshake : permet de faire le lien entre le protocole HTTP et WS. Le client envoie une requête HTTP demandant un upgrade de la connexion en protocole WS et le serveur répond en configurant la connexion (détail dans la documentation [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers]).&lt;br /&gt;
&lt;br /&gt;
3) Réception et décodage des messages : le serveurs reçoit des trames brutes, on extrait donc la taille du message ainsi que le message. De plus, les données son encodées (cryptage XOR) par un masque qui doit également être extrait.&lt;br /&gt;
&lt;br /&gt;
4) Fermeture de la communication.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le serveur supporte le multi-client il est donc nécessaire qu'il effectue ces étapes en &amp;quot;parallèle&amp;quot;. Nous utilisons donc les threads ou fils d’exécution. Un thread est donc responsable d'attendre qu'un nouveau client se connecte et effectue le &amp;quot;handshake&amp;quot;, il crée ensuite un thread associé à ce client afin d'établir un canal de communication. Il y a donc au moins un thread par client. Par la suite il faudra également implémenter une déconnexion automatique d'un client notamment après un timeout.&lt;br /&gt;
&lt;br /&gt;
Exemple d’exécution du serveur avec deux clients qui se connectent et envoient un message : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testServeur.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Les clients sont des navigateurs web. Pour les tests nous avons repris les exemples utilisés dans le cadre das projets IMA3 SC avec le titre de la page HTML qui se colore en vert lorsque le client est connecté, et un champ de saisie pour envoyer des messages au serveur : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testClient.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 4===&lt;br /&gt;
&lt;br /&gt;
*Mise en place d’algorithmes de traitement d'image&lt;br /&gt;
&lt;br /&gt;
====Détection de contour====&lt;br /&gt;
&lt;br /&gt;
L'objectif de notre projet est de pouvoir projeter n'importe quelle image envoyé grâce à l'application web. Pour cela nous allons tracer à une vitesse élevée les contours de l'image sur par exemple un mur grâce au laser. Il est donc nécessaire de détecter les contours de l'image grâce à plusieurs traitements.&lt;br /&gt;
&lt;br /&gt;
=====Conversion en niveau de gris=====&lt;br /&gt;
&lt;br /&gt;
Une des étapes préliminaires pour effectuer la détection de contour est de convertir l'image couleur en niveau de gris. Pour cela l'algorithme est simple : il suffit pour chaque pixel de l'image d'effectuer la moyenne des composantes rouge, verte, bleu de chaque pixel. En effet, si l'on considère une image matricielle (l'image est considérée comme un tableau à deux dimensions avec chaque case qui contient la couleur du pixel), chaque pixel contient les composantes RGB codées sur un octet. La couleur gris correspond aux composantes RGB égales. Le niveau de gris est donc codé de 0 à 255, avec 0 donnant du noir et 255 du blanc. &lt;br /&gt;
&lt;br /&gt;
Voici le résultat obtenu : [[Fichier:testGrayScale.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Filtre de Prewit et Sobel=====&lt;br /&gt;
&lt;br /&gt;
Un contour est défini par un changement brutal d'intensité lumineuse, il s'agit donc de détecter selon plusieurs directions (au moins 2) ces changements. Il existe de nombreuses techniques afin de détecter les contours d'une image (gradient, Laplacien). L'une des techniques avec un rapport efficacité/temps d'exécution correct repose sur les algorithmes de Prewit ou Sobel. L'algorithme repose sur la convolution de matrices.&lt;br /&gt;
Cela consiste à appliquer sur chaque pixel de l'image la matrice de Prewit définie comme &lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L_x = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; ainsi que sa transposée : &amp;lt;math&amp;gt;&lt;br /&gt;
L_y = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; -1 &amp;amp; -1 \\&lt;br /&gt;
 0 &amp;amp; 0 &amp;amp; 0 \\&lt;br /&gt;
+1 &amp;amp; +1 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Convoluer ces deux filtres sur l'image permet de détecter respectivement les contours verticaux et horizontaux.&lt;br /&gt;
&lt;br /&gt;
D'après wikipedia [https://fr.wikipedia.org/wiki/D%C3%A9tection_de_contours], on obtient de meilleurs résultats en appliquant un filtre triangulaire, on introduit donc la matrice de Sobel :&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-2 &amp;amp; 0 &amp;amp; +2 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
On obtient le résultat suivant : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testOutline1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Pré-traitement : Flou Gaussien=====&lt;br /&gt;
&lt;br /&gt;
Afin de réduire significativement le nombre de contours, il est nécessaire d'effectuer un pré-traitement avant la détection de contours. On utilise généralement un flou gaussien afin de réduire les transitions lumineuses et ainsi réduire le nombre de contours. L’algorithme de flou gaussien repose également sur la convolution de matrices sauf qu'ici la matrice filtre est générée grâce à une fonction gaussienne paramétrée par '''Sigma''' qui va directement impacter le niveau de flou. Plus la matrice de filtrage est grande plus la qualité du résultat est meilleure, mais le temps d’exécution devient également plus grand.&lt;br /&gt;
&lt;br /&gt;
Voici la fonction de génération du filtre : &amp;lt;math&amp;gt;G(x,y) = \frac{1}{{2\pi \sigma^2}} e^{-\frac{x^2 + y^2}{2 \sigma^2}}&amp;lt;/math&amp;gt; où x et y correspondent aux indices de la cellule de la matrice.&lt;br /&gt;
&lt;br /&gt;
On obtient ce résultat :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testGaussianBlur.png]]&lt;br /&gt;
&lt;br /&gt;
On note un bien meilleur résultat. Cependant on remarque que les composantes horizontales ne sont pas correctement détectées il subsiste un problème avec le filtrage vertical que je n'ai pas réussi à identifier. De plus, il s'agit par sa suite d'éliminer les contours parasites ainsi que d'affiner le trait pour n'avoir plus qu'un pixel d'épaisseur.&lt;br /&gt;
&lt;br /&gt;
=====Post-traitement : Algorithme de Canny=====&lt;br /&gt;
&lt;br /&gt;
Afin d'obtenir un résultat exploitable il est nécessaire d'appliquer encore quelques traitements. Pour cela nous utilisons l’algorithme de Canny qui repose que celui de Sobel mais qui ajoute un algorithme de seuillage par hysteresis qui permet de retirer les contours secondaires et de ne garder que les contours connexes dans une seuil haut et un seuil bas définis. En outre, cette algorithme affine également le trait obtenu. Pour cet algorithme nous avons directement trouvé des sources libres de droits [http://www.tomgibara.com/computer-vision/canny-edge-detector] qui donne des résultats très corrects.&lt;br /&gt;
&lt;br /&gt;
Par exemple :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ou encore : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny2.png]]&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;br /&gt;
&lt;br /&gt;
==Bibliographie==&lt;br /&gt;
&lt;br /&gt;
http://www.ebay.com/itm/20KPPS-30KPPS-laser-scanning-galvo-scanner-ILDA-Closed-Loop-max-30kpps-for-laser-/261517002270?hash=item3ce3a0c61e&lt;br /&gt;
&lt;br /&gt;
https://icn.fenelonlille.org/mediawiki/index.php/Projet_ICN_commun_2016/2017&lt;br /&gt;
&lt;br /&gt;
https://www.g33k-zone.org/post/2016/05/11/Configurer-le-Raspberry-Pi-en-point-d-acc%C3%A8s-Wifi&lt;br /&gt;
&lt;br /&gt;
http://stackoverflow.com/questions/22087076/how-to-make-a-simple-image-upload-using-javascript-html&lt;br /&gt;
&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_a_WebSocket_server_in_Java&lt;br /&gt;
&lt;br /&gt;
export http_proxy=http://proxy.polytech-lille.fr:3128&lt;/div&gt;</summary>
		<author><name>Mtrimbur</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=Fichier:TestCanny2.png&amp;diff=39464</id>
		<title>Fichier:TestCanny2.png</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=Fichier:TestCanny2.png&amp;diff=39464"/>
				<updated>2017-02-22T17:29:53Z</updated>
		
		<summary type="html">&lt;p&gt;Mtrimbur : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Mtrimbur</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=Fichier:TestCanny1.png&amp;diff=39463</id>
		<title>Fichier:TestCanny1.png</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=Fichier:TestCanny1.png&amp;diff=39463"/>
				<updated>2017-02-22T17:28:46Z</updated>
		
		<summary type="html">&lt;p&gt;Mtrimbur : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Mtrimbur</name></author>	</entry>

	<entry>
		<id>https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=39462</id>
		<title>IMA4 2016/2017 P39</title>
		<link rel="alternate" type="text/html" href="https://projets-ima.plil.fr/mediawiki/index.php?title=IMA4_2016/2017_P39&amp;diff=39462"/>
				<updated>2017-02-22T17:25:49Z</updated>
		
		<summary type="html">&lt;p&gt;Mtrimbur : /* Détection de contour */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
==Cahier des charges==&lt;br /&gt;
&lt;br /&gt;
===Présentation générale du projet=== &lt;br /&gt;
&lt;br /&gt;
===Contexte===&lt;br /&gt;
&lt;br /&gt;
Le laser est une technologie largement utilisé de nos jours dans de diverses applications. En effet, on retrouve cette technologie dans le domaine médical notamment pour la chirurgie oculaire ou encore dans industrie avec la découpe laser ou la soudure au laser.&lt;br /&gt;
&lt;br /&gt;
Le laser est une émission de photons produit par excitation d'un milieu amplificateur (ex : CO2), le rayonnement produit est unidirectionnel et monochromatique. Ce sont ces propriétés que nous allons exploiter afin réaliser un projecteur laser qui mis en mouvement est capable de dessiner des formes sur une surface à l'instar de systèmes existants utilisés pour des effets lumineux lors de festivités.&lt;br /&gt;
&lt;br /&gt;
====Objectif du projet====&lt;br /&gt;
&lt;br /&gt;
L'objectif du projet est de créer un système de projection laser à plusieurs couleurs (au minimum deux) avec une application web pour programmer les formes à dessiner afin d'agrémenter des compétitions de gymnastique rythmique.&lt;br /&gt;
&lt;br /&gt;
====Description du projet====&lt;br /&gt;
&lt;br /&gt;
Le projet consiste à réaliser avec des lasers des figures géométriques par l'intermédiaire d'un système galvanométrique. &lt;br /&gt;
&lt;br /&gt;
Notre premier travail sera de concevoir la partie projection. Pour cela, nous devrons aligner les lasers et les galvanomètres. En effet, ces derniers posséderont des miroirs à l'extrémité, ainsi les miroirs changeront d'inclinaison suivant le courant traversant les galvanomètres (similaire à l'image ci-contre). Il nous faudra également créer un système d'alimentation qui à partir d'une même source (réseau 230 V) sera capable d'alimenter les lasers et les galvanomètres ainsi qu'une Arduino et une Raspberry Pi.&lt;br /&gt;
[[File:Scanhead.jpeg|thumb]]&lt;br /&gt;
&lt;br /&gt;
Ensuite nous nous intéresserons à l'utilisation d'un système embarqué pour contrôler les galvanomètres et donc dessiner avec les lasers sur un plan 2D. En effet, le laser restera toujours fixe, seuls les galvanomètres, et donc les miroirs bougeront. Les galvanomètres étant contrôlés en courant il faudra réaliser une interface électronique pour convertir une commande en tension en commande de courant. La commande en tension sera assuré par une carte Arduino. Nous n'utiliserons qu'une seule paire de galvanomètres pour les deux laser. Il faudra donc multiplexer les deux faisceaux. La programmation des formes à effectuer, se fera par l'intermédiaire d'une application web PHP hébergée sur une RaspberryPi qui permettra de récupérer une image, d'y appliquer divers traitements et filtres afin d'en extraire les contours, et de calculer les commandes pour positionner les galvanomètres. Un serveur WebSocket également hébergé sur la RaspberryPi servira d'interface entre l'application web et L'arduino qui sera connecté via une liaison série sur la raspberryPI.&lt;br /&gt;
&lt;br /&gt;
Comme animation de test, nous dessinerons le contour d'une gymnaste avec une couleur et son ballon d'une autre couleur. La gymnaste devra lancer son ballon, réaliser quelques difficultés et récupérer son ballon.&lt;br /&gt;
&lt;br /&gt;
====Choix techniques : matériel et logiciel====&lt;br /&gt;
Nous utiliserons comme matériels :&lt;br /&gt;
*Deux lasers de différentes couleurs&lt;br /&gt;
*Une paire de galvanomètres à miroir&lt;br /&gt;
*Arduino&lt;br /&gt;
*Raspberry Pi3&lt;br /&gt;
*Alimentation 230V/5V 1A [http://www.miniinthebox.com/fr/dual-usb-eu-prise-murale-5v-2a-voyage-adaptateur-chargeur-d-alimentation-pour-iphone7-6-xiaomi-samsung-et-autre-telephone-portable_p5410410.html?currency=EUR&amp;amp;litb_from=paid_adwords_shopping&amp;amp;sku=429_6917%7C752_20648&amp;amp;utm_source=google_shopping&amp;amp;utm_medium=cpc&amp;amp;adword_mt=&amp;amp;adword_ct=138705676724&amp;amp;adword_kw=&amp;amp;adword_pos=1o5&amp;amp;adword_pl=&amp;amp;adword_net=g&amp;amp;adword_tar=&amp;amp;adw_src_id=9653316068_661261352_33588296076_aud-79897721311:pla-256966386459&amp;amp;gclid=Cj0KEQiA_KvEBRCtzNil4-KR-LIBEiQAmgekFxxKjJJWBYCJlDZEa3Ke_2_WR0DzGVbz-jaCZHVIBoMaAvld8P8HAQ]&lt;br /&gt;
*Drivers galvanomètres x2&lt;br /&gt;
*Alimentation laser&lt;br /&gt;
*Lunette de sécurité x2 [https://www.amazon.fr/Uvex-S1933X-Eyewear-SCTOrange-Anti-Fog/dp/B000USRG90/ref=sr_1_1?ie=UTF8&amp;amp;qid=1485441383&amp;amp;sr=8-1&amp;amp;keywords=uvex+s1933x]&lt;br /&gt;
*Boitier ABS [http://fr.farnell.com/multicomp/g3118/boitier-abs-240x120x60mm-ip65/dp/1526656]&lt;br /&gt;
*DAC 4 canaux, avec interface I²C [https://www.adafruit.com/products/1083]&lt;br /&gt;
*Connecteur C14 [http://www.conrad.fr/ce/fr/product/715001/Connecteur-secteur-C14-Embase-male-verticale-715001-Nombre-de-poles-2-PE-10-A-noir-1-pcs/?ref=detview1&amp;amp;rt=detview1&amp;amp;rb=1]&lt;br /&gt;
*Câble secteur&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Logiciel :&lt;br /&gt;
&lt;br /&gt;
*Serveur web : Apache2, HTML5, PHP5, CSS&lt;br /&gt;
*Base de donnée : MySQL&lt;br /&gt;
*Serveur WebSocket : JQuerry, websocket&lt;br /&gt;
*Arduino : IDE Arduino&lt;br /&gt;
&lt;br /&gt;
===Calendrier prévisionnel===&lt;br /&gt;
&lt;br /&gt;
====Liste des tâches à effectuer====&lt;br /&gt;
Les différentes tâches à effectuer sont :&lt;br /&gt;
*Partie préliminaire : étude de fonctionnement des galvanomètres&lt;br /&gt;
**Déterminer comment est effectuée la commande des galvanomètres (protocole, tension...)&lt;br /&gt;
**Effectuer des tests avec l'Arduino ou la Raspberry Pi&lt;br /&gt;
**Effectuer des tests avec une LED à la place du laser &lt;br /&gt;
*Partie projection&lt;br /&gt;
**Fixer les lasers&lt;br /&gt;
**Aligner les lasers et les galvanomètres&lt;br /&gt;
**Créer le système d'alimentation&lt;br /&gt;
**Création d'un boitier&lt;br /&gt;
*Partie système embarqué&lt;br /&gt;
**Asservissement des galvanomètres avec l'Arduino&lt;br /&gt;
**Système électronique de commande en courant pour les galvanomètres&lt;br /&gt;
*Interface Web&lt;br /&gt;
**Installation et configuration Apache2&lt;br /&gt;
**Création d'une interface graphique simple&lt;br /&gt;
**Implémentation d'algorithmes de traitement d'image&lt;br /&gt;
**Mise en forme avec des CSS&lt;br /&gt;
**Sytème d'authentification avec mot de passe&lt;br /&gt;
**Utilisation d'une base de données pour enregistrer toutes les images déjà utilisés afin de les réutiliser&lt;br /&gt;
*Serveur Web Socket&lt;br /&gt;
**Récupération des données de l'interface web&lt;br /&gt;
**Mise en place de la liaison série avec l'Arduino&lt;br /&gt;
&lt;br /&gt;
====Calendrier====&lt;br /&gt;
Répartition du temps consacré au projet (240h) :&lt;br /&gt;
*Partie projection : 80h&lt;br /&gt;
*Partie système embarqué : 40h&lt;br /&gt;
*Partie interface web et websocket: 120h&lt;br /&gt;
&lt;br /&gt;
==Feuille d'heures==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!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&lt;br /&gt;
|-&lt;br /&gt;
| Définition cahier des charges &lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 8&lt;br /&gt;
| 14&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|38&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Avancement du Projet==&lt;br /&gt;
&lt;br /&gt;
===Semaine 1===&lt;br /&gt;
&lt;br /&gt;
*Finalisation du cahier des charges avec les responsables&lt;br /&gt;
&lt;br /&gt;
*Acquisition de matériels :&lt;br /&gt;
**Projecteur Laser&lt;br /&gt;
**Galvanomètres&lt;br /&gt;
**Alimentation des galvanomètres&lt;br /&gt;
&lt;br /&gt;
*Listage du matériels à acquérir :&lt;br /&gt;
**Lunettes de sécurité&lt;br /&gt;
**DAC&lt;br /&gt;
**Alimentation 230V/5V 1A&lt;br /&gt;
** Boitier ABS &lt;br /&gt;
**...&lt;br /&gt;
&lt;br /&gt;
===Semaine 2===&lt;br /&gt;
&lt;br /&gt;
*Obtention de l'arduino et de la raspberryPI&lt;br /&gt;
&lt;br /&gt;
*Démontage du projecteur laser&lt;br /&gt;
**Deux lasers de classe 3b (vert et rouge)&lt;br /&gt;
**Circuit d'alimentation des deux lasers&lt;br /&gt;
&lt;br /&gt;
*Initialisation du port série de la raspberryPI&lt;br /&gt;
**Modification du fichier ''config.txt'' dans la partition boot&lt;br /&gt;
**Ajout d'une ligne autorisant la communication série ('''enable_uart=1''')&lt;br /&gt;
&lt;br /&gt;
===Semaine 3===&lt;br /&gt;
&lt;br /&gt;
*Installation du serveur apache sur la raspberryPI&lt;br /&gt;
**Modification du fichier ''/etc/network/interfaces'' (Static, Address, Netmask, Gateway)&lt;br /&gt;
**Modification du fichier ''/etc/resolv.conf'' (Adresse du serveur)&lt;br /&gt;
**Utilisation d'un proxy pour la récupération outils de programmation (Apache2, Php5)&lt;br /&gt;
&lt;br /&gt;
*Mise en place du point d’accès wifi de la raspberryPI&lt;br /&gt;
**Récupération des logiciels nécessaires (dnsmasq, hostapd)&lt;br /&gt;
**Mise en place d'une adresse IP statique pour le point d'accès par l'intermédiaire du fichier ''/etc/dhcpcd.conf''&lt;br /&gt;
**Désactivation de la négociation automatique de bail dans le fichier ''/etc/network/interfaces''&lt;br /&gt;
**Configuration du logiciel hostapd ''/etc/hostapd/hostapd.conf''&lt;br /&gt;
**Activation du démarrage automatique du point d'accès ''/etc/default/hostapd''&lt;br /&gt;
**Configuration du serveur DNS par ''/etc/dnsmasq.conf''&lt;br /&gt;
&lt;br /&gt;
*Instauration de la page d'accueil de l'interface web à l'adresse ''192.168.3.1''&lt;br /&gt;
**Téléversement de fichiers images sur la page web et affichage de celle-ci&lt;br /&gt;
**Voyant de confirmation du bon fonctionnement du serveur web&lt;br /&gt;
&lt;br /&gt;
*Développement du serveur websocket&lt;br /&gt;
&lt;br /&gt;
Le développement du serveur websocket, initialement prévu en C (il était prévu de reprendre les sources utilisées l'année précédente dans le cadre des projet IMA3 SC), a finalement été réalisé en JAVA pour plusieurs raisons.&lt;br /&gt;
Premièrement, un seul programme met en œuvre le serveur websocket, les divers traitements d'image, ainsi que les contrôles des galvanomètres (par l'intermédiaire des DAC) via la liaison I²C de la Raspberry Pi. Le langage JAVA fournit nativement des bibliothèques d'objets pour manipuler assez simplement des images, il existe également des librairies pour contrôler le port GPIO de la Raspberry et il était également intéressant de travailler avec un langage de plus haut niveau que le C.&lt;br /&gt;
En outre, la totale portabilité de ce langage nous permet de travailler sur n'importe quelle machine et ensuite transférer notre programme sur la Raspberry Pi et l’exécuter sans même repasser par une phase de compilation. Et finalement, c'est le langage que nous étudions actuellement en cours de programmation orientée objet, ce qui permet de nous perfectionner.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Serveur WebSocket====&lt;br /&gt;
&lt;br /&gt;
N'ayant pas trouvé d'API WebSocket en Java satisfaisante (qui ne nécessitent pas l'installation et la configuration de nombreux outils additionnels), j'ai estimé plus commode et plus formateur de développer notre propre serveur WebSocket en se basant sur les librairies sockets de Java avec l'aide d'une documentation assez exhaustive [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers].&lt;br /&gt;
&lt;br /&gt;
Les WebSockets désignent à la fois un protocole réseau qui étend le protocole TCP ainsi qu'une API du World Wide Web. Nous nous en servons afin d'établir une communication asynchrone et bidirectionnelle entre un navigateur web et le serveur, notamment pour envoyer l'image à projeter. L’implémentation du serveur repose sur plusieurs étapes.&lt;br /&gt;
&lt;br /&gt;
1) Connexion d'un client &lt;br /&gt;
&lt;br /&gt;
2) Handshake : permet de faire le lien entre le protocole HTTP et WS. Le client envoie une requête HTTP demandant un upgrade de la connexion en protocole WS et le serveur répond en configurant la connexion (détail dans la documentation [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers]).&lt;br /&gt;
&lt;br /&gt;
3) Réception et décodage des messages : le serveurs reçoit des trames brutes, on extrait donc la taille du message ainsi que le message. De plus, les données son encodées (cryptage XOR) par un masque qui doit également être extrait.&lt;br /&gt;
&lt;br /&gt;
4) Fermeture de la communication.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le serveur supporte le multi-client il est donc nécessaire qu'il effectue ces étapes en &amp;quot;parallèle&amp;quot;. Nous utilisons donc les threads ou fils d’exécution. Un thread est donc responsable d'attendre qu'un nouveau client se connecte et effectue le &amp;quot;handshake&amp;quot;, il crée ensuite un thread associé à ce client afin d'établir un canal de communication. Il y a donc au moins un thread par client. Par la suite il faudra également implémenter une déconnexion automatique d'un client notamment après un timeout.&lt;br /&gt;
&lt;br /&gt;
Exemple d’exécution du serveur avec deux clients qui se connectent et envoient un message : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testServeur.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Les clients sont des navigateurs web. Pour les tests nous avons repris les exemples utilisés dans le cadre das projets IMA3 SC avec le titre de la page HTML qui se colore en vert lorsque le client est connecté, et un champ de saisie pour envoyer des messages au serveur : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testClient.png]]&lt;br /&gt;
&lt;br /&gt;
===Semaine 4===&lt;br /&gt;
&lt;br /&gt;
*Mise en place d’algorithmes de traitement d'image&lt;br /&gt;
&lt;br /&gt;
====Détection de contour====&lt;br /&gt;
&lt;br /&gt;
L'objectif de notre projet est de pouvoir projeter n'importe quelle image envoyé grâce à l'application web. Pour cela nous allons tracer à une vitesse élevée les contours de l'image sur par exemple un mur grâce au laser. Il est donc nécessaire de détecter les contours de l'image grâce à plusieurs traitements.&lt;br /&gt;
&lt;br /&gt;
=====Conversion en niveau de gris=====&lt;br /&gt;
&lt;br /&gt;
Une des étapes préliminaires pour effectuer la détection de contour est de convertir l'image couleur en niveau de gris. Pour cela l'algorithme est simple : il suffit pour chaque pixel de l'image d'effectuer la moyenne des composantes rouge, verte, bleu de chaque pixel. En effet, si l'on considère une image matricielle (l'image est considérée comme un tableau à deux dimensions avec chaque case qui contient la couleur du pixel), chaque pixel contient les composantes RGB codées sur un octet. La couleur gris correspond aux composantes RGB égales. Le niveau de gris est donc codé de 0 à 255, avec 0 donnant du noir et 255 du blanc. &lt;br /&gt;
&lt;br /&gt;
Voici le résultat obtenu : [[Fichier:testGrayScale.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Filtre de Prewit et Sobel=====&lt;br /&gt;
&lt;br /&gt;
Un contour est défini par un changement brutal d'intensité lumineuse, il s'agit donc de détecter selon plusieurs directions (au moins 2) ces changements. Il existe de nombreuses techniques afin de détecter les contours d'une image (gradient, Laplacien). L'une des techniques avec un rapport efficacité/temps d'exécution correct repose sur les algorithmes de Prewit ou Sobel. L'algorithme repose sur la convolution de matrices.&lt;br /&gt;
Cela consiste à appliquer sur chaque pixel de l'image la matrice de Prewit définie comme &lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L_x = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; ainsi que sa transposée : &amp;lt;math&amp;gt;&lt;br /&gt;
L_y = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; -1 &amp;amp; -1 \\&lt;br /&gt;
 0 &amp;amp; 0 &amp;amp; 0 \\&lt;br /&gt;
+1 &amp;amp; +1 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Convoluer ces deux filtres sur l'image permet de détecter respectivement les contours verticaux et horizontaux.&lt;br /&gt;
&lt;br /&gt;
D'après wikipedia [https://fr.wikipedia.org/wiki/D%C3%A9tection_de_contours], on obtient de meilleurs résultats en appliquant un filtre triangulaire, on introduit donc la matrice de Sobel :&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L = \begin{bmatrix}&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1 \\&lt;br /&gt;
-2 &amp;amp; 0 &amp;amp; +2 \\&lt;br /&gt;
-1 &amp;amp; 0 &amp;amp; +1&lt;br /&gt;
\end{bmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
On obtient le résultat suivant : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testOutline1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Pré-traitement : Flou Gaussien=====&lt;br /&gt;
&lt;br /&gt;
Afin de réduire significativement le nombre de contours, il est nécessaire d'effectuer un pré-traitement avant la détection de contours. On utilise généralement un flou Gaussien afin de réduire les transitions lumineuses et ainsi réduire le nombre de contours. L’algorithme de flou Gaussien repose également sur la convolution de matrice sauf qu'ici la matrice filtre est générée grâce à une fonction gaussienne paramétrée par '''Sigma''' qui va directement impacter le niveau de flou. Plus la matrice de filtrage est grande plus la qualité du résultat est meilleure, mais le temps d’exécution devient également plus grand.&lt;br /&gt;
&lt;br /&gt;
Voici la fonction de génération du filtre : &amp;lt;math&amp;gt;G(x,y) = \frac{1}{{2\pi \sigma^2}} e^{-\frac{x^2 + y^2}{2 \sigma^2}}&amp;lt;/math&amp;gt; où x et y correspondent au indices de la cellule de la matrice.&lt;br /&gt;
&lt;br /&gt;
On obtient ce résultat :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testGaussianBlur.png]]&lt;br /&gt;
&lt;br /&gt;
On note un bien meilleur résultat. Cependant on remarque que les composantes horizontales ne sont pas correctement détectées il subsiste un problème avec le filtrage vertical que je n'ai pas réussi à identifier. De plus, il s'agit par sa suite d'éliminer les contours parasites ainsi que d'affiner le trait pour n'avoir plus qu'un pixel d'épaisseur.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====Post-traitement : Algorithme de Canny=====&lt;br /&gt;
&lt;br /&gt;
Afin d'obtenir un résultat exploitable il est nécessaire d'appliquer encore quelques traitements. Pour cela nous utilisons l’algorithme de Canny qui repose que celui de Sobel mais qui ajoute un algorithme de seuillage par hysteresis qui permet de retirer les contours secondaires et de ne garder que les contours connexes dans une seuil haut et un seuil bas définis. En outre, cette algorithme affine également le trait obtenu. Pour cet algorithme nous avons directement trouvé des sources libres de droits [http://www.tomgibara.com/computer-vision/canny-edge-detector] qui donne des résultats très corrects.&lt;br /&gt;
&lt;br /&gt;
Par exemple :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny1.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ou encore : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:testCanny2.png]]&lt;br /&gt;
&lt;br /&gt;
== Fichiers Rendus ==&lt;br /&gt;
&lt;br /&gt;
==Bibliographie==&lt;br /&gt;
&lt;br /&gt;
http://www.ebay.com/itm/20KPPS-30KPPS-laser-scanning-galvo-scanner-ILDA-Closed-Loop-max-30kpps-for-laser-/261517002270?hash=item3ce3a0c61e&lt;br /&gt;
&lt;br /&gt;
https://icn.fenelonlille.org/mediawiki/index.php/Projet_ICN_commun_2016/2017&lt;br /&gt;
&lt;br /&gt;
https://www.g33k-zone.org/post/2016/05/11/Configurer-le-Raspberry-Pi-en-point-d-acc%C3%A8s-Wifi&lt;br /&gt;
&lt;br /&gt;
http://stackoverflow.com/questions/22087076/how-to-make-a-simple-image-upload-using-javascript-html&lt;br /&gt;
&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_a_WebSocket_server_in_Java&lt;br /&gt;
&lt;br /&gt;
export http_proxy=http://proxy.polytech-lille.fr:3128&lt;/div&gt;</summary>
		<author><name>Mtrimbur</name></author>	</entry>

	</feed>