!7 cmodule ImageSegmenter > DynImageSurface { float contrastThreshold = 0.5f; int gridSize = 2; DoubleRange widthRange = new(0, 1); DoubleRange heightRange = new(0, 1); transient ReliableSingleThread rst = dm_rst(this, r segmentIt); visualize { JSlider slider = jLiveValueSlider(dm_fieldLiveValue('contrastThreshold)); main.onChange(slider, rst); JSpinner spinner = liveValueSpinner(dm_fieldLiveValue('gridSize), 2, 10); main.onChange(spinner, rst); ret withCenteredLineBelow( withCenteredLineBelow(super.visualize(), withLabel("Contrast Threshold:", slider), withLabel("Grid size:", spinner), jbutton("Segment", rst)), withLabel("Width range:", main.onChange(doubleRangeLiveValueSlider(dm_fieldLiveValue('widthRange)), rst)), withLabel("Height range:", main.onChange(doubleRangeLiveValueSlider(dm_fieldLiveValue('heightRange)), rst))); } start { if (!hasImage()) setImage(whiteImage(100, 100)); dm_vmBus_onMessage('newClipboardContents, voidfunc(O o) { if (o cast BufferedImage) thread { setImage(o); rst.trigger(); } }); } void segmentIt enter { if (!hasImage()) ret; int w = imageWidth(), h = imageHeight(); new AutoSegmenter as; as.g = gridSize; as.contrastThreshold = contrastThreshold; L segments = as.go(BWImage(getImage()); segments = filterRectsByWidthRange(intRange(iround(widthRange.start*w), iround(widthRange.end*w)+1)); segments = filterRectsByHeightRange(intRange(iround(heightRange.start*h), iround(heightRange.end*h)+1)); overlaySelectionsOnImageSurface(imageSurface, segments)); } }