Précédent   Forum des professionnels en informatique > Autres langages > Algorithmes > Traitement d'images
Traitement d'images Forum d'entraide sur le traitement d'images et l'analyse d'images et de vidéos. Avant de poster : Cours de traitement d'images
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 21/02/2005, 14h48   #61
Invité de passage
 
Inscription : novembre 2004
Messages : 38
Détails du profil
Informations forums :
Inscription : novembre 2004
Messages : 38
Points : 2
Points : 2
Citation:
La skeletization Zhang suen tu veux plus d'infos la dessus ? Je croyais pourtant avec mon shéma t'avoir largement éclairé
nan c pas ça, la skeletization, j'ai pigé ce que ça fait

ce que je veux savoir, c comment on fait pour skeletizer,
ça veut dire koi que ça fait plusieurs passes qd ça scanne l'image...

dsl de rien comprendre
bigbill est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 21/02/2005, 15h02   #62
Nouveau Membre du Club
 
Avatar de ALEX77
 
Inscription : juillet 2002
Messages : 99
Détails du profil
Informations forums :
Inscription : juillet 2002
Messages : 99
Points : 36
Points : 36
Si tu veux vraiement piger ce que ça fait, va voir vec 1.1.5 sur sourceforge.net et regardes l'unité skeletize.
http://sourceforge.net/project/showf...kage_id=102521

Tu trouveras ces fonctions :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
////////////////////////////////////////////////////////////////////////////////////////////////

// count neighbors
int count_neighbors(Rasterimage* raster,int i,int j){
        int count;

        // count neighbors
        count=0;
        if(raster->getPixel(i,j-1)!=raster->getBackground()){
                count++;
        }
        if(raster->getPixel(i+1,j-1)!=raster->getBackground()){
                count++;
        }
        if(raster->getPixel(i+1,j)!=raster->getBackground()){
                count++;
        }
        if(raster->getPixel(i+1,j+1)!=raster->getBackground()){
                count++;
        }
        if(raster->getPixel(i,j+1)!=raster->getBackground()){
                count++;
        }
        if(raster->getPixel(i-1,j+1)!=raster->getBackground()){
                count++;
        }
        if(raster->getPixel(i-1,j)!=raster->getBackground()){
                count++;
        }
        if(raster->getPixel(i-1,j-1)!=raster->getBackground()){
                count++;
        }

        // return count
        return count;
}


////////////////////////////////////////////////////////////////////////////////////////////////

// ccount zero-to-one transitions
int count_transitions(Rasterimage* raster,int i,int j){
        int count;

        // count zero-to-one transitions
        count=0;
        if(raster->getPixel(i,j-1)==raster->getBackground() && raster->getPixel(i+1,j-1)!=raster->getBackground()){
                count++;
        }
        if(raster->getPixel(i+1,j-1)==raster->getBackground() && raster->getPixel(i+1,j)!=raster->getBackground()){
                count++;
        }
        if(raster->getPixel(i+1,j)==raster->getBackground() && raster->getPixel(i+1,j+1)!=raster->getBackground()){
                count++;
        }
        if(raster->getPixel(i+1,j+1)==raster->getBackground() && raster->getPixel(i,j+1)!=raster->getBackground()){
                count++;
        }
        if(raster->getPixel(i,j+1)==raster->getBackground() && raster->getPixel(i-1,j+1)!=raster->getBackground()){
                count++;
        }
        if(raster->getPixel(i-1,j+1)==raster->getBackground() && raster->getPixel(i-1,j)!=raster->getBackground()){
                count++;
        }
        if(raster->getPixel(i-1,j)==raster->getBackground() && raster->getPixel(i-1,j-1)!=raster->getBackground()){
                count++;
        }
        if(raster->getPixel(i-1,j-1)==raster->getBackground() && raster->getPixel(i,j-1)!=raster->getBackground()){
                count++;
        }

        // return count
        return count;
}


////////////////////////////////////////////////////////////////////////////////////////////////

// check boundary at south-east
int check_se(Rasterimage* raster,int i,int j){
        int count;

        // check neighbors
        count=count_neighbors(raster,i,j);
        if(count < 2 || count > 6){
                return 0;
        }


        // check zero-to-one transitions
        count=count_transitions(raster,i,j);
        if(count != 1){
                return 0;
        }

        // check east
        if(raster->getPixel(i,j-1)!=raster->getBackground() &&
           raster->getPixel(i+1,j)!=raster->getBackground() &&
           raster->getPixel(i,j+1)!=raster->getBackground() ){
                return 0;
        }

        // check south
        if(raster->getPixel(i+1,j)!=raster->getBackground() &&
           raster->getPixel(i,j+1)!=raster->getBackground() &&
           raster->getPixel(i-1,j)!=raster->getBackground() ){
                return 0;
        }

        // return true
        return 1;
}


