@searpent/react-image-annotate 2.0.0 → 2.0.3

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.
Files changed (174) hide show
  1. package/Annotator/index.js +169 -0
  2. package/Annotator/reducers/combine-reducers.js +14 -0
  3. package/Annotator/reducers/convert-expanding-line-to-polygon.js +73 -0
  4. package/{src/Annotator → Annotator}/reducers/fix-twisted.js +3 -5
  5. package/Annotator/reducers/general-reducer.js +1058 -0
  6. package/Annotator/reducers/get-active-image.js +27 -0
  7. package/Annotator/reducers/get-implied-video-regions.js +180 -0
  8. package/Annotator/reducers/history-handler.js +38 -0
  9. package/Annotator/reducers/image-reducer.js +20 -0
  10. package/Annotator/reducers/video-reducer.js +88 -0
  11. package/ClassSelectionMenu/index.js +135 -0
  12. package/Crosshairs/index.js +53 -0
  13. package/DebugSidebarBox/index.js +20 -0
  14. package/DemoSite/Editor.js +194 -0
  15. package/DemoSite/ErrorBoundaryDialog.js +64 -0
  16. package/DemoSite/index.js +40 -0
  17. package/FullImageSegmentationAnnotator/index.js +7 -0
  18. package/GroupSelectorSidebarBox/index.js +63 -0
  19. package/HighlightBox/index.js +99 -0
  20. package/HistorySidebarBox/index.js +71 -0
  21. package/ImageCanvas/index.js +424 -0
  22. package/ImageCanvas/region-tools.js +165 -0
  23. package/{src/ImageCanvas → ImageCanvas}/styles.js +12 -8
  24. package/ImageCanvas/use-mouse.js +180 -0
  25. package/ImageCanvas/use-project-box.js +27 -0
  26. package/ImageCanvas/use-wasd-mode.js +62 -0
  27. package/ImageMask/index.js +133 -0
  28. package/ImageMask/load-image.js +25 -0
  29. package/ImageSelectorSidebarBox/index.js +60 -0
  30. package/KeyframeTimeline/get-time-string.js +27 -0
  31. package/KeyframeTimeline/index.js +233 -0
  32. package/KeyframesSelectorSidebarBox/index.js +93 -0
  33. package/LandingPage/index.js +159 -0
  34. package/MainLayout/icon-dictionary.js +104 -0
  35. package/MainLayout/index.js +366 -0
  36. package/{src/MainLayout → MainLayout}/styles.js +6 -7
  37. package/MainLayout/types.js +0 -0
  38. package/MainLayout/use-implied-video-regions.js +13 -0
  39. package/PointDistances/index.js +73 -0
  40. package/PreventScrollToParents/index.js +51 -0
  41. package/RegionLabel/index.js +191 -0
  42. package/{src/RegionLabel → RegionLabel}/styles.js +12 -15
  43. package/RegionSelectAndTransformBoxes/index.js +167 -0
  44. package/RegionSelectorSidebarBox/index.js +248 -0
  45. package/{src/RegionSelectorSidebarBox → RegionSelectorSidebarBox}/styles.js +13 -14
  46. package/RegionShapes/index.js +274 -0
  47. package/RegionTags/index.js +138 -0
  48. package/SettingsDialog/index.js +52 -0
  49. package/SettingsProvider/index.js +53 -0
  50. package/Shortcuts/ShortcutField.js +46 -0
  51. package/Shortcuts/index.js +133 -0
  52. package/ShortcutsManager/index.js +155 -0
  53. package/Sidebar/index.js +69 -0
  54. package/SidebarBoxContainer/index.js +93 -0
  55. package/SmallToolButton/index.js +42 -0
  56. package/TagsSidebarBox/index.js +105 -0
  57. package/TaskDescriptionSidebarBox/index.js +58 -0
  58. package/Theme/index.js +30 -0
  59. package/VideoOrImageCanvasBackground/index.js +151 -0
  60. package/colors.js +14 -0
  61. package/hooks/use-event-callback.js +10 -0
  62. package/hooks/use-exclude-pattern.js +24 -0
  63. package/hooks/use-load-image.js +26 -0
  64. package/hooks/use-window-size.js +46 -0
  65. package/{src/hooks → hooks}/xpattern.js +1 -1
  66. package/index.js +3 -0
  67. package/lib.js +3 -0
  68. package/package.json +1 -1
  69. package/stories.js +5 -0
  70. package/utils/get-from-local-storage.js +7 -0
  71. package/utils/get-hotkey-help-text.js +9 -0
  72. package/utils/get-landmarks-with-transform.js +40 -0
  73. package/utils/set-in-local-storage.js +3 -0
  74. package/.babelrc +0 -6
  75. package/.env +0 -1
  76. package/.flowconfig +0 -2
  77. package/.github/workflows/release-on-master.yml +0 -32
  78. package/.github/workflows/test.yml +0 -16
  79. package/.prettierrc +0 -3
  80. package/.releaserc.js +0 -18
  81. package/.storybook/addons.js +0 -2
  82. package/.storybook/config.js +0 -16
  83. package/LICENSE +0 -21
  84. package/public/favicon.ico +0 -0
  85. package/public/index.html +0 -38
  86. package/src/Annotator/bike-pic.png +0 -0
  87. package/src/Annotator/bike-pic2.png +0 -0
  88. package/src/Annotator/dab-keyframes.story.json +0 -1
  89. package/src/Annotator/index.js +0 -206
  90. package/src/Annotator/index.story.js +0 -727
  91. package/src/Annotator/poses.story.js +0 -150
  92. package/src/Annotator/reducers/combine-reducers.js +0 -7
  93. package/src/Annotator/reducers/convert-expanding-line-to-polygon.js +0 -53
  94. package/src/Annotator/reducers/general-reducer.js +0 -914
  95. package/src/Annotator/reducers/get-active-image.js +0 -21
  96. package/src/Annotator/reducers/get-implied-video-regions.js +0 -115
  97. package/src/Annotator/reducers/history-handler.js +0 -60
  98. package/src/Annotator/reducers/image-reducer.js +0 -23
  99. package/src/Annotator/reducers/video-reducer.js +0 -85
  100. package/src/Annotator/video.story.js +0 -51
  101. package/src/ClassSelectionMenu/index.js +0 -108
  102. package/src/Crosshairs/index.js +0 -64
  103. package/src/DebugSidebarBox/index.js +0 -36
  104. package/src/DemoSite/Editor.js +0 -235
  105. package/src/DemoSite/ErrorBoundaryDialog.js +0 -34
  106. package/src/DemoSite/index.js +0 -41
  107. package/src/DemoSite/index.story.js +0 -10
  108. package/src/DemoSite/simple-segmentation-example.json +0 -572
  109. package/src/FullImageSegmentationAnnotator/hard1.story.jpg +0 -0
  110. package/src/FullImageSegmentationAnnotator/hard2.story.jpg +0 -0
  111. package/src/FullImageSegmentationAnnotator/hard3.story.jpg +0 -0
  112. package/src/FullImageSegmentationAnnotator/index.js +0 -7
  113. package/src/FullImageSegmentationAnnotator/index.story.js +0 -177
  114. package/src/FullImageSegmentationAnnotator/orange.story.png +0 -0
  115. package/src/HighlightBox/index.js +0 -143
  116. package/src/HistorySidebarBox/index.js +0 -78
  117. package/src/ImageCanvas/dancing-man.story.jpg +0 -0
  118. package/src/ImageCanvas/index.js +0 -488
  119. package/src/ImageCanvas/index.story.js +0 -214
  120. package/src/ImageCanvas/mouse_mask.story.png +0 -0
  121. package/src/ImageCanvas/region-tools.js +0 -171
  122. package/src/ImageCanvas/seves_desk.story.jpg +0 -0
  123. package/src/ImageCanvas/use-mouse.js +0 -168
  124. package/src/ImageCanvas/use-project-box.js +0 -23
  125. package/src/ImageCanvas/use-wasd-mode.js +0 -50
  126. package/src/ImageMask/index.js +0 -127
  127. package/src/ImageMask/load-image.js +0 -32
  128. package/src/ImageSelectorSidebarBox/index.js +0 -54
  129. package/src/KeyframeTimeline/get-time-string.js +0 -25
  130. package/src/KeyframeTimeline/index.js +0 -223
  131. package/src/KeyframesSelectorSidebarBox/index.js +0 -93
  132. package/src/LandingPage/content.md +0 -57
  133. package/src/LandingPage/github-markdown.css +0 -964
  134. package/src/LandingPage/index.js +0 -147
  135. package/src/MainLayout/icon-dictionary.js +0 -79
  136. package/src/MainLayout/index.js +0 -420
  137. package/src/MainLayout/index.story.js +0 -240
  138. package/src/MainLayout/types.js +0 -156
  139. package/src/MainLayout/use-implied-video-regions.js +0 -17
  140. package/src/PointDistances/index.js +0 -90
  141. package/src/PreventScrollToParents/index.js +0 -48
  142. package/src/PreventScrollToParents/index.story.js +0 -23
  143. package/src/RegionLabel/index.js +0 -201
  144. package/src/RegionSelectAndTransformBoxes/index.js +0 -234
  145. package/src/RegionSelectorSidebarBox/index.js +0 -216
  146. package/src/RegionShapes/index.js +0 -236
  147. package/src/RegionTags/index.js +0 -130
  148. package/src/SettingsDialog/index.js +0 -58
  149. package/src/SettingsProvider/index.js +0 -44
  150. package/src/Shortcuts/ShortcutField.js +0 -44
  151. package/src/Shortcuts/index.js +0 -129
  152. package/src/ShortcutsManager/index.js +0 -162
  153. package/src/Sidebar/index.js +0 -117
  154. package/src/SidebarBoxContainer/index.js +0 -93
  155. package/src/SmallToolButton/index.js +0 -57
  156. package/src/TagsSidebarBox/index.js +0 -93
  157. package/src/TaskDescriptionSidebarBox/index.js +0 -43
  158. package/src/Theme/index.js +0 -36
  159. package/src/VideoOrImageCanvasBackground/index.js +0 -170
  160. package/src/colors.js +0 -32
  161. package/src/hooks/use-event-callback.js +0 -11
  162. package/src/hooks/use-exclude-pattern.js +0 -27
  163. package/src/hooks/use-load-image.js +0 -21
  164. package/src/hooks/use-window-size.js +0 -46
  165. package/src/hooks/xpattern.png +0 -0
  166. package/src/index.js +0 -18
  167. package/src/lib.js +0 -7
  168. package/src/screenshot.png +0 -0
  169. package/src/site.css +0 -5
  170. package/src/stories.js +0 -2
  171. package/src/utils/get-from-local-storage.js +0 -7
  172. package/src/utils/get-hotkey-help-text.js +0 -11
  173. package/src/utils/get-landmarks-with-transform.js +0 -23
  174. package/src/utils/set-in-local-storage.js +0 -6
