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

172
LINES

< > BotCompany Repo | #1035858 // G22CriticalPixelSearch - find best pixel to split list of masks at

JavaX fragment (include) [tags: use-pretranspiled]

Transpiled version (29124L) is out of date.

1  
sclass G22CriticalPixelSearch is Steppable {
2  
  // input
3  
  settable IG22MasksHolder<?> masksHolder;
4  
  settable bool keepAllEntries;
5  
  settable bool sortPixelsFirst = true;
6  
  
7  
  // internal
8  
  int w, h;
9  
  Iterator<Pt> pixelIterator;
10  
  
11  
  // output
12  
  new Best<Pt> bestPixel;
13  
  Entry bestEntry;
14  
  Pt lastPixelLookedAt;
15  
  Entry lastEntry;
16  
  Entry[] pixelEntries;
17  
  float[] pixelScores;
18  
  int nPixelsTested;
19  
  
20  
  // stores all subsets of masks found if not null
21  
  CompactHashSet<HashedByteArray> subSets;
22  
  
23  
  *() {}
24  
  *(IG22MasksHolder *masksHolder) {}
25  
  
26  
  class Entry {
27  
    Pt pixel;
28  
    // child mask holders for pixel dark or pixel bright
29  
    //IG22MasksHolder darkChild, brightChild;
30  
    gettable L<IG22Mask> darkMasks;
31  
    gettable L<IG22Mask> brightMasks;
32  
    G22GhostImage darkGhost;
33  
    G22GhostImage brightGhost;
34  
    
35  
    simplyCached IG22MasksHolder darkHolder() {
36  
      ret new G22HashedMasks(darkMasks, darkGhost);
37  
    }
38  
    
39  
    simplyCached IG22MasksHolder brightHolder() {
40  
      ret new G22HashedMasks(brightMasks, brightGhost);
41  
    }
42  
    
43  
    void calcGhosts {
44  
      if (l(darkMasks) < l(brightMasks)) {
45  
        darkGhost = new G22GhostImage(lmapMethod image(darkMasks));
46  
        brightGhost = masksHolder().ghost().minus(darkGhost);
47  
      } else {
48  
        brightGhost = new G22GhostImage(lmapMethod image(brightMasks));
49  
        darkGhost = masksHolder().ghost().minus(brightGhost);
50  
      }
51  
    }
52  
    
53  
    toString {
54  
      ret commaCombine(
55  
        "Split at " + pixel,
56  
        "dark=" + darkHolder().renderCountAndCertainty(),
57  
        "bright=" + brightHolder().renderCountAndCertainty());
58  
    }
59  
  }
60  
  
61  
  public bool step() {
62  
    if (w == 0) {
63  
      if (!masksHolder.canSplit()) false;
64  
      
65  
      meta-for w also as h { w = masksHolder.maskSize().w(); }
66  
      pixelEntries = new Entry[w*h];
67  
      pixelScores = new float[w*h];
68  
      arrayfill(pixelScores, -1);
69  
      pixelIterator = makePixelIterator();
70  
    }
71  
    
72  
    if (!pixelIterator.hasNext()) false;
73  
    lastPixelLookedAt = pixelIterator.next();
74  
    testPixel(lastPixelLookedAt);
75  
    true;
76  
  }
77  
  
78  
  int idx(Pt p) { ret p.y*w+p.x; }
79  
  
80  
  void testPixel(Pt p) {
81  
    double score;
82  
    Entry e = null;
83  
    ++nPixelsTested;
84  
    
85  
    // Find out if pixel is the same in all masks
86  
    float ghostBrightness = masksHolder.ghost().getFloatPixel(p);
87  
    if (ghostBrightness == 0 || ghostBrightness == 1)
88  
      // Pixel is determined, not usable for splitting
89  
      score = -2;
90  
    else {
91  
      // Pixel is not determined - let's make the 2 subsets
92  
      
93  
      e = new Entry;
94  
      e.pixel = p;
95  
      lastEntry = e;
96  
      if (keepAllEntries)
97  
        pixelEntries[idx(p)] = e;
98  
        
99  
      L<IG22Mask> masks = wideningListCast(masksHolder.masks());
100  
      int n = l(masks);
101  
      
102  
      // bit is 1 when pixel is bright
103  
      byte[] brightBits = byteArrayForNBits(n);
104  
105  
      // calculate the split
106  
      for i to n:
107  
        if (masks.get(i).image().getBoolPixel(p))
108  
          setBit(brightBits, i);
109  
          
110  
      subSets?.add(new HashedByteArray(brightBits));
111  
      
112  
      var splitMasks = filterAntiFilterByBitSet(masks, brightBits);
113  
      e.brightMasks = splitMasks.a;
114  
      e.darkMasks = splitMasks.b;
115  
      e.calcGhosts();
116  
117  
      score = scoreEntry(e);
118  
    }
119  
    
120  
    pixelScores[idx(p)] = (float) score;
121  
    if (score > 0 && bestPixel.put(p, score))
122  
      bestEntry = e;
123  
  }
124  
  
125  
  swappable double scoreEntry(Entry e) {
126  
    double c1 = e.darkGhost.certainty();
127  
    double c2 = e.brightGhost.certainty();
128  
    
129  
    // ret avg(c1, c2);
130  
    ret min(c1, c2);
131  
  }
132  
  
133  
  double bestScore() {
134  
    ret bestPixel.score();
135  
  }
136  
  
137  
  BWImage scoreImage() {
138  
    double min = masksHolder.certainty();
139  
    double max = bestPixel.score();
140  
    ret bwImageFromFunction(w, h,
141  
      (x, y) -> transformToZeroToOne(pixelScores[y*w+x], max, min));
142  
  }
143  
  
144  
  G22PixelSplitMasks<?> splitMasksHolder() {
145  
    if (!bestPixel.has()) null;
146  
    ret new G22PixelSplitMasks()
147  
      .splitPixel(bestPixel!)
148  
      .darkHolder(bestEntry.darkHolder())
149  
      .brightHolder(bestEntry.brightHolder());
150  
  }
151  
  
152  
  IG22MasksHolder makeBestTree aka bestTree aka get() {
153  
    stepAll(this);
154  
    G22PixelSplitMasks<?> split = splitMasksHolder();
155  
    if (split == null) ret masksHolder;
156  
    split.transformSubHolders(subHolder
157  
      -> new G22CriticalPixelSearch(subHolder).makeBestTree());
158  
    ret split;
159  
  }
160  
  
161  
  void collectSubSets {
162  
    subSets if null = new CompactHashSet;
163  
  }
164  
  
165  
  Iterator<Pt> makePixelIterator() {
166  
    if (sortPixelsFirst)
167  
      // try least certain pixels first
168  
      ret iterator(pixelsByBrightness(masksHolder().ghost().certaintyImage()));
169  
    else
170  
      ret new WeightlessShuffledIterator<Pt>(pixelsInImage(w, h));
171  
  }
172  
}

download  show line numbers  debug dex  old transpilations   

Travelled to 3 computer(s): elmgxqgtpvxh, mqqgnosmbjvj, wnsclhtenguj

No comments. add comment

Snippet ID: #1035858
Snippet name: G22CriticalPixelSearch - find best pixel to split list of masks at
Eternal ID of this version: #1035858/61
Text MD5: 2ca7213890235ca20d11062a4a943c7a
Author: stefan
Category: javax / gazelle 22
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2023-02-13 22:43:02
Source code size: 4836 bytes / 172 lines
Pitched / IR pitched: No / No
Views / Downloads: 277 / 628
Version history: 60 change(s)
Referenced in: [show references]