sclass G22CriticalPixelSearch is Steppable { // input settable IG22MasksHolder masksHolder; settable bool keepAllEntries = true; // internal int w, h; ItIt pixelIterator; // output new Best bestPixel; Pt lastPixelLookedAt; Entry lastEntry; Entry[] pixelEntries; float[] pixelScores; *() {} *(IG22MasksHolder *masksHolder) {} class Entry { Pt pixel; // child mask holders for pixel dark or pixel bright //IG22MasksHolder darkChild, brightChild; L darkMasks, brightMasks; IG22MasksHolder darkHolder, brightHolder; } public bool step() { if (w == 0) { meta-for w also as h { w = masksHolder.maskSize().w(); } pixelEntries = new Entry[w*h]; pixelScores = new float[w*h]; arrayfill(pixelScores, -1); pixelIterator = new WeightlessShuffledIterator(pixelsInImage(w, h)); } if (!pixelIterator.hasNext()) false; lastPixelLookedAt = pixelIterator.next(); testPixel(lastPixelLookedAt); true; } int idx(Pt p) { ret p.y*w+p.x; } void testPixel(Pt p) { double score; // Find out if pixel is the same in all masks float ghostBrightness = masksHolder.ghost().getFloatPixel(p); if (ghostBrightness == 0 || ghostBrightness == 1) // Pixel is determined, not usable for splitting score = -2; else { // Pixel is not determined - let's make the 2 subsets new Entry e; e.pixel = p; lastEntry = e; if (keepAllEntries) pixelEntries[idx(p)] = e; Pair> pair = filterAntiFilter(masksHolder.masks(), mask -> !mask.image.getBoolPixel(p)); e.darkMasks = pair.a; e.brightMasks = pair.b; e.darkHolder = new G22HashedMasks(e.darkMasks); e.brightHolder = new G22HashedMasks(e.brightMasks); score = e.darkHolder().certainty() + e.brightHolder().certainty(); } pixelScores[idx(p)] = (float) score; if (score > 0) bestPixel.put(p, score); } }