Uses 1113K of libraries. Click here for Pure Java version (22296L/123K).
1 | !7 |
2 | |
3 | // TODO: port upload to gazelle |
4 | |
5 | cm ImageSegmenter > DynImageSurface { |
6 | !include #1024657 // Image Segmenter Parameters |
7 | |
8 | float maxGain = 25f; |
9 | |
10 | transient S sliceID = agiBlue_imageSegmentationSlice(); |
11 | |
12 | // output |
13 | L<Rect> segments; |
14 | |
15 | transient BufferedImage filteredImage; |
16 | transient JLabel lblFound; |
17 | transient ReliableSingleThread rst = dm_rst(this, r segmentIt); |
18 | |
19 | visualize { |
20 | JSlider slider = main.onChange(jLiveValueSlider(dm_fieldLiveValue('contrastThreshold)), rst); |
21 | JSpinner spinner = main.onChange(dm_spinner gridSize(2, 99), rst); |
22 | JSpinner filterSpinner = main.onChange(dm_spinner filterLevel(0, 10), rst); |
23 | |
24 | afterwards { |
25 | imageSurfaceOnHover(imageSurface, voidfunc(Pt p) { |
26 | RGB rgb = bufferedImage_getRGB(filteredImage, p); |
27 | setToolTip(imageSurface, rgb == null ? null : "Color: " + rgb + "/" + rgbToIntTriple(rgb) + ", position: " + p |
28 | + (imageSurface.getSelection() == null ? "" : ", selection: " + toRect(imageSurface.getSelection()))); |
29 | }); |
30 | componentPopupMenu_top(imageSurface, voidfunc(JPopupMenu menu) { |
31 | Pt p = imageSurface.pointFromEvent(componentPopupMenu_getEvent()); |
32 | RGB rgb = bufferedImage_getRGB(filteredImage, p); |
33 | if (rgb == null) ret; |
34 | Rect r = smallestRectContaining(segments, p); |
35 | |
36 | addPopupMenuItem(menu, "Pick color", r { |
37 | setField(dc_r := rgb.redInt()); |
38 | setField(dc_g := rgb.greenInt()); |
39 | setField(dc_b := rgb.blueInt()); |
40 | setField(distanceFromColor := true); |
41 | rst.trigger(); |
42 | }); |
43 | |
44 | if (r != null) addPopupMenuItem(menu, "Show segment", r { |
45 | showImage("Segment " + r, cloneClipBufferedImage(getImage(), r)); |
46 | }); |
47 | }); |
48 | updateLblFound(); rst.trigger(); |
49 | } |
50 | ret withCenteredLinesBelow(super.visualize(), |
51 | ll(jCenteredSection(" Preprocessing ", withSideMargin(20, jline( |
52 | withLabel("Filter:", jMinWidth(75, main.onChange(dm_comboBox filter(ll("blur", "min", "max")), rst))), |
53 | filterSpinner, |
54 | main.onChange(dm_checkBox("Distance from color:", 'distanceFromColor), rst), |
55 | withLabel("R:", main.onChange(dm_spinner dc_r(0, 255), rst)), |
56 | withLabel("G:", main.onChange(dm_spinner dc_g(0, 255), rst)), |
57 | withLabel("B:", main.onChange(dm_spinner dc_b(0, 255), rst)), |
58 | withLabel("Gain:", main.onChange(jMinWidth(100, jLiveValueSliderZeroToX(maxGain, dm_fieldLiveValue('dc_gain))), rst)))))), |
59 | ll( |
60 | jVerticalCenter(jThreadedButton("Screenshot", rThread { setImage(dm_shootScreenHidingOS()); /*rst.trigger();*/ })), |
61 | jCenteredSection(" Segmenting ", withSideMargin(20, jline( |
62 | withLabel("Contrast Threshold:", jMinWidth(100, slider)), |
63 | withLabel("Grid size:", spinner), |
64 | jbutton("Segment", rst)))), |
65 | jCenteredSection(" Result ", withSideMargin(20, lblFound = jboldlabel(" "))), |
66 | jVerticalCenter(jPopDownButton_noText( |
67 | "Show segments", rThread showSegments, |
68 | "Publish result...", rThread publish, |
69 | "---", null, |
70 | "Load segmenter...", rThread loadSegmenter, |
71 | "Paste segmenter from clipboard", rThread pasteSegmenter, |
72 | "Revert to default settings", rThread loadDefaultSegmenter |
73 | )) |
74 | ), |
75 | ll( |
76 | withLabel("Width range:", main.onChange(doubleRangeLiveValueSlider(dm_fieldLiveValue('widthRange)), rst)), |
77 | withLabel("Height range:", main.onChange(doubleRangeLiveValueSlider(dm_fieldLiveValue('heightRange)), rst))), |
78 | ll( |
79 | withLabel("X position:", main.onChange(doubleRangeLiveValueSlider(dm_fieldLiveValue('xRange)), rst)), |
80 | withLabel("Y position:", main.onChange(doubleRangeLiveValueSlider(dm_fieldLiveValue('yRange)), rst)))); |
81 | } |
82 | |
83 | start { |
84 | set zoomToWindowOnSetImage; |
85 | if (!hasImage()) setImage(whiteImage(100, 100)); |
86 | dm_vmBus_onMessage('newClipboardContents, voidfunc(O o) { |
87 | if (o cast BufferedImage) thread { setImage(o); } |
88 | }); |
89 | onNewImage = rst; |
90 | } |
91 | |
92 | void segmentIt enter { |
93 | if (!hasImage()) ret; |
94 | new ParameterizedSegmenter segmenter; |
95 | copyFields(module(), segmenter); |
96 | segmenter.image = getImage(); |
97 | segmenter.run(); |
98 | filteredImage = or(segmenter.filteredImage1, getImage()); |
99 | setField(segments := segmenter.segments); |
100 | updateLblFound(); |
101 | imageSurface.imageToDraw = segmenter.filteredImage; |
102 | overlaySelectionsOnImageSurface(imageSurface, segments); |
103 | } |
104 | |
105 | void showSegments { |
106 | L<Rect> segments = this.segments; |
107 | showImage_centered(n2(segments, "segment") + " found", |
108 | mergeBufferedImagesVertically(map(segments, r -> clipBufferedImage(getImage(), r)))); |
109 | } |
110 | |
111 | void updateLblFound { |
112 | setText(lblFound, nSegments(segments) + " found"); |
113 | } |
114 | |
115 | void publish enter { |
116 | SS map = parameters(); |
117 | BufferedImage image = getImage(); |
118 | JTextField tfDesc = jtextfield(), tfSuccess = jtextfield(), |
119 | tfImageCredits = jtextfield(); |
120 | |
121 | showFormTitled("Publish image segmentation result", |
122 | "Image", jImageSurface(scaleImageToWidth(image, 200)), |
123 | "Task description", tfDesc, |
124 | "How successful was the result?", tfSuccess, |
125 | "Image credits (optional)", tfImageCredits, |
126 | "# segments found", l_str(segments), |
127 | "Parameters", jMinHeight(200, disableTextArea(jWordWrapTextArea(pnlToString(mapMinus(map, "segments"))))), |
128 | "NOTE:", jMultiLineLabel("By clicking 'publish', you PUBLISH this image (fair use/public domain)."), |
129 | "", jThreadedButton("Publish", r { |
130 | S desc = gtt(tfDesc), success = gtt(tfSuccess); |
131 | if (empty(desc)) ret with infoBox("Need a description"); |
132 | temp tempInfoBox_noHide("Uploading..."); |
133 | S imageURL = uploadToImageServer(desc, image); |
134 | map.put("Successful?", success); |
135 | map.put("Input image", print(+imageURL)); |
136 | mapPutIfNemptyValue(map, "Image credits", gtt(tfImageCredits)); |
137 | map.put("Segmenter", programID()); |
138 | map.put("_class", "Segmenter preset"); |
139 | new L<Map> toPost; |
140 | S name = agiBlue_createUnusedNumberedPage(sliceID, desc + " #"); |
141 | for (S key, value : map) |
142 | toPost.add(litmap(q := name, +key, +value)); |
143 | agiBot_postMulti(keyPairForProgram(), toPost, slice := sliceID); |
144 | infoBox("Segmentation result uploaded!"); |
145 | openURLInBrowser(agiBlue_linkForPhrase(name, slice := sliceID)); |
146 | disposePIFrame(heldButton()); |
147 | }) |
148 | ); |
149 | } |
150 | |
151 | Set<S> parameterFields() { ret nonStaticNonTransientFields_withoutSuperclasses(this); } |
152 | |
153 | SS parameters() { |
154 | ret mapToValues_treeMap(parameterFields(), field -> struct(get(module(), field))); |
155 | } |
156 | |
157 | void loadSegmenter enter { |
158 | JComboBox cb = jComboBox(agiBlue_segmenterPresetNames()); |
159 | |
160 | showFormTitled("Load segmenter preset", |
161 | "Preset", cb, r { |
162 | ParameterizedSegmenter seg = parameterizedSegmenterFromAGIBlue(getText(cb)); |
163 | if (seg == null) infoBox("Segmenter not found: " + name); |
164 | loadSegmenter(seg); |
165 | }); |
166 | } |
167 | |
168 | void loadSegmenter(ParameterizedSegmenter seg) enter { |
169 | if (seg == null) ret; |
170 | copyFields(seg, module(), parameterFields()); |
171 | change(); rst.trigger(); |
172 | infoBox("Segmenter loaded"); |
173 | } |
174 | |
175 | void loadDefaultSegmenter { |
176 | loadSegmenter(new ParameterizedSegmenter); |
177 | } |
178 | |
179 | void pasteSegmenter enter { |
180 | loadSegmenter((ParameterizedSegmenter) unstructure(textFromClipboard())); |
181 | } |
182 | } |
Began life as a copy of #1024568
download show line numbers debug dex old transpilations
Travelled to 7 computer(s): bhatertpkbcr, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tvejysmllsmz, vouqrxazstgt, xrpafgyirdlv
No comments. add comment
Snippet ID: | #1024655 |
Snippet name: | Image Segmenter v4 [best version, with min filter] |
Eternal ID of this version: | #1024655/44 |
Text MD5: | 2e8ff4500f32b2e2f0cd92781ddd68c9 |
Transpilation MD5: | 46aaea46bfb844b46c196cf85d56095e |
Author: | stefan |
Category: | javax / image analysis |
Type: | JavaX source code (Dynamic Module) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2021-09-12 03:05:33 |
Source code size: | 7599 bytes / 182 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 383 / 14432 |
Version history: | 43 change(s) |
Referenced in: | [show references] |