Académique Documents
Professionnel Documents
Culture Documents
Projet: apOCRyphe
Sommaire
1. Introduction
2. Pré-traitement de l’image
5. Réseau de neurones
6. Interface graphique
7. Site web
8. Conclusion
9. Annexes
2 10 décembre 2014
apOCRyphe Shut up and calculate!
Introduction
Voici notre premier rapport concernant le projet du premier semestre
de la 2ème année à l’EPITA. Après avoir réalisé l’année dernière un jeu
vidéo en C#, nous allons devoir cette année implémenter un logiciel de
Reconnaissance Optique de Caractères (R.O.C.), plus connu sous le nom
de Optical Character Recognition (O.C.R.) en anglais, servant à recopier
automatiquement, dans un fichier texte, une page scannée.
3 10 décembre 2014
apOCRyphe Shut up and calculate!
4 10 décembre 2014
apOCRyphe Shut up and calculate!
Pré-traitement de l’image
Avant qu’il soit possible de travailler sur l’image, il faut que celle-ci
soit pré-traitée pour faciliter l’identification des caractères. En effet, il
faut binariser l’image et supprimer le bruit de l’image ainsi qu’effectuer
une rotation de l’image si le texte n’est pas droit. Cette partie a été
réalisée par Guillaume avec l’aide de Thomas.
1. Débruitage
Afin d’effectuer la suppression du bruit de l’image, nous utilisons une
combinaison de trois méthodes de filtrage d’image : le passage en niveau
de gris, la binarisation Sauvola et le filtre Gaussien.
Binarisation
La méthode de binarisation choisie est une méthode adaptative et
plus précisément à seuil local. En effet, la méthode choisie est celle de
Sauvola qui s’adapte à l’image et qui requiert une image en niveau de
gris. Le principal objectif est de déterminer un seuil. Pour ce faire, il
faut créer une variable qui servira de seuil (nommons la average). Lors
du parcours de l’image, nous ajoutons à average la somme des valeurs
de gris des pixels présents dans un rayon prédéfini que nous divisons
par le nombre de pixels présents. Par la même occasion, nous calculons
la déviation (que nous plaçons dans une variable deviation) qui est la
somme des valeurs de gris des pixels voisins soustrait à la moyenne av-
erage divisé par le nombre de pixels voisins présents. Ensuite, le seuil
final est égal à T = m × 1 + k × Rd − 1 où T représente le nouveau
5 10 décembre 2014
apOCRyphe Shut up and calculate!
des composantes du pixel (peu importe laquelle étant donné que le pixel
est gris (donc ses composantes ont la même valeur)) est plus grande que
le seuil, nous la mettons en blanc, sinon en noir. L’avantage principal
de cette méthode est qu’elle peut être utilisée sur les images à fond non
blanc.
Image d’orgine
6 10 décembre 2014
apOCRyphe Shut up and calculate!
Filtre Gaussien
Le filtre Gaussien est la méthode permettant de supprimer le bruit et
est à utiliser avant la binarisation lorsqu’il est nécessaire. Cette méthode
utilise une matrice de convolution 3 * 3 sur chaque pixel de l’image. Le
principe est le suivant : chaque composante de couleur des pixels voisins
et du pixel actuel est multipliée par la valeur de la matrice de convolu-
tion correspondante et la somme est divisée par 16 (qui est la somme des
valeurs présentes dans la matrice de convolution). Le tout est disposé
dans une variable qui correspond à la nouvelle composante R, G et B du
pixel actuel.
1 2 1
La matrice de convolution est la suivante : 2 4 2
1 2 1
7 10 décembre 2014
apOCRyphe Shut up and calculate!
8 10 décembre 2014
apOCRyphe Shut up and calculate!
2. Rotation
Une fois tous les élément réunis, nous effectuons les deux calculs des
nouvelles coordonnées :
9 10 décembre 2014
apOCRyphe Shut up and calculate!
10 10 décembre 2014
apOCRyphe Shut up and calculate!
Principe
Cet algorithme se divise en quatre parties : une découpe verticale
sur l’image d’origine, une découpe horizontale sur l’image d’origine, une
opération logique AND sur les deux images résultantes et le calcul des
coordonnées des blocs obtenus. Grâce à cet algorithme, nous obtenons
des blocs noirs qui représentent les paragraphes ce qui nous facilite le
calcul des coordonnées de ces blocs pour pouvoir ensuite y détecter les
lignes et enfin les caractères.
Découpe verticale
Pour effectuer la découpe verticale, nous parcourons notre feuille de
haut en bas et de gauche à droite. Lorsque nous rencontrons un pixel
noir, nous passons un booléen countWhitePixel à true pour indiquer que,
à partir de maintenant, nous voulons connaître le nombre de pixels blancs
qui séparent deux pixels noirs. À la nouvelle rencontre d’un pixel noir,
nous regardons le nombre de pixels blancs que nous avons rencontré et si
ce nombre est plus petit qu’un seuil (l’espace moyen entre deux lettres),
nous transformons les pixels blancs situés entre ces deux pixels noirs en
1
Voir Annexes
11 10 décembre 2014
apOCRyphe Shut up and calculate!
Une fois l’image traitée dans son intégralité, nous créons un tableau
binaire de taille égale à la dimension de la feuille et qui contient un 0 si
le pixel est blanc et un 1 s’il est noir et nous renvoyons ce tableau.
Découpe horizontale
La découpe horizontale est, dans sa majorité, similaire à la découpe
verticale. En effet, le seul changement est le parcours de l’image qui
s’effectue de gauche à droite et de haut en bas.
Une fois l’image traitée dans son intégralité, nous renvoyons égale-
ment un tableau binaire.
Découpe finale
La découpe finale est, comme son nom le laisse supposer, l’étape
finale de la découpe des blocs. En effet, elle se sert des deux tableaux
obtenus avec la découpe verticale et horizontale pour effectuer une opéra-
tion logique AND dessus. Une fois fait, chaque ligne de notre texte est
représentée par une ligne noire. Cependant, nous devons obtenir un
gros bloc pour chaque paragraphe pour pouvoir appliquer la détection
des lignes dessus. Par conséquent, nous réalisons de nouveau une dé-
coupe verticale puis une découpe horizontale sur la même image et nous
obtenons ainsi des blocs représentants les différents paragraphes et par-
ties du texte.
12 10 décembre 2014
apOCRyphe Shut up and calculate!
visité ou non.
13 10 décembre 2014
apOCRyphe Shut up and calculate!
La détection des lignes utilise un principe très simple : tant que nous
sommes sur la même ligne, nous prenons les coordonnées de chaque pixel
noir pour, au final, obtenir l’encadrement de la ligne. Pour savoir si nous
nous trouvons toujours sur la même ligne ou si nous sommes sur une
nouvelle ligne, à chaque itération des abscisses, nous incrémentons un
compteur de pixel noir si le pixel sur lequel nous nous trouvons est noir.
Si le booléen est à true et que nous avons un pixel noir, alors nous
sommes sur une nouvelle ligne. Par conséquent, nous incrémentons le
nombre de ligne et répétons le même principe que précédemment pour
encadrer cette ligne.
Une fois l’image parcourue dans son intégralité, nous renvoyons notre
tableau à deux dimensions pour l’utiliser dans la détection des caractères.
14 10 décembre 2014
apOCRyphe Shut up and calculate!
15 10 décembre 2014
apOCRyphe Shut up and calculate!
16 10 décembre 2014
apOCRyphe Shut up and calculate!
3
Voir Annexes
17 10 décembre 2014
apOCRyphe Shut up and calculate!
Redimensionnement des
caractères
Afin de pouvoir utiliser le réseau de neurone et d’apprendre plus pré-
cisément et plus rapidement les différents caractères qui existent, nous
avons décidé de redimensionner tous les caractères que le réseau trait-
era en 16x16 pixels. Pour cela, nous avons implémenté une fonction de
redimensionnement matriciel basée sur le principe de l’interpolation bil-
inéaire. Cette méhode fontionne un peu comme une règle de trois, mais
sur deux dimensions. Cette méthode très simple nous permet de ren-
dre l’implémentation de la reconnaissance des caractères beaucoup plus
facile.
18 10 décembre 2014
apOCRyphe Shut up and calculate!
Réseau de neurones
1. Principe
19 10 décembre 2014
apOCRyphe Shut up and calculate!
20 10 décembre 2014
apOCRyphe Shut up and calculate!
21 10 décembre 2014
apOCRyphe Shut up and calculate!
2. Perceptron multicouche
22 10 décembre 2014
apOCRyphe Shut up and calculate!
23 10 décembre 2014
apOCRyphe Shut up and calculate!
4. Les caractères
24 10 décembre 2014
apOCRyphe Shut up and calculate!
25 10 décembre 2014
apOCRyphe Shut up and calculate!
26 10 décembre 2014
apOCRyphe Shut up and calculate!
Interface graphique
Lors de la précédente soutenance, nous avons voulu faire une ébauche
d’interface graphique, répondant aux besoin de notre O.C.R.. Concer-
nant l’interface graphique, nous avons essayé d’en créer une qui ne soit
pas en reste. L’interface graphique, étant une façon rapide et intuitive
d’utiliser le logiciel, doit être assez optimisée : une apparence simple,
peu de boutons, pas de couleurs exotiques. L’interface se divise en deux
zones :
• L’initialisation de GTK+
• L’affichage de l’interface
27 10 décembre 2014
apOCRyphe Shut up and calculate!
1. Aspect graphique
En premier lieu, nous avons créé la fenêtre pour pouvoir y mettre tous
les autres widgets. Vu que nous allons afficher une image et un texte, il
nous faut de la place. Nous avons alors définit sa taille de façon à ce que
l’interface occupe tout l’écran. Enuite il nous faut des boutons. Nous
avons donc créé un premier bouton, nouvs l’avons définit et nous l’avons
placé dans la fenêtre. Lorsque nous compilons, nous voyons une fenêtre
prenant tout l’écran et un bouton au milieu en haut s’étendant sur toute
la largeur. Pour une économie de lignes de code, au lieu d’afficher chaque
widget un par un, nous affichons tous les widgets contenu dans la fenêtre
grâce à la fonction show_all.
Ensuite, nous avons créé un second bouton, nous l’avons définit, nous
l’avons placé, lui aussi, dans la fenêtre. Nous avons compilé et le premier
problème est survenu. Nous avons eu une erreur comme quoi la fenêtre
n’accepte pas plus d’un objet à l’intérieur.
Premier problème
Nous avions une fenêtre qui n’acceptait de contenir qu’un seul widget,
or nous avions au moins 4 widgets à utiliser.
Pour cela, il existe un widget appelé vbox, servant à contenir d’autres
widgets. Ainsi, la fenêtre contient la boîte et la boîte contiendra les
autres widgets nécessaires à l’interface graphique.
Une fois ce problème règlé, nous avons compilé et nous avons obtenu
une fenêtre blanche avec en haut 2 boutons superposés horizontalement,
ce qui, pour être honnête, était assez moche et réduisait aussi la taille
de l’interface. Avec 2 boutons, c’était encore passable mais avec plus de
boutons ce ne serait plus possible d’avoir de la place pour l’affichage de
l’image et du texte.
28 10 décembre 2014
apOCRyphe Shut up and calculate!
Deuxième problème
Afin d’afficher les boutons de manière plus optimisée, il existe un
widget, appelé button_box, qui permet d’afficher les boutons sur la même
ligne. Ainsi, la boîte contient la boîte à boutons qui contient à son tour
tous les boutons actuels et futurs.
Troisième problème
Les 2 zones étant l’une en dessous de l’autre, cela donne un rendu
peu pratique et assez inhabituel.
29 10 décembre 2014
apOCRyphe Shut up and calculate!
2. Aspect fonctionnel
Maintenant que l’aspect graphique est fini, il nous faut rendre les
boutons fonctionnels et les zones capables d’afficher l’image et le texte.
Tout d’abord, il nous faut capter les actions de l’utilisateur. S’il clique
sur un bouton, logiquement une action est normalement censée se pro-
duire. Pour ce faire, nous avons utilisé la fonction g_signal_connect,
qui prend en paramètre l’objet ciblé, l’action, la conséquence et l’objet
auquel celle-ci s’applique.
Par exemple, pour fermer la fenêtre, nous avons : g_signal_connect
(G_OBJECT (p_window), "destroy", G_CALLBACK (gtk_main_quit),
NULL);
30 10 décembre 2014
apOCRyphe Shut up and calculate!
Quatrième problème
Afin de permettre à l’utilisateur de mettre le chemin de l’image à
charger, il existe un widget qui ouvre une fenêtre de dialogue. L’utilisateur
choisi le fichier à ouvrir et clique sur le bouton ouvrir. À ce moment là,
en théorie, nous stockons le nom du fichier, nous fermons la fenêtre de
dialogue, nous chargeons l’image à sa place et nous chargeons le résultat
du traitement dans la text_view. Mais, malheureusement, ce n’est pas
ce qui s’est produit.
31 10 décembre 2014
apOCRyphe Shut up and calculate!
3. Résultat
32 10 décembre 2014
apOCRyphe Shut up and calculate!
4. Bilan GTK+
33 10 décembre 2014
apOCRyphe Shut up and calculate!
Site web
Nous avons décidé, sur ce projet, de ne pas trop nous concentrer sur
la création du site web. En effet, ayant que trois mois pour réaliser notre
O.C.R., nous ne voulions pas être retardés par l’aspect communication du
projet. C’est pour cela que nous avons décidé de créer un site web de type
wordpress, un éditeur de site web, nous permettant de le confectionner
facilement. Notre site est en apparence plus un blog qu’autre chose, mais
nous avons jugé que celà était suffisant pour le moment.
34 10 décembre 2014
apOCRyphe Shut up and calculate!
Conclusion
1. Personnelle
Thomas
Ce projet m’a beaucoup apporté, autant en expérience de program-
mation avec la découverte du C, qu’en organisation de projet avec un
sujet beaucoup plus complexe que le jeu vidéo que nous devions créer
l’année précédente. Je pense m’être beaucoup impliqué dans ce projet
mais je suis moyennement fier du résultat, surtout concernant ma partie
du réseau neuronal. J’ai beaucoup travailler dessus afin de l’optimiser le
plus possible, je l’ai ré-implémenté plusieurs fois, tout ceci pour arriver
à un réseau ne pouvant pas reconnaître tous les caractères. Ceci est en
partie dû au fait que je n’ai pas réussi à finir l’implémentation du réseau
assez rapidement pour avoir le temps de lui faire apprendre les caractères.
Je pense que c’est une grande leçon sur l’organisation de travail : toujours
essayer de finir son travail un peu en avance et non juste pour la deadline.
Corentin
Ce projet m’a aidé a découvrir le C et la manipulation de fichiers, de
façon plus poussée que dans les TP. Bien que les bases de GTK soient
assez simples à comprendre, la manipulationde fichiers était sensiblement
plus difficile et à conduit à de nombreux échecs. Au final, pour ce qui est
de ma partie, je suis assez déçu. L’interface fonctionne à moitié, n’a pas
été utilisée ce qui rend mon travail totalement inutile. Cependant, cela
m’a permis de faire un choix, si à l’avenir, j’ai le choix entre programmer
en C et en C#, je choisirai la seconde option.
35 10 décembre 2014
apOCRyphe Shut up and calculate!
Guillaume
Ce projet fut un grand plaisir personnel et m’a permis de découvrir
des qualités que je pensais ne pas avoir en programmation. En effet,
j’ai su tenir mes engagements en ce qui concerne ma partie de l’O.C.R.
voire plus que ce que j’étais censé faire. À l’opposé de l’an dernier, où
nous devions coder un jeu vidéo, j’ai su me débrouiller seul et réaliser
des tâches assez complexes.
De plus, j’ai pu renforcer mes liens avec Thomas avec qui je travaille
depuis maintenant deux ans rendant le travail en groupe encore plus
plaisant qu’il ne l’est déjà.
2. Globale
36 10 décembre 2014
apOCRyphe Shut up and calculate!
Annexes
37 10 décembre 2014
apOCRyphe Shut up and calculate!
38 10 décembre 2014
apOCRyphe Shut up and calculate!
2. Introduction 3
3. Pré-traitement de l’image 5
1. Débruitage . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2. Binarisation . . . . . . . . . . . . . . . . . . . . . . . 5
3. Filtre Gaussien . . . . . . . . . . . . . . . . . . . . . . 7
2. Rotation . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1. Principe . . . . . . . . . . . . . . . . . . . . . . . . . 11
2. Découpe verticale . . . . . . . . . . . . . . . . . . . . 11
3. Découpe horizontale . . . . . . . . . . . . . . . . . . . 12
4. Découpe finale . . . . . . . . . . . . . . . . . . . . . . 12
6. Réseau de neurones 19
39 10 décembre 2014
apOCRyphe Shut up and calculate!
1. Principe . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
2. Perceptron multicouche . . . . . . . . . . . . . . . . . . . . 22
4. Les caractères . . . . . . . . . . . . . . . . . . . . . . . . . 24
7. Interface graphique 27
1. Aspect graphique . . . . . . . . . . . . . . . . . . . . . . . 28
1. Premier problème . . . . . . . . . . . . . . . . . . . . 28
2. Deuxième problème . . . . . . . . . . . . . . . . . . . 29
3. Troisième problème . . . . . . . . . . . . . . . . . . . 29
2. Aspect fonctionnel . . . . . . . . . . . . . . . . . . . . . . . 30
1. Quatrième problème . . . . . . . . . . . . . . . . . . . 31
3. Résultat . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
4. Bilan GTK+ . . . . . . . . . . . . . . . . . . . . . . . . . . 33
8. Site web 34
9. Conclusion 35
1. Personnelle . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
1. Thomas . . . . . . . . . . . . . . . . . . . . . . . . . . 35
2. Corentin . . . . . . . . . . . . . . . . . . . . . . . . . 35
3. Guillaume . . . . . . . . . . . . . . . . . . . . . . . . 36
2. Globale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
10. Annexes 37
40 10 décembre 2014