// A is the user object associated with each mask (aka a "label"). // Each mask now has a multi-set of labels. persistable sclass G22HashedMasks is IG22SimpleMasksHolder { record noeq Mask(Image2B image) is IG22Mask { gettable new A labels; int hash; public bool equals(O o) { if (o cast G22HashedMasks.Mask) ret hashCode() == o.hashCode() && binaryImagesIdentical(image, o.image); false; } public int hashCode() { if (hash == 0) hash = (int) hashImage2B(image); ret hash; } public Image2B image() { ret image; } public A label() { ret labels; } } new CompactHashSet masks; // creating a sub-holder *(L> masks) { assertNempty(masks); maskSize(imageSize(first(masks).image())); fOr (mask : masks) this.masks.add(mask); } // same with pre-calculated ghost *(L> masks, G22GhostImage ghost) { this(masks); ghost_cache = ghost; } void addRegion(IImageRegion region, A label) { addRegion(region, ll(label)); } void addRegion(IImageRegion region, Cl labels) { if (empty(labels)) ret; var mask = new Mask(regionToMaskImage(region)); var existingMask = masks.find(mask); if (existingMask != null) mask = existingMask; else masks.add(mask); mask.labels.addAll(labels); ghost_cache = null; certainty_cache = null; this.labels.addAll(labels); } public L masks() { ret asList(masks); } /*public LPair maskImagesWithLabels() { ret map(masks(), mask -> pair(mask.image, mask.labels)); }*/ !include early #1035854 // Masks holder Include }