////////////////////////////////////////////////////////////////////////////////////////////////

// check boundary at north-west
int check_nw(Rasterimage* raster,int i,int j){
        int count;

        // check neighbors
        count=count_neighbors(raster,i,j);
        if(count < 2 || count > 6){
                return 0;
        }


        // check zero-to-one transition
        count=count_transitions(raster,i,j);
        if(count != 1){
                return 0;
        }

        // check north
        if(raster->getPixel(i,j-1)!=raster->getBackground() &&
           raster->getPixel(i+1,j)!=raster->getBackground() &&
           raster->getPixel(i-1,j)!=raster->getBackground() ){
                return 0;
        }

        // check west
        if(raster->getPixel(i,j-1)!=raster->getBackground() &&
           raster->getPixel(i,j+1)!=raster->getBackground() &&
           raster->getPixel(i-1,j)!=raster->getBackground() ){
                return 0;
        }

        // return true
        return 1;
}


////////////////////////////////////////////////////////////////////////////////////////////////

//! Zhang-Suen skeletonizing
/*!
  Uses the Zhang-Suen skeletonizing algorithm to get the skeletons
  of objects in a binary image.
  \param raster A binarized Rasterimage
  \return The medial axes transformed Rasterimage
*/
Rasterimage* skel_zhang_suen(Rasterimage* raster){

        int i,j,changes;
        int width,height;
        unsigned char background;
        Rasterimage* tmp_raster;

        // set size
        width=raster->getWidth();
        height=raster->getHeight();

        // background color
        background=raster->getBackground();

        // allocate memory / make new raster
        tmp_raster=new Rasterimage(raster->getWidth(),raster->getHeight(),raster->getColors(),raster->getType());

        // set colors
        for (i=0; i<(int)raster->getColors();i++){
                tmp_raster->setColorPalette(i,raster->getColorPalette(i));
        }
        tmp_raster->setBackground(background);

        // calculate skeleton / first iteration
        for (j=0;j<height;j++){
                for (i=0;i<width;i++){
                        if(i>0 && j>0 && i<width-1 && j<height-1 && raster->getPixel(i,j)!=background){
                                if( check_se(raster,i,j) ){
                                        // set white if not skeleton
                                        tmp_raster->setPixel(i,j,background);
                                }else{
                                        // set old color
                                        tmp_raster->setPixel(i,j,raster->getPixel(i,j));
                                        tmp_raster->incrPointcount();
                                }
                        }else{
                                // set white if not point or border
                                tmp_raster->setPixel(i,j,background);

                        }
                        ;
                }
        }

        // calculate skeleton / second iteration
        for (j=0;j<height;j++){
                for (i=0;i<width;i++){
                        if(i>0 && j>0 && i<width-1 && j<height-1 && raster->getPixel(i,j)!=background){
                                if( check_nw(raster,i,j) ){
                                        // set white if not skeleton
                                        tmp_raster->setPixel(i,j,background);
                                }else{
                                        // set old color
                                        tmp_raster->setPixel(i,j,raster->getPixel(i,j));
                                        tmp_raster->incrPointcount();
                                }
                        }else{
                                // set white if not point or border
                                tmp_raster->setPixel(i,j,background);

                        }
                        ;
                }
        }

        // check changes
        changes=0;
        for (j=0;j<height;j++){
                for (i=0;i<width;i++){
                        if(raster->getPixel(i,j)!=tmp_raster->getPixel(i,j)){
                                        changes=1;
                        }
                }
        }

        // free memory
        delete raster;

        // if changes, do it again
        if(changes){
                return skel_zhang_suen(tmp_raster);
        }else{
                // return raster
                return tmp_raster;
        }
}
ALEX77 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 22/02/2005, 19h19   #63
Invité de passage
 
Inscription : novembre 2004
Messages : 38
Détails du profil
Informations forums :
Inscription : novembre 2004
Messages : 38
Points : 2
Points : 2
j'ai fait encore qq recherches sur ces algo d'affinement et je suis tombé sur plusieurs trucs.

En gros, il faut connaitre l'algo du "hit-and-miss". C ce qu'il fo utiliser pour faire l'amincicement d'une lettre.
Je sais pas si c ça qu'utilise l'algo de Zhang suen, vu que je l'ai pas super compris. C peut être la mm chose, je sais po ....

