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: | 377 / 479 |
| Referenced in: | [show references] |