@searpent/react-image-annotate 2.0.77 → 2.0.78
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Annotator/exampleImages.js +41 -0
- package/Annotator/examplePhotos.js +6980 -0
- package/Annotator/index.js +417 -0
- package/Annotator/reducers/combine-reducers.js +14 -0
- package/Annotator/reducers/convert-expanding-line-to-polygon.js +73 -0
- package/{src/Annotator → Annotator}/reducers/fix-twisted.js +3 -5
- package/Annotator/reducers/general-reducer.js +1430 -0
- package/Annotator/reducers/get-active-image.js +27 -0
- package/Annotator/reducers/get-implied-video-regions.js +180 -0
- package/Annotator/reducers/history-handler.js +38 -0
- package/Annotator/reducers/image-reducer.js +20 -0
- package/Annotator/reducers/video-reducer.js +88 -0
- package/ClassSelectionMenu/index.js +140 -0
- package/Crosshairs/index.js +53 -0
- package/DebugSidebarBox/index.js +20 -0
- package/DemoSite/Editor.js +194 -0
- package/DemoSite/ErrorBoundaryDialog.js +64 -0
- package/DemoSite/index.js +40 -0
- package/Editor/annotation-plugin/annotation.js +697 -0
- package/Editor/index.js +93 -0
- package/Editor/readOnly.js +123 -0
- package/{src/Editor → Editor}/tools.js +2 -3
- package/Errorer/index.js +11 -0
- package/FullImageSegmentationAnnotator/index.js +7 -0
- package/GroupSelectorSidebarBox/index.js +63 -0
- package/GroupsEditorSidebarBox/index.js +138 -0
- package/HelpSidebarBox/index.js +58 -0
- package/HighlightBox/index.js +102 -0
- package/HistorySidebarBox/index.js +71 -0
- package/ImageCanvas/index.js +441 -0
- package/ImageCanvas/region-tools.js +165 -0
- package/{src/ImageCanvas → ImageCanvas}/styles.js +12 -8
- package/ImageCanvas/use-mouse.js +180 -0
- package/ImageCanvas/use-project-box.js +27 -0
- package/ImageCanvas/use-wasd-mode.js +62 -0
- package/ImageMask/index.js +133 -0
- package/ImageMask/load-image.js +25 -0
- package/ImageSelectorSidebarBox/index.js +60 -0
- package/KeyframeTimeline/get-time-string.js +27 -0
- package/KeyframeTimeline/index.js +233 -0
- package/KeyframesSelectorSidebarBox/index.js +93 -0
- package/LandingPage/index.js +159 -0
- package/Locker/index.js +11 -0
- package/MainLayout/RightSidebarItemsWrapper.js +19 -0
- package/MainLayout/icon-dictionary.js +104 -0
- package/MainLayout/index.js +526 -0
- package/{src/MainLayout → MainLayout}/styles.js +6 -7
- package/MainLayout/types.js +0 -0
- package/MainLayout/use-implied-video-regions.js +13 -0
- package/MetadataEditorSidebarBox/index.js +231 -0
- package/PageSelector/index.js +180 -0
- package/PointDistances/index.js +73 -0
- package/PreventScrollToParents/index.js +51 -0
- package/RegionLabel/index.js +232 -0
- package/{src/RegionLabel → RegionLabel}/styles.js +12 -15
- package/RegionSelectAndTransformBoxes/index.js +169 -0
- package/RegionSelectorSidebarBox/index.js +254 -0
- package/{src/RegionSelectorSidebarBox → RegionSelectorSidebarBox}/styles.js +13 -14
- package/RegionShapes/index.js +294 -0
- package/RegionTags/index.js +144 -0
- package/SettingsDialog/index.js +52 -0
- package/SettingsProvider/index.js +60 -0
- package/Shortcuts/ShortcutField.js +46 -0
- package/Shortcuts/index.js +133 -0
- package/ShortcutsManager/index.js +155 -0
- package/Sidebar/index.js +69 -0
- package/SidebarBoxContainer/index.js +93 -0
- package/SmallToolButton/index.js +42 -0
- package/TagsSidebarBox/index.js +105 -0
- package/TaskDescriptionSidebarBox/index.js +58 -0
- package/Theme/index.js +30 -0
- package/VideoOrImageCanvasBackground/index.js +151 -0
- package/colors.js +14 -0
- package/hooks/use-colors.js +127 -0
- package/hooks/use-event-callback.js +10 -0
- package/hooks/use-exclude-pattern.js +24 -0
- package/hooks/use-load-image.js +26 -0
- package/hooks/use-window-size.js +46 -0
- package/{src/hooks → hooks}/xpattern.js +1 -1
- package/index.js +3 -0
- package/lib.js +3 -0
- package/package.json +1 -1
- package/stories.js +5 -0
- package/utils/blocks-to-article.js +60 -0
- package/{src/utils → utils}/blocks-to-article.test.js +5 -8
- package/{src/utils → utils}/default-locked-until.js +2 -1
- package/{src/utils → utils}/filter-only-unique.js +1 -1
- package/utils/get-from-local-storage.js +7 -0
- package/utils/get-hotkey-help-text.js +9 -0
- package/utils/get-landmarks-with-transform.js +40 -0
- package/utils/photosToImages.js +85 -0
- package/utils/regions-groups.js +28 -0
- package/utils/regions-to-blocks.js +18 -0
- package/utils/saveable-actions-enum.js +3 -0
- package/utils/set-in-local-storage.js +3 -0
- package/utils/sleep.js +7 -0
- package/utils/uuid-to-hash.js +5 -0
- package/.babelrc +0 -6
- package/.env +0 -1
- package/.flowconfig +0 -2
- package/.github/workflows/release-on-master.yml +0 -32
- package/.github/workflows/test.yml +0 -16
- package/.prettierrc +0 -3
- package/.releaserc.js +0 -18
- package/.storybook/addons.js +0 -2
- package/.storybook/config.js +0 -16
- package/LICENSE +0 -21
- package/public/favicon.ico +0 -0
- package/public/index.html +0 -38
- package/src/Annotator/bike-pic.png +0 -0
- package/src/Annotator/bike-pic2.png +0 -0
- package/src/Annotator/dab-keyframes.story.json +0 -1
- package/src/Annotator/exampleImages.js +0 -48
- package/src/Annotator/examplePhotos.js +0 -7603
- package/src/Annotator/index.js +0 -380
- package/src/Annotator/index.story.js +0 -899
- package/src/Annotator/poses.story.js +0 -150
- package/src/Annotator/reducers/combine-reducers.js +0 -7
- package/src/Annotator/reducers/convert-expanding-line-to-polygon.js +0 -53
- package/src/Annotator/reducers/general-reducer.js +0 -1228
- package/src/Annotator/reducers/get-active-image.js +0 -21
- package/src/Annotator/reducers/get-implied-video-regions.js +0 -115
- package/src/Annotator/reducers/history-handler.js +0 -60
- package/src/Annotator/reducers/image-reducer.js +0 -23
- package/src/Annotator/reducers/video-reducer.js +0 -85
- package/src/Annotator/video.story.js +0 -51
- package/src/ClassSelectionMenu/index.js +0 -112
- package/src/Crosshairs/index.js +0 -64
- package/src/DebugSidebarBox/index.js +0 -36
- package/src/DemoSite/Editor.js +0 -235
- package/src/DemoSite/ErrorBoundaryDialog.js +0 -34
- package/src/DemoSite/index.js +0 -41
- package/src/DemoSite/index.story.js +0 -10
- package/src/DemoSite/simple-segmentation-example.json +0 -572
- package/src/Editor/annotation-plugin/annotation.js +0 -546
- package/src/Editor/index.js +0 -50
- package/src/Editor/readOnly.js +0 -31
- package/src/Errorer/index.js +0 -13
- package/src/FullImageSegmentationAnnotator/hard1.story.jpg +0 -0
- package/src/FullImageSegmentationAnnotator/hard2.story.jpg +0 -0
- package/src/FullImageSegmentationAnnotator/hard3.story.jpg +0 -0
- package/src/FullImageSegmentationAnnotator/index.js +0 -7
- package/src/FullImageSegmentationAnnotator/index.story.js +0 -177
- package/src/FullImageSegmentationAnnotator/orange.story.png +0 -0
- package/src/GroupSelectorSidebarBox/index.js +0 -48
- package/src/GroupsEditorSidebarBox/index.js +0 -108
- package/src/HelpSidebarBox/index.js +0 -43
- package/src/HighlightBox/index.js +0 -143
- package/src/HistorySidebarBox/index.js +0 -78
- package/src/ImageCanvas/dancing-man.story.jpg +0 -0
- package/src/ImageCanvas/index.js +0 -515
- package/src/ImageCanvas/index.story.js +0 -314
- package/src/ImageCanvas/mouse_mask.story.png +0 -0
- package/src/ImageCanvas/region-tools.js +0 -171
- package/src/ImageCanvas/seves_desk.story.jpg +0 -0
- package/src/ImageCanvas/use-mouse.js +0 -168
- package/src/ImageCanvas/use-project-box.js +0 -23
- package/src/ImageCanvas/use-wasd-mode.js +0 -50
- package/src/ImageMask/index.js +0 -127
- package/src/ImageMask/load-image.js +0 -32
- package/src/ImageSelectorSidebarBox/index.js +0 -54
- package/src/KeyframeTimeline/get-time-string.js +0 -25
- package/src/KeyframeTimeline/index.js +0 -223
- package/src/KeyframesSelectorSidebarBox/index.js +0 -93
- package/src/LandingPage/content.md +0 -57
- package/src/LandingPage/github-markdown.css +0 -964
- package/src/LandingPage/index.js +0 -147
- package/src/Locker/index.js +0 -13
- package/src/MainLayout/RightSidebarItemsWrapper.js +0 -21
- package/src/MainLayout/icon-dictionary.js +0 -79
- package/src/MainLayout/index.js +0 -564
- package/src/MainLayout/index.story.js +0 -240
- package/src/MainLayout/types.js +0 -171
- package/src/MainLayout/use-implied-video-regions.js +0 -17
- package/src/MetadataEditorSidebarBox/index.js +0 -160
- package/src/PageSelector/index.js +0 -159
- package/src/PointDistances/index.js +0 -90
- package/src/PreventScrollToParents/index.js +0 -48
- package/src/PreventScrollToParents/index.story.js +0 -23
- package/src/RegionLabel/index.js +0 -236
- package/src/RegionSelectAndTransformBoxes/index.js +0 -236
- package/src/RegionSelectorSidebarBox/index.js +0 -220
- package/src/RegionShapes/index.js +0 -254
- package/src/RegionTags/index.js +0 -136
- package/src/SettingsDialog/index.js +0 -58
- package/src/SettingsProvider/index.js +0 -57
- package/src/Shortcuts/ShortcutField.js +0 -44
- package/src/Shortcuts/index.js +0 -129
- package/src/ShortcutsManager/index.js +0 -162
- package/src/Sidebar/index.js +0 -117
- package/src/SidebarBoxContainer/index.js +0 -93
- package/src/SmallToolButton/index.js +0 -57
- package/src/TagsSidebarBox/index.js +0 -93
- package/src/TaskDescriptionSidebarBox/index.js +0 -43
- package/src/Theme/index.js +0 -36
- package/src/VideoOrImageCanvasBackground/index.js +0 -170
- package/src/colors.js +0 -32
- package/src/hooks/use-colors.js +0 -95
- package/src/hooks/use-event-callback.js +0 -11
- package/src/hooks/use-exclude-pattern.js +0 -27
- package/src/hooks/use-load-image.js +0 -21
- package/src/hooks/use-window-size.js +0 -46
- package/src/hooks/xpattern.png +0 -0
- package/src/index.js +0 -18
- package/src/lib.js +0 -7
- package/src/screenshot.png +0 -0
- package/src/site.css +0 -5
- package/src/stories.js +0 -2
- package/src/utils/blocks-to-article.js +0 -61
- package/src/utils/get-from-local-storage.js +0 -7
- package/src/utils/get-hotkey-help-text.js +0 -11
- package/src/utils/get-landmarks-with-transform.js +0 -23
- package/src/utils/photosToImages.js +0 -67
- package/src/utils/regions-groups.js +0 -19
- package/src/utils/regions-to-blocks.js +0 -16
- package/src/utils/saveable-actions-enum.js +0 -5
- package/src/utils/set-in-local-storage.js +0 -6
- package/src/utils/sleep.js +0 -3
- package/src/utils/uuid-to-hash.js +0 -5
- /package/{src/Editor → Editor}/annotation-plugin/annotation.css +0 -0
- /package/{src/Errorer → Errorer}/errorer.css +0 -0
- /package/{src/Locker → Locker}/locker.css +0 -0
- /package/{src/PageSelector → PageSelector}/page-selector.css +0 -0
- /package/{src/utils → utils}/next-group-id.js +0 -0
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { getIn } from "seamless-immutable"
|
|
2
|
-
|
|
3
|
-
export default (state) => {
|
|
4
|
-
let currentImageIndex = null,
|
|
5
|
-
pathToActiveImage,
|
|
6
|
-
activeImage
|
|
7
|
-
if (state.annotationType === "image") {
|
|
8
|
-
currentImageIndex = state.selectedImage
|
|
9
|
-
if (currentImageIndex === -1) {
|
|
10
|
-
currentImageIndex = null
|
|
11
|
-
activeImage = null
|
|
12
|
-
} else {
|
|
13
|
-
pathToActiveImage = ["images", currentImageIndex]
|
|
14
|
-
activeImage = getIn(state, pathToActiveImage)
|
|
15
|
-
}
|
|
16
|
-
} else if (state.annotationType === "video") {
|
|
17
|
-
pathToActiveImage = ["keyframes", state.currentVideoTime || 0]
|
|
18
|
-
activeImage = getIn(state, pathToActiveImage) || null
|
|
19
|
-
}
|
|
20
|
-
return { currentImageIndex, pathToActiveImage, activeImage }
|
|
21
|
-
}
|
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
// @flow
|
|
2
|
-
|
|
3
|
-
import type { Region } from "../../ImageCanvas/region-tools.js"
|
|
4
|
-
|
|
5
|
-
const emptyArr = []
|
|
6
|
-
|
|
7
|
-
export default (
|
|
8
|
-
keyframes: { [string | number]: { regions: Array<Region> } },
|
|
9
|
-
time: number
|
|
10
|
-
) => {
|
|
11
|
-
if (keyframes[time || 0]) {
|
|
12
|
-
return keyframes[time || 0].regions
|
|
13
|
-
}
|
|
14
|
-
// Get surrounding video keyframes
|
|
15
|
-
const keyframeTimes = Object.keys(keyframes)
|
|
16
|
-
.map((a) => parseInt(a))
|
|
17
|
-
.filter((a) => !isNaN(a))
|
|
18
|
-
if (keyframeTimes.length === 0) return emptyArr
|
|
19
|
-
keyframeTimes.sort((a, b) => a - b)
|
|
20
|
-
let nextKeyframeTimeIndex = keyframeTimes.findIndex((kt) => kt >= time)
|
|
21
|
-
if (nextKeyframeTimeIndex === -1) {
|
|
22
|
-
return (
|
|
23
|
-
keyframes[keyframeTimes[keyframeTimes.length - 1]].regions || emptyArr
|
|
24
|
-
)
|
|
25
|
-
} else if (nextKeyframeTimeIndex === 0) {
|
|
26
|
-
return emptyArr
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const t1 = keyframeTimes[nextKeyframeTimeIndex - 1]
|
|
30
|
-
const prevKeyframe = keyframes[t1]
|
|
31
|
-
const t2 = keyframeTimes[nextKeyframeTimeIndex]
|
|
32
|
-
const nextKeyframe = keyframes[t2]
|
|
33
|
-
|
|
34
|
-
const [prevRegionMap, nextRegionMap] = [{}, {}]
|
|
35
|
-
for (const region of prevKeyframe.regions) prevRegionMap[region.id] = region
|
|
36
|
-
for (const region of nextKeyframe.regions) nextRegionMap[region.id] = region
|
|
37
|
-
|
|
38
|
-
const impliedRegions = []
|
|
39
|
-
|
|
40
|
-
// Weighted time coefficients for linear transition
|
|
41
|
-
const w1 = (t2 - time) / (t2 - t1)
|
|
42
|
-
const w2 = 1 - w1
|
|
43
|
-
|
|
44
|
-
for (const regionId in prevRegionMap) {
|
|
45
|
-
const [prev, next] = [prevRegionMap[regionId], nextRegionMap[regionId]]
|
|
46
|
-
if (!next) {
|
|
47
|
-
impliedRegions.push({
|
|
48
|
-
...prev,
|
|
49
|
-
highlighted: false,
|
|
50
|
-
editingLabels: false,
|
|
51
|
-
})
|
|
52
|
-
continue
|
|
53
|
-
}
|
|
54
|
-
switch (prev.type) {
|
|
55
|
-
case "point": {
|
|
56
|
-
impliedRegions.push({
|
|
57
|
-
...prev,
|
|
58
|
-
highlighted: false,
|
|
59
|
-
editingLabels: false,
|
|
60
|
-
x: prev.x * w1 + next.x * w2,
|
|
61
|
-
y: prev.y * w1 + next.y * w2,
|
|
62
|
-
})
|
|
63
|
-
break
|
|
64
|
-
}
|
|
65
|
-
case "box": {
|
|
66
|
-
impliedRegions.push({
|
|
67
|
-
...prev,
|
|
68
|
-
highlighted: false,
|
|
69
|
-
editingLabels: false,
|
|
70
|
-
x: prev.x * w1 + next.x * w2,
|
|
71
|
-
y: prev.y * w1 + next.y * w2,
|
|
72
|
-
w: prev.w * w1 + next.w * w2,
|
|
73
|
-
h: prev.h * w1 + next.h * w2,
|
|
74
|
-
})
|
|
75
|
-
break
|
|
76
|
-
}
|
|
77
|
-
case "polygon": {
|
|
78
|
-
if (next.points.length === prev.points.length) {
|
|
79
|
-
impliedRegions.push({
|
|
80
|
-
...prev,
|
|
81
|
-
highlighted: false,
|
|
82
|
-
editingLabels: false,
|
|
83
|
-
points: prev.points.map((pp, i) => [
|
|
84
|
-
pp[0] * w1 + next.points[i][0] * w2,
|
|
85
|
-
pp[1] * w1 + next.points[i][1] * w2,
|
|
86
|
-
]),
|
|
87
|
-
})
|
|
88
|
-
} else {
|
|
89
|
-
impliedRegions.push(prev)
|
|
90
|
-
}
|
|
91
|
-
break
|
|
92
|
-
}
|
|
93
|
-
case "keypoints": {
|
|
94
|
-
const newPoints = {}
|
|
95
|
-
for (const [pointId, prevPoint] of Object.entries(prev.points)) {
|
|
96
|
-
newPoints[pointId] = {
|
|
97
|
-
x: prevPoint.x * w1 + next.points[pointId].x * w2,
|
|
98
|
-
y: prevPoint.y * w1 + next.points[pointId].y * w2,
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
impliedRegions.push({
|
|
102
|
-
...prev,
|
|
103
|
-
highlighted: false,
|
|
104
|
-
editingLabels: false,
|
|
105
|
-
points: newPoints,
|
|
106
|
-
})
|
|
107
|
-
break
|
|
108
|
-
}
|
|
109
|
-
default:
|
|
110
|
-
break
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
return impliedRegions
|
|
115
|
-
}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
// @flow
|
|
2
|
-
|
|
3
|
-
import type { MainLayoutState, Action } from "../../MainLayout/types"
|
|
4
|
-
import { setIn, updateIn, asMutable, without } from "seamless-immutable"
|
|
5
|
-
import moment from "moment"
|
|
6
|
-
|
|
7
|
-
const typesToSaveWithHistory = {
|
|
8
|
-
BEGIN_BOX_TRANSFORM: "Transform/Move Box",
|
|
9
|
-
BEGIN_MOVE_POINT: "Move Point",
|
|
10
|
-
DELETE_REGION: "Delete Region",
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export const saveToHistory = (state: MainLayoutState, name: string) =>
|
|
14
|
-
updateIn(state, ["history"], (h) =>
|
|
15
|
-
[
|
|
16
|
-
{
|
|
17
|
-
time: moment().toDate(),
|
|
18
|
-
state: without(state, "history"),
|
|
19
|
-
name,
|
|
20
|
-
},
|
|
21
|
-
].concat((h || []).slice(0, 9))
|
|
22
|
-
)
|
|
23
|
-
|
|
24
|
-
export default (reducer) => {
|
|
25
|
-
return (state: MainLayoutState, action: Action) => {
|
|
26
|
-
const prevState = state
|
|
27
|
-
const nextState = reducer(state, action)
|
|
28
|
-
|
|
29
|
-
if (action.type === "RESTORE_HISTORY") {
|
|
30
|
-
if (state.history.length > 0) {
|
|
31
|
-
return setIn(
|
|
32
|
-
nextState.history[0].state,
|
|
33
|
-
["history"],
|
|
34
|
-
nextState.history.slice(1)
|
|
35
|
-
)
|
|
36
|
-
}
|
|
37
|
-
} else {
|
|
38
|
-
if (
|
|
39
|
-
prevState !== nextState &&
|
|
40
|
-
Object.keys(typesToSaveWithHistory).includes(action.type)
|
|
41
|
-
) {
|
|
42
|
-
return setIn(
|
|
43
|
-
nextState,
|
|
44
|
-
["history"],
|
|
45
|
-
[
|
|
46
|
-
{
|
|
47
|
-
time: moment().toDate(),
|
|
48
|
-
state: without(prevState, "history"),
|
|
49
|
-
name: typesToSaveWithHistory[action.type] || action.type,
|
|
50
|
-
},
|
|
51
|
-
]
|
|
52
|
-
.concat(nextState.history || [])
|
|
53
|
-
.slice(0, 9)
|
|
54
|
-
)
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
return nextState
|
|
59
|
-
}
|
|
60
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
// @flow
|
|
2
|
-
|
|
3
|
-
import type {
|
|
4
|
-
MainLayoutImageAnnotationState,
|
|
5
|
-
Action,
|
|
6
|
-
} from "../../MainLayout/types"
|
|
7
|
-
import { setIn } from "seamless-immutable"
|
|
8
|
-
import getActiveImage from "./get-active-image"
|
|
9
|
-
|
|
10
|
-
export default (state: MainLayoutImageAnnotationState, action: Action) => {
|
|
11
|
-
const { currentImageIndex, pathToActiveImage, activeImage } =
|
|
12
|
-
getActiveImage(state)
|
|
13
|
-
|
|
14
|
-
switch (action.type) {
|
|
15
|
-
case "IMAGE_OR_VIDEO_LOADED": {
|
|
16
|
-
return setIn(state, ["images", currentImageIndex, "pixelSize"], {
|
|
17
|
-
w: action.metadata.naturalWidth,
|
|
18
|
-
h: action.metadata.naturalHeight,
|
|
19
|
-
})
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
return state
|
|
23
|
-
}
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
// @flow
|
|
2
|
-
|
|
3
|
-
import type {
|
|
4
|
-
MainLayoutVideoAnnotationState,
|
|
5
|
-
Action,
|
|
6
|
-
} from "../../MainLayout/types"
|
|
7
|
-
import { setIn, without } from "seamless-immutable"
|
|
8
|
-
import getImpliedVideoRegions from "./get-implied-video-regions"
|
|
9
|
-
import { saveToHistory } from "./history-handler.js"
|
|
10
|
-
|
|
11
|
-
export default (state: MainLayoutVideoAnnotationState, action: Action) => {
|
|
12
|
-
const copyImpliedRegions = () => {
|
|
13
|
-
return setIn(
|
|
14
|
-
saveToHistory(state, "Add Keyframe"),
|
|
15
|
-
["keyframes", state.currentVideoTime || 0],
|
|
16
|
-
{
|
|
17
|
-
regions: getImpliedVideoRegions(
|
|
18
|
-
state.keyframes,
|
|
19
|
-
state.currentVideoTime
|
|
20
|
-
),
|
|
21
|
-
}
|
|
22
|
-
)
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
switch (action.type) {
|
|
26
|
-
case "IMAGE_OR_VIDEO_LOADED": {
|
|
27
|
-
const { duration } = action.metadata
|
|
28
|
-
if (typeof duration === "number") {
|
|
29
|
-
return setIn(state, ["videoDuration"], duration * 1000)
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
case "HEADER_BUTTON_CLICKED": {
|
|
33
|
-
switch (action.buttonName.toLowerCase()) {
|
|
34
|
-
case "play":
|
|
35
|
-
return setIn(state, ["videoPlaying"], true)
|
|
36
|
-
case "pause":
|
|
37
|
-
return setIn(state, ["videoPlaying"], false)
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
case "CHANGE_VIDEO_TIME": {
|
|
41
|
-
return setIn(state, ["currentVideoTime"], action.newTime)
|
|
42
|
-
}
|
|
43
|
-
case "CHANGE_VIDEO_PLAYING": {
|
|
44
|
-
return setIn(state, ["videoPlaying"], action.isPlaying)
|
|
45
|
-
}
|
|
46
|
-
case "DELETE_KEYFRAME": {
|
|
47
|
-
return setIn(state, ["keyframes"], without(state.keyframes, action.time))
|
|
48
|
-
}
|
|
49
|
-
default:
|
|
50
|
-
break
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// Before the user modifies regions, copy the interpolated regions over to a
|
|
54
|
-
// new keyframe
|
|
55
|
-
if (!state.keyframes[state.currentVideoTime]) {
|
|
56
|
-
switch (action.type) {
|
|
57
|
-
case "BEGIN_BOX_TRANSFORM":
|
|
58
|
-
case "BEGIN_MOVE_POINT":
|
|
59
|
-
case "BEGIN_MOVE_KEYPOINT":
|
|
60
|
-
case "BEGIN_MOVE_POLYGON_POINT":
|
|
61
|
-
case "ADD_POLYGON_POINT":
|
|
62
|
-
case "SELECT_REGION":
|
|
63
|
-
case "CHANGE_REGION":
|
|
64
|
-
case "DELETE_REGION":
|
|
65
|
-
case "OPEN_REGION_EDITOR":
|
|
66
|
-
return copyImpliedRegions()
|
|
67
|
-
case "MOUSE_DOWN": {
|
|
68
|
-
switch (state.selectedTool) {
|
|
69
|
-
case "create-point":
|
|
70
|
-
case "create-polygon":
|
|
71
|
-
case "create-box":
|
|
72
|
-
case "create-keypoints":
|
|
73
|
-
return copyImpliedRegions()
|
|
74
|
-
default:
|
|
75
|
-
break
|
|
76
|
-
}
|
|
77
|
-
break
|
|
78
|
-
}
|
|
79
|
-
default:
|
|
80
|
-
break
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
return state
|
|
85
|
-
}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
// @flow
|
|
2
|
-
|
|
3
|
-
import React from "react"
|
|
4
|
-
|
|
5
|
-
import { storiesOf } from "@storybook/react"
|
|
6
|
-
import { action } from "@storybook/addon-actions"
|
|
7
|
-
import Annotator from "./"
|
|
8
|
-
|
|
9
|
-
storiesOf("Annotator(video)", module).add("Video Annotator", () => {
|
|
10
|
-
const props = {
|
|
11
|
-
regionClsList: ["valid", "invalid"],
|
|
12
|
-
enabledTools: ["select", "create-box", "create-polygon", "create-point"],
|
|
13
|
-
keyframes: {
|
|
14
|
-
0: {
|
|
15
|
-
regions: [
|
|
16
|
-
{
|
|
17
|
-
id: "910517662556203",
|
|
18
|
-
cls: "valid",
|
|
19
|
-
color: "#f44336",
|
|
20
|
-
type: "box",
|
|
21
|
-
x: 0.12195121951219515,
|
|
22
|
-
y: 0.28726287262872624,
|
|
23
|
-
w: 0.2606707317073171,
|
|
24
|
-
h: 0.4769647696476965,
|
|
25
|
-
},
|
|
26
|
-
],
|
|
27
|
-
},
|
|
28
|
-
2656: {
|
|
29
|
-
regions: [
|
|
30
|
-
{
|
|
31
|
-
id: "910517662556203",
|
|
32
|
-
cls: "valid",
|
|
33
|
-
color: "#f44336",
|
|
34
|
-
type: "box",
|
|
35
|
-
x: 0.13109756097560976,
|
|
36
|
-
y: 0.08672086720867206,
|
|
37
|
-
w: 0.3445121951219512,
|
|
38
|
-
h: 0.7913279132791328,
|
|
39
|
-
},
|
|
40
|
-
],
|
|
41
|
-
},
|
|
42
|
-
},
|
|
43
|
-
onExit: action("onExit"),
|
|
44
|
-
taskDescription: "",
|
|
45
|
-
videoName: "",
|
|
46
|
-
videoTime: 0,
|
|
47
|
-
videoSrc:
|
|
48
|
-
"https://s3.amazonaws.com/asset.workaround.online/SampleVideo_1280x720_1mb.mp4",
|
|
49
|
-
}
|
|
50
|
-
return <Annotator {...props} />
|
|
51
|
-
})
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import React, { useEffect } from "react"
|
|
2
|
-
import { styled } from "@mui/material/styles"
|
|
3
|
-
import { createTheme, ThemeProvider } from "@mui/material/styles"
|
|
4
|
-
import Box from "@mui/material/Box"
|
|
5
|
-
import * as muiColors from "@mui/material/colors"
|
|
6
|
-
import SidebarBoxContainer from "../SidebarBoxContainer"
|
|
7
|
-
import BallotIcon from "@mui/icons-material/Ballot"
|
|
8
|
-
import capitalize from "lodash/capitalize"
|
|
9
|
-
import classnames from "classnames"
|
|
10
|
-
import useColors from "../hooks/use-colors"
|
|
11
|
-
|
|
12
|
-
const theme = createTheme()
|
|
13
|
-
const LabelContainer = styled("div")(({ theme }) => ({
|
|
14
|
-
display: "flex",
|
|
15
|
-
paddingTop: 4,
|
|
16
|
-
paddingBottom: 4,
|
|
17
|
-
paddingLeft: 16,
|
|
18
|
-
paddingRight: 16,
|
|
19
|
-
alignItems: "center",
|
|
20
|
-
cursor: "pointer",
|
|
21
|
-
opacity: 0.7,
|
|
22
|
-
backgroundColor: "#fff",
|
|
23
|
-
"&:hover": {
|
|
24
|
-
opacity: 1,
|
|
25
|
-
},
|
|
26
|
-
"&.selected": {
|
|
27
|
-
opacity: 1,
|
|
28
|
-
fontWeight: "bold",
|
|
29
|
-
},
|
|
30
|
-
}))
|
|
31
|
-
const Circle = styled("div")(({ theme }) => ({
|
|
32
|
-
width: 12,
|
|
33
|
-
height: 12,
|
|
34
|
-
borderRadius: 12,
|
|
35
|
-
marginRight: 8,
|
|
36
|
-
}))
|
|
37
|
-
const Label = styled("div")(({ theme }) => ({
|
|
38
|
-
fontSize: 11,
|
|
39
|
-
}))
|
|
40
|
-
const DashSep = styled("div")(({ theme }) => ({
|
|
41
|
-
flexGrow: 1,
|
|
42
|
-
borderBottom: `2px dotted ${muiColors.grey[300]}`,
|
|
43
|
-
marginLeft: 8,
|
|
44
|
-
marginRight: 8,
|
|
45
|
-
}))
|
|
46
|
-
const Number = styled("div")(({ theme }) => ({
|
|
47
|
-
fontSize: 11,
|
|
48
|
-
textAlign: "center",
|
|
49
|
-
minWidth: 14,
|
|
50
|
-
paddingTop: 2,
|
|
51
|
-
paddingBottom: 2,
|
|
52
|
-
fontWeight: "bold",
|
|
53
|
-
color: muiColors.grey[700],
|
|
54
|
-
}))
|
|
55
|
-
|
|
56
|
-
export const ClassSelectionMenu = ({
|
|
57
|
-
selectedCls,
|
|
58
|
-
regionClsList,
|
|
59
|
-
onSelectCls,
|
|
60
|
-
}) => {
|
|
61
|
-
const { clsColor } = useColors()
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
useEffect(() => {
|
|
65
|
-
const keyMapping = {}
|
|
66
|
-
for (let i = 0; i < 9 && i < regionClsList.length; i++) {
|
|
67
|
-
keyMapping[i + 1] = () => onSelectCls(regionClsList[i])
|
|
68
|
-
}
|
|
69
|
-
const onKeyDown = (e) => {
|
|
70
|
-
if (keyMapping[e.key]) {
|
|
71
|
-
keyMapping[e.key]()
|
|
72
|
-
e.preventDefault()
|
|
73
|
-
e.stopPropagation()
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
window.addEventListener("keydown", onKeyDown)
|
|
77
|
-
return () => window.removeEventListener("keydown", onKeyDown)
|
|
78
|
-
}, [regionClsList, selectedCls])
|
|
79
|
-
|
|
80
|
-
return (
|
|
81
|
-
<ThemeProvider theme={theme}>
|
|
82
|
-
<SidebarBoxContainer
|
|
83
|
-
title="Classifications"
|
|
84
|
-
subTitle=""
|
|
85
|
-
icon={<BallotIcon style={{ color: muiColors.grey[700] }} />}
|
|
86
|
-
expandedByDefault
|
|
87
|
-
>
|
|
88
|
-
{regionClsList.map((label, index) => (
|
|
89
|
-
<LabelContainer
|
|
90
|
-
key={label}
|
|
91
|
-
className={classnames({ selected: label === selectedCls })}
|
|
92
|
-
onClick={() => onSelectCls(label)}
|
|
93
|
-
>
|
|
94
|
-
<Circle
|
|
95
|
-
style={{ backgroundColor: clsColor(label) }}
|
|
96
|
-
/>
|
|
97
|
-
<Label className={classnames({ selected: label === selectedCls })}>
|
|
98
|
-
{capitalize(label)}
|
|
99
|
-
</Label>
|
|
100
|
-
<DashSep />
|
|
101
|
-
<Number className={classnames({ selected: label === selectedCls })}>
|
|
102
|
-
{index < 9 ? `Key [${index + 1}]` : ""}
|
|
103
|
-
</Number>
|
|
104
|
-
</LabelContainer>
|
|
105
|
-
))}
|
|
106
|
-
<Box pb={2} />
|
|
107
|
-
</SidebarBoxContainer>
|
|
108
|
-
</ThemeProvider>
|
|
109
|
-
)
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
export default ClassSelectionMenu
|
package/src/Crosshairs/index.js
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
// @flow
|
|
2
|
-
|
|
3
|
-
import React, { Fragment, useEffect, useState } from "react"
|
|
4
|
-
|
|
5
|
-
export const Crosshairs = ({
|
|
6
|
-
mousePosition,
|
|
7
|
-
x,
|
|
8
|
-
y,
|
|
9
|
-
}: {
|
|
10
|
-
mousePosition: { current: { x: number, y: number } },
|
|
11
|
-
x?: number,
|
|
12
|
-
y?: number,
|
|
13
|
-
}) => {
|
|
14
|
-
const [forceRenderState, changeForceRenderState] = useState()
|
|
15
|
-
|
|
16
|
-
if (mousePosition) {
|
|
17
|
-
x = mousePosition.current.x
|
|
18
|
-
y = mousePosition.current.y
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
useEffect(() => {
|
|
22
|
-
if (!mousePosition) return
|
|
23
|
-
const interval = setInterval(() => {
|
|
24
|
-
if (x !== mousePosition.current.x || y !== mousePosition.current.y) {
|
|
25
|
-
changeForceRenderState([
|
|
26
|
-
mousePosition.current.x,
|
|
27
|
-
mousePosition.current.y,
|
|
28
|
-
])
|
|
29
|
-
}
|
|
30
|
-
}, 10)
|
|
31
|
-
return () => clearInterval(interval)
|
|
32
|
-
})
|
|
33
|
-
|
|
34
|
-
return (
|
|
35
|
-
<Fragment>
|
|
36
|
-
<div
|
|
37
|
-
style={{
|
|
38
|
-
position: "absolute",
|
|
39
|
-
height: "100%",
|
|
40
|
-
width: 1,
|
|
41
|
-
zIndex: 10,
|
|
42
|
-
backgroundColor: "#f00",
|
|
43
|
-
left: x,
|
|
44
|
-
pointerEvents: "none",
|
|
45
|
-
top: 0,
|
|
46
|
-
}}
|
|
47
|
-
/>
|
|
48
|
-
<div
|
|
49
|
-
style={{
|
|
50
|
-
position: "absolute",
|
|
51
|
-
width: "100%",
|
|
52
|
-
zIndex: 10,
|
|
53
|
-
height: 1,
|
|
54
|
-
backgroundColor: "#f00",
|
|
55
|
-
top: y,
|
|
56
|
-
pointerEvents: "none",
|
|
57
|
-
left: 0,
|
|
58
|
-
}}
|
|
59
|
-
/>
|
|
60
|
-
</Fragment>
|
|
61
|
-
)
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export default Crosshairs
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
// @flow
|
|
2
|
-
|
|
3
|
-
import React from "react"
|
|
4
|
-
import SidebarBoxContainer from "../SidebarBoxContainer"
|
|
5
|
-
|
|
6
|
-
export const DebugSidebarBox = ({ state, lastAction }: any) => {
|
|
7
|
-
const image = (state.images || [])[state.selectedImage]
|
|
8
|
-
const region = image
|
|
9
|
-
? (image.regions || []).filter((r) => r.highlighted)
|
|
10
|
-
: null
|
|
11
|
-
|
|
12
|
-
return (
|
|
13
|
-
<SidebarBoxContainer title="Debug" icon={<span />} expandedByDefault>
|
|
14
|
-
<div style={{ padding: 4 }}>
|
|
15
|
-
<div>
|
|
16
|
-
<b>region</b>:
|
|
17
|
-
</div>
|
|
18
|
-
<pre>{JSON.stringify(region, null, " ")}</pre>
|
|
19
|
-
<div>
|
|
20
|
-
<b>lastAction</b>:
|
|
21
|
-
</div>
|
|
22
|
-
<pre>{JSON.stringify(lastAction, null, " ")}</pre>
|
|
23
|
-
<div>
|
|
24
|
-
<b>mode</b>:
|
|
25
|
-
</div>
|
|
26
|
-
<pre>{JSON.stringify(state.mode, null, " ")}</pre>
|
|
27
|
-
<div>
|
|
28
|
-
<b>frame:</b>
|
|
29
|
-
</div>
|
|
30
|
-
<pre>{JSON.stringify(state.selectedImageFrameTime, null, " ")}</pre>
|
|
31
|
-
</div>
|
|
32
|
-
</SidebarBoxContainer>
|
|
33
|
-
)
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export default DebugSidebarBox
|