Skip to content

Commit a1fdaa6

Browse files
committed
expanding line tool, aesthetic improvements, perf improvements, wasd
mode
1 parent d86aba4 commit a1fdaa6

File tree

22 files changed

+518
-253
lines changed

22 files changed

+518
-253
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
"@material-ui/core": "^4.6.0",
99
"@material-ui/icons": "^4.9.1",
1010
"@semantic-release/git": "^9.0.0",
11+
"color-alpha": "^1.0.4",
1112
"get-image-data": "^3.0.1",
1213
"material-survey": "^1.0.34",
1314
"mmgc1-cpp": "^1.0.26",

src/Annotator/index.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ export const Annotator = ({
5757
"create-box",
5858
"create-polygon",
5959
"create-expanding-line",
60+
"show-mask",
6061
],
6162
selectedTool = "select",
6263
regionTagList = [],
@@ -71,7 +72,6 @@ export const Annotator = ({
7172
videoTime = 0,
7273
videoName,
7374
onExit,
74-
mask,
7575
onNextImage,
7676
onPrevImage,
7777
}: Props) => {
@@ -92,8 +92,10 @@ export const Annotator = ({
9292
showPointDistances,
9393
pointDistancePrecision,
9494
selectedTool,
95+
fullImageSegmentationMode: fullImageSegmentationMode,
9596
mode: null,
9697
taskDescription,
98+
showMask: true,
9799
labelImages: imageClsList.length > 0 || imageTagList.length > 0,
98100
regionClsList,
99101
regionTagList,
@@ -144,9 +146,6 @@ export const Annotator = ({
144146
RegionEditLabel={RegionEditLabel}
145147
alwaysShowNextButton={Boolean(onNextImage)}
146148
alwaysShowPrevButton={Boolean(onPrevImage)}
147-
mask={mask}
148-
fullImageSegmentationMode={fullImageSegmentationMode}
149-
// maskVersion={maskVersion}
150149
state={state}
151150
dispatch={dispatch}
152151
/>
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// @flow
2+
3+
function clamp(num, min, max) {
4+
return num <= min ? min : num >= max ? max : num
5+
}
6+
7+
export default (expandingLine) => {
8+
console.log({ expandingLine })
9+
const expandingWidth = expandingLine.expandingWidth || 0.005
10+
const pointPairs = expandingLine.points.map(({ x, y, angle, width }, i) => {
11+
if (!angle) {
12+
const n =
13+
expandingLine.points[clamp(i + 1, 0, expandingLine.points.length - 1)]
14+
const p =
15+
expandingLine.points[clamp(i - 1, 0, expandingLine.points.length - 1)]
16+
angle = Math.atan2(p.x - n.x, p.y - n.y) + Math.PI / 2
17+
}
18+
const dx = (Math.sin(angle) * (width || expandingWidth)) / 2
19+
const dy = (Math.cos(angle) * (width || expandingWidth)) / 2
20+
return [
21+
{ x: x + dx, y: y + dy },
22+
{ x: x - dx, y: y - dy },
23+
]
24+
})
25+
const firstSection = pointPairs.map(([p1, p2]) => p1)
26+
const secondSection = pointPairs.map(([p1, p2]) => p2).asMutable()
27+
secondSection.reverse()
28+
29+
const newPoints = firstSection.concat(secondSection).map(({ x, y }) => [x, y])
30+
31+
return {
32+
...expandingLine,
33+
type: "polygon",
34+
open: false,
35+
points: newPoints,
36+
unfinished: undefined,
37+
candidatePoint: undefined,
38+
}
39+
40+
// let { expandingWidth = 0.005, points } = region
41+
// expandingWidth = points.slice(-1)[0].width || expandingWidth
42+
// const lastPoint = points.slice(-1)[0]
43+
// return (
44+
// <>
45+
// <polygon
46+
// points={
47+
// .map((p) => `${p.x * iw} ${p.y * ih}`)
48+
// .join(" ")}
49+
// return {
50+
// ...expandingLine,
51+
// unfinished: undefined,
52+
// candidatePoint: undefined,
53+
// }
54+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// @flow
2+
3+
export default (pointsWithAngles) => {
4+
// Adjacent angles should not have an angular distance of more than Math.PI
5+
return pointsWithAngles
6+
}

src/Annotator/reducers/general-reducer.js

Lines changed: 148 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import isEqual from "lodash/isEqual"
77
import getActiveImage from "./get-active-image"
88
import { saveToHistory } from "./history-handler.js"
99
import colors from "../../colors"
10+
import fixTwisted from "./fix-twisted"
11+
import convertExpandingLineToPolygon from "./convert-expanding-line-to-polygon"
1012

1113
const getRandomId = () => Math.random().toString().split(".")[1]
1214

@@ -199,6 +201,7 @@ export default (state: MainLayoutState, action: Action) => {
199201
const { x, y } = action
200202
if (!state.mode) return state
201203
if (!activeImage) return state
204+
const { mouseDownAt } = state
202205
switch (state.mode.mode) {
203206
case "MOVE_POLYGON_POINT": {
204207
const { pointIndex, regionId } = state.mode
@@ -283,13 +286,65 @@ export default (state: MainLayoutState, action: Action) => {
283286
[x, y]
284287
)
285288
}
289+
case "DRAW_EXPANDING_LINE": {
290+
const { regionId } = state.mode
291+
const [expandingLine, regionIndex] = getRegion(regionId)
292+
if (!expandingLine) return state
293+
const isMouseDown = Boolean(state.mouseDownAt)
294+
if (isMouseDown) {
295+
// If the mouse is down, set width/angle
296+
const lastPoint = expandingLine.points.slice(-1)[0]
297+
const mouseDistFromLastPoint = Math.sqrt(
298+
(lastPoint.x - x) ** 2 + (lastPoint.y - y) ** 2
299+
)
300+
if (mouseDistFromLastPoint < 0.002 && !lastPoint.width) return state
301+
302+
const newState = setIn(
303+
state,
304+
[...pathToActiveImage, "regions", regionIndex, "points"],
305+
expandingLine.points.slice(0, -1).concat([
306+
{
307+
...lastPoint,
308+
width: mouseDistFromLastPoint * 2,
309+
angle: Math.atan2(lastPoint.x - x, lastPoint.y - y),
310+
},
311+
])
312+
)
313+
return newState
314+
} else {
315+
// If mouse is up, move the next candidate point
316+
return setIn(
317+
state,
318+
[...pathToActiveImage, "regions", regionIndex],
319+
{
320+
...expandingLine,
321+
candidatePoint: { x, y },
322+
}
323+
)
324+
}
325+
326+
return state
327+
}
328+
case "SET_EXPANDING_LINE_WIDTH": {
329+
const { regionId } = state.mode
330+
const [expandingLine, regionIndex] = getRegion(regionId)
331+
if (!expandingLine) return state
332+
const lastPoint = expandingLine.points.slice(-1)[0]
333+
const { mouseDownAt } = state
334+
return setIn(
335+
state,
336+
[...pathToActiveImage, "regions", regionIndex, "expandingWidth"],
337+
Math.sqrt((lastPoint.x - x) ** 2 + (lastPoint.y - y) ** 2)
338+
)
339+
}
286340
default:
287341
return state
288342
}
289343
}
290344
case "MOUSE_DOWN": {
291345
if (!activeImage) return state
292346
const { x, y } = action
347+
state = setIn(state, ["mouseDownAt"], { x, y })
293348

294349
if (state.allowedArea) {
295350
// TODO clamp x/y instead of giving up
@@ -314,7 +369,49 @@ export default (state: MainLayoutState, action: Action) => {
314369
case "DRAW_EXPANDING_LINE": {
315370
const [expandingLine, regionIndex] = getRegion(state.mode.regionId)
316371
if (!expandingLine) break
372+
const lastPoint = expandingLine.points.slice(-1)[0]
373+
if (
374+
expandingLine.points.length > 1 &&
375+
Math.sqrt((lastPoint.x - x) ** 2 + (lastPoint.y - y) ** 2) < 0.002
376+
) {
377+
if (!lastPoint.width) {
378+
return setIn(state, ["mode"], {
379+
mode: "SET_EXPANDING_LINE_WIDTH",
380+
regionId: state.mode.regionId,
381+
})
382+
} else {
383+
return state
384+
.setIn(
385+
[...pathToActiveImage, "regions", regionIndex],
386+
convertExpandingLineToPolygon(expandingLine)
387+
)
388+
.setIn(["mode"], null)
389+
}
390+
}
391+
392+
// Create new point
393+
return setIn(
394+
state,
395+
[...pathToActiveImage, "regions", regionIndex, "points"],
396+
expandingLine.points.concat([{ x, y, angle: null, width: null }])
397+
)
398+
}
399+
case "SET_EXPANDING_LINE_WIDTH": {
400+
const [expandingLine, regionIndex] = getRegion(state.mode.regionId)
401+
if (!expandingLine) break
402+
const { expandingWidth } = expandingLine
317403
return state
404+
.setIn(
405+
[...pathToActiveImage, "regions", regionIndex],
406+
convertExpandingLineToPolygon({
407+
...expandingLine,
408+
points: expandingLine.points.map((p) =>
409+
p.width ? p : { ...p, width: expandingWidth }
410+
),
411+
expandingWidth: undefined,
412+
})
413+
)
414+
.setIn(["mode"], null)
318415
}
319416
default:
320417
break
@@ -424,13 +521,15 @@ export default (state: MainLayoutState, action: Action) => {
424521
}
425522
case "MOUSE_UP": {
426523
const { x, y } = action
524+
const { mouseDownAt = { x, y } } = state
427525
if (!state.mode) return state
526+
state = setIn(state, ["mouseDownAt"], null)
428527
switch (state.mode.mode) {
429528
case "RESIZE_BOX": {
430529
if (state.mode.isNew) {
431530
if (
432-
Math.abs(state.mode.original.x - x) < 0.01 &&
433-
Math.abs(state.mode.original.y - y) < 0.01
531+
Math.abs(state.mode.original.x - x) < 0.002 &&
532+
Math.abs(state.mode.original.y - y) < 0.002
434533
) {
435534
return setIn(
436535
modifyRegion(state.mode.regionId, null),
@@ -450,6 +549,50 @@ export default (state: MainLayoutState, action: Action) => {
450549
case "MOVE_POLYGON_POINT": {
451550
return { ...state, mode: null }
452551
}
552+
case "CREATE_POINT_LINE": {
553+
return state
554+
}
555+
case "DRAW_EXPANDING_LINE": {
556+
const [expandingLine, regionIndex] = getRegion(state.mode.regionId)
557+
if (!expandingLine) return state
558+
let newExpandingLine = expandingLine
559+
const lastPoint =
560+
expandingLine.points.length !== 0
561+
? expandingLine.points.slice(-1)[0]
562+
: mouseDownAt
563+
let jointStart
564+
if (expandingLine.points.length > 1) {
565+
jointStart = expandingLine.points.slice(-2)[0]
566+
} else {
567+
jointStart = lastPoint
568+
}
569+
const mouseDistFromLastPoint = Math.sqrt(
570+
(lastPoint.x - x) ** 2 + (lastPoint.y - y) ** 2
571+
)
572+
if (mouseDistFromLastPoint > 0.002) {
573+
// The user is drawing has drawn the width for the last point
574+
const newPoints = [...expandingLine.points]
575+
for (let i = 0; i < newPoints.length - 1; i++) {
576+
if (newPoints[i].width) continue
577+
newPoints[i] = {
578+
...newPoints[i],
579+
width: lastPoint.width,
580+
}
581+
}
582+
newExpandingLine = setIn(
583+
expandingLine,
584+
["points"],
585+
fixTwisted(newPoints)
586+
)
587+
} else {
588+
return state
589+
}
590+
return setIn(
591+
state,
592+
[...pathToActiveImage, "regions", regionIndex],
593+
newExpandingLine
594+
)
595+
}
453596
default:
454597
return state
455598
}
@@ -538,10 +681,12 @@ export default (state: MainLayoutState, action: Action) => {
538681
}
539682
}
540683
case "SELECT_TOOL": {
541-
state = setIn(state, ["mode"], null)
542684
if (action.selectedTool === "show-tags") {
543685
return setIn(state, ["showTags"], !state.showTags)
686+
} else if (action.selectedTool === "show-mask") {
687+
return setIn(state, ["showMask"], !state.showMask)
544688
}
689+
state = setIn(state, ["mode"], null)
545690
return setIn(state, ["selectedTool"], action.selectedTool)
546691
}
547692
case "CANCEL": {

src/HighlightBox/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ export const HighlightBox = ({
5656
pbox: { x: number, y: number, w: number, h: number },
5757
}) => {
5858
const classes = useStyles()
59+
if (!pbox.w || pbox.w === Infinity) return null
60+
if (!pbox.h || pbox.h === Infinity) return null
61+
if (r.unfinished) return null
5962

6063
const styleCoords =
6164
r.type === "point"

src/IconTools/index.js

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
faVectorSquare,
1515
faHandPaper,
1616
faSearch,
17+
faMask,
1718
} from "@fortawesome/free-solid-svg-icons"
1819
import SmallToolButton, { SelectedTool } from "../SmallToolButton"
1920
import { makeStyles } from "@material-ui/core/styles"
@@ -29,10 +30,12 @@ const useStyles = makeStyles({
2930
borderRight: `1px solid ${grey[300]}`,
3031
backgroundColor: grey[100],
3132
},
33+
grow: { flexGrow: 1 },
3234
})
3335

3436
type Props = {
3537
showTags?: boolean,
38+
showMask?: boolean,
3639
enabledTools?: Array<string>,
3740
selectedTool: string,
3841
onClickTool: (string) => any,
@@ -48,6 +51,7 @@ const defaultTools = [
4851

4952
export const IconTools = ({
5053
showTags,
54+
showMask,
5155
selectedTool,
5256
onClickTool,
5357
enabledTools = defaultTools,
@@ -115,11 +119,13 @@ export const IconTools = ({
115119
name="Add Expanding Line"
116120
icon={<FontAwesomeIcon size="xs" fixedWidth icon={faGripLines} />}
117121
/>
118-
{/* <SmallToolButton
119-
id="create-pixel"
120-
name="Add Pixel Region"
121-
icon={<FontAwesomeIcon size="xs" fixedWidth icon={faPaintBrush} />}
122-
/> */}
122+
<SmallToolButton
123+
togglable
124+
selected={showMask}
125+
id="show-mask"
126+
name="Show / Hide Mask"
127+
icon={<FontAwesomeIcon size="xs" fixedWidth icon={faMask} />}
128+
/>
123129
</SelectedTool.Provider>
124130
</div>
125131
)

0 commit comments

Comments
 (0)