@searpent/react-image-annotate 2.0.1 → 2.0.2

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 (173) hide show
  1. package/Annotator/index.js +161 -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/HighlightBox/index.js +99 -0
  19. package/HistorySidebarBox/index.js +71 -0
  20. package/ImageCanvas/index.js +424 -0
  21. package/ImageCanvas/region-tools.js +165 -0
  22. package/{src/ImageCanvas → ImageCanvas}/styles.js +12 -8
  23. package/ImageCanvas/use-mouse.js +180 -0
  24. package/ImageCanvas/use-project-box.js +27 -0
  25. package/ImageCanvas/use-wasd-mode.js +62 -0
  26. package/ImageMask/index.js +133 -0
  27. package/ImageMask/load-image.js +25 -0
  28. package/ImageSelectorSidebarBox/index.js +60 -0
  29. package/KeyframeTimeline/get-time-string.js +27 -0
  30. package/KeyframeTimeline/index.js +233 -0
  31. package/KeyframesSelectorSidebarBox/index.js +93 -0
  32. package/LandingPage/index.js +159 -0
  33. package/MainLayout/icon-dictionary.js +104 -0
  34. package/MainLayout/index.js +352 -0
  35. package/{src/MainLayout → MainLayout}/styles.js +6 -7
  36. package/MainLayout/types.js +0 -0
  37. package/MainLayout/use-implied-video-regions.js +13 -0
  38. package/PointDistances/index.js +73 -0
  39. package/PreventScrollToParents/index.js +51 -0
  40. package/RegionLabel/index.js +191 -0
  41. package/{src/RegionLabel → RegionLabel}/styles.js +12 -15
  42. package/RegionSelectAndTransformBoxes/index.js +167 -0
  43. package/RegionSelectorSidebarBox/index.js +248 -0
  44. package/{src/RegionSelectorSidebarBox → RegionSelectorSidebarBox}/styles.js +13 -14
  45. package/RegionShapes/index.js +274 -0
  46. package/RegionTags/index.js +138 -0
  47. package/SettingsDialog/index.js +52 -0
  48. package/SettingsProvider/index.js +53 -0
  49. package/Shortcuts/ShortcutField.js +46 -0
  50. package/Shortcuts/index.js +133 -0
  51. package/ShortcutsManager/index.js +155 -0
  52. package/Sidebar/index.js +69 -0
  53. package/SidebarBoxContainer/index.js +93 -0
  54. package/SmallToolButton/index.js +42 -0
  55. package/TagsSidebarBox/index.js +105 -0
  56. package/TaskDescriptionSidebarBox/index.js +58 -0
  57. package/Theme/index.js +30 -0
  58. package/VideoOrImageCanvasBackground/index.js +151 -0
  59. package/colors.js +14 -0
  60. package/hooks/use-event-callback.js +10 -0
  61. package/hooks/use-exclude-pattern.js +24 -0
  62. package/hooks/use-load-image.js +26 -0
  63. package/hooks/use-window-size.js +46 -0
  64. package/{src/hooks → hooks}/xpattern.js +1 -1
  65. package/index.js +3 -0
  66. package/lib.js +3 -0
  67. package/package.json +1 -1
  68. package/stories.js +5 -0
  69. package/utils/get-from-local-storage.js +7 -0
  70. package/utils/get-hotkey-help-text.js +9 -0
  71. package/utils/get-landmarks-with-transform.js +40 -0
  72. package/utils/set-in-local-storage.js +3 -0
  73. package/.babelrc +0 -6
  74. package/.env +0 -1
  75. package/.flowconfig +0 -2
  76. package/.github/workflows/release-on-master.yml +0 -32
  77. package/.github/workflows/test.yml +0 -16
  78. package/.prettierrc +0 -3
  79. package/.releaserc.js +0 -18
  80. package/.storybook/addons.js +0 -2
  81. package/.storybook/config.js +0 -16
  82. package/LICENSE +0 -21
  83. package/public/favicon.ico +0 -0
  84. package/public/index.html +0 -38
  85. package/src/Annotator/bike-pic.png +0 -0
  86. package/src/Annotator/bike-pic2.png +0 -0
  87. package/src/Annotator/dab-keyframes.story.json +0 -1
  88. package/src/Annotator/index.js +0 -211
  89. package/src/Annotator/index.story.js +0 -758
  90. package/src/Annotator/poses.story.js +0 -150
  91. package/src/Annotator/reducers/combine-reducers.js +0 -7
  92. package/src/Annotator/reducers/convert-expanding-line-to-polygon.js +0 -53
  93. package/src/Annotator/reducers/general-reducer.js +0 -914
  94. package/src/Annotator/reducers/get-active-image.js +0 -21
  95. package/src/Annotator/reducers/get-implied-video-regions.js +0 -115
  96. package/src/Annotator/reducers/history-handler.js +0 -60
  97. package/src/Annotator/reducers/image-reducer.js +0 -23
  98. package/src/Annotator/reducers/video-reducer.js +0 -85
  99. package/src/Annotator/video.story.js +0 -51
  100. package/src/ClassSelectionMenu/index.js +0 -108
  101. package/src/Crosshairs/index.js +0 -64
  102. package/src/DebugSidebarBox/index.js +0 -36
  103. package/src/DemoSite/Editor.js +0 -235
  104. package/src/DemoSite/ErrorBoundaryDialog.js +0 -34
  105. package/src/DemoSite/index.js +0 -41
  106. package/src/DemoSite/index.story.js +0 -10
  107. package/src/DemoSite/simple-segmentation-example.json +0 -572
  108. package/src/FullImageSegmentationAnnotator/hard1.story.jpg +0 -0
  109. package/src/FullImageSegmentationAnnotator/hard2.story.jpg +0 -0
  110. package/src/FullImageSegmentationAnnotator/hard3.story.jpg +0 -0
  111. package/src/FullImageSegmentationAnnotator/index.js +0 -7
  112. package/src/FullImageSegmentationAnnotator/index.story.js +0 -177
  113. package/src/FullImageSegmentationAnnotator/orange.story.png +0 -0
  114. package/src/HighlightBox/index.js +0 -143
  115. package/src/HistorySidebarBox/index.js +0 -78
  116. package/src/ImageCanvas/dancing-man.story.jpg +0 -0
  117. package/src/ImageCanvas/index.js +0 -488
  118. package/src/ImageCanvas/index.story.js +0 -214
  119. package/src/ImageCanvas/mouse_mask.story.png +0 -0
  120. package/src/ImageCanvas/region-tools.js +0 -171
  121. package/src/ImageCanvas/seves_desk.story.jpg +0 -0
  122. package/src/ImageCanvas/use-mouse.js +0 -168
  123. package/src/ImageCanvas/use-project-box.js +0 -23
  124. package/src/ImageCanvas/use-wasd-mode.js +0 -50
  125. package/src/ImageMask/index.js +0 -127
  126. package/src/ImageMask/load-image.js +0 -32
  127. package/src/ImageSelectorSidebarBox/index.js +0 -54
  128. package/src/KeyframeTimeline/get-time-string.js +0 -25
  129. package/src/KeyframeTimeline/index.js +0 -223
  130. package/src/KeyframesSelectorSidebarBox/index.js +0 -93
  131. package/src/LandingPage/content.md +0 -57
  132. package/src/LandingPage/github-markdown.css +0 -964
  133. package/src/LandingPage/index.js +0 -147
  134. package/src/MainLayout/icon-dictionary.js +0 -79
  135. package/src/MainLayout/index.js +0 -420
  136. package/src/MainLayout/index.story.js +0 -240
  137. package/src/MainLayout/types.js +0 -156
  138. package/src/MainLayout/use-implied-video-regions.js +0 -17
  139. package/src/PointDistances/index.js +0 -90
  140. package/src/PreventScrollToParents/index.js +0 -48
  141. package/src/PreventScrollToParents/index.story.js +0 -23
  142. package/src/RegionLabel/index.js +0 -201
  143. package/src/RegionSelectAndTransformBoxes/index.js +0 -234
  144. package/src/RegionSelectorSidebarBox/index.js +0 -216
  145. package/src/RegionShapes/index.js +0 -236
  146. package/src/RegionTags/index.js +0 -130
  147. package/src/SettingsDialog/index.js +0 -58
  148. package/src/SettingsProvider/index.js +0 -44
  149. package/src/Shortcuts/ShortcutField.js +0 -44
  150. package/src/Shortcuts/index.js +0 -129
  151. package/src/ShortcutsManager/index.js +0 -162
  152. package/src/Sidebar/index.js +0 -117
  153. package/src/SidebarBoxContainer/index.js +0 -93
  154. package/src/SmallToolButton/index.js +0 -57
  155. package/src/TagsSidebarBox/index.js +0 -93
  156. package/src/TaskDescriptionSidebarBox/index.js +0 -43
  157. package/src/Theme/index.js +0 -36
  158. package/src/VideoOrImageCanvasBackground/index.js +0 -170
  159. package/src/colors.js +0 -32
  160. package/src/hooks/use-event-callback.js +0 -11
  161. package/src/hooks/use-exclude-pattern.js +0 -27
  162. package/src/hooks/use-load-image.js +0 -21
  163. package/src/hooks/use-window-size.js +0 -46
  164. package/src/hooks/xpattern.png +0 -0
  165. package/src/index.js +0 -18
  166. package/src/lib.js +0 -7
  167. package/src/screenshot.png +0 -0
  168. package/src/site.css +0 -5
  169. package/src/stories.js +0 -2
  170. package/src/utils/get-from-local-storage.js +0 -7
  171. package/src/utils/get-hotkey-help-text.js +0 -11
  172. package/src/utils/get-landmarks-with-transform.js +0 -23
  173. 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