@@ -1,171 +0,0 @@
1
- // @flow
2
-
3
- export type BaseRegion = {
4
- id: string | number,
5
- cls?: string,
6
- locked?: boolean,
7
- visible?: boolean,
8
- color: string,
9
- editingLabels?: boolean,
10
- highlighted?: boolean,
11
- tags?: Array<string>,
12
- }
13
-
14
- export type Point = {|
15
- ...$Exact<BaseRegion>,
16
- type: "point",
17
- x: number,
18
- y: number,
19
- |}
20
-
21
- export type PixelRegion =
22
- | {|
23
- ...$Exact<BaseRegion>,
24
- type: "pixel",
25
- sx: number,
26
- sy: number,
27
- w: number,
28
- h: number,
29
- src: string,
30
- |}
31
- | {|
32
- ...$Exact<BaseRegion>,
33
- type: "pixel",
34
- points: Array<[number, number]>,
35
- |}
36
- export type Box = {|
37
- ...$Exact<BaseRegion>,
38
- type: "box",
39
- x: number,
40
- y: number,
41
- w: number,
42
- h: number,
43
- |}
44
-
45
- export type Polygon = {|
46
- ...$Exact<BaseRegion>,
47
- type: "polygon",
48
- open?: boolean,
49
- points: Array<[number, number]>,
50
- |}
51
-
52
- export type Line = {|
53
- ...$Exact<BaseRegion>,
54
- type: "line",
55
- x1: number,
56
- y1: number,
57
- x2: number,
58
- y2: number,
59
- |}
60
-
61
- export type ExpandingLine = {|
62
- ...$Exact<BaseRegion>,
63
- type: "expanding-line",
64
- points: Array<{ x: number, y: number, angle: number, width: number }>,
65
- |}
66
-
67
- export type KeypointDefinition = {|
68
- label: string,
69
- color: string,
70
- defaultPosition: [number, number],
71
- |}
72
-
73
- export type KeypointId = string
74
-
75
- export type KeypointsDefinition = {|
76
- [id: string]: {
77
- connections: Array<[KeypointId, KeypointId]>,
78
- landmarks: {
79
- [KeypointId]: KeypointDefinition,
80
- },
81
- },
82
- |}
83
-
84
- export type Keypoints = {|
85
- ...$Exact<BaseRegion>,
86
- type: "keypoints",
87
- keypointsDefinitionId: string,
88
- points: {
89
- [string]: { x: number, y: number },
90
- },
91
- |}
92
-
93
- export type Region =
94
- | Point
95
- | PixelRegion
96
- | Box
97
- | Polygon
98
- | ExpandingLine
99
- | Keypoints
100
-
101
- export const getEnclosingBox = (region: Region) => {
102
- switch (region.type) {
103
- case "polygon": {
104
- const box = {
105
- x: Math.min(...region.points.map(([x, y]) => x)),
106
- y: Math.min(...region.points.map(([x, y]) => y)),
107
- w: 0,
108
- h: 0,
109
- }
110
- box.w = Math.max(...region.points.map(([x, y]) => x)) - box.x
111
- box.h = Math.max(...region.points.map(([x, y]) => y)) - box.y
112
- return box
113
- }
114
- case "keypoints": {
115
- const minX = Math.min(
116
- ...Object.values(region.points).map(({ x, y }) => x)
117
- )
118
- const minY = Math.min(
119
- ...Object.values(region.points).map(({ x, y }) => y)
120
- )
121
- const maxX = Math.max(
122
- ...Object.values(region.points).map(({ x, y }) => x)
123
- )
124
- const maxY = Math.max(
125
- ...Object.values(region.points).map(({ x, y }) => y)
126
- )
127
- return {
128
- x: minX,
129
- y: minY,
130
- w: maxX - minX,
131
- h: maxY - minY,
132
- }
133
- }
134
- case "expanding-line": {
135
- const box = {
136
- x: Math.min(...region.points.map(({ x, y }) => x)),
137
- y: Math.min(...region.points.map(({ x, y }) => y)),
138
- w: 0,
139
- h: 0,
140
- }
141
- box.w = Math.max(...region.points.map(({ x, y }) => x)) - box.x
142
- box.h = Math.max(...region.points.map(({ x, y }) => y)) - box.y
143
- return box
144
- }
145
- case "line": {
146
- return { x: region.x1, y: region.y1, w: 0, h: 0 }
147
- }
148
- case "box": {
149
- return { x: region.x, y: region.y, w: region.w, h: region.h }
150
- }
151
- case "point": {
152
- return { x: region.x, y: region.y, w: 0, h: 0 }
153
- }
154
- default: {
155
- return { x: 0, y: 0, w: 0, h: 0 }
156
- }
157
- }
158
- throw new Error("unknown region")
159
- }
160
-
161
- export const moveRegion = (region: Region, x: number, y: number) => {
162
- switch (region.type) {
163
- case "point": {
164
- return { ...region, x, y }
165
- }
166
- case "box": {
167
- return { ...region, x: x - region.w / 2, y: y - region.h / 2 }
168
- }
169
- }
170
- return region
171
- }
@@ -1,168 +0,0 @@
1
- // @flow weak
2
-
3
- import { useRef } from "react"
4
- import { Matrix } from "transformation-matrix-js"
5
-
6
- const getDefaultMat = () => Matrix.from(1, 0, 0, 1, -10, -10)
7
-
8
- export default ({
9
- canvasEl,
10
- changeMat,
11
- changeDragging,
12
- zoomStart,
13
- zoomEnd,
14
- changeZoomStart,
15
- changeZoomEnd,
16
- layoutParams,
17
- zoomWithPrimary,
18
- dragWithPrimary,
19
- mat,
20
- onMouseMove,
21
- onMouseUp,
22
- onMouseDown,
23
- dragging,
24
- }) => {
25
- const mousePosition = useRef({ x: 0, y: 0 })
26
- const prevMousePosition = useRef({ x: 0, y: 0 })
27
-
28
- const zoomIn = (direction, point) => {
29
- const [mx, my] = [point.x, point.y]
30
- let scale =
31
- typeof direction === "object" ? direction.to / mat.a : 1 + 0.2 * direction
32
-
33
- // NOTE: We're mutating mat here
34
- mat.translate(mx, my).scaleU(scale)
35
- if (mat.a > 2) mat.scaleU(2 / mat.a)
36
- if (mat.a < 0.05) mat.scaleU(0.05 / mat.a)
37
- mat.translate(-mx, -my)
38
-
39
- changeMat(mat.clone())
40
- }
41
-
42
- const mouseEvents = {
43
- onMouseMove: (e) => {
44
- const { left, top } = canvasEl.current.getBoundingClientRect()
45
- prevMousePosition.current.x = mousePosition.current.x
46
- prevMousePosition.current.y = mousePosition.current.y
47
- mousePosition.current.x = e.clientX - left
48
- mousePosition.current.y = e.clientY - top
49
-
50
- const projMouse = mat.applyToPoint(
51
- mousePosition.current.x,
52
- mousePosition.current.y
53
- )
54
-
55
- if (zoomWithPrimary && zoomStart) {
56
- changeZoomEnd(projMouse)
57
- }
58
-
59
- const { iw, ih } = layoutParams.current
60
- onMouseMove({ x: projMouse.x / iw, y: projMouse.y / ih })
61
-
62
- if (dragging) {
63
- mat.translate(
64
- prevMousePosition.current.x - mousePosition.current.x,
65
- prevMousePosition.current.y - mousePosition.current.y
66
- )
67
-
68
- changeMat(mat.clone())
69
- }
70
- e.preventDefault()
71
- },
72
- onMouseDown: (e, specialEvent = {}) => {
73
- e.preventDefault()
74
-
75
- if (
76
- e.button === 1 ||
77
- e.button === 2 ||
78
- (e.button === 0 && dragWithPrimary)
79
- )
80
- return changeDragging(true)
81
-
82
- const projMouse = mat.applyToPoint(
83
- mousePosition.current.x,
84
- mousePosition.current.y
85
- )
86
- if (zoomWithPrimary && e.button === 0) {
87
- changeZoomStart(projMouse)
88
- changeZoomEnd(projMouse)
89
- return
90
- }
91
- if (e.button === 0) {
92
- if (specialEvent.type === "resize-box") {
93
- // onResizeBox()
94
- }
95
- if (specialEvent.type === "move-region") {
96
- // onResizeBox()
97
- }
98
- const { iw, ih } = layoutParams.current
99
- onMouseDown({ x: projMouse.x / iw, y: projMouse.y / ih })
100
- }
101
- },
102
- onMouseUp: (e) => {
103
- e.preventDefault()
104
- const projMouse = mat.applyToPoint(
105
- mousePosition.current.x,
106
- mousePosition.current.y
107
- )
108
- if (zoomStart) {
109
- const zoomEnd = projMouse
110
- if (
111
- Math.abs(zoomStart.x - zoomEnd.x) < 10 &&
112
- Math.abs(zoomStart.y - zoomEnd.y) < 10
113
- ) {
114
- if (mat.a < 1) {
115
- zoomIn({ to: 1 }, mousePosition.current)
116
- } else {
117
- zoomIn({ to: 0.25 }, mousePosition.current)
118
- }
119
- } else {
120
- const { iw, ih } = layoutParams.current
121
-
122
- if (zoomStart.x > zoomEnd.x) {
123
- ;[zoomStart.x, zoomEnd.x] = [zoomEnd.x, zoomStart.x]
124
- }
125
- if (zoomStart.y > zoomEnd.y) {
126
- ;[zoomStart.y, zoomEnd.y] = [zoomEnd.y, zoomStart.y]
127
- }
128
-
129
- // The region defined by zoomStart and zoomEnd should be the new transform
130
- let scale = Math.min(
131
- (zoomEnd.x - zoomStart.x) / iw,
132
- (zoomEnd.y - zoomStart.y) / ih
133
- )
134
- if (scale < 0.05) scale = 0.05
135
- if (scale > 10) scale = 10
136
-
137
- const newMat = getDefaultMat()
138
- .translate(zoomStart.x, zoomStart.y)
139
- .scaleU(scale)
140
-
141
- changeMat(newMat.clone())
142
- }
143
-
144
- changeZoomStart(null)
145
- changeZoomEnd(null)
146
- }
147
- if (
148
- e.button === 1 ||
149
- e.button === 2 ||
150
- (e.button === 0 && dragWithPrimary)
151
- )
152
- return changeDragging(false)
153
- if (e.button === 0) {
154
- const { iw, ih } = layoutParams.current
155
- onMouseUp({ x: projMouse.x / iw, y: projMouse.y / ih })
156
- }
157
- },
158
- onWheel: (e) => {
159
- const direction = e.deltaY > 0 ? 1 : e.deltaY < 0 ? -1 : 0
160
- zoomIn(direction, mousePosition.current)
161
- // e.preventDefault()
162
- },
163
- onContextMenu: (e) => {
164
- e.preventDefault()
165
- },
166
- }
167
- return { mouseEvents, mousePosition }
168
- }
@@ -1,23 +0,0 @@
1
- // @flow weak
2
- import useEventCallback from "use-event-callback"
3
- import { getEnclosingBox } from "./region-tools.js"
4
-
5
- export default ({ layoutParams, mat }) => {
6
- return useEventCallback((r) => {
7
- const { iw, ih } = layoutParams.current
8
- const bbox = getEnclosingBox(r)
9
- const margin = r.type === "point" ? 15 : 2
10
- const cbox = {
11
- x: bbox.x * iw - margin,
12
- y: bbox.y * ih - margin,
13
- w: bbox.w * iw + margin * 2,
14
- h: bbox.h * ih + margin * 2,
15
- }
16
- const pbox = {
17
- ...mat.clone().inverse().applyToPoint(cbox.x, cbox.y),
18
- w: cbox.w / mat.a,
19
- h: cbox.h / mat.d,
20
- }
21
- return pbox
22
- })
23
- }
@@ -1,50 +0,0 @@
1
- import { useEffect } from "react"
2
- import { useSettings } from "../SettingsProvider"
3
-
4
- export default ({ getLatestMat, changeMat }) => {
5
- const { wasdMode } = useSettings()
6
- useEffect(() => {
7
- if (!wasdMode) return
8
- const vel = 10
9
- const dirs = {
10
- w: [0, -vel],
11
- a: [-vel, 0],
12
- s: [0, vel],
13
- d: [vel, 0],
14
- }
15
- const keysDown = {}
16
- const keys = Object.keys(dirs)
17
- const keyDownListener = (e) => {
18
- if (keys.includes(e.key)) {
19
- keysDown[e.key] = true
20
- e.preventDefault()
21
- e.stopPropagation()
22
- }
23
- }
24
- const keyUpListener = (e) => {
25
- if (keys.includes(e.key)) {
26
- keysDown[e.key] = false
27
- e.preventDefault()
28
- e.stopPropagation()
29
- }
30
- }
31
- const interval = setInterval(() => {
32
- let newMat = getLatestMat().clone()
33
- let somethingChanged = false
34
- for (const key in keysDown) {
35
- if (keysDown[key]) {
36
- newMat = newMat.translate(...dirs[key])
37
- somethingChanged = true
38
- }
39
- }
40
- if (somethingChanged) changeMat(newMat)
41
- }, 16)
42
- window.addEventListener("keydown", keyDownListener)
43
- window.addEventListener("keyup", keyUpListener)
44
- return () => {
45
- clearInterval(interval)
46
- window.removeEventListener("keydown", keyDownListener)
47
- window.removeEventListener("keyup", keyUpListener)
48
- }
49
- }, [wasdMode])
50
- }
@@ -1,127 +0,0 @@
1
- // @flow
2
-
3
- import React, { useState, useEffect, useMemo, useRef } from "react"
4
- import { colorInts } from "../colors"
5
- import { useDebounce } from "react-use"
6
- import loadImage from "./load-image"
7
- import autoseg from "autoseg/webworker"
8
-
9
- function convertToUDTRegions(regions) {
10
- return regions
11
- .map((r) => {
12
- switch (r.type) {
13
- case "point": {
14
- return {
15
- regionType: "point",
16
- classification: r.cls,
17
- x: r.x,
18
- y: r.y,
19
- }
20
- }
21
- case "polygon": {
22
- return {
23
- regionType: "polygon",
24
- classification: r.cls,
25
- points: r.points.map(([x, y]) => ({ x, y })),
26
- }
27
- }
28
- case "box": {
29
- return {
30
- regionType: "bounding-box",
31
- classification: r.cls,
32
- centerX: r.x + r.w / 2,
33
- centerY: r.y + r.h / 2,
34
- width: r.w,
35
- height: r.h,
36
- }
37
- }
38
- default: {
39
- return null
40
- }
41
- }
42
- })
43
- .filter(Boolean)
44
- }
45
-
46
- export const ImageMask = ({
47
- regions,
48
- regionClsList,
49
- imageSrc,
50
- imagePosition,
51
- zIndex = 1,
52
- hide = false,
53
- autoSegmentationOptions = { type: "simple" },
54
- }) => {
55
- // if (!window.mmgc) window.mmgc = MMGC_INIT()
56
- // const mmgc = window.mmgc
57
- const [canvasRef, setCanvasRef] = useState(null)
58
-
59
- const [sampleImageData, setSampleImageData] = useState()
60
-
61
- useEffect(() => {
62
- if (!imageSrc) return
63
-
64
- loadImage(imageSrc).then((imageData) => {
65
- autoseg.setConfig({
66
- classNames: regionClsList,
67
- ...autoSegmentationOptions,
68
- })
69
- autoseg.loadImage(imageData)
70
- setSampleImageData(imageData)
71
- })
72
- }, [imageSrc])
73
-
74
- useDebounce(
75
- () => {
76
- if (hide) return
77
- if (!canvasRef) return
78
- if (!sampleImageData) return
79
- if (regions.filter((cp) => cp.cls).length < 2) return
80
-
81
- const udtRegions = convertToUDTRegions(regions)
82
-
83
- autoseg.getMask(udtRegions).then((maskImageData) => {
84
- const context = canvasRef.getContext("2d")
85
- context.clearRect(0, 0, maskImageData.width, maskImageData.height)
86
- context.putImageData(maskImageData, 0, 0)
87
- })
88
- },
89
- 1000,
90
- [canvasRef, sampleImageData, regions, hide]
91
- )
92
-
93
- const style = useMemo(() => {
94
- let width = imagePosition.bottomRight.x - imagePosition.topLeft.x
95
- let height = imagePosition.bottomRight.y - imagePosition.topLeft.y
96
- return {
97
- display: hide ? "none" : undefined,
98
- imageRendering: "pixelated",
99
- transform: "translateZ(0px)",
100
- left: imagePosition.topLeft.x,
101
- top: imagePosition.topLeft.y,
102
- width: isNaN(width) ? 0 : width,
103
- height: isNaN(height) ? 0 : height,
104
- zIndex,
105
- position: "absolute",
106
- pointerEvents: "none",
107
- }
108
- }, [
109
- imagePosition.topLeft.x,
110
- imagePosition.topLeft.y,
111
- imagePosition.bottomRight.x,
112
- imagePosition.bottomRight.y,
113
- zIndex,
114
- hide,
115
- ])
116
-
117
- return (
118
- <canvas
119
- style={style}
120
- width={sampleImageData ? sampleImageData.width : 0}
121
- height={sampleImageData ? sampleImageData.height : 0}
122
- ref={setCanvasRef}
123
- />
124
- )
125
- }
126
-
127
- export default ImageMask
@@ -1,32 +0,0 @@
1
- export const loadImage = (imageSrc) => {
2
- // Check if image is already loaded in a page element
3
- let image = Array.from(document.getElementsByTagName("img")).find(
4
- (img) => img.src === imageSrc
5
- )
6
-
7
- const canvas = document.createElement("canvas")
8
- const ctx = canvas.getContext("2d")
9
-
10
- if (!image) {
11
- image = new Image()
12
- image.crossOrigin = "anonymous"
13
- image.src = imageSrc
14
- }
15
-
16
- return new Promise((resolve, reject) => {
17
- image.onload = () => {
18
- canvas.width = image.naturalWidth
19
- canvas.height = image.naturalHeight
20
- ctx.drawImage(image, 0, 0)
21
- const imageData = ctx.getImageData(
22
- 0,
23
- 0,
24
- image.naturalWidth,
25
- image.naturalHeight
26
- )
27
- resolve(imageData)
28
- }
29
- })
30
- }
31
-
32
- export default loadImage
@@ -1,54 +0,0 @@
1
- // @flow
2
-
3
- import React, { memo } from "react"
4
- import { makeStyles } from "@mui/styles"
5
- import { createTheme, ThemeProvider } from "@mui/material/styles"
6
- import SidebarBoxContainer from "../SidebarBoxContainer"
7
- import CollectionsIcon from "@mui/icons-material/Collections"
8
- import { grey } from "@mui/material/colors"
9
- import List from "@mui/material/List"
10
- import ListItem from "@mui/material/ListItem"
11
- import ListItemText from "@mui/material/ListItemText"
12
- import Avatar from "@mui/material/Avatar"
13
- import isEqual from "lodash/isEqual"
14
-
15
- const theme = createTheme()
16
- const useStyles = makeStyles((theme) => ({
17
- img: { width: 40, height: 40, borderRadius: 8 },
18
- }))
19
-
20
- export const ImageSelectorSidebarBox = ({ images, onSelect }) => {
21
- const classes = useStyles()
22
- return (
23
- <ThemeProvider theme={theme}>
24
- <SidebarBoxContainer
25
- title="Images"
26
- subTitle={`(${images.length})`}
27
- icon={<CollectionsIcon style={{ color: grey[700] }} />}
28
- >
29
- <div>
30
- <List>
31
- {images.map((img, i) => (
32
- <ListItem button onClick={() => onSelect(img)} dense key={i}>
33
- <img className={classes.img} src={img.src} />
34
- <ListItemText
35
- primary={img.name}
36
- secondary={`${(img.regions || []).length} Labels`}
37
- />
38
- </ListItem>
39
- ))}
40
- </List>
41
- </div>
42
- </SidebarBoxContainer>
43
- </ThemeProvider>
44
- )
45
- }
46
-
47
- const mapUsedImageProps = (a) => [a.name, (a.regions || []).length, a.src]
48
-
49
- export default memo(ImageSelectorSidebarBox, (prevProps, nextProps) =>
50
- isEqual(
51
- prevProps.images.map(mapUsedImageProps),
52
- nextProps.images.map(mapUsedImageProps)
53
- )
54
- )
@@ -1,25 +0,0 @@
1
- // @flow
2
-
3
- const getTimeString = (ms, precision = 1) => {
4
- if (ms < 1000) {
5
- return ms + "ms"
6
- } else {
7
- const secs = ms / 1000
8
- if (secs < 60) {
9
- if (Number.isInteger(secs)) {
10
- return secs + "s"
11
- } else {
12
- return secs.toFixed(precision) + "s"
13
- }
14
- } else {
15
- const mins = secs / 60
16
- if (Number.isInteger(mins)) {
17
- return mins + "m"
18
- } else {
19
- return mins.toFixed(precision) + "m"
20
- }
21
- }
22
- }
23
- }
24
-
25
- export default getTimeString