Uses 108K of libraries. Click here for Pure Java version (10776L/76K).
1 | // complexity is number of assumed heights * number of widths |
2 | sclass MultiLevelRecognizer1 { |
3 | // how big do we think the prototype is in the whole image |
4 | // (percentage by height) |
5 | transient L<Double> assumedPrototypeHeightPercentages = |
6 | ll(70.0, 70.0/sqrt(2), 35.0, 35.0/sqrt(2), 17.0); |
7 | |
8 | // widths to scale camera image to |
9 | transient L<Int> widths = ll(32, 64, 128); |
10 | |
11 | transient JTabbedPane tabs; // initialize if you want visualization |
12 | transient ImageSurface bestImageSurface; |
13 | transient JLabel bestLabel; |
14 | |
15 | transient BWIntegralImage baseImage; |
16 | transient BWImage prototypeImage; |
17 | transient new L<IBWIntegralImage> integralImages; |
18 | transient new L<Chain> chains; // one per assumed height |
19 | |
20 | // chain of recognizers for one assumed height |
21 | class Chain { |
22 | double assumedHeightPercentage; |
23 | new L<OneLevel> levels; // recognizers for each granularity |
24 | |
25 | *(double *assumedHeightPercentage) { make(); } |
26 | |
27 | void make { |
28 | for (int w : widths) { |
29 | IBWIntegralImage ii = scaledIBWIntegralImage(baseImage, w); |
30 | integralImages.add(ii); |
31 | OneLevel lvl = new(this, ii); |
32 | levels.add(lvl); |
33 | if (tabs != null && eq(w, last(widths))) { |
34 | lvl.is = jPixelatedZoomedImageSurface( |
35 | doubleRatio(baseImage.getWidth(), w), iBWIntegralImageToBWImage(ii)); |
36 | addTab(tabs, iround(assumedHeightPercentage) + ":" + w, northAndCenterWithMargins( |
37 | lvl.infoLabel = jcenteredlabel(), jFullCenterScroll(lvl.is))); |
38 | } |
39 | } |
40 | } |
41 | |
42 | Steppable makeSteppable() { |
43 | ret iteratorToSteppable(roundRobinCombinedIterator(lambdaMap steppableToIterator(levels))); |
44 | } |
45 | |
46 | Scored<Rect> bestResult() { |
47 | ret last(levels).scoredBestRescaled(); |
48 | } |
49 | } |
50 | |
51 | class OneLevel extends SteppableAndBest<Rect> { |
52 | Chain chain; |
53 | IBWIntegralImage ii; // scaled integral image |
54 | BWImage image; // scaled image |
55 | BWImage prototype; // scaled prototype |
56 | float minSimilarity = 0.5f; |
57 | |
58 | ImageSurface is; |
59 | JLabel infoLabel; |
60 | |
61 | // candidates are top-left corner of rect to try in our coordinates |
62 | L<Pt> candidatesQueue = syncLinkedList(); |
63 | new Set<Pt> candidatesTried; |
64 | Iterator<Pt> candidatesStream; |
65 | |
66 | *(Chain *chain, IBWIntegralImage *ii) { |
67 | image = iBWIntegralImageToBWImage(ii); |
68 | // get assumed height of prototype in scaled-down image |
69 | int ph = iround(ii.getHeight()*chain.assumedHeightPercentage/100.0); |
70 | // resize prototype |
71 | prototype = bwResizeToHeightSmooth(prototypeImage, ph); |
72 | /*addTab(tabs, "proto " + ii.getWidth(), |
73 | jFullCenterScroll(jPixelatedZoomedImageSurface(4.0, prototype))); |
74 | */ |
75 | candidatesStream = mapI rectTopLeftCorner(allSubRectsOfSizeIterator(prototype.getWidth(), prototype.getHeight(), |
76 | imageRect(image))); |
77 | } |
78 | |
79 | public bool step() { |
80 | Pt p = nextCandidate(); |
81 | if (p != null) ret true with tryCandidate(p); |
82 | false; |
83 | } |
84 | |
85 | Pt nextCandidate() { |
86 | try object Pt p = popFirst(candidatesQueue); |
87 | ret nextFromIterator(candidatesStream); |
88 | } |
89 | |
90 | void tryCandidate(Pt p) { |
91 | if (!candidatesTried.add(p)) ret; |
92 | |
93 | int x = p.x, y = p.y, wp = prototype.getWidth(), hp = prototype.getHeight(); |
94 | |
95 | float maxError = (1f-minSimilarity)*wp*hp; |
96 | float diff = bwImageSectionsSimilarity(image, prototype, x, y, maxError); |
97 | if (diff <= maxError) |
98 | best.put(new Rect(x, y, wp, hp), 1-diff/(wp*hp)); |
99 | } |
100 | |
101 | void showBest() { |
102 | setImageSurfaceSelection(is, best!); |
103 | setText(infoLabel, best); |
104 | } |
105 | |
106 | // best rect in original image coordinates |
107 | Rect bestRescaled() { |
108 | ret rescaleRect(best!, ii.getWidth(), ii.getHeight(), |
109 | baseImage.getWidth(), baseImage.getHeight()); |
110 | } |
111 | |
112 | Scored<Rect> scoredBestRescaled() { |
113 | ret scored(bestRescaled(), best.score); |
114 | } |
115 | } |
116 | |
117 | *() {} |
118 | *(File prototypeImage, File imgFile) { |
119 | this.prototypeImage = loadBWImage(prototypeImage); |
120 | this.baseImage = loadBWIntegralImage(imgFile); |
121 | } |
122 | |
123 | Scored<Rect> go() { |
124 | assertNotNull(+baseImage); |
125 | assertNotNull(+prototypeImage); |
126 | |
127 | if (tabs != null) |
128 | addTab(tabs, "Best", northAndCenterWithMargins( |
129 | bestLabel = jcenteredlabel(), |
130 | jFullCenterScroll(bestImageSurface = jImageSurface(bwIntegralImageToBWImage(baseImage))))); |
131 | |
132 | makeChains(); |
133 | |
134 | time "Process" { |
135 | print("Steps: " + stepAll_roundRobin(map(chains, c -> c.makeSteppable()))); |
136 | } |
137 | |
138 | showBest(); |
139 | ret bestResult(); |
140 | } |
141 | |
142 | void showBest { |
143 | for (Chain c : chains) |
144 | for (OneLevel l : c.levels) |
145 | l.showBest(); |
146 | setText(bestLabel, bestResult()); |
147 | setImageSurfaceSelection(bestImageSurface, bestResult()!); |
148 | } |
149 | |
150 | void makeChains { |
151 | for (double ah : assumedPrototypeHeightPercentages) |
152 | chains.add(new Chain(ah)); |
153 | } |
154 | |
155 | Scored<Rect> bestResult() { |
156 | ret bestScored(map(methodLambda0 bestResult, chains)); |
157 | } |
158 | } |
Began life as a copy of #1027225
download show line numbers debug dex old transpilations
Travelled to 7 computer(s): bhatertpkbcr, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tvejysmllsmz, vouqrxazstgt, xrpafgyirdlv
No comments. add comment
Snippet ID: | #1027246 |
Snippet name: | MultiLevelRecognizer1 (backup 2, with chains, single prototype) |
Eternal ID of this version: | #1027246/1 |
Text MD5: | d1d0d632adccf67a773a573761e40d1f |
Transpilation MD5: | 5a51d97151ef9ec3448dd97453313a56 |
Author: | stefan |
Category: | javax / image recognition |
Type: | JavaX fragment (include) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2020-02-26 16:42:50 |
Source code size: | 5081 bytes / 158 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 153 / 227 |
Referenced in: | [show references] |