Libraryless. Click here for Pure Java version (5300L/30K).
1 | sclass AutoSegmenter { |
2 | int g = 3; |
3 | L<Rect> clips; |
4 | bool[] grid; |
5 | int gw, gh; |
6 | bool diag; // merge diagonally too |
7 | BWImage img; |
8 | // contrastMethod2 = look at local contrast regardless of absolute brightness |
9 | bool contrastMethod2 = true, blackBG; |
10 | float contrastThreshold = 0.5f, brightnessThreshold = 0.5f; |
11 | int overlap = 1; |
12 | |
13 | *() {} |
14 | *(int *g) {} |
15 | |
16 | L<Rect> go(RGBImage img) { ret go(new BWImage(img)); } |
17 | |
18 | L<Rect> go(BWImage img) { |
19 | this.img = img; |
20 | int w = img.getWidth(), h = img.getHeight(); |
21 | gw = w/g; |
22 | gh = h/g; // width & height of grid |
23 | |
24 | step1(); |
25 | |
26 | new L<S> result; |
27 | clips = new L; |
28 | |
29 | for (int y = 0; y < gh; y++) |
30 | for (int x = 0; x < gw; x++) |
31 | if (grid[y*gw+x]) { |
32 | Rect r = fill(x, y); |
33 | r = scaleRect(r, g); |
34 | r = blackBG |
35 | ? autoCropOfBWImage_blackBG(img, r, brightnessThreshold) |
36 | : autoCropOfBWImage(img, r, brightnessThreshold); |
37 | clips.add(r); |
38 | } |
39 | |
40 | ret clips; |
41 | } |
42 | |
43 | void step1() { |
44 | int w = img.getWidth(), h = img.getHeight(); |
45 | grid = new bool[gw*gh]; |
46 | |
47 | for (int gy = 0; gy <= h- g; gy += g) |
48 | next: for (int gx = 0; gx <= w- g; gx += g) { |
49 | float min = 1, max = 0; |
50 | int y2 = min(h, gy + g + overlap); |
51 | int x2 = min(w, gx + g + overlap); |
52 | for (int y = gy; y < y2; y++) |
53 | for (int x = gx; x < x2; x++) { |
54 | float b = img.getPixel(x, y); |
55 | min = Math.min(min, b); |
56 | max = Math.max(max, b); |
57 | if (contrastMethod2 |
58 | ? max-min >= contrastThreshold |
59 | : min < brightnessThreshold && max > brightnessThreshold) { |
60 | grid[(gy / g) * gw + (gx / g)] = true; |
61 | continue next; |
62 | } |
63 | } |
64 | } |
65 | } |
66 | |
67 | // with virtual stack |
68 | Rect fill(int x, int y) { |
69 | Rect r = null; |
70 | new L<Pt> stack; |
71 | stack.add(new Pt(x, y)); |
72 | while (nempty(stack)) { |
73 | Pt p = popLast(stack); |
74 | x = p.x; |
75 | y = p.y; |
76 | |
77 | if (!(x < 0 || y < 0 || x >= gw || y >= gh)) { |
78 | int idx = y*gw+x; |
79 | |
80 | if (grid[idx]) { |
81 | grid[idx] = false; |
82 | Rect me = new Rect(x, y, 1, 1); |
83 | if (r == null) |
84 | r = me; |
85 | else |
86 | r = rectUnion(r, me); |
87 | |
88 | stack.add(new Pt(x-1, y)); |
89 | stack.add(new Pt(x+1, y)); |
90 | stack.add(new Pt(x, y-1)); |
91 | stack.add(new Pt(x, y+1)); |
92 | } |
93 | } |
94 | } |
95 | ret r; |
96 | } |
97 | |
98 | float visualizeGrid_darkening = 0.0f; |
99 | |
100 | BWImage visualizeGrid() { |
101 | step1(); |
102 | BWImage im = new BWImage(img); |
103 | for (int y = 0; y < gh; y++) |
104 | for (int x = 0; x < gw; x++) { |
105 | if (grid[y*gw+x]) continue; |
106 | darkenBWImagePart(im, new Rect(x*g, y*g, g, g), visualizeGrid_darkening); |
107 | } |
108 | ret im; |
109 | } |
110 | } |
Began life as a copy of #1005836
download show line numbers debug dex old transpilations
Travelled to 15 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, onxytkatvevr, pyentgdyhuwx, pzhvpgtvlbxg, sawdedvomwva, tslmcundralx, tvejysmllsmz, vouqrxazstgt
No comments. add comment
Snippet ID: | #1005840 |
Snippet name: | class AutoSegmenter |
Eternal ID of this version: | #1005840/4 |
Text MD5: | 67c85c8b56838955c855122659933a6d |
Transpilation MD5: | 1d8bbcb9de34e2955393be554968d38b |
Author: | stefan |
Category: | javax / ocr |
Type: | JavaX fragment (include) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2018-05-15 02:49:43 |
Source code size: | 2904 bytes / 110 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 659 / 1649 |
Version history: | 3 change(s) |
Referenced in: | [show references] |