Skip to content

Commit d5c2adb

Browse files
authored
fix: Merge pull request #202 from UniversalDataTool/feat/full-segmentation
Updates and improvements to full segmentation
2 parents 69b39d9 + dd6e274 commit d5c2adb

File tree

6 files changed

+171
-47
lines changed

6 files changed

+171
-47
lines changed

package-lock.json

Lines changed: 31 additions & 31 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@
103103
"react-github-btn": "^1.2.0",
104104
"react-hotkeys": "^2.0.0",
105105
"react-icons": "^3.9.0",
106-
"react-image-annotate": "^1.2.1",
106+
"react-image-annotate": "^1.2.7",
107107
"react-scripts": "^3.4.1",
108108
"react-select": "^3.0.8",
109109
"rfc6902": "^3.0.4",

src/components/ConfigureImagePixelSegmentation/index.js

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ import React, { useMemo } from "react"
33
import Survey from "material-survey/components/Survey"
44
import { setIn } from "seamless-immutable"
55

6+
const autoSegmentationOptions = {
7+
simple: { type: "simple" },
8+
autoseg: { type: "autoseg" },
9+
}
10+
611
const form = {
712
questions: [
813
{
@@ -26,6 +31,12 @@ const form = {
2631
description: "Any instructions or notes in markdown.",
2732
type: "text",
2833
},
34+
{
35+
name: "autoseg",
36+
type: "dropdown",
37+
title: "Automatic Segmentation Engine",
38+
choices: ["simple", "autoseg"],
39+
},
2940
],
3041
}
3142

@@ -37,18 +48,31 @@ export default ({ iface, onChange }) => {
3748
(iface.labels || []).map((a) =>
3849
typeof a === "string" ? { id: a, description: a } : a
3950
) || [],
51+
autoseg: iface.autoSegmentationEngine?.type,
4052
}),
4153
[iface]
4254
)
4355
return (
44-
<Survey
45-
noActions
46-
variant="flat"
47-
defaultAnswers={defaultAnswers}
48-
onQuestionChange={(questionId, newValue, answers) => {
49-
onChange(setIn(iface, [questionId], newValue))
50-
}}
51-
form={form}
52-
/>
56+
<>
57+
<Survey
58+
noActions
59+
variant="flat"
60+
defaultAnswers={defaultAnswers}
61+
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+
}
73+
}}
74+
form={form}
75+
/>
76+
</>
5377
)
5478
}

src/components/ImageSegmentation/index.js

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010

1111
const regionTypeToTool = {
1212
"bounding-box": "create-box",
13-
polygon: "create-polygon",
13+
polygon: ["create-polygon", "create-expanding-line"],
1414
point: "create-point",
1515
}
1616

@@ -115,17 +115,20 @@ export default ({
115115
() =>
116116
["select"].concat(
117117
regionTypesAllowed
118-
.map((rt) => regionTypeToTool[rt])
118+
.flatMap((rt) => regionTypeToTool[rt])
119119
.filter(Boolean)
120120
),
121121
[regionTypesAllowed]
122122
)
123123

124124
const allowedArea = useMemo(() => {
125-
if (!iface.allowedArea) return undefined
126-
const { x, y, width: w, height: h } = iface.allowedArea
125+
if (!iface.allowedArea && !samples[selectedIndex].allowedArea)
126+
return undefined
127+
const { x, y, width: w, height: h } =
128+
samples[selectedIndex].allowedArea || iface.allowedArea
127129
return { x, y, w, h }
128-
}, [iface.allowedArea])
130+
// eslint-disable-next-line
131+
}, [iface.allowedArea, samples[selectedIndex].allowedArea])
129132

