!7 // TODO: port upload to gazelle cm ImageSegmenter > DynImageSurface { !include #1024657 // Image Segmenter Parameters float maxGain = 25f; transient S sliceID = agiBlue_imageSegmentationSlice(); // output L segments; transient BufferedImage filteredImage; 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, 99), rst); JSpinner filterSpinner = main.onChange(dm_spinner filterLevel(0, 10), rst); afterwards { imageSurfaceOnHover(imageSurface, voidfunc(Pt p) { RGB rgb = bufferedImage_getRGB(filteredImage, p); setToolTip(imageSurface, rgb == null ? null : "Color: " + rgb + "/" + rgbToIntTriple(rgb) + ", position: " + p + (imageSurface.getSelection() == null ? "" : ", selection: " + toRect(imageSurface.getSelection()))); }); componentPopupMenu_top(imageSurface, voidfunc(JPopupMenu menu) { Pt p = imageSurface.pointFromEvent(componentPopupMenu_getEvent()); RGB rgb = bufferedImage_getRGB(filteredImage, p); if (rgb == null) ret; Rect r = smallestRectContaining(segments, p); addPopupMenuItem(menu, "Pick color", r { setField(dc_r := rgb.redInt()); setField(dc_g := rgb.greenInt()); setField(dc_b := rgb.blueInt()); setField(distanceFromColor := true); rst.trigger(); }); if (r != null) addPopupMenuItem(menu, "Show segment", r { showImage("Segment " + r, cloneClipBufferedImage(getImage(), r)); }); }); updateLblFound(); rst.trigger(); } ret withCenteredLinesBelow(super.visualize(), ll(jCenteredSection(" Preprocessing ", withSideMargin(20, jline( withLabel("Filter:", jMinWidth(75, main.onChange(dm_comboBox filter(ll("blur", "min", "max")), rst))), filterSpinner, 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( jVerticalCenter(jThreadedButton("Screenshot", rThread { setImage(dm_shootScreenHidingOS()); /*rst.trigger();*/ })), 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, "Load segmenter...", rThread loadSegmenter, "Paste segmenter from clipboard", rThread pasteSegmenter, "Revert to default settings", rThread loadDefaultSegmenter )) ), 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 { set zoomToWindowOnSetImage; if (!hasImage()) setImage(whiteImage(100, 100)); dm_vmBus_onMessage('newClipboardContents, voidfunc(O o) { if (o cast BufferedImage) thread { setImage(o); } }); onNewImage = rst; } void segmentIt enter { if (!hasImage()) ret; new ParameterizedSegmenter segmenter; copyFields(module(), segmenter); segmenter.image = getImage(); segmenter.run(); filteredImage = or(segmenter.filteredImage1, getImage()); setField(segments := segmenter.segments); updateLblFound(); imageSurface.imageToDraw = segmenter.filteredImage; 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(), tfImageCredits = jtextfield(); showFormTitled("Publish image segmentation result", "Image", jImageSurface(scaleImageToWidth(image, 200)), "Task description", tfDesc, "How successful was the result?", tfSuccess, "Image credits (optional)", tfImageCredits, "# 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", print(+imageURL)); mapPutIfNemptyValue(map, "Image credits", gtt(tfImageCredits)); map.put("Segmenter", programID()); map.put("_class", "Segmenter preset"); 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)); disposePIFrame(heldButton()); }) ); } Set parameterFields() { ret nonStaticNonTransientFields_withoutSuperclasses(this); } SS parameters() { ret mapToValues_treeMap(parameterFields(), field -> struct(get(module(), field))); } void loadSegmenter enter { JComboBox cb = jComboBox(agiBlue_segmenterPresetNames()); showFormTitled("Load segmenter preset", "Preset", cb, r { ParameterizedSegmenter seg = parameterizedSegmenterFromAGIBlue(getText(cb)); if (seg == null) infoBox("Segmenter not found: " + name); loadSegmenter(seg); }); } void loadSegmenter(ParameterizedSegmenter seg) enter { if (seg == null) ret; copyFields(seg, module(), parameterFields()); change(); rst.trigger(); infoBox("Segmenter loaded"); } void loadDefaultSegmenter { loadSegmenter(new ParameterizedSegmenter); } void pasteSegmenter enter { loadSegmenter((ParameterizedSegmenter) unstructure(textFromClipboard())); } }