Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

201
LINES

< > BotCompany Repo | #1027270 // Image Recognition for Vector Spike v2 (two levels)

JavaX source code (Dynamic Module) [tags: use-pretranspiled] - run with: Stefan's OS

Uses 911K of libraries. Click here for Pure Java version (10273L/54K).

1  
!7
2  
3  
// multi-resolution image search
4  
// uses only one prototype image
5  
6  
cmodule ImageRecogSpike {
7  
  switchable S prototypeImageID = #1102884;
8  
  switchable S inputImageID = #1102883;
9  
  switchable bool showResizedProtos;
10  
  switchable int numberOfCandidatesToShow = 3;
11  
  switchable int nTimes = 10;
12  
13  
  // how big do we think the prototype is in the whole image
14  
  // (percentage by height)
15  
  switchable double assumedPrototypeHeightPercentage = 70;
16  
  
17  
  transient L<Int> widths = ll(1, 2, 4, 8, 16, 32, 64, 128);
18  
  transient new L<IBWIntegralImage> integralImages;
19  
  transient BWIntegralImage baseImage;
20  
  transient JTabbedPane tabs = jTabbedPane();
21  
  transient ImageSurface isResult;
22  
  transient BWImage prototypeImage;
23  
  transient new L<OneLevel> levels; // recognizers for each granularity
24  
  
25  
  transient new Best<Rect> allBest;
26  
  transient S status;
27  
28  
  class OneLevel extends SteppableAndBest<Rect> {
29  
    IBWIntegralImage ii; // scaled integral image
30  
    BWImage image;       // scaled image
31  
    BWImage prototype;   // scaled prototype
32  
    float minSimilarity = 0.5f;
33  
    ImageSurface is;
34  
    new Map<Rect, Double> allScores;
35  
36  
    // candidates are top-left corner of rect to try in our coordinates
37  
    L<Pt> candidatesQueue = syncLinkedList();
38  
    new Set<Pt> candidatesTried;
39  
    Iterator<Pt> candidatesStream;
40  
    
41  
    void reset {
42  
      clear(allScores);
43  
      best.clear();
44  
      clear(candidatesQueue);
45  
      clear(candidatesTried);
46  
      makeCandidatesStream();
47  
    }
48  
49  
    *(IBWIntegralImage *ii) {
50  
      image = iBWIntegralImageToBWImage(ii);
51  
      // get assumed height of prototype in scaled-down image
52  
      int ph = max(1, iround(ii.getHeight()*assumedPrototypeHeightPercentage/100.0));
53  
      // resize prototype
54  
      prototype = bwResizeToHeightSmooth(prototypeImage, ph);
55  
      if (showResizedProtos)
56  
        addTab(tabs, "proto " + ii.getWidth(),
57  
          jFullCenterScroll(jPixelatedZoomedImageSurface(4.0, prototype)));
58  
      makeCandidatesStream();
59  
    }
60  
    
61  
    void makeCandidatesStream {
62  
      candidatesStream = mapI rectTopLeftCorner(allSubRectsOfSizeIterator(prototype.getWidth(), prototype.getHeight(),
63  
        imageRect(image)));
64  
    }
65  
    
66  
    int width() { ret ii.getWidth(); }
67  
    int height() { ret ii.getHeight(); }
68  
    
69  
    public bool step() {
70  
      Pt p = nextCandidate();
71  
      if (p != null) ret true with tryCandidate(p);
72  
      false;
73  
    }
74  
75  
    Pt nextCandidate() {
76  
      try object Pt p = popFirst(candidatesQueue);
77  
      ret nextFromIterator(candidatesStream);
78  
    }
79  
80  
    void tryCandidate(Pt p) {
81  
      if (!candidatesTried.add(p)) ret;
82  
83  
      int x = p.x, y = p.y, wp = prototype.getWidth(), hp = prototype.getHeight();
84  
85  
      float maxError = (1f-minSimilarity)*wp*hp;
86  
      float diff = bwImageSectionsSimilarity(image, prototype, x, y, maxError);
87  
      if (diff <= maxError)
88  
        putInBestAndMap(best, allScores, new Rect(x, y, wp, hp), 1-diff/(wp*hp);
89  
    }
90  
91  
    void showBest() {
92  
      overlaySelectionsOnImageSurface(is, nBest(numberOfCandidatesToShow));
93  
    }
94  
    
95  
    L<Rect> nBest(int n) {
96  
      ret topTenKeysByValue(n, allScores);
97  
    }
98  
  }
99  
  
100  
  start-thread {
101  
    dm_watchField numberOfCandidatesToShow(r showBest);
102  
    if (baseImage == null)
103  
      baseImage = BWIntegralImage(loadImage2(inputImageID));
104  
    addTab(tabs, "Result", isResult = jPixelatedZoomedImageSurface(1.0, iBWIntegralImageToBWImage(baseImage)));
105  
    if (prototypeImage == null)
106  
      prototypeImage = loadBWImage(prototypeImageID);
107  
    for (int w : widths) {
108  
      IBWIntegralImage ii = scaledIBWIntegralImage(baseImage, w);
109  
      integralImages.add(ii);
110  
      ImageSurface is = jPixelatedZoomedImageSurface(
111  
        doubleRatio(baseImage.getWidth(), w), iBWIntegralImageToBWImage(ii));
112  
      addTab(tabs, "w=" + w, jFullCenterScroll(is));
113  
      levels.add(setAll(new OneLevel(ii), +is));
114  
    }
115  
    addTab(tabs, "Prototype", jFullCenterScroll(jPixelatedZoomedImageSurface(4, prototypeImage)));
116  
117  
    repeat nTimes {
118  
      recogWithTiming();
119  
    }
120  
    showBest();
121  
  }
122  
123  
  void recogWithTiming {  
124  
    time "Recognition" { 
125  
      recog();
126  
    }
127  
    setField(status := "Recognized in " + lastTiming() + " ms: " + allBest);
128  
  }
129  
  
130  
  void recog {
131  
    reset();
132  
    //fullSearch();
133  
    twoLevels(16, 128, 5);
134  
  }
135  
  
136  
  void fullSearch {
137  
    print("Steps: " + stepAll_roundRobin(levels));
138  
    copyBestFromLevel(last(levels));
139  
  }
140  
  
141  
  void copyBestFromLevel(OneLevel lvl) {
142  
    if (lvl.best.has())
143  
      allBest.put(scaleBetweenWidths(lvl.width(), baseImage.getWidth(), lvl.best!), lvl.best.score);
144  
  }
145  
  
146  
  void twoLevels(int width1, int width2, int candidatesToUse) {
147  
    int spiralSize = width2/width1*2;
148  
    int pixelsPerSpiral = sqr(spiralSize);
149  
    print("Spiral size: " + spiralSize + " / " + pixelsPerSpiral);
150  
    
151  
    int i1 = indexOf(widths, width1), i2 = indexOf(widths, width2);
152  
    if (i1 < 0) fail("Width " + width1 + " not in list: " + widths);
153  
    if (i2 < 0) fail("Width " + width2 + " not in list: " + widths);
154  
    OneLevel lvl1 = levels.get(i1), lvl2 = levels.get(i2);
155  
    
156  
    // Full search in level 1
157  
    stepAll(lvl1);
158  
    
159  
    // Circle around n best candidates found in level 1
160  
    L<Pt> candidates = scaleBetweenLevels(lvl1, lvl2, map topLeftCorner(lvl1.nBest(candidatesToUse)));
161  
    for (Pt p : combineIterators_roundRobin(map(candidates, c ->
162  
      pixelSpiral(c.x, c.y, lvl2.width(), lvl2.height(), pixelsPerSpiral))))
163  
      lvl2.tryCandidate(p);
164  
      
165  
    copyBestFromLevel(lvl2);
166  
  }
167  
  
168  
  Rect scaleBetweenWidths(int w1, int w2, Rect r) {
169  
    ret scaleRect(doubleRatio(w2, w1), r);
170  
  }
171  
  
172  
  Pt scaleBetweenWidths(int w1, int w2, Pt p) {
173  
    ret scalePt(doubleRatio(w2, w1), p);
174  
  }
175  
  
176  
  Pt scaleBetweenLevels(OneLevel lvl1, OneLevel lvl2, Pt p) {
177  
    ret scaleBetweenWidths(lvl1.width(), lvl2.width(), p);
178  
  }
179  
  
180  
  L<Pt> scaleBetweenLevels(OneLevel lvl1, OneLevel lvl2, Iterable<Pt> l) {
181  
    ret map(l, p -> scaleBetweenLevels(lvl1, lvl2, p));
182  
  }
183  
184  
  void showBest {  
185  
    for (OneLevel l : levels) l.showBest();
186  
    setImageSurfaceSelection(isResult, allBest!);
187  
    print("Best: " + allBest);
188  
    print("Candidates tried: " + mapNonNulls(levels, l ->
189  
      empty(l.candidatesTried) ? null : l(l.candidatesTried) + " for w=" + l.width()));
190  
  }
191  
  
192  
  void reset {
193  
    for (OneLevel l : levels) l.reset();
194  
    allBest.clear();
195  
  }
196  
197  
  visual withCenteredButtons(tabs,
198  
    vstackWithSpacing(
199  
      withLabel("# of candidates to show:", dm_fieldSpinner numberOfCandidatesToShow(1, 100)),
200  
      dm_centeredLabel status()));
201  
}

Author comment

Began life as a copy of #1027204

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: #1027270
Snippet name: Image Recognition for Vector Spike v2 (two levels)
Eternal ID of this version: #1027270/27
Text MD5: 5f97ffea279f3895b98801d784d9ac4d
Transpilation MD5: 79b14b73336418e7e0c898e9d6c61655
Author: stefan
Category: javax / image recognition
Type: JavaX source code (Dynamic Module)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2020-02-29 17:40:37
Source code size: 6669 bytes / 201 lines
Pitched / IR pitched: No / No
Views / Downloads: 175 / 1366
Version history: 26 change(s)
Referenced in: [show references]