130133
return (
131134
<div
@@ -140,9 +143,10 @@ export default ({
140143
fullImageSegmentationMode={isPixel}
141144
selectedImage={samples[selectedIndex].imageUrl}
142145
taskDescription={iface.description}
143-
allowedArea={allowedArea}
144146
showTags={showTags}
145147
{...labelProps}
148+
autoSegmentationOptions={iface.autoSegmentationEngine}
149+
allowedArea={allowedArea}
146150
onNextImage={onNextImage}
147151
onPrevImage={onPrevImage}
148152
enabledTools={enabledTools}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
// @flow weak
2+
3+
import React, { useState } from "react"
4+
import SimpleDialog from "../SimpleDialog"
5+
import { styled } from "@material-ui/core/styles"
6+
import { setIn } from "seamless-immutable"
7+
import Box from "@material-ui/core/Box"
8+
import Select from "react-select"
9+
import range from "lodash/range"
10+
11+
const ErrorBox = styled("pre")({
12+
color: "red",
13+
whiteSpace: "prewrap",
14+
fontSize: 11,
15+
})
16+
17+
const splitOptions = [
18+
{ label: "2x2", value: "2x2" },
19+
{ label: "3x3", value: "3x3" },
20+
{ label: "4x4", value: "4x4" },
21+
{ label: "3x4", value: "3x4" },
22+
]
23+
24+
export default ({ open, onChangeDataset, onClose, dataset }) => {
25+
const [errors, setErrors] = useState("")
26+
const [splitType, setSplitType] = useState(splitOptions[0].value)
27+
return (
28+
<SimpleDialog
29+
open={open}
30+
onClose={onClose}
31+
title="Convert Image Samples into Segments"
32+
actions={[
33+
{
34+
text: "Convert Image Samples into Segments",
35+
onClick: async () => {
36+
const [w, h] = splitType.split("x").map((v) => parseInt(v))
37+
38+
try {
39+
onChangeDataset(
40+
setIn(
41+
dataset,
42+
["samples"],
43+
range(h).flatMap((y) =>
44+
range(w).flatMap((x) =>
45+
dataset.samples.map((s) => {
46+
return setIn(s, ["allowedArea"], {
47+
x: x / w,
48+
y: y / h,
49+
width: 1 / w,
50+
height: 1 / h,
51+
})
52+
})
53+
)
54+
)
55+
)
56+
)
57+
onClose()
58+
} catch (e) {
59+
setErrors(e.toString())
60+
}
61+
},
62+
},
63+
]}
64+
>
65+
This transformation will multiply the number of image samples you have,
66+
splitting each individual image into segments. The image is not processed
67+
and clipped, but rather an "allowedArea" property is placed on the sample
68+
which limits the labeling to a section of the image. This is useful when
69+
trying to reduce the amount of work per image sample.
70+
<Box padding={4}>
71+
<Select
72+
defaultValue={splitOptions[0]}
73+
options={splitOptions}
74+
onChange={({ value }) => setSplitType(value)}
75+
/>
76+
</Box>
77+
{errors && <ErrorBox>{errors}</ErrorBox>}
78+
</SimpleDialog>
79+
)
80+
}

src/components/TransformPage/index.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,12 @@ import CollectionsIcon from "@material-ui/icons/Collections"
1616
import TransformVideoFramesToImagesDialog from "../TransformVideoFramesToImagesDialog"
1717
import usePosthog from "../../utils/use-posthog"
1818
import TransformLocalFilesToWebURLs from "../TransformLocalFilesToWebURLs"
19+
import TransformImageSamplesIntoSegmentsDialog from "../TransformImageSamplesIntoSegmentsDialog"
1920

2021
import ComputerIcon from "@material-ui/icons/Computer"
2122
import LanguageIcon from "@material-ui/icons/Language"
23+
import CheckBoxOutlineBlankIcon from "@material-ui/icons/CheckBoxOutlineBlank"
24+
import GridOnIcon from "@material-ui/icons/GridOn"
2225

2326
const ButtonBase = styled(MuiButton)({
2427
width: 240,
@@ -139,6 +142,13 @@ export default ({ dataset, onChangeDataset }) => {
139142
>
140143
Convert Video Frames to Images
141144
</Button>
145+
<Button
146+
dialog="split-image-samples-into-segments"
147+
Icon1={CheckBoxOutlineBlankIcon}
148+
Icon2={GridOnIcon}
149+
>
150+
Split Image Samples into Segments
151+
</Button>
142152
<TransformVideoKeyframesDialog
143153
open={selectedDialog === "convert-keyframes-to-samples"}
144154
onClose={closeDialog}
@@ -169,6 +179,12 @@ export default ({ dataset, onChangeDataset }) => {
169179
desktopOnly
170180
onChangeDataset={onChangeDataset}
171181
></TransformVideoFramesToImagesDialog>
182+
<TransformImageSamplesIntoSegmentsDialog
183+
dataset={dataset}
184+
open={selectedDialog === "split-image-samples-into-segments"}
185+
onClose={closeDialog}
186+
onChangeDataset={onChangeDataset}
187+
></TransformImageSamplesIntoSegmentsDialog>
172188
</div>
173189
</SelectDialogContext.Provider>
174190
)

0 commit comments

Comments
 (0)