Uses 108K of libraries. Click here for Pure Java version (10828L/76K).
1 | // complexity is number of assumed heights * number of widths |
2 | sclass MultiLevelRecognizer2 { |
3 | // how big do we think the prototype is in the whole image |
4 | // (percentage by height) |
5 | transient L<Double> assumedPrototypeHeightPercentages = ll(70.0, 70.0/sqrt(2), 35.0, 35.0/sqrt(2), 17.0); |
6 | |
7 | // widths to scale camera image to |
8 | transient L<Int> widths = ll(32, 64, 128); |
9 | |
10 | transient JTabbedPane tabs; // initialize if you want visualization |
11 | transient ImageSurface bestImageSurface; |
12 | transient JLabel bestLabel; |
13 | |
14 | transient BWIntegralImage baseImage; |
15 | transient new L<BWIntegralImage> prototypeImages; |
16 | transient new Map<Int, IBWIntegralImage> integralImages; // key = width |
17 | transient new L<Chain> chains; // one per assumed height & prototype |
18 | |
19 | // chain of recognizers for one assumed height |
20 | class Chain { |
21 | BWIntegralImage prototypeImage; |
22 | double assumedHeightPercentage; |
23 | new L<OneLevel> levels; // recognizers for each granularity |
24 | new Map<Int, BWImage> scaledPrototypeImages; // key = height |
25 | |
26 | *(double *assumedHeightPercentage, BWIntegralImage *prototypeImage) { make(); } |
27 | |
28 | void make { |
29 | for (int w : widths) { |
30 | IBWIntegralImage ii = mapGetOrCreate(integralImages, w, () -> scaledIBWIntegralImage(baseImage, w)); |
31 | OneLevel lvl = new(this, last(levels), 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 | void reset { |
43 | for (OneLevel l : levels) l.reset(); |
44 | } |
45 | |
46 | Steppable makeSteppable() { |
47 | ret iteratorToSteppable(roundRobinCombinedIterator(lambdaMap steppableToIterator(levels))); |
48 | } |
49 | |
50 | Scored<Rect> bestResult() { |
51 | ret last(levels).scoredBestRescaled(); |
52 | } |
53 | } |
54 | |
55 | class OneLevel extends SteppableAndBest<Rect> { |
56 | Chain chain; |
57 | OneLevel previous, next; |
58 | |
59 | IBWIntegralImage ii; // scaled integral image |
60 | BWImage image; // scaled image |
61 | BWImage prototype; // scaled prototype |
62 | float minSimilarity = 0.5f; |
63 | |
64 | ImageSurface is; |
65 | JLabel infoLabel; |
66 | |
67 | // candidates are top-left corner of rect to try in our coordinates |
68 | L<Pt> candidatesQueue = syncLinkedList(); |
69 | new Set<Pt> candidatesTried; |
70 | Iterator<Pt> candidatesStream; |
71 | |
72 | *(Chain *chain, OneLevel *previous, IBWIntegralImage *ii) { |
73 | if (previous != null) previous.next = this; |
74 | image = iBWIntegralImageToBWImage(ii); |
75 | // get assumed height of prototype in scaled-down image |
76 | int ph = iround(ii.getHeight()*chain.assumedHeightPercentage/100.0); |
77 | // resize prototype |
78 | prototype = mapGetOrCreate(chain.scaledPrototypeImages, ph, |
79 | () -> scaleDownUsingIntegralImageBW(chain.prototypeImage, ph); |
80 | /*addTab(tabs, "proto " + ii.getWidth(), |
81 | jFullCenterScroll(jPixelatedZoomedImageSurface(4.0, prototype))); |
82 | */ |
83 | |
84 | reset(); |
85 | } |
86 | |
87 | void reset { |
88 | candidatesTried.clear(); |
89 | candidatesStream = fullStream(); |
90 | } |
91 | |
92 | // all candidates |
93 | Iterator<Pt> fullStream() { |
94 | ret allSubRectsOfSizeIterator_topLeftCorners(prototype.getWidth(), prototype.getHeight(), |
95 | imageRect(image)); |
96 | } |
97 | |
98 | public bool step() { |
99 | Pt p = nextCandidate(); |
100 | if (p != null) ret true with tryCandidate(p); |
101 | false; |
102 | } |
103 | |
104 | Pt nextCandidate() { |
105 | try object Pt p = popFirst(candidatesQueue); |
106 | ret nextFromIterator(candidatesStream); |
107 | } |
108 | |
109 | void tryCandidate(Pt p) { |
110 | if (!candidatesTried.add(p)) ret; |
111 | |
112 | int x = p.x, y = p.y, wp = prototype.getWidth(), hp = prototype.getHeight(); |
113 | |
114 | float maxError = (1f-minSimilarity)*wp*hp; |
115 | float diff = bwImageSectionsSimilarity(image, prototype, x, y, maxError); |
116 | if (diff <= maxError) |
117 | best.put(new Rect(x, y, wp, hp), 1-diff/(wp*hp)); |
118 | } |
119 | |
120 | void showBest() { |
121 | setImageSurfaceSelection(is, best!); |
122 | setText(infoLabel, best); |
123 | } |
124 | |
125 | // best rect in original image coordinates |
126 | Rect bestRescaled() { |
127 | ret rescaleRect(best!, ii.getWidth(), ii.getHeight(), |
128 | baseImage.getWidth(), baseImage.getHeight()); |
129 | } |
130 | |
131 | Scored<Rect> scoredBestRescaled() { |
132 | ret scored(bestRescaled(), best.score); |
133 | } |
134 | } |
135 | |
136 | *() {} |
137 | *(File imgFile) { |
138 | baseImage = loadBWIntegralImage(imgFile); |
139 | } |
140 | |
141 | void addPrototype(BufferedImage img) { |
142 | prototypeImages.add(bwIntegralImage(img)); |
143 | } |
144 | |
145 | void addPrototype(File imgFile) { |
146 | addPrototype(loadImage2(imgFile)); |
147 | } |
148 | |
149 | void addPrototypes(Iterable<BufferedImage> l) { |
150 | fOr (BufferedImage img : l) addPrototype(img); |
151 | } |
152 | |
153 | Scored<Rect> go() { |
154 | if (empty(chains)) { |
155 | assertNotNull(+baseImage); |
156 | assertNempty(+prototypeImages); |
157 | |
158 | if (tabs != null) |
159 | addTab(tabs, "Best", northAndCenterWithMargins( |
160 | bestLabel = jcenteredlabel(), |
161 | jFullCenterScroll(bestImageSurface = jImageSurface(bwIntegralImageToBWImage(baseImage))))); |
162 | |
163 | makeChains(); |
164 | } else |
165 | reset(); |
166 | |
167 | time "Process" { |
168 | print("Steps: " + stepAll_roundRobin(map(chains, c -> c.makeSteppable()))); |
169 | } |
170 | |
171 | showBest(); |
172 | ret bestResult(); |
173 | } |
174 | |
175 | void showBest { |
176 | for (Chain c : chains) |
177 | for (OneLevel l : c.levels) |
178 | l.showBest(); |
179 | setText(bestLabel, bestResult()); |
180 | setImageSurfaceSelection(bestImageSurface, bestResult()!); |
181 | } |
182 | |
183 | void makeChains { |
184 | chains.clear(); |
185 | for (double ah : assumedPrototypeHeightPercentages) |
186 | for (BWIntegralImage proto : prototypeImages) |
187 | chains.add(new Chain(ah, proto)); |
188 | } |
189 | |
190 | Scored<Rect> bestResult() { |
191 | ret bestScored(map(methodLambda0 bestResult, chains)); |
192 | } |
193 | |
194 | void reset { |
195 | for (Chain c : chains) c.reset(); |
196 | } |
197 | } |
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: | #1027247 |
Snippet name: | MultiLevelRecognizer2 - finds multiple prototype images |
Eternal ID of this version: | #1027247/21 |
Text MD5: | 62585171456f4f4485b719caf910587a |
Transpilation MD5: | d796895d36c2cd115c37b580cbd9a70b |
Author: | stefan |
Category: | |
Type: | JavaX fragment (include) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2020-02-28 15:55:31 |
Source code size: | 6141 bytes / 197 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 253 / 664 |
Version history: | 20 change(s) |
Referenced in: | [show references] |