!7 cmodule ImageSegmenter > DynImageSurface { // parameters int blur; bool distanceFromColor; int dc_r, dc_g, dc_b; float dc_gain = 5f, maxGain = 25f; float contrastThreshold = 0.5f; int gridSize = 2; DoubleRange widthRange = new(0, 1); DoubleRange heightRange = new(0, 1); DoubleRange xRange = new(0, 1); DoubleRange yRange = new(0, 1); // output L segments; transient BufferedImage blurredImage; transient JLabel lblFound; transient ReliableSingleThread rst = dm_rst(this, r segmentIt); visualize { JSlider slider = main.onChange(jLiveValueSlider(dm_fieldLiveValue('contrastThreshold)), rst); JSpinner spinner = main.onChange(dm_spinner gridSize(2, 10), rst); JSpinner blurSpinner = main.onChange(dm_spinner blur(0, 10), rst); afterwards { imageSurfaceOnHover(imageSurface, voidfunc(Pt p) { RGB rgb = bufferedImage_getRGB(blurredImage, p); setToolTip(imageSurface, rgb == null ? null : "Color: " + rgbToIntTriple(rgb)); }); updateLblFound(); rst.trigger(); } ret withCenteredLinesBelow(super.visualize(), ll(jCenteredSection(" Preprocessing ", withSideMargin(20, jline( withLabel("Blur:", blurSpinner), main.onChange(dm_checkBox("Distance from color:", 'distanceFromColor), rst), withLabel("R:", main.onChange(dm_spinner dc_r(0, 255), rst)), withLabel("G:", main.onChange(dm_spinner dc_g(0, 255), rst)), withLabel("B:", main.onChange(dm_spinner dc_b(0, 255), rst)), withLabel("Gain:", main.onChange(jMinWidth(100, jLiveValueSliderZeroToX(maxGain, dm_fieldLiveValue('dc_gain))), rst)))))), ll(jCenteredSection(" Segmenting ", withSideMargin(20, jline( withLabel("Contrast Threshold:", jMinWidth(100, slider)), withLabel("Grid size:", spinner), jbutton("Segment", rst)))), jCenteredSection(" Result ", withSideMargin(20, lblFound = jboldlabel(" "))), jVerticalCenter(jPopDownButton_noText( "Show segments", rThread showSegments ))), ll( withLabel("Width range:", main.onChange(doubleRangeLiveValueSlider(dm_fieldLiveValue('widthRange)), rst)), withLabel("Height range:", main.onChange(doubleRangeLiveValueSlider(dm_fieldLiveValue('heightRange)), rst))), ll( withLabel("X position:", main.onChange(doubleRangeLiveValueSlider(dm_fieldLiveValue('xRange)), rst)), withLabel("Y position:", main.onChange(doubleRangeLiveValueSlider(dm_fieldLiveValue('yRange)), 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(); BufferedImage image = getImage(); BufferedImage imageToDraw = null; if (blur != 0) image = imageToDraw = new BoxBlurFilter(blur).filter(image, null); blurredImage = image; new AutoSegmenter as; as.g = gridSize; as.contrastThreshold = contrastThreshold; BWImage bw; if (distanceFromColor) { bw = img_distanceFromColor_withGain(image, rgbFromInts(dc_r, dc_g, dc_b), dc_gain); imageToDraw = bw.getBufferedImage(); } else bw = BWImage(image); L segments = as.go(bw); IntRange wr = doubleToIntRange_endPlus1(w, widthRange); IntRange hr = doubleToIntRange_endPlus1(h, heightRange); IntRange xr = doubleToIntRange_endPlus1(w, xRange); IntRange yr = doubleToIntRange_endPlus1(h, yRange); printVars_str(+wr, +hr, +xr, +yr); segments = filterRectsByWidthRange(segments, wr); segments = filterRectsByHeightRange(segments, hr); segments = filterRectsByCenterXRange(segments, xr); segments = filterRectsByCenterYRange(segments, yr); setField(+segments); updateLblFound(); imageSurface.imageToDraw = imageToDraw; overlaySelectionsOnImageSurface(imageSurface, segments); } void showSegments { L segments = this.segments; showImage_centered(n2(segments, "segment") + " found", mergeBufferedImagesVertically(map(segments, r -> clipBufferedImage(getImage(), r)))); } void updateLblFound() { setText(lblFound, nSegments(segments) + " found"); } }