gocr-ruby 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|