!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); transient S sliceID = "lgobeactljkewwtz"; // 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, "Publish result...", rThread publish, "---", null, "Screenshot (hiding OS)", rThread { setImage(dm_shootScreenHidingOS()); rst.trigger(); }, ))), 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"); } void publish enter { SS map = parameters(); BufferedImage image = getImage(); JTextField tfDesc = jtextfield(), tfSuccess = jtextfield(); showFormTitled("Publish image segmentation result", "Image", jImageSurface(scaleImageToWidth(image, 200)), "Task description", tfDesc, "How successful was the result?", tfSuccess, "# segments found", l_str(segments), "Parameters", jMinHeight(200, disableTextArea(jWordWrapTextArea(pnlToString(mapMinus(map, "segments"))))), "NOTE:", jMultiLineLabel("By clicking 'publish', you PUBLISH this image (fair use/public domain)."), "", jThreadedButton("Publish", r { S desc = gtt(tfDesc), success = gtt(tfSuccess); if (empty(desc)) ret with infoBox("Need a description"); temp tempInfoBox_noHide("Uploading..."); S imageURL = uploadToImageServer(desc, image); map.put("Successful?", success); map.put("Input image", imageURL); new L toPost; S name = agiBlue_createUnusedNumberedPage(sliceID, desc + " #"); for (S key, value : map) toPost.add(litmap(q := name, +key, +value)); agiBot_postMulti(keyPairForProgram(), toPost, slice := sliceID); infoBox("Segmentation result uploaded!"); openURLInBrowser(agiBlue_linkForPhrase(name, slice := sliceID)); disposeWindow(heldButton()); }) ); } Set parameterFields() { ret nonStaticNonTransientFields_withoutSuperclasses(this); } SS parameters() { ret mapToValues_treeMap(parameterFields(), field -> struct(get(module(), field))); } }