lost-sia 2.0.0-alpha8 → 2.0.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lost-sia",
3
- "version": "2.0.0-alpha8",
3
+ "version": "2.0.0",
4
4
  "description": "Single Image Annotation Tool",
5
5
  "license": "MIT",
6
6
  "repository": "l3p-cv/lost-sia",
@@ -42,6 +42,7 @@
42
42
  "@fortawesome/free-regular-svg-icons": "^6.5.2",
43
43
  "@fortawesome/free-solid-svg-icons": "^6.5.2",
44
44
  "@fortawesome/react-fontawesome": "^0.2.0",
45
+ "lodash-es": "^4.17.21",
45
46
  "react": "^18.0.0",
46
47
  "react-dom": "^18.0.0",
47
48
  "react-draggable": "^4.4.6",
@@ -90,4 +91,4 @@
90
91
  "plugin:storybook/recommended"
91
92
  ]
92
93
  }
93
- }
94
+ }
@@ -281,6 +281,7 @@ class Annotation extends Component {
281
281
  // this.props.allowedActions,
282
282
  // this.state.anno
283
283
  // )
284
+ if (this.state.anno){console.log('ANNOTATION: ', this.state.anno.mode, this.state.anno)}
284
285
  switch (type) {
285
286
  case "point":
286
287
  return (
@@ -135,6 +135,11 @@ class Polygon extends Component {
135
135
  );
136
136
  }
137
137
  break;
138
+ case modes.ADD:
139
+ if (e.button === 0) {
140
+ this.removeNode(e, idx)
141
+ }
142
+ break;
138
143
  default:
139
144
  break;
140
145
  }
@@ -228,6 +233,17 @@ class Polygon extends Component {
228
233
  this.performedAction(newAnno, canvasActions.ANNO_ADDED_NODE);
229
234
  }
230
235
 
236
+ removeNode(e, idx) {
237
+ let newAnnoData = [...this.state.anno.data]
238
+ newAnnoData.splice(idx, 1)
239
+ const newAnno = {
240
+ ...this.state.anno,
241
+ data: newAnnoData,
242
+ };
243
+ this.setState({ anno: newAnno });
244
+ this.performedAction(newAnno, canvasActions.ANNO_REMOVED_SPECIFIC_NODE);
245
+ }
246
+
231
247
  removeLastNode() {
232
248
  const newAnno = {
233
249
  ...this.state.anno,
package/src/Canvas.jsx CHANGED
@@ -1,37 +1,29 @@
1
+ import _ from "lodash";
1
2
  import React, { Component } from "react";
2
- import _, { transform } from "lodash";
3
+ import { uniqueId } from "lodash-es";
3
4
  import Annotation from "./Annotation/Annotation";
4
5
  import AnnoLabelInput from "./AnnoLabelInput";
6
+ import AnnoToolBar from "./AnnoToolBar";
5
7
  import ImgBar from "./ImgBar";
6
- import Prompt from "./Prompt";
7
8
  import LabelInput from "./LabelInput";
8
- import AnnoToolBar from "./AnnoToolBar";
9
+ import Prompt from "./Prompt";
9
10
 
10
- import * as annoConversion from "./utils/annoConversion";
11
- import * as keyActions from "./utils/keyActions";
12
- import KeyMapper from "./utils/keyActions";
13
- import * as TOOLS from "./types/tools";
14
- import * as modes from "./types/modes";
15
- import UndoRedo from "./utils/hist";
16
- import * as transformAnnos from "./utils/transform";
11
+ import { Button, Dimmer, Header, Icon, Loader } from "semantic-ui-react";
17
12
  import * as annoStatus from "./types/annoStatus";
18
13
  import * as canvasActions from "./types/canvasActions";
19
- import {
20
- Loader,
21
- Dimmer,
22
- Icon,
23
- Header,
24
- Button,
25
- Form,
26
- TextArea,
27
- } from "semantic-ui-react";
28
- import * as mouse from "./utils/mouse";
29
- import * as colorlut from "./utils/colorlut";
14
+ import * as modes from "./types/modes";
30
15
  import * as notificationType from "./types/notificationType";
16
+ import * as TOOLS from "./types/tools";
17
+ import * as annoConversion from "./utils/annoConversion";
18
+ import * as colorlut from "./utils/colorlut";
19
+ import UndoRedo from "./utils/hist";
20
+ import KeyMapper, * as keyActions from "./utils/keyActions";
21
+ import * as mouse from "./utils/mouse";
22
+ import * as transformAnnos from "./utils/transform";
31
23
  import * as wv from "./utils/windowViewport";
32
24
 
33
- import "./SIA.scss";
34
25
  import InfoBoxes from "./InfoBoxes/InfoBoxArea";
26
+ import "./SIA.scss";
35
27
 
36
28
  /**
37
29
  * SIA Canvas element that handles annotations within an image
@@ -192,6 +184,8 @@ class Canvas extends Component {
192
184
  possibleLabels: undefined,
193
185
  annoCommentInputTrigger: 0,
194
186
  imgActions: [],
187
+ isDrawingSamBBox: false, // Flag to indicate if a SAM bbox is currently being drawn,
188
+ samBBoxStartPoint: null,
195
189
  };
196
190
  this.img = React.createRef();
197
191
  this.svg = React.createRef();
@@ -386,6 +380,13 @@ class Canvas extends Component {
386
380
  } else if (e.button === 1) {
387
381
  this.setMode(modes.CAMERA_MOVE);
388
382
  } else if (e.button === 2) {
383
+ if (
384
+ this.props.selectedTool === TOOLS.POSITIVE_POINT ||
385
+ this.props.selectedTool === TOOLS.NEGATIVE_POINT ||
386
+ this.props.selectedTool === TOOLS.SAM_BBOX
387
+ ) {
388
+ return; // do nothing for sam tools
389
+ }
389
390
  //Create annotation on right click
390
391
  this.createNewAnnotation(e);
391
392
  }
@@ -396,6 +397,13 @@ class Canvas extends Component {
396
397
  // this.collectAnnos()
397
398
  this.setMode(modes.CAMERA_MOVE);
398
399
  } else if (e.button === 2) {
400
+ if (
401
+ this.props.selectedTool === TOOLS.POSITIVE_POINT ||
402
+ this.props.selectedTool === TOOLS.NEGATIVE_POINT ||
403
+ this.props.selectedTool === TOOLS.SAM_BBOX
404
+ ) {
405
+ return; // Note: do nothing for sam tools
406
+ }
399
407
  //Create annotation on right click
400
408
  this.createNewAnnotation(e);
401
409
  } else if (e.button === 0) {
@@ -427,6 +435,7 @@ class Canvas extends Component {
427
435
  handleKeyAction(action) {
428
436
  const anno = this.findAnno(this.state.selectedAnnoId);
429
437
  const camKeyStepSize = 20 * this.state.svg.scale;
438
+ console.log('handleKeyAction', action, anno)
430
439
 
431
440
  switch (action) {
432
441
  case keyActions.EDIT_LABEL:
@@ -499,7 +508,7 @@ class Canvas extends Component {
499
508
  this.recreateAnnotation(this.state.selectedAnnoId);
500
509
  break;
501
510
  default:
502
- // console.warn("Unknown key action", action);
511
+ // console.warn("Unknown key action", action);
503
512
  }
504
513
  }
505
514
 
@@ -585,6 +594,7 @@ class Canvas extends Component {
585
594
  // console.log("handleAnnoEvent", pAction, anno);
586
595
  let newAnnos = undefined;
587
596
  let actionHistoryStore = undefined;
597
+ console.log('canvasActions: ', anno, pAction)
588
598
 
589
599
  switch (pAction) {
590
600
  case canvasActions.ANNO_ENTER_CREATE_MODE:
@@ -644,7 +654,7 @@ class Canvas extends Component {
644
654
  break;
645
655
  case canvasActions.ANNO_ADDED_NODE:
646
656
  actionHistoryStore = [...this.state.imgActions, pAction];
647
- newAnnos = this.updateSelectedAnno(anno, modes.VIEW);
657
+ newAnnos = this.updateSelectedAnno(anno, modes.ADD);
648
658
  this.pushHist(newAnnos, anno.id, pAction, this.state.showSingleAnno);
649
659
  this.handleAnnoSaveEvent(pAction, anno, {
650
660
  imgActions: actionHistoryStore,
@@ -665,6 +675,21 @@ class Canvas extends Component {
665
675
  });
666
676
  }
667
677
  break;
678
+ case canvasActions.ANNO_REMOVED_SPECIFIC_NODE:
679
+ actionHistoryStore = [...this.state.imgActions, pAction];
680
+ if (!this.checkAnnoLength(anno)) {
681
+ newAnnos = this.updateSelectedAnno(anno, modes.DELETED);
682
+ this.showSingleAnno(undefined);
683
+ } else {
684
+ newAnnos = this.updateSelectedAnno(anno, modes.ADD)
685
+ }
686
+ this.pushHist(newAnnos, anno.id, pAction, this.state.showSingleAnno);
687
+ if (anno.status !== annoStatus.NEW) {
688
+ this.handleAnnoSaveEvent(pAction, anno, {
689
+ imgActions: actionHistoryStore,
690
+ });
691
+ }
692
+ break;
668
693
  case canvasActions.ANNO_EDITED:
669
694
  actionHistoryStore = [...this.state.imgActions, pAction];
670
695
  anno = this.stopAnnotimeMeasure(anno);
@@ -860,6 +885,53 @@ class Canvas extends Component {
860
885
  }
861
886
  }
862
887
 
888
+ handleContextMenu(e) {
889
+ e.preventDefault();
890
+ if (
891
+ this.props.selectedTool === TOOLS.POSITIVE_POINT ||
892
+ this.props.selectedTool === TOOLS.NEGATIVE_POINT
893
+ ) {
894
+ const { x, y } = this.getMousePosition(e);
895
+
896
+ const imgWidth = this.state.svg.width - 2 * this.state.imageOffset.x;
897
+ const imgHeight = this.state.svg.height - 2 * this.state.imageOffset.y;
898
+
899
+ const normX = (x - this.state.imageOffset.x) / imgWidth;
900
+ const normY = (y - this.state.imageOffset.y) / imgHeight;
901
+
902
+ const type =
903
+ this.props.selectedTool === TOOLS.POSITIVE_POINT
904
+ ? "positive"
905
+ : "negative";
906
+
907
+ this.props.onSamPointClick(x, y, normX, normY, type);
908
+ }
909
+ }
910
+
911
+ handleMouseDown(e) {
912
+ if (this.props.selectedTool === TOOLS.SAM_BBOX) {
913
+ if (e.button !== 2) {
914
+ return;
915
+ }
916
+
917
+ e.preventDefault();
918
+ const { x, y } = this.getMousePosition(e);
919
+
920
+ this.setState({
921
+ isDrawingSamBBox: true,
922
+ samBBoxStartPoint: { x, y },
923
+ });
924
+
925
+ // start a new rectangle
926
+ this.props.onUpdateSamBBox({
927
+ x,
928
+ y,
929
+ width: 0,
930
+ height: 0,
931
+ });
932
+ }
933
+ }
934
+
863
935
  handleImgBarMouseEnter(e) {
864
936
  this.setState({ imgBarVisible: false });
865
937
  }
@@ -870,6 +942,64 @@ class Canvas extends Component {
870
942
 
871
943
  handleSvgMouseMove(e) {
872
944
  this.mousePosAbs = mouse.getMousePositionAbs(e, this.state.svg);
945
+
946
+ if (this.props.selectedTool === TOOLS.SAM_BBOX) {
947
+ if (!this.state.isDrawingSamBBox || !this.state.samBBoxStartPoint) {
948
+ // If not drawing a SAM bbox, do nothing
949
+ return;
950
+ }
951
+
952
+ const { x, y } = this.getMousePosition(e);
953
+ const startPoint = this.state.samBBoxStartPoint;
954
+
955
+ const imgWidth = this.state.svg.width - 2 * this.state.imageOffset.x;
956
+ const imgHeight = this.state.svg.height - 2 * this.state.imageOffset.y;
957
+
958
+ const xMin = Math.min(startPoint.x, x);
959
+ const yMin = Math.min(startPoint.y, y);
960
+ const width = Math.abs(x - startPoint.x);
961
+ const height = Math.abs(y - startPoint.y);
962
+
963
+ // normalized coordinates
964
+ const xMinNorm = (xMin - this.state.imageOffset.x) / imgWidth;
965
+ const yMinNorm = (yMin - this.state.imageOffset.y) / imgHeight;
966
+ const xMaxNorm = (xMin + width - this.state.imageOffset.x) / imgWidth;
967
+ const yMaxNorm = (yMin + height - this.state.imageOffset.y) / imgHeight;
968
+
969
+ // update the rectangle with the new width and height
970
+ this.props.onUpdateSamBBox({
971
+ x: xMin,
972
+ y: yMin,
973
+ width,
974
+ height,
975
+ xMinNorm,
976
+ yMinNorm,
977
+ xMaxNorm,
978
+ yMaxNorm,
979
+ });
980
+ }
981
+ }
982
+
983
+ handleMouseUp(e) {
984
+ if (this.props.selectedTool === TOOLS.SAM_BBOX) {
985
+ if (e.button !== 2) {
986
+ return;
987
+ }
988
+
989
+ e.preventDefault();
990
+ this.setState({
991
+ isDrawingSamBBox: false,
992
+ });
993
+ }
994
+ }
995
+
996
+ handleMouseLeave(e) {
997
+ if (this.props.selectedTool === TOOLS.SAM_BBOX) {
998
+ // If mouse leaves the canvas while drawing a SAM bbox, reset the state
999
+ this.setState({
1000
+ isDrawingSamBBox: false,
1001
+ });
1002
+ }
873
1003
  }
874
1004
 
875
1005
  handleNotification(messageObj) {
@@ -929,7 +1059,7 @@ class Canvas extends Component {
929
1059
  // const corrected = transform.correctAnnotation(anno.data, this.props.svg, this.props.imageOffset)
930
1060
  if (this.clipboard) {
931
1061
  // let annos = [...this.state.annos]
932
- const uid = _.uniqueId("new");
1062
+ const uid = uniqueId("new");
933
1063
  // this.handleAnnoEvent()
934
1064
  const newData = this.clipboard.data.map((e) => {
935
1065
  return { x: e.x + offset, y: e.y + offset };
@@ -1333,6 +1463,7 @@ class Canvas extends Component {
1333
1463
  //Do not create new Annotation if controlKey was pressed!
1334
1464
  let allowed = false;
1335
1465
  if (this.keyMapper.controlDown) return;
1466
+ if (this.keyMapper.shiftDown) return;
1336
1467
  if (this.props.selectedTool) {
1337
1468
  const maxAnnos = this.props.canvasConfig.annos.maxAnnos;
1338
1469
  if (maxAnnos) {
@@ -1364,7 +1495,7 @@ class Canvas extends Component {
1364
1495
  const mousePos = this.getMousePosition(e);
1365
1496
  // const selAnno = this.findAnno(this.state.selectedAnnoId)
1366
1497
  let newAnno = {
1367
- id: this.props.nextAnnoId ? this.props.nextAnnoId : _.uniqueId("new"),
1498
+ id: this.props.nextAnnoId ? this.props.nextAnnoId : uniqueId("new"),
1368
1499
  type: this.props.selectedTool,
1369
1500
  data: [
1370
1501
  {
@@ -1587,6 +1718,7 @@ class Canvas extends Component {
1587
1718
  * the new annos list that was set in state
1588
1719
  */
1589
1720
  updateSelectedAnno(anno, mode = undefined, returnNewAnno = false) {
1721
+ // console.log('updateSelectedAnno: ', mode, anno)
1590
1722
  if (!anno) return;
1591
1723
  const { newAnnos, newAnno } = this.mergeSelectedAnno(anno, mode);
1592
1724
  this.setState({
@@ -1878,6 +2010,34 @@ class Canvas extends Component {
1878
2010
  );
1879
2011
  }
1880
2012
 
2013
+ renderSamPoints() {
2014
+ return this.props.samPoints.map((point, index) => (
2015
+ <circle
2016
+ key={index}
2017
+ cx={point.x}
2018
+ cy={point.y}
2019
+ r={5}
2020
+ fill={point.type === "positive" ? "lightgreen" : "lightcoral"}
2021
+ />
2022
+ ));
2023
+ }
2024
+
2025
+ renderSamBBox() {
2026
+ return (
2027
+ this.props.samBBox && (
2028
+ <rect
2029
+ x={this.props.samBBox.x}
2030
+ y={this.props.samBBox.y}
2031
+ width={this.props.samBBox.width}
2032
+ height={this.props.samBBox.height}
2033
+ fill="rgba(0, 0, 255, 0.1)"
2034
+ stroke="blue"
2035
+ strokeWidth="2"
2036
+ />
2037
+ )
2038
+ );
2039
+ }
2040
+
1881
2041
  render() {
1882
2042
  const selectedAnno = this.findAnno(this.state.selectedAnnoId);
1883
2043
  return (
@@ -1970,6 +2130,10 @@ class Canvas extends Component {
1970
2130
  onKeyUp={(e) => this.onKeyUp(e)}
1971
2131
  onClick={(e) => this.handleCanvasClick(e)}
1972
2132
  onMouseMove={(e) => this.handleSvgMouseMove(e)}
2133
+ onContextMenu={(e) => this.handleContextMenu(e)}
2134
+ onMouseDown={(e) => this.handleMouseDown(e)}
2135
+ onMouseUp={(e) => this.handleMouseUp(e)}
2136
+ onMouseLeave={(e) => this.handleMouseLeave(e)}
1973
2137
  tabIndex="0"
1974
2138
  >
1975
2139
  <g
@@ -2005,6 +2169,8 @@ class Canvas extends Component {
2005
2169
  }
2006
2170
  />
2007
2171
  {this.renderAnnotations()}
2172
+ {this.renderSamPoints()}
2173
+ {this.renderSamBBox()}
2008
2174
  </g>
2009
2175
  </svg>
2010
2176
  <img
package/src/Sia.jsx CHANGED
@@ -1,10 +1,10 @@
1
- import React, { useRef, useEffect, useState } from "react";
1
+ import React, { useEffect, useRef, useState } from "react";
2
2
 
3
- import ToolBar from "./ToolBar";
4
3
  import Canvas from "./Canvas";
5
- import * as tbe from "./types/toolbarEvents";
6
- import * as annoActions from "./types/canvasActions";
7
4
  import { noAnnos } from "./siaDummyData";
5
+ import ToolBar from "./ToolBar";
6
+ import * as annoActions from "./types/canvasActions";
7
+ import * as tbe from "./types/toolbarEvents";
8
8
 
9
9
  /**
10
10
  * SIA element that handles annotations within an image
@@ -446,6 +446,10 @@ const Sia = (props) => {
446
446
  isImageChanging={props.isImageChanging}
447
447
  isStaticPosition={props.isStaticPosition}
448
448
  fixedImageSize={props.fixedImageSize}
449
+ samPoints={props.samPoints || []}
450
+ onSamPointClick={props.onSamPointClick}
451
+ samBBox={props.samBBox || null}
452
+ onUpdateSamBBox={props.onUpdateSamBBox}
449
453
  />
450
454
  <ToolBar
451
455
  onToolBarEvent={(e, data) => handleToolBarEvent(e, data)}
package/src/ToolBar.jsx CHANGED
@@ -1,11 +1,16 @@
1
- import React, { useState, useEffect, useRef } from "react";
2
- import { Button, Card } from "semantic-ui-react";
1
+ import {
2
+ faPaperPlane,
3
+ faSquare,
4
+ faTrashCan,
5
+ } from "@fortawesome/free-regular-svg-icons";
3
6
  import {
4
7
  faArrowLeft,
5
8
  faArrowRight,
6
9
  faBan,
7
10
  faCheck,
8
11
  faMaximize,
12
+ faMinusCircle,
13
+ faPlusCircle,
9
14
  faQuestion,
10
15
  faSave,
11
16
  faSearch,
@@ -13,18 +18,19 @@ import {
13
18
  faTrash,
14
19
  faVectorSquare,
15
20
  } from "@fortawesome/free-solid-svg-icons";
16
- import { faPaperPlane } from "@fortawesome/free-regular-svg-icons";
17
- import SIASettingButton from "./SIASettingButton";
18
- import SIAFilterButton from "./SIAFilterButton";
21
+ import React, { useEffect, useRef, useState } from "react";
22
+ import { Button, Card } from "semantic-ui-react";
19
23
  import Prompt from "./Prompt";
24
+ import SIAFilterButton from "./SIAFilterButton";
25
+ import SIASettingButton from "./SIASettingButton";
20
26
  import "./Toolbar.css";
21
27
 
22
- import * as TOOLS from "./types/tools";
23
- import * as siaIcons from "./utils/siaIcons";
24
- import * as tbe from "./types/toolbarEvents";
25
28
  import { CSidebar, CSidebarNav } from "@coreui/react";
26
- import ToolbarItem from "./ToolbarItem";
27
29
  import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
30
+ import ToolbarItem from "./ToolbarItem";
31
+ import * as tbe from "./types/toolbarEvents";
32
+ import * as TOOLS from "./types/tools";
33
+ import * as siaIcons from "./utils/siaIcons";
28
34
 
29
35
  const ToolBar = (props) => {
30
36
  const [position, setPosition] = useState({
@@ -125,6 +131,44 @@ const ToolBar = (props) => {
125
131
  if (!props.enabled.toolSelection) return null;
126
132
  if (!props.canvasConfig.annos.actions.draw) return null;
127
133
  let btns = [];
134
+
135
+ if (props.canvasConfig.tools.sam) {
136
+ btns.push(
137
+ <ToolbarItem
138
+ color="#0081FB"
139
+ active={props.active.selectedTool === TOOLS.POSITIVE_POINT}
140
+ onClick={(e) => onClick(e, TOOLS.POSITIVE_POINT)}
141
+ faIcon={faPlusCircle}
142
+ />,
143
+ );
144
+
145
+ btns.push(
146
+ <ToolbarItem
147
+ color="#0081FB"
148
+ active={props.active.selectedTool === TOOLS.NEGATIVE_POINT}
149
+ onClick={(e) => onClick(e, TOOLS.NEGATIVE_POINT)}
150
+ faIcon={faMinusCircle}
151
+ />,
152
+ );
153
+
154
+ btns.push(
155
+ <ToolbarItem
156
+ color="#0081FB"
157
+ active={props.active.selectedTool === TOOLS.SAM_BBOX}
158
+ onClick={(e) => onClick(e, TOOLS.SAM_BBOX)}
159
+ faIcon={faSquare}
160
+ />,
161
+ );
162
+
163
+ btns.push(
164
+ <ToolbarItem
165
+ color="#0081FB"
166
+ onClick={(e) => triggerToolBarEvent(tbe.CLEAR_SAM_HELPER_ANNOS)}
167
+ faIcon={faTrashCan}
168
+ />,
169
+ );
170
+ }
171
+
128
172
  if (props.canvasConfig.tools.point) {
129
173
  btns.push(
130
174
  <ToolbarItem
@@ -279,8 +323,9 @@ const ToolBar = (props) => {
279
323
  <Card.Content description="Redo: Hit STRG + R" />
280
324
  </Card>
281
325
  <Card>
282
- <Card.Content header="Add a node to Line/Polygon" />
283
- <Card.Content description="Hit STRG + Click left on the line" />
326
+ <Card.Content header="Add/ Remove a node to Line/Polygon" />
327
+ <Card.Content description="Add: Hit STRG + Click left on the line" />
328
+ <Card.Content description="Remove: Hit STRG + Click left on the node to delete" />
284
329
  </Card>
285
330
  <Card>
286
331
  <Card.Content header="Remove a node from Line/Polygon in create mode" />
@@ -8,8 +8,8 @@ const ToolbarItem = ({
8
8
  faIcon,
9
9
  siaIcon,
10
10
  onClick,
11
+ color = "white",
11
12
  }) => {
12
- let color = "white";
13
13
  if (active) color = "red";
14
14
  if (disabled) color = "grey";
15
15
 
package/src/index.js CHANGED
@@ -4,13 +4,13 @@ import './SIA.scss'
4
4
 
5
5
  // import { default as Canvas } from './Canvas'
6
6
  // import { default as Toolbar } from './ToolBar'
7
- export { default as Canvas } from "./Canvas.js";
7
+ export { default as Canvas } from "./Canvas.jsx";
8
8
 
9
9
  // export { Canvas }
10
10
  // export { Toolbar }
11
11
 
12
12
 
13
- export { default as Sia } from './Sia.js'
13
+ export { default as Sia } from './Sia.jsx'
14
14
  export { default as dummyData } from './siaDummyData.js'
15
15
  export { default as transform } from './utils/transform.js'
16
16
  export { default as annoConversion } from './utils/annoConversion.js'
@@ -8,6 +8,7 @@ export const ANNO_EDITED = "annoEdited";
8
8
  export const ANNO_ENTER_EDIT_MODE = "annoEnterEditMode";
9
9
  export const ANNO_ADDED_NODE = "annoAddedNode";
10
10
  export const ANNO_REMOVED_NODE = "annoRemovedNode";
11
+ export const ANNO_REMOVED_SPECIFIC_NODE = "annoRemovedSpecificNode";
11
12
  export const ANNO_LABEL_UPDATE = "annoLabelUpdate";
12
13
  export const ANNO_CREATED_NODE = "annoCreatedNode";
13
14
  export const ANNO_CREATED_FINAL_NODE = "annoCreatedFinalNode";
@@ -3,6 +3,7 @@ export const EDIT = "edit";
3
3
  export const CREATE = "create";
4
4
  export const MOVE = "move";
5
5
  export const ADD = "add";
6
+ export const REMOVE_NODE = "removeNode";
6
7
  export const CAMERA_MOVE = "cameraMove";
7
8
  export const EDIT_LABEL = "editLabel";
8
9
  export const DELETED = "deleted";
@@ -13,6 +13,7 @@ export const EDIT_STROKE_WIDTH = "editStrokeWidth";
13
13
  export const EDIT_NODE_RADIUS = "editNodeRadius";
14
14
  export const APPLY_FILTER = "applyFilter";
15
15
  export const SAVE = "save";
16
+ export const CLEAR_SAM_HELPER_ANNOS = "clearSamHelperAnnos"; // for clearing SAM helper annotations
16
17
 
17
18
  export default {
18
19
  TOOL_SELECTED,
@@ -30,4 +31,5 @@ export default {
30
31
  EDIT_NODE_RADIUS,
31
32
  APPLY_FILTER,
32
33
  SAVE,
34
+ CLEAR_POINTS: CLEAR_SAM_HELPER_ANNOS,
33
35
  };
@@ -2,10 +2,16 @@ export const POINT = "point";
2
2
  export const BBOX = "bBox";
3
3
  export const LINE = "line";
4
4
  export const POLYGON = "polygon";
5
+ export const POSITIVE_POINT = "positivePoint"; // for positive point SAM
6
+ export const NEGATIVE_POINT = "negativePoint"; // for negative point SAM
7
+ export const SAM_BBOX = "samBBox"; // bbox for guiding SAM
5
8
 
6
9
  export default {
7
10
  POINT,
8
11
  BBOX,
9
12
  LINE,
10
13
  POLYGON,
14
+ POSITIVE_POINT,
15
+ NEGATIVE_POINT,
16
+ SAM_BBOX,
11
17
  };
@@ -1,12 +1,12 @@
1
1
  import * as transform from "./transform";
2
2
  import * as annoStatus from "../types/annoStatus";
3
3
  import * as modes from "../types/modes";
4
- import _ from "lodash";
4
+ import { uniqueId } from "lodash-es";
5
5
 
6
6
  function _fixBackendAnnoElement(element) {
7
7
  return {
8
8
  ...element,
9
- id: element.id ? element.id : _.uniqueId("new"),
9
+ id: element.id ? element.id : uniqueId("new"),
10
10
  annoTime: element.annoTime ? element.annoTime : 0.0,
11
11
  mode: element.mode ? element.mode : modes.VIEW,
12
12
  status: element.status ? element.status : annoStatus.DATABASE,
@@ -19,6 +19,7 @@ export const TOGGLE_ANNO_COMMENT_INPUT = "toggleAnnoCommentInput";
19
19
  class KeyMapper {
20
20
  constructor(keyActionHandler = undefined) {
21
21
  this.controlDown = false;
22
+ this.shiftDown = false;
22
23
  this.keyActionHandler = keyActionHandler;
23
24
  }
24
25
 
@@ -37,6 +38,9 @@ class KeyMapper {
37
38
  this.controlDown = true;
38
39
  this.triggerKeyAction(ENTER_ANNO_ADD_MODE);
39
40
  break;
41
+ case "Shift":
42
+ this.shiftDown = true;
43
+ break;
40
44
  case "z":
41
45
  if (this.controlDown) {
42
46
  this.triggerKeyAction(UNDO);
@@ -91,6 +95,9 @@ class KeyMapper {
91
95
  this.controlDown = false;
92
96
  this.triggerKeyAction(LEAVE_ANNO_ADD_MODE);
93
97
  break;
98
+ case "Shift":
99
+ this.shiftDown = false;
100
+ break;
94
101
  default:
95
102
  break;
96
103
  }