Tu connais le "hit-and-miss" alex ?
bigbill est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 22/02/2005, 22h54   #64
Nouveau Membre du Club
 
Avatar de ALEX77
 
Inscription : juillet 2002
Messages : 99
Détails du profil
Informations forums :
Inscription : juillet 2002
Messages : 99
Points : 36
Points : 36
Non je connais pas le hit and miss mais essayes ce code c'est l'algo de Zhang Suen. Disons qu'en gros ça garde que le squelette des lettres d'où le nom de cette opération : la squeletisation. En tout cas ça fonctionne chez moi. La preuve en images :

avant :


après :


Si ça marche pour moi pourquoi pas pour toi ? C'est pas si compliqué à mettre en place et comme je te l'ai dis si tu programmes en C, tu sera plus avantagé que moi car je programme en Delphi. Donc tu ne devrais pas trop rencontré de problèmes pour comprendre les projets que j'ai mis en liens sur ce sujet.
ALEX77 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 22/02/2005, 23h33   #65
Invité de passage
 
Inscription : novembre 2004
Messages : 38
Détails du profil
Informations forums :
Inscription : novembre 2004
Messages : 38
Points : 2
Points : 2
tu peux me faire voir ce que ça donne pour le "fi" en Times new roman ? ( c une des polices pour lesquelles ces 2 lettres sont collées )
en une police assez grosse

c juste pour vérifier .....
bigbill est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 22/02/2005, 23h44   #66
Nouveau Membre du Club
 
Avatar de ALEX77
 
Inscription : juillet 2002
Messages : 99
Détails du profil
Informations forums :
Inscription : juillet 2002
Messages : 99
Points : 36
Points : 36



comme tu peux le constater avec certaines tailles le f et le i ne se touchent pas toujours.

J'espères que ça répond à ta question.
ALEX77 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 22/02/2005, 23h59   #67
Invité de passage
 
Inscription : novembre 2004
Messages : 38
Détails du profil
Informations forums :
Inscription : novembre 2004
Messages : 38
Points : 2
Points : 2
a mes questions : OUI
a mes attentes : NON

je croyais que ça les séparerais complètement, moi...
bigbill est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 23/02/2005, 00h11   #68
Nouveau Membre du Club
 
Avatar de ALEX77
 
Inscription : juillet 2002
Messages : 99
Détails du profil
Informations forums :
Inscription : juillet 2002
Messages : 99
Points : 36
Points : 36
Par exemple avec le mot "fin". Si vraiement ton souci est d'éviter que le programme ne considère fi comme un seul caractère lors de la segmentation, autant envisager la comparaison de ce bloc non ? Tu créer un bitmap généré "fi" et lorsque le programme fera la comparaison, il trouvera que c'est plus adapté et te renverra deux lettres au lieu d'une fausse : "fi".

Après, la méthode de skeletization, c'est utile uniquement si tu souhaites extraire des vecteurs, courbes mathématiques mais pas dans le cas d'une analyse matricielle.
ALEX77 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 23/02/2005, 12h37   #69
Nouveau Membre du Club
 
Avatar de ALEX77
 
Inscription : juillet 2002
Messages : 99
Détails du profil
Informations forums :
Inscription : juillet 2002
Messages : 99
Points : 36
Points : 36
Pour ceux que ça intéresse, voici un article que j'ai scanné dans un vieux numéro SVM de 1993.

Y est expliqué comment fonctionne un OCR, 6 pages :

http://grosalex.free.fr/images/ocr/a...VM-1993-01.jpg
http://grosalex.free.fr/images/ocr/a...VM-1993-02.jpg
http://grosalex.free.fr/images/ocr/a...VM-1993-03.jpg
http://grosalex.free.fr/images/ocr/a...VM-1993-04.jpg
http://grosalex.free.fr/images/ocr/a...VM-1993-05.jpg
http://grosalex.free.fr/images/ocr/a...VM-1993-06.jpg

J'espère que vous y trouverez votre inspiration, surtout toi BigBill
ALEX77 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/02/2005, 19h06   #70
Membre actif
 
Inscription : novembre 2004
Messages : 270
Détails du profil
Informations forums :
Inscription : novembre 2004
Messages : 270
Points : 176
Points : 176
Pour le f et le i qui sont collés, il faut savoir que souvent, c'est fait exprès ! En typographie, ça s'appelle une ligature, c'est-à-dire un caractère qui en combine 2 (ou plus).

