// A is the user object associated with each mask (aka a "label").
persistable sclass G22HashedMasks is IG22SimpleMasksHolder {
!include early #1035854 // Masks holder Include
record noeq Mask(Image2B image) is IG22Mask {
settable A label;
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; }
}
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) {
addMask(regionToMaskImage(region), label);
}
void addMask(IBinaryImage maskImage, A label default null) {
var mask = new Mask(toImage2B(maskImage));
var existingMask = masks.find(mask);
if (existingMask != null) {
mask = existingMask;
mask.label = combineLabels(mask.label, label);
} else {
mask.label = label;
masks.add(mask);
}
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));
}*/
A combineLabels(A label1, A label2) {
if (eq(label1, label2)) ret label1;
if (label1 == null) ret label2;
if (label2 == null) ret label1;
if (label1 cast MultiSet) {
if (label2 cast MultiSet) {
label1.addAll(label2);
ret (A) label1;
}
}
ret specialCombineLabels(label1, label2);
}
swappable A specialCombineLabels(A label1, A label2) {
fail("Can't combine labels: " + label1 + " + " + label2);
}
public IG22MasksHolder cloneTreeWithLabelTransform(IF1 f) {
new G22HashedMasks clone;
for (mask : masks) {
G22HashedMasks.Mask clonedMask = clone.new Mask;
clonedMask.image = mask.image;
clonedMask.hash = mask.hash;
clonedMask.label = f.get(mask.label);
clone.masks.add(clonedMask);
}
ret clone;
}
}