Libraryless. Click here for Pure Java version (5300L/30K).
sclass AutoSegmenter { int g = 3; L<Rect> clips; bool[] grid; int gw, gh; bool diag; // merge diagonally too BWImage img; // contrastMethod2 = look at local contrast regardless of absolute brightness bool contrastMethod2 = true, blackBG; float contrastThreshold = 0.5f, brightnessThreshold = 0.5f; int overlap = 1; *() {} *(int *g) {} L<Rect> go(RGBImage img) { ret go(new BWImage(img)); } L<Rect> go(BWImage img) { this.img = img; int w = img.getWidth(), h = img.getHeight(); gw = w/g; gh = h/g; // width & height of grid step1(); new L<S> result; clips = new L; for (int y = 0; y < gh; y++) for (int x = 0; x < gw; x++) if (grid[y*gw+x]) { Rect r = fill(x, y); r = scaleRect(r, g); r = blackBG ? autoCropOfBWImage_blackBG(img, r, brightnessThreshold) : autoCropOfBWImage(img, r, brightnessThreshold); clips.add(r); } ret clips; } void step1() { int w = img.getWidth(), h = img.getHeight(); grid = new bool[gw*gh]; for (int gy = 0; gy <= h- g; gy += g) next: for (int gx = 0; gx <= w- g; gx += g) { float min = 1, max = 0; int y2 = min(h, gy + g + overlap); int x2 = min(w, gx + g + overlap); for (int y = gy; y < y2; y++) for (int x = gx; x < x2; x++) { float b = img.getPixel(x, y); min = Math.min(min, b); max = Math.max(max, b); if (contrastMethod2 ? max-min >= contrastThreshold : min < brightnessThreshold && max > brightnessThreshold) { grid[(gy / g) * gw + (gx / g)] = true; continue next; } } } } // with virtual stack Rect fill(int x, int y) { Rect r = null; new L<Pt> stack; stack.add(new Pt(x, y)); while (nempty(stack)) { Pt p = popLast(stack); x = p.x; y = p.y; if (!(x < 0 || y < 0 || x >= gw || y >= gh)) { int idx = y*gw+x; if (grid[idx]) { grid[idx] = false; Rect me = new Rect(x, y, 1, 1); if (r == null) r = me; else r = rectUnion(r, me); stack.add(new Pt(x-1, y)); stack.add(new Pt(x+1, y)); stack.add(new Pt(x, y-1)); stack.add(new Pt(x, y+1)); } } } ret r; } float visualizeGrid_darkening = 0.0f; BWImage visualizeGrid() { step1(); BWImage im = new BWImage(img); for (int y = 0; y < gh; y++) for (int x = 0; x < gw; x++) { if (grid[y*gw+x]) continue; darkenBWImagePart(im, new Rect(x*g, y*g, g, g), visualizeGrid_darkening); } ret im; } }
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: | 658 / 1648 |
Version history: | 3 change(s) |
Referenced in: | #1034167 - Standard Classes + Interfaces (LIVE, continuation of #1003674) |