Skip to content

Commit a6378bd

Browse files
authored
feat: Merge pull request #232 from UniversalDataTool/improved-pixel-segmentation
improved pixel segmentation with web workers and configurable quality
2 parents 2d3a18d + d41b4c8 commit a6378bd

File tree

4 files changed

+80
-31
lines changed

4 files changed

+80
-31
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@
106106
"react-hotkeys": "^2.0.0",
107107
"react-i18next": "^11.4.0",
108108
"react-icons": "^3.9.0",
109-
"react-image-annotate": "^1.2.7",
109+
"react-image-annotate": "^1.3.1",
110110
"react-material-workspace-layout": "^0.1.6",
111111
"react-scripts": "^3.4.1",
112112
"react-select": "^3.0.8",

src/components/ConfigureImagePixelSegmentation/index.js

Lines changed: 47 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
11
// @flow
22
import React, { useMemo } from "react"
33
import Survey from "material-survey/components/Survey"
4-
import { setIn } from "seamless-immutable"
54

6-
const autoSegmentationOptions = {
7-
simple: { type: "simple" },
8-
autoseg: { type: "autoseg" },
5+
const maxClusterPresets = {
6+
low: 1000,
7+
medium: 8000,
8+
high: 64000,
99
}
10+
const maxClusterPresetsRev = Object.entries(maxClusterPresets).reduce(
11+
(acc, curr) => {
12+
acc[curr[1]] = curr[0]
13+
return acc
14+
},
15+
{}
16+
)
1017

1118
const form = {
1219
questions: [
@@ -32,11 +39,28 @@ const form = {
3239
type: "text",
3340
},
3441
{
35-
name: "autoseg",
42+
name: "autosegMode",
3643
type: "dropdown",
3744
title: "Automatic Segmentation Engine",
3845
choices: ["simple", "autoseg"],
3946
},
47+
{
48+
name: "autosegPreset",
49+
type: "dropdown",
50+
visibleIf: "{autosegMode}='autoseg'",
51+
title: "Super Pixel Quality",
52+
choices: ["low", "medium", "high", "custom"],
53+
},
54+
{
55+
name: "autosegMaxClusters",
56+
type: "slider",
57+
visibleIf: "{autosegPreset}='custom'",
58+
title: "Total Super Pixels",
59+
min: 10,
60+
max: 100000,
61+
step: 10,
62+
defaultValue: 1000,
63+
},
4064
],
4165
}
4266

@@ -48,7 +72,12 @@ export default ({ iface, onChange }) => {
4872
(iface.labels || []).map((a) =>
4973
typeof a === "string" ? { id: a, description: a } : a
5074
) || [],
51-
autoseg: iface.autoSegmentationEngine?.type,
75+
autosegMode: iface.autoSegmentationEngine?.mode,
76+
autosegPreset:
77+
maxClusterPresetsRev[
78+
iface.autoSegmentationEngine?.maxClusters || 1000
79+
] || "custom",
80+
autosegMaxClusters: iface.autoSegmentationEngine?.maxClusters || 1000,
5281
}),
5382
[iface]
5483
)
@@ -59,17 +88,18 @@ export default ({ iface, onChange }) => {
5988
variant="flat"
6089
defaultAnswers={defaultAnswers}
6190
onQuestionChange={(questionId, newValue, answers) => {
62-
if (questionId === "autoseg") {
63-
onChange(
64-
setIn(
65-
iface,
66-
["autoSegmentationEngine"],
67-
autoSegmentationOptions[newValue]
68-
)
69-
)
70-
} else {
71-
onChange(setIn(iface, [questionId], newValue))
72-
}
91+
onChange({
92+
...iface,
93+
description: answers.description,
94+
labels: answers.labels,
95+
autoSegmentationEngine: {
96+
mode: answers.autosegMode,
97+
maxClusters:
98+
answers.autosegPreset === "custom"
99+
? answers.autosegMaxClusters
100+
: maxClusterPresets[answers.autosegPreset],
101+
},
102+
})
73103
}}
74104
form={form}
75105
/>

src/components/ConfigureInterface/index.js

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// @flow weak
22

3-
import React, { useState, useEffect } from "react"
3+
import React, { useState, useEffect, useReducer } from "react"
44
import { styled } from "@material-ui/core/styles"
55
import templates, { templateMap } from "../StartingPage/templates"
66
import Button from "@material-ui/core/Button"
@@ -134,6 +134,16 @@ export const ConfigureInterface = ({
134134
const iface = dataset.interface
135135
const [previewChangedTime, changePreviewChangedTime] = useState(0)
136136
const [previewLoading, changePreviewLoading] = useState(false)
137+
const [previewVersion, incPreviewVersion] = useReducer(
138+
(state) => state + 1,
139+
0
140+
)
141+
const [previewDataset, setPreviewDataset] = useState({
142+
interface: iface,
143+
samples: dataset?.samples?.length
144+
? [dataset.samples[0]]
145+
: [templateMap[iface.type].dataset.samples[0]],
146+
})
137147
const onChange = useEventCallback((...args) => {
138148
changePreviewChangedTime(Date.now())
139149
onChangeProp(...args)
@@ -143,10 +153,18 @@ export const ConfigureInterface = ({
143153
changePreviewLoading(true)
144154
let timeout = setTimeout(() => {
145155
changePreviewLoading(false)
156+
incPreviewVersion()
157+
setPreviewDataset({
158+
interface: iface,
159+
samples: dataset?.samples?.length
160+
? [dataset.samples[0]]
161+
: [templateMap[iface.type].dataset.samples[0]],
162+
})
146163
}, 1000)
147164
return () => {
148165
clearTimeout(timeout)
149166
}
167+
// eslint-disable-next-line
150168
}, [previewChangedTime])
151169

152170
if (!iface.type || iface.type === "empty") {
@@ -192,18 +210,13 @@ export const ConfigureInterface = ({
192210
<PreviewContent
193211
style={{ opacity: previewLoading ? 0.5 : 1, height: "100%" }}
194212
>
195-
<LabelErrorBoundary key={previewChangedTime}>
213+
<LabelErrorBoundary key={previewVersion}>
196214
<UniversalDataViewer
197-
key={previewChangedTime}
215+
key={previewVersion}
198216
height={600}
199217
onExit={noop}
200218
onSaveTaskOutputItem={noop}
201-
dataset={{
202-
interface: iface,
203-
samples: dataset?.samples?.length
204-
? [dataset.samples[0]]
205-
: [templateMap[iface.type].dataset.samples[0]],
206-
}}
219+
dataset={previewDataset}
207220
/>
208221
</LabelErrorBoundary>
209222
</PreviewContent>

yarn.lock

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4943,6 +4943,11 @@ autoprefixer@^9.6.1, autoprefixer@^9.7.2:
49434943
postcss "^7.0.32"
49444944
postcss-value-parser "^4.1.0"
49454945

4946+
autoseg@^0.0.8:
4947+
version "0.0.8"
4948+
resolved "https://registry.yarnpkg.com/autoseg/-/autoseg-0.0.8.tgz#30e900afd41db964c5cdaf93f322211548444620"
4949+
integrity sha512-Kf6qQXiaxe+J1DrNP4dfWH92tRZ9MMwaO06TtzfKxBR/wtlC745aTP3YmKAP/a2ikpIfPKz9Hf6yR2Y7SeVagg==
4950+
49464951
ava@^3.7.0:
49474952
version "3.10.1"
49484953
resolved "https://registry.yarnpkg.com/ava/-/ava-3.10.1.tgz#a4e68b1a2bb248fa0d96529d23dd83f57082e944"
@@ -16143,17 +16148,18 @@ react-icons@^3.9.0:
1614316148
dependencies:
1614416149
camelcase "^5.0.0"
1614516150

16146-
react-image-annotate@^1.2.7:
16147-
version "1.2.7"
16148-
resolved "https://registry.yarnpkg.com/react-image-annotate/-/react-image-annotate-1.2.7.tgz#e9f050640d8a55474b3b16f8fe9ea98fe324d4e0"
16149-
integrity sha512-JZGsaTG6AET0IFGZ408/uzWYDtT71SUpG1ghUN+xzXzmP9MZV+oWyET4i7sXBqZA/5hcWghzQrG1TWp0FAjvaw==
16151+
react-image-annotate@^1.3.1:
16152+
version "1.3.1"
16153+
resolved "https://registry.yarnpkg.com/react-image-annotate/-/react-image-annotate-1.3.1.tgz#721353966c7a25a7c7d832262a50f9488ab78808"
16154+
integrity sha512-d3sErEQPmSIjq1ib89PEnIJa6T7eTgpen/fVHBFEJ9e5QyFAF6LQpnAS6s8jZ/wXtBLYTwstavYe2yNmY8kyPw==
1615016155
dependencies:
1615116156
"@fortawesome/fontawesome-svg-core" "^1.2.12"
1615216157
"@fortawesome/free-solid-svg-icons" "^5.6.3"
1615316158
"@fortawesome/react-fontawesome" "^0.1.3"
1615416159
"@material-ui/core" "^4.6.0"
1615516160
"@material-ui/icons" "^4.9.1"
1615616161
"@semantic-release/git" "^9.0.0"
16162+
autoseg "^0.0.8"
1615716163
color-alpha "^1.0.4"
1615816164
get-image-data "^3.0.1"
1615916165
material-survey "^1.0.34"

0 commit comments

Comments
 (0)