Si vous regardez les tables de caractères d'une police truetype ou postscript, vous verrez quelque part qu'un caractère correspond au doublet "fi" (vous en trouverez aussi pour "ff", "fl", plus rarement pour "ffi", "ffl", "ct", "st", voire d'autres).

Ca veut donc dire que dans un OCR, il faut prévoir non seulement les lettres simples, mais aussi certains doublets.
Le Furet est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/07/2009, 04h18   #71
Candidat au titre de Membre du Club
 
Inscription : mars 2008
Messages : 44
Détails du profil
Informations forums :
Inscription : mars 2008
Messages : 44
Points : 13
Points : 13
Et au final ça marche ou pas ???
aydin24alain est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 03/10/2010, 17h58   #72
Invité de passage
 
Julien Beraud
Inscription : février 2010
Messages : 22
Détails du profil
Informations personnelles :
Nom : Julien Beraud

Informations forums :
Inscription : février 2010
Messages : 22
Points : 2
Points : 2
ou en etes vous ? quelqu'un aurait-il un code ?
julienber est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 25/01/2012, 22h11   #73
Invité régulier
 
Femme marwa amara
Étudiant
Inscription : juin 2011
Messages : 21
Détails du profil
Informations personnelles :
Nom : Femme marwa amara
Localisation : Tunisie

Informations professionnelles :
Activité : Étudiant
Secteur : High Tech - Matériel informatique

Informations forums :
Inscription : juin 2011
Messages : 21
Points : 7
Points : 7
Par défaut OCR matlab

Citation:
Envoyé par ALEX77 Voir le message
La réalisation d'un OCR est quelque chose de TRES TRES difficile.

Et je sais de quoi je parle vous pouvez me croire je m'y suis essayé. 8)

Celui qui m'a le plus fasciné est FineReader, sa facilité de reconnaissance est déconcertante et à pleurer. Sur une page en 300 ppp, il faut le voir pour le croire. Les OCR ont depuis beaucoup progressé pour atteindre la quasi perfection.

Bigbill, si tu peux essayer FineReader, tu comprendras la difficulté de l'opération car il cela consiste en gros à :

-analyser la page : repérer les blocs de texte et les différencier des images
-remettre la page bien droite (deskewing pour le connaisseurs)
-analyser chaque bloc : segmenter les lignes, puis isoler les caractères, en sachant que dans certaines polices de caractères, certains caractères s'emboîtent les uns dans les autres (comme "Fin" par exemple en Times New Roman, le i est à l'intérieur du F)

La méthode que j'ai essayé est proche de la tienne. En fait je n'ai pas besoin de deviner pour mon application la police de caractère à tester puique cette appplication récupère des formulaire grâce à un scanner à chargeur automatique et donc lorsqu'on créé un formulaire, on renseigne quelle police de caractère on va tester. Il faut fixer un taux de tolérance, et encore quelques paramètres comme le nombre le pixels minimum entre chaque caractère considérés comme des espaces, etc... mais ça fonctionne pas trop mal.

J'aimerais changer de méthode et faire en sorte que le programme "squelettise" ou en déduise des courbes mathémathiques comme là encore c'est un secret bien gardé. L'idée est de "squelettiser", d'en déduire des courbes et d'attribuer un poids à chacune de ces courbes, le score obtenu oriente le choix du caractère reconnu.

C'est la méthode d'analyse qui permet non seulement de reconnaitre des polices de caractères inconnues (sans avoir besoin comme dans le cas d'une analyse matricielle de renseigner celle qu'on doit tester) mais c'est celle ci qui est utilisée par les logiciels du marché tels qu'Omnipage, FineReader, etc... les pros quoi.

Si quelqu'un a des tuyaux moi aussi ça m'intérresse de pouvoir faire ça !


Je vous mets quelques liens :

http://http.cs.berkeley.edu/~fateman/kathey/ code source en C++, projet OCRchie
http://jocr.sourceforge.net/download.html code source encore en C++, projet GOCR s'utilise en ligne de commande
http://web.mit.edu/stanrost/www/cs585p1/p1.html comment faire un OCR avec MatLab
http://www.efg2.com/Lab/ImageProcessing/index.html faire un OCR c'est aussi comprendre et manipuler les pixels, faire de l'image processing, ce site est une mine d'or pour la manipulation d'image en Delphi

En espérant que cela a pu vous être utile.
Salut
Mon sujet de recherche set la reconnaissance d'écriture rabe imprimé AOCR le lien d'OCR sous matlab ne fonctionne pas...Est ce que vous pouvez m'aider par un lien d'OCR sous matlab.Essentiellement, la segmentation en caractère de l'écriture cursive
Merciiii
pretyy est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 16h31.


 
 
 
 
Partenaires

Hébergement Web