gocr-ruby 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/Gemfile +4 -0
- data/LICENSE +21 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +49 -0
- data/ext/gocr/Makefile +141 -0
- data/ext/gocr/Makefile.in +140 -0
- data/ext/gocr/amiga.h +31 -0
- data/ext/gocr/barcode.c +2108 -0
- data/ext/gocr/barcode.h +11 -0
- data/ext/gocr/box.c +496 -0
- data/ext/gocr/config.h +37 -0
- data/ext/gocr/config.h.in +36 -0
- data/ext/gocr/database.c +468 -0
- data/ext/gocr/detect.c +1003 -0
- data/ext/gocr/extconf.rb +6 -0
- data/ext/gocr/gocr.c +436 -0
- data/ext/gocr/gocr.h +290 -0
- data/ext/gocr/jconv.c +168 -0
- data/ext/gocr/job.c +92 -0
- data/ext/gocr/lines.c +364 -0
- data/ext/gocr/list.c +334 -0
- data/ext/gocr/list.h +91 -0
- data/ext/gocr/ocr0.c +7312 -0
- data/ext/gocr/ocr0.h +63 -0
- data/ext/gocr/ocr0n.c +1527 -0
- data/ext/gocr/ocr1.c +85 -0
- data/ext/gocr/ocr1.h +3 -0
- data/ext/gocr/otsu.c +310 -0
- data/ext/gocr/otsu.h +23 -0
- data/ext/gocr/output.c +291 -0
- data/ext/gocr/output.h +37 -0
- data/ext/gocr/pcx.c +153 -0
- data/ext/gocr/pcx.h +9 -0
- data/ext/gocr/pgm2asc.c +3259 -0
- data/ext/gocr/pgm2asc.h +105 -0
- data/ext/gocr/pixel.c +538 -0
- data/ext/gocr/pnm.c +538 -0
- data/ext/gocr/pnm.h +35 -0
- data/ext/gocr/progress.c +87 -0
- data/ext/gocr/progress.h +42 -0
- data/ext/gocr/remove.c +715 -0
- data/ext/gocr/tga.c +87 -0
- data/ext/gocr/tga.h +6 -0
- data/ext/gocr/unicode.c +1318 -0
- data/ext/gocr/unicode.h +62 -0
- data/ext/gocr/unicode_defs.h +1245 -0
- data/ext/gocr/version.h +2 -0
- data/gocr-ruby.gemspec +28 -0
- data/image.png +0 -0
- data/lib/gocr.rb +6 -0
- data/lib/gocr/image.rb +8 -0
- data/lib/gocr/version.rb +3 -0
- metadata +156 -0
data/ext/gocr/barcode.h
ADDED
data/ext/gocr/box.c
ADDED
@@ -0,0 +1,496 @@
|
|
1
|
+
/*
|
2
|
+
This is a Optical-Character-Recognition program
|
3
|
+
Copyright (C) 2000-2010 Joerg Schulenburg
|
4
|
+
|
5
|
+
This program is free software; you can redistribute it and/or
|
6
|
+
modify it under the terms of the GNU General Public License
|
7
|
+
as published by the Free Software Foundation; either version 2
|
8
|
+
of the License, or (at your option) any later version.
|
9
|
+
|
10
|
+
This program is distributed in the hope that it will be useful,
|
11
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
GNU General Public License for more details.
|
14
|
+
|
15
|
+
You should have received a copy of the GNU General Public License
|
16
|
+
along with this program; if not, write to the Free Software
|
17
|
+
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
18
|
+
|
19
|
+
see README for EMAIL address
|
20
|
+
|
21
|
+
*/
|
22
|
+
|
23
|
+
#include <stdio.h>
|
24
|
+
#include <stdlib.h>
|
25
|
+
#include <assert.h>
|
26
|
+
#include <string.h>
|
27
|
+
#include "gocr.h"
|
28
|
+
#include "pgm2asc.h"
|
29
|
+
|
30
|
+
/* for sorting letters by position on the image
|
31
|
+
/ ToDo: - use function same line like this or include lines.m1 etc. */
|
32
|
+
int box_gt(struct box *box1, struct box *box2) {
|
33
|
+
// box1 after box2 ?
|
34
|
+
if (box1->line > box2->line)
|
35
|
+
return 1;
|
36
|
+
if (box1->line < box2->line)
|
37
|
+
return 0;
|
38
|
+
if (box1->x0 > box2->x1) // before
|
39
|
+
return 1;
|
40
|
+
if (box1->x1 < box2->x0) // before
|
41
|
+
return 0;
|
42
|
+
if (box1->x0 > box2->x0) // before, overlapping!
|
43
|
+
return 1;
|
44
|
+
|
45
|
+
return 0;
|
46
|
+
}
|
47
|
+
|
48
|
+
/* --- copy part of pix p into new pix b ---- len=10000
|
49
|
+
* Returns: 0 on success, 1 on error.
|
50
|
+
* naming it as copybox isnt very clever, because it dont have to do with the
|
51
|
+
* char boxes (struct box)
|
52
|
+
*/
|
53
|
+
int copybox (pix * p, int x0, int y0, int dx, int dy, pix * b, int len) {
|
54
|
+
int x, y;
|
55
|
+
|
56
|
+
/* test boundaries */
|
57
|
+
if (b->p == NULL || dx < 0 || dy < 0 || dx * dy > len) {
|
58
|
+
fprintf(stderr, " error-copybox x=%5d %5d d=%5d %5d\n", x0, y0, dx, dy);
|
59
|
+
return 1;
|
60
|
+
}
|
61
|
+
|
62
|
+
b->x = dx;
|
63
|
+
b->y = dy;
|
64
|
+
b->bpp = 1;
|
65
|
+
#ifdef FASTER_INCOMPLETE
|
66
|
+
for (y = 0; y < dy; y++)
|
67
|
+
memcpy(&pixel_atp(b, 0, y), &pixel_atp(p, x0, y + y0 ), dx);
|
68
|
+
// and unmark pixels
|
69
|
+
#else
|
70
|
+
for (y = 0; y < dy; y++)
|
71
|
+
for (x = 0; x < dx; x++)
|
72
|
+
pixel_atp(b, x, y) = getpixel(p, x + x0, y + y0);
|
73
|
+
#endif
|
74
|
+
|
75
|
+
return 0;
|
76
|
+
}
|
77
|
+
|
78
|
+
/* reset table of alternative chars (and free memory) */
|
79
|
+
int reset_box_ac(struct box *box){
|
80
|
+
int i;
|
81
|
+
for (i=0; i<box->num_ac; i++)
|
82
|
+
if (box->tas[i]) {
|
83
|
+
/* fprintf(stderr,"DBG free_s[%d] %p %s\n",i,box->tas[i],box->tas[i]); */
|
84
|
+
free(box->tas[i]);
|
85
|
+
box->tas[i]=0; /* prevent double freeing */
|
86
|
+
}
|
87
|
+
box->num_ac=0; /* mark as freed */
|
88
|
+
return 0;
|
89
|
+
}
|
90
|
+
|
91
|
+
/* ini or copy a box: get memory for box and initialize the memory */
|
92
|
+
struct box *malloc_box (struct box *inibox) {
|
93
|
+
struct box *buf;
|
94
|
+
int i;
|
95
|
+
|
96
|
+
buf = (struct box *) malloc(sizeof(struct box));
|
97
|
+
if (!buf)
|
98
|
+
return NULL;
|
99
|
+
if (inibox) {
|
100
|
+
memcpy(buf, inibox, sizeof(struct box));
|
101
|
+
/* only pointer are copied, we want to copy the contents too */
|
102
|
+
for (i=0;i<inibox->num_ac;i++) {
|
103
|
+
if (inibox->tas[i]) {
|
104
|
+
buf->tas[i]=(char *)malloc(strlen(inibox->tas[i])+1);
|
105
|
+
memcpy(buf->tas[i], inibox->tas[i], strlen(inibox->tas[i])+1);
|
106
|
+
}
|
107
|
+
}
|
108
|
+
}
|
109
|
+
else { /* ToDo: init it */
|
110
|
+
buf->num_ac=0;
|
111
|
+
buf->num_frames=0;
|
112
|
+
}
|
113
|
+
/* fprintf(stderr,"\nDBG ini_box %p",buf); */
|
114
|
+
return buf;
|
115
|
+
}
|
116
|
+
|
117
|
+
/* free memory of box */
|
118
|
+
int free_box (struct box *box) {
|
119
|
+
if (!box) return 0;
|
120
|
+
/* fprintf(stderr,"DBG free_box %p\n",box); out_x(box); */
|
121
|
+
reset_box_ac(box); /* free alternative char table */
|
122
|
+
free(box); /* free the box memory */
|
123
|
+
return 0;
|
124
|
+
}
|
125
|
+
|
126
|
+
/* simplify the vectorgraph,
|
127
|
+
* but what is the best way?
|
128
|
+
* a) melting two neighbouring vectors with nearly same direction?
|
129
|
+
* (nearest angle to pi)
|
130
|
+
* b) melting three neigbours with smallest area?
|
131
|
+
* ToDo:
|
132
|
+
* mode = 0 - only lossless
|
133
|
+
* mode = 1 - reduce one vector, smallest possible loss
|
134
|
+
* mode = 2 - remove jitter (todo, or somewhere else)
|
135
|
+
* ToDo: include also loop around (last - first element)
|
136
|
+
* ToDo: reduce by 10..50%
|
137
|
+
*/
|
138
|
+
int reduce_vectors ( struct box *box1, int mode ) {
|
139
|
+
int i1, i2, nx, ny, mx, my, len,
|
140
|
+
minlen=1024, /* minlength of to neighbouring vectors */
|
141
|
+
besti1=0, /* frame for best reduction */
|
142
|
+
besti2=2; /* vector replacing its predecessor */
|
143
|
+
double sprod, maxsprod=-1;
|
144
|
+
if (mode!=1) fprintf(stderr,"ERR not supported yet, ToDo\n");
|
145
|
+
for (i2=1,i1=0; i1<box1->num_frames; i1++) { /* every frame */
|
146
|
+
for (;i2<box1->num_frame_vectors[i1]-1; i2++) { /* every vector */
|
147
|
+
/* predecessor n */
|
148
|
+
nx = box1->frame_vector[i2-0][0] - box1->frame_vector[i2-1][0];
|
149
|
+
ny = box1->frame_vector[i2-0][1] - box1->frame_vector[i2-1][1];
|
150
|
+
/* successor m */
|
151
|
+
mx = box1->frame_vector[i2+1][0] - box1->frame_vector[i2-0][0];
|
152
|
+
my = box1->frame_vector[i2+1][1] - box1->frame_vector[i2-0][1];
|
153
|
+
/* angle is w = a*b/(|a|*|b|) = 1 means parallel */
|
154
|
+
/* normalized: minimize w^2 = (a*b/(|a|*|b|)-1)^2 */
|
155
|
+
/* -1=90grd, 0=0grd, -2=180grd */
|
156
|
+
sprod = /* fabs */(abs(nx*mx+ny*my)*(nx*mx+ny*my)
|
157
|
+
/(1.*(nx*nx+ny*ny)*(mx*mx+my*my))-1);
|
158
|
+
if (sprod<0) sprod=-sprod;
|
159
|
+
len = (mx*mx+my*my)*(nx*nx+ny*ny); /* sum lengths^2 */
|
160
|
+
// ..c ###c ... .. ...
|
161
|
+
// .b. len=2+2 #b.. len=2+5 #bc len=1+2 bc len=1+1 b#a len=4+5
|
162
|
+
// a.. spr=0 a... spr=1/10 a.. spr=1/4 a. spr=1 ##c spr=9/5
|
163
|
+
//
|
164
|
+
if ( len* sprod* sprod* sprod* sprod
|
165
|
+
<minlen*maxsprod*maxsprod*maxsprod*maxsprod
|
166
|
+
|| maxsprod<0) /* Bad! ToDo! */
|
167
|
+
{ maxsprod=sprod; besti1=i1; besti2=i2; minlen=len; }
|
168
|
+
}
|
169
|
+
}
|
170
|
+
if (box1->num_frames>0)
|
171
|
+
for (i2=besti2; i2<box1->num_frame_vectors[ box1->num_frames-1 ]-1; i2++) {
|
172
|
+
box1->frame_vector[i2][0]=box1->frame_vector[i2+1][0];
|
173
|
+
box1->frame_vector[i2][1]=box1->frame_vector[i2+1][1];
|
174
|
+
}
|
175
|
+
for (i1=besti1; i1<box1->num_frames; i1++)
|
176
|
+
box1->num_frame_vectors[i1]--;
|
177
|
+
// fprintf(stderr,"\nDBG_reduce_vectors i= %d nv= %d sprod=%f len2=%d\n# ...",
|
178
|
+
// besti2,box1->num_frame_vectors[ box1->num_frames-1 ],maxsprod,minlen);
|
179
|
+
// out_x(box1);
|
180
|
+
return 0;
|
181
|
+
}
|
182
|
+
|
183
|
+
/* add the contents of box2 to box1
|
184
|
+
* especially add vectors of box2 to box1
|
185
|
+
*/
|
186
|
+
int merge_boxes( struct box *box1, struct box *box2 ) {
|
187
|
+
int i1, i2, i3, i4;
|
188
|
+
struct box tmpbox, *bsmaller, *bbigger; /* for mixing and sorting */
|
189
|
+
/* DEBUG, use valgrind to check uninitialized memory */
|
190
|
+
#if 0
|
191
|
+
fprintf(stderr,"\nDBG merge_boxes_input:"); out_x(box1); out_x(box2);
|
192
|
+
#endif
|
193
|
+
/* pair distance is to expendable, taking borders is easier */
|
194
|
+
// JS-2010-09 fix bug width=1
|
195
|
+
if ((box2->x1 - box2->x0 + 1)*(box2->y1 - box2->y0 + 1)
|
196
|
+
>(box1->x1 - box1->x0 + 1)*(box1->y1 - box1->y0 + 1)) {
|
197
|
+
bbigger=box2; bsmaller=box1; }
|
198
|
+
else {
|
199
|
+
bbigger=box1; bsmaller=box2; } // if called by glue_holes_inside_chars()
|
200
|
+
// fprintf(stderr,"\n y bigger"); out_x(bbigger); out_x(bsmaller);
|
201
|
+
/* ToDo: does not work if a third box is added */
|
202
|
+
if (box2->y0>box1->y1 || box2->y1<box1->y0
|
203
|
+
|| box2->x0>box1->x1 || box2->x1<box1->x0) {
|
204
|
+
box1->num_boxes += box2->num_boxes; /* num separate objects 2=ij */
|
205
|
+
// if ( 4 * box2->y1 < 3*box1->y0 + box1->y1
|
206
|
+
// && box2->y0 < box1->y0 ) (box1->dots)++; // 2010-09-24 ???
|
207
|
+
if ( 4 * box1->y1 < 3*box2->y0 + box2->y1
|
208
|
+
&& box1->y0 < box2->y0 ) (box2->dots)++; // 2010-09-24 :
|
209
|
+
} else {
|
210
|
+
if (box2->num_boxes>box1->num_boxes) box1->num_boxes=box2->num_boxes;
|
211
|
+
// 2010-09 subboxes are already counted, do not count twice!
|
212
|
+
box1->num_subboxes = bbigger->num_subboxes; /* num holes 1=abdepq 2=B */
|
213
|
+
// box1->num_subboxes += box2->num_subboxes+1; /* num holes 1=abdepq 2=B */
|
214
|
+
}
|
215
|
+
box1->dots += box2->dots; /* num i-dots ??? */
|
216
|
+
if ( box2->x0 < box1->x0 ) box1->x0 = box2->x0;
|
217
|
+
if ( box2->x1 > box1->x1 ) box1->x1 = box2->x1;
|
218
|
+
if ( box2->y0 < box1->y0 ) box1->y0 = box2->y0;
|
219
|
+
if ( box2->y1 > box1->y1 ) box1->y1 = box2->y1;
|
220
|
+
i1 = i2 = 0;
|
221
|
+
if (bbigger->num_frames)
|
222
|
+
i1 = bbigger->num_frame_vectors[ bbigger->num_frames - 1 ];
|
223
|
+
if (bsmaller->num_frames)
|
224
|
+
i2 = bsmaller->num_frame_vectors[ bsmaller->num_frames - 1 ];
|
225
|
+
while (i1+i2 > MaxFrameVectors) {
|
226
|
+
if (i1>i2) { reduce_vectors( bbigger, 1 ); i1--; }
|
227
|
+
else { reduce_vectors( bsmaller, 1 ); i2--; }
|
228
|
+
}
|
229
|
+
/* if i1+i2>MaxFrameVectors simplify the vectorgraph */
|
230
|
+
/* if sum num_frames>MaxNumFrames through shortest graph away and warn */
|
231
|
+
/* first copy the bigger box */
|
232
|
+
memcpy(&tmpbox, bbigger, sizeof(struct box));
|
233
|
+
/* attach the smaller box */
|
234
|
+
for (i4=i3=0; i3<bsmaller->num_frames; i3++) {
|
235
|
+
if (tmpbox.num_frames>=MaxNumFrames) break;
|
236
|
+
|
237
|
+
for (; i4<bsmaller->num_frame_vectors[i3]; i4++) {
|
238
|
+
memcpy(tmpbox.frame_vector[i1],
|
239
|
+
bsmaller->frame_vector[i4],2*sizeof(int));
|
240
|
+
i1++;
|
241
|
+
}
|
242
|
+
tmpbox.num_frame_vectors[ tmpbox.num_frames ] = i1;
|
243
|
+
tmpbox.frame_vol[ tmpbox.num_frames ] = bsmaller->frame_vol[ i3 ];
|
244
|
+
tmpbox.frame_per[ tmpbox.num_frames ] = bsmaller->frame_per[ i3 ];
|
245
|
+
tmpbox.num_frames++;
|
246
|
+
if (tmpbox.num_frames>=MaxNumFrames) {
|
247
|
+
if (OCR_JOB->cfg.verbose)
|
248
|
+
fprintf(stderr,"\nDBG merge_boxes MaxNumFrames reached");
|
249
|
+
break;
|
250
|
+
}
|
251
|
+
}
|
252
|
+
/* copy tmpbox to destination */
|
253
|
+
box1->num_frames = tmpbox.num_frames;
|
254
|
+
memcpy(box1->num_frame_vectors,
|
255
|
+
tmpbox.num_frame_vectors,sizeof(int)*MaxNumFrames);
|
256
|
+
memcpy(box1->frame_vol,
|
257
|
+
tmpbox.frame_vol,sizeof(int)*MaxNumFrames);
|
258
|
+
memcpy(box1->frame_per,
|
259
|
+
tmpbox.frame_per,sizeof(int)*MaxNumFrames);
|
260
|
+
memcpy(box1->frame_vector,
|
261
|
+
tmpbox.frame_vector,sizeof(int)*2*MaxFrameVectors);
|
262
|
+
#if 0
|
263
|
+
if ((OCR_JOB->cfg.verbose&48)==48) {
|
264
|
+
fprintf(stderr,"\nDBG merge_boxes_result:"); out_x(box1); }
|
265
|
+
#endif
|
266
|
+
return 0;
|
267
|
+
}
|
268
|
+
|
269
|
+
/* used for division of glued chars
|
270
|
+
* after a box is splitted into 2, where vectors are copied to both,
|
271
|
+
* vectors outside the new box are cutted and thrown away,
|
272
|
+
* later replaced by
|
273
|
+
* - 1st remove outside vectors with outside neighbours (complete frames?)
|
274
|
+
* add vector on outside vector with inside neighbours
|
275
|
+
* care about connections through box between outside vectors
|
276
|
+
* - 2nd reduce outside crossings (inclusive splitting frames if necessary)
|
277
|
+
* depending on direction (rotation) of outside connections
|
278
|
+
* - 3th shift outside vectors to crossing points
|
279
|
+
* - split add this points, connect only in-out...out-in,
|
280
|
+
* - cutting can result in more (fi) or less objects (ke)
|
281
|
+
* ToDo:
|
282
|
+
* dont connect --1---4--------3----2-- new-y1 (inside above not drawn)
|
283
|
+
* \ \-<<<<-/ / outside
|
284
|
+
* \---->>>>-----/ old-y1
|
285
|
+
* |======| subtractable?
|
286
|
+
*
|
287
|
+
* only connect --1---2--------3----4-- new-y1
|
288
|
+
* \>>/ \>>>/ old-y1 outside
|
289
|
+
* ToDo: what about cutting 2 frames (example: 2fold melted MN,ke)
|
290
|
+
* better restart framing algo (modified pgm2asc.frame_vector())?
|
291
|
+
* (would be require pixel last 3 bits modifications?)
|
292
|
+
*
|
293
|
+
* ToDo: new vol, per
|
294
|
+
* sample: tmp08/gocr0810* 2010-10-12
|
295
|
+
frame 0 ( +66, 50,21)
|
296
|
+
#00 0 0 #01 0 8 #02 0 6 #03 1 5 #04 4 8 #05 5 8 #06 6 7
|
297
|
+
#07 7 8 #08 11 8 #09 8 8 #10 6 6 #11 7 5 #12 12 5 #13 12 3
|
298
|
+
#14 11 2 #15 7 2 #16 6 3 #17 5 2 #18 4 2 #19 1 5 #20 0 4
|
299
|
+
frame 1 ( -10, 13, 8)
|
300
|
+
#21 4 3 #22 5 2 #23 6 3 #24 6 7 #25 5 8 #26 2 5 #27 2 4
|
301
|
+
#28 3 3
|
302
|
+
frame 2 ( -8, 12, 7)
|
303
|
+
#29 7 3 #30 8 2 #31 10 2 #32 12 4 #33 11 5 #34 7 5 #35 6 4
|
304
|
+
# list pattern d= 13 9
|
305
|
+
$............ @............<-
|
306
|
+
@............ @............
|
307
|
+
@...$$.$$@$$. @...@@.@@@@@.<
|
308
|
+
@..$$.$$...@$ @..@@.@@...@@
|
309
|
+
$.$...$.....$ @.@...@.....@
|
310
|
+
@$$...@$@@@$$ @@@...@@@@@@@
|
311
|
+
$.@@..$...... @.@@..@......
|
312
|
+
@..@@.$@..... @..@@.@@.....
|
313
|
+
$...$$.$$@@$. @...@@.@@@@@.<-
|
314
|
+
^cut ^cut
|
315
|
+
1st) get a list of cutting positions and sort them (going along border):
|
316
|
+
[#05-#06(5,8,io) #16-#17(5,2,oi)] [#22-#23(5,2,io) #24-#25(5,8,oi)]
|
317
|
+
[#05-#06(5,8,io) [#24-#25(5,8,oi) #22-#23(5,2,io)] #16-#17(5,2,oi)]
|
318
|
+
// positive rotation momentum io(0)->io(1)->oi(0)->oi(1)->back
|
319
|
+
// io=inside_to_outside oi=outside_to_inside
|
320
|
+
2nd)
|
321
|
+
rebuild frames ... #04 #05 - #25 #26 #27 #28 #21 #22 #23 - #17 #18 ...
|
322
|
+
*/
|
323
|
+
#if 0 // new version 1010-10 works on cutting multiple frames
|
324
|
+
#define MAXNUMCUTS 8 // used in function cut_box() only
|
325
|
+
int cut_box( struct box *box1) {
|
326
|
+
int i1, i2, i3, i4, i4l, i5, x, y, lx, ly, dbg=0;
|
327
|
+
int cut_num = 0, // number of cuts
|
328
|
+
cut_idx[MAXNUMCUTS], // index to cutted vector
|
329
|
+
cut_dir[MAXNUMCUTS]; // direction of vector inside_outside=1
|
330
|
+
// outside_inside=2
|
331
|
+
struct box tmpbox; // = (*box1); temp. buffer, after some corrections
|
332
|
+
#ifdef DO_DEBUG
|
333
|
+
if (OCR_JOB->cfg.verbose) dbg=1+2; // debug level, enlarge to get more output
|
334
|
+
#endif
|
335
|
+
if (dbg) fprintf(stderr,"\n cut box x= %3d %3d", box1->x0, box1->y0);
|
336
|
+
/* check if complete frames are outside the box */
|
337
|
+
for (i1=0; i1<box1->num_frames; i1++){
|
338
|
+
if (dbg>2) fprintf(stderr,"\n checking frame %d ", i1);
|
339
|
+
/* using frame_per as marker first (recalculate later) */
|
340
|
+
i2 = ((i1)?box1->num_frame_vectors[ i1-1 ]:0); // start of this frame
|
341
|
+
i3 = box1->num_frame_vectors[ i1 ]; // start of next frame
|
342
|
+
x = box1->frame_vector[ i3-1 ][0]; /* initial */
|
343
|
+
y = box1->frame_vector[ i3-1 ][1]; /* initial */
|
344
|
+
i4l = i3 - 1; // initial index of last vector
|
345
|
+
if (x<box1->x0 || x>box1->x1 || y<box1->y0 || y>box1->y1) i5=1; // outside
|
346
|
+
for (i4=i2; i4 < i3; i4++) {
|
347
|
+
lx = x; /* last x = vector[i4l] */
|
348
|
+
ly = y; /* last y = vector[i4l] */
|
349
|
+
x = box1->frame_vector[i4][0];
|
350
|
+
y = box1->frame_vector[i4][1];
|
351
|
+
// fprintf(stderr,"DBG LEV3 i4= %3d xy= %3d %3d",i4,x,y);
|
352
|
+
/* check if outside */
|
353
|
+
if (x<box1->x0 || x>box1->x1 || y<box1->y0 || y>box1->y1) { // outside
|
354
|
+
/* replace by nearest point at border, ToDo: better crossingpoint */
|
355
|
+
if (i5==0) { /* inside_to_outside, wrong if it starts outside */
|
356
|
+
if (x < box1->x0) x = box1->frame_vector[i4][0] = box1->x0;
|
357
|
+
if (x > box1->x1) x = box1->frame_vector[i4][0] = box1->x1;
|
358
|
+
if (y < box1->y0) y = box1->frame_vector[i4][1] = box1->y0;
|
359
|
+
if (y > box1->y1) y = box1->frame_vector[i4][1] = box1->y1;
|
360
|
+
if (cut_num<MAXCUTNUM) {
|
361
|
+
cut_idx[cut_num] = i4;
|
362
|
+
cut_dir[cut_num] = 1; // inside_to_outside
|
363
|
+
cut_num++;
|
364
|
+
}
|
365
|
+
/* search other frames for near outside_to_inside and copy frame in */
|
366
|
+
}
|
367
|
+
i5 = 1; // flag: we_are_outside_of_box
|
368
|
+
} else if (i5==1) { /* outside_to_inside */
|
369
|
+
/* ToDo: better crossing point last vector and border */
|
370
|
+
if (lx < box1->x0) lx = box1->x0;
|
371
|
+
if (lx > box1->x1) lx = box1->x1;
|
372
|
+
if (ly < box1->y0) ly = box1->y0;
|
373
|
+
if (ly > box1->y1) ly = box1->y1;
|
374
|
+
box1->frame_vector[i4l][0] = lx;
|
375
|
+
box1->frame_vector[i4l][1] = ly;
|
376
|
+
if (cut_num<MAXCUTNUM) {
|
377
|
+
cut_idx[cut_num] = i4l;
|
378
|
+
cut_dir[cut_num] = 2; // outside_to_inside
|
379
|
+
cut_num++;
|
380
|
+
}
|
381
|
+
i5 = 0; // flag: we_are_inside_of_box
|
382
|
+
}
|
383
|
+
i4l=i4; // index of last vector
|
384
|
+
// fprintf(stderr," xy= %3d %3d\n",x,y);
|
385
|
+
}
|
386
|
+
}
|
387
|
+
for (i1=0; i1<cut_num; i1+=2) {
|
388
|
+
}
|
389
|
+
if (dbg>2) { fprintf(stderr,"\nDBG cut_box_result:"); out_x(box1); }
|
390
|
+
return 0;
|
391
|
+
}
|
392
|
+
#else // old bad version works for one cutted frame only
|
393
|
+
int cut_box( struct box *box1) {
|
394
|
+
int i1, i2, i3, i4, x, y, lx, ly, dbg=0;
|
395
|
+
#ifdef DO_DEBUG
|
396
|
+
if (OCR_JOB->cfg.verbose) dbg=1+2; // debug level, enlarge to get more output
|
397
|
+
#endif
|
398
|
+
if (dbg) fprintf(stderr,"\n cut box x= %3d %3d", box1->x0, box1->y0);
|
399
|
+
/* check if complete frames are outside the box */
|
400
|
+
for (i1=0; i1<box1->num_frames; i1++){
|
401
|
+
if (dbg>2) fprintf(stderr,"\n checking frame %d ", i1);
|
402
|
+
/* using frame_per as marker first (recalculate later) */
|
403
|
+
box1->frame_per[i1]=0;
|
404
|
+
i2 = ((i1)?box1->num_frame_vectors[ i1-1 ]:0); // this frame
|
405
|
+
i3 = box1->num_frame_vectors[ i1 ]; // next frame
|
406
|
+
for (i4=i2; i4 < i3; i4++) {
|
407
|
+
x = box1->frame_vector[i4][0];
|
408
|
+
y = box1->frame_vector[i4][1];
|
409
|
+
/* 1 if one vector is lying inside */
|
410
|
+
/* 2 if one vector is lying outside */
|
411
|
+
if (x>=box1->x0 && x<=box1->x1
|
412
|
+
&& y>=box1->y0 && y<=box1->y1) box1->frame_per[i1]|=1;
|
413
|
+
if (x< box1->x0 || x> box1->x1
|
414
|
+
|| y< box1->y0 || y> box1->y1) box1->frame_per[i1]|=2;
|
415
|
+
}
|
416
|
+
if (dbg>2) fprintf(stderr,"in1+out2= %d", box1->frame_per[i1]);
|
417
|
+
if (box1->frame_per[i1]==2) { /* all vectors outside */
|
418
|
+
if (dbg>1) fprintf(stderr," remove frame %d",i1);
|
419
|
+
/* replace all frames i1,i1+1,... by i1+1,i1+2,... */
|
420
|
+
/* replace (x,y) pairs first */
|
421
|
+
for (i4=i2; i4<box1->num_frame_vectors[ box1->num_frames-1 ]-(i3-i2);
|
422
|
+
i4++) {
|
423
|
+
box1->frame_vector[i4][0] = box1->frame_vector[i4+i3-i2][0];
|
424
|
+
box1->frame_vector[i4][1] = box1->frame_vector[i4+i3-i2][1];
|
425
|
+
}
|
426
|
+
/* replace the num_frame_vectors */
|
427
|
+
for (i4=i1; i4<box1->num_frames-1; i4++) {
|
428
|
+
box1->num_frame_vectors[ i4 ] =
|
429
|
+
box1->num_frame_vectors[ i4+1 ]-(i3-i2);
|
430
|
+
box1->frame_vol[i4]=box1->frame_vol[i4+1];
|
431
|
+
box1->frame_per[i4]=box1->frame_per[i4+1];
|
432
|
+
}
|
433
|
+
box1->num_frames--; i1--;
|
434
|
+
}
|
435
|
+
}
|
436
|
+
/* remove vectors outside the box and connect vectors pointing outside
|
437
|
+
* to next vectors pointing inside (every frame), see above sample "ke"
|
438
|
+
* ToDo: partly implemented, start i2source=search = i2dest=trace,
|
439
|
+
* i2source>i2dest on reconnect (evl. frame number changed)
|
440
|
+
*/
|
441
|
+
i3=0; /* flag 0=inside=no_change 1++=outside_remove_or_concat */
|
442
|
+
for (i1=0; i1<box1->num_frames; i1++){
|
443
|
+
if (dbg>2) fprintf(stderr,"\n check cutting vectors on frame %d", i1);
|
444
|
+
x = box1->frame_vector[0][0]; /* initial x */
|
445
|
+
y = box1->frame_vector[0][1]; /* initial y */
|
446
|
+
/* ToDo: start inside to get a closed object */
|
447
|
+
if (x<box1->x0 || x>box1->x1 || y<box1->y0 || y>box1->y1) i3=1;
|
448
|
+
for (i2=0; i2<box1->num_frame_vectors[ i1 ]; i2++) {
|
449
|
+
lx = x; /* last x */
|
450
|
+
ly = y; /* last y */
|
451
|
+
x = box1->frame_vector[i2][0];
|
452
|
+
y = box1->frame_vector[i2][1];
|
453
|
+
// fprintf(stderr,"DBG LEV3 i2= %3d xy= %3d %3d",i2,x,y);
|
454
|
+
/* check if outside */
|
455
|
+
if (x<box1->x0 || x>box1->x1 || y<box1->y0 || y>box1->y1) {
|
456
|
+
/* replace by nearest point at border, ToDo: better crossingpoint */
|
457
|
+
if (i3==0) { /* inside_to_outside, wrong if it starts outside */
|
458
|
+
if (x < box1->x0) x = box1->frame_vector[i2][0] = box1->x0;
|
459
|
+
if (x > box1->x1) x = box1->frame_vector[i2][0] = box1->x1;
|
460
|
+
if (y < box1->y0) y = box1->frame_vector[i2][1] = box1->y0;
|
461
|
+
if (y > box1->y1) y = box1->frame_vector[i2][1] = box1->y1;
|
462
|
+
/* search other frames for near outside_to_inside and copy frame in */
|
463
|
+
} else { /* outside_to_outside */
|
464
|
+
/* remove vector */
|
465
|
+
if (dbg>1) fprintf(stderr,"\n remove vector[%d][%d] x= %2d %2d",i1,i2,x-box1->x0,y-box1->y0);
|
466
|
+
for (i4=i2;i4<box1->num_frame_vectors[ box1->num_frames-1 ]-1;i4++) {
|
467
|
+
box1->frame_vector[i4][0] = box1->frame_vector[i4+1][0];
|
468
|
+
box1->frame_vector[i4][1] = box1->frame_vector[i4+1][1];
|
469
|
+
}
|
470
|
+
for (i4=i1; i4<box1->num_frames; i4++)
|
471
|
+
box1->num_frame_vectors[ i4 ]--;
|
472
|
+
i2--; /* next element is shiftet now, setting back the counter */
|
473
|
+
}
|
474
|
+
i3++;
|
475
|
+
// fprintf(stderr," outside i3= %d\n",i3);
|
476
|
+
continue;
|
477
|
+
}
|
478
|
+
/* outside_or_inside to inside */
|
479
|
+
// fprintf(stderr," inside i3= %d",i3);
|
480
|
+
if (i3) { /* outside_to_inside */
|
481
|
+
/* ToDo: better crossing point last vector and border */
|
482
|
+
if (lx < box1->x0) lx = box1->x0;
|
483
|
+
if (lx > box1->x1) lx = box1->x1;
|
484
|
+
if (ly < box1->y0) ly = box1->y0;
|
485
|
+
if (ly > box1->y1) ly = box1->y1;
|
486
|
+
x = box1->frame_vector[i2][0] = lx;
|
487
|
+
y = box1->frame_vector[i2][1] = ly;
|
488
|
+
i3 = 0;
|
489
|
+
}
|
490
|
+
// fprintf(stderr," xy= %3d %3d\n",x,y);
|
491
|
+
}
|
492
|
+
}
|
493
|
+
if (dbg>2) { fprintf(stderr,"\nDBG cut_box_result:"); out_x(box1); }
|
494
|
+
return 0;
|
495
|
+
}
|
496
|
+
#endif
|