lost-sia 1.2.0 → 2.0.0-alpha0
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/LICENSE +21 -0
- package/README.md +0 -0
- package/package.json +60 -47
- package/src/AnnoExampleViewer.jsx +57 -0
- package/src/AnnoLabelInput.jsx +99 -0
- package/src/AnnoToolBar.jsx +132 -0
- package/src/Annotation/AnnoBar.jsx +148 -0
- package/src/Annotation/Annotation.jsx +358 -0
- package/src/Annotation/Annotation.scss +47 -0
- package/src/Annotation/BBox.jsx +291 -0
- package/src/Annotation/Edge.jsx +82 -0
- package/src/Annotation/InfSelectionArea.jsx +71 -0
- package/src/Annotation/Line.jsx +60 -0
- package/src/Annotation/Node.jsx +278 -0
- package/src/Annotation/Point.jsx +196 -0
- package/src/Annotation/Polygon.jsx +361 -0
- package/src/Canvas.jsx +1839 -0
- package/src/ImgBar.jsx +123 -0
- package/src/InfoBoxes/AnnoDetails.jsx +166 -0
- package/src/InfoBoxes/AnnoStats.jsx +104 -0
- package/src/InfoBoxes/InfoBox.jsx +78 -0
- package/src/InfoBoxes/InfoBoxArea.jsx +155 -0
- package/src/InfoBoxes/LabelInfo.jsx +95 -0
- package/src/LabelInput.jsx +224 -0
- package/src/Prompt.jsx +46 -0
- package/src/SIA.scss +10 -0
- package/src/SIAFilterButton.jsx +178 -0
- package/src/SIASettingButton.jsx +122 -0
- package/src/Sia.jsx +485 -0
- package/src/SiaPopup.jsx +10 -0
- package/src/ToolBar.jsx +399 -0
- package/src/Toolbar.css +13 -0
- package/src/ToolbarItem.jsx +25 -0
- package/src/filterTools.js +3 -0
- package/src/index.js +17 -0
- package/src/siaDummyData.js +265 -0
- package/src/test.js +7 -0
- package/src/types/annoStatus.js +4 -0
- package/src/types/canvasActions.js +57 -0
- package/src/types/cursorstyles.js +3 -0
- package/src/types/modes.js +8 -0
- package/src/types/notificationType.js +4 -0
- package/src/types/toolbarEvents.js +33 -0
- package/src/types/tools.js +11 -0
- package/src/utils/annoConversion.js +115 -0
- package/src/utils/colorlut.js +67 -0
- package/src/utils/constraints.js +75 -0
- package/src/utils/hist.js +67 -0
- package/src/utils/keyActions.js +107 -0
- package/src/utils/mouse.js +14 -0
- package/src/utils/siaIcons.jsx +95 -0
- package/src/utils/transform.js +318 -0
- package/src/utils/uiConfig.js +57 -0
- package/src/utils/windowViewport.js +35 -0
- package/CHANGELOG.md +0 -163
- package/dist/index.css +0 -24823
- package/dist/index.es.js +0 -10431
- package/dist/index.es.js.map +0 -1
- package/dist/index.js +0 -10446
- package/dist/index.js.map +0 -1
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
export function toSia(data, image, type, imgOffset) {
|
|
2
|
+
switch (type) {
|
|
3
|
+
case 'bBox':
|
|
4
|
+
const w = image.width * data.w
|
|
5
|
+
const h = image.height * data.h
|
|
6
|
+
const x0 = imgOffset.x + image.width * data.x - w / 2.0
|
|
7
|
+
const y0 = imgOffset.y + image.height * data.y - h / 2.0
|
|
8
|
+
return [
|
|
9
|
+
{
|
|
10
|
+
x: x0,
|
|
11
|
+
y: y0
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
x: x0 + w,
|
|
15
|
+
y: y0
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
x: x0 + w,
|
|
19
|
+
y: y0 + h
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
x: x0,
|
|
23
|
+
y: y0 + h
|
|
24
|
+
}
|
|
25
|
+
]
|
|
26
|
+
case 'point':
|
|
27
|
+
return [{
|
|
28
|
+
x: imgOffset.x + image.width * data.x,
|
|
29
|
+
y: imgOffset.y + image.height * data.y
|
|
30
|
+
}]
|
|
31
|
+
case 'line':
|
|
32
|
+
case 'polygon':
|
|
33
|
+
return data.map((e) => {
|
|
34
|
+
return {
|
|
35
|
+
x: imgOffset.x + image.width * e.x,
|
|
36
|
+
y: imgOffset.y + image.height * e.y
|
|
37
|
+
}
|
|
38
|
+
})
|
|
39
|
+
default:
|
|
40
|
+
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Transform a sia annotation to backend format.
|
|
46
|
+
*
|
|
47
|
+
* @param {Array} data Annotation data
|
|
48
|
+
* @param {*} svg Image object {width, height}
|
|
49
|
+
* @param {String} type Type of the annotation bBox, point, line, polygon
|
|
50
|
+
* @returns Annotation data in backend style (relative, centered)
|
|
51
|
+
*/
|
|
52
|
+
export function toBackend(data, svg, type, imgOffset = { x: 0, y: 0 }) {
|
|
53
|
+
const imgWidth = svg.width - 2 * imgOffset.x
|
|
54
|
+
const imgHeight = svg.height - 2 * imgOffset.y
|
|
55
|
+
switch (type) {
|
|
56
|
+
case 'bBox':
|
|
57
|
+
// const w = svg.width * data.w
|
|
58
|
+
// const h = svg.height * data.h
|
|
59
|
+
// const x0 = svg.width * data.x - w/2.0
|
|
60
|
+
// const y0 = svg.height * data.y - h/2.0
|
|
61
|
+
|
|
62
|
+
// console.error('GO On Here! w = max_x - min_x; h = max_y - min_y')
|
|
63
|
+
const xList = data.map(e => { return e.x })
|
|
64
|
+
const yList = data.map(e => { return e.y })
|
|
65
|
+
const minX = Math.min(...xList) - imgOffset.x
|
|
66
|
+
const maxX = Math.max(...xList) - imgOffset.x
|
|
67
|
+
const minY = Math.min(...yList) - imgOffset.y
|
|
68
|
+
const maxY = Math.max(...yList) - imgOffset.y
|
|
69
|
+
const w = maxX - minX
|
|
70
|
+
const h = maxY - minY
|
|
71
|
+
const x = minX + w / 2.0
|
|
72
|
+
const y = minY + h / 2.0
|
|
73
|
+
return {
|
|
74
|
+
x: x / imgWidth,
|
|
75
|
+
y: y / imgHeight,
|
|
76
|
+
w: w / imgWidth,
|
|
77
|
+
h: h / imgHeight
|
|
78
|
+
}
|
|
79
|
+
case 'point':
|
|
80
|
+
return {
|
|
81
|
+
x: (data[0].x - imgOffset.x) / imgWidth,
|
|
82
|
+
y: (data[0].y - imgOffset.y) / imgHeight
|
|
83
|
+
}
|
|
84
|
+
case 'line':
|
|
85
|
+
case 'polygon':
|
|
86
|
+
return data.map((e) => {
|
|
87
|
+
return {
|
|
88
|
+
x: (e.x - imgOffset.x) / imgWidth,
|
|
89
|
+
y: (e.y - imgOffset.y) / imgHeight
|
|
90
|
+
}
|
|
91
|
+
})
|
|
92
|
+
default:
|
|
93
|
+
console.warn("Wrong annotation type!")
|
|
94
|
+
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function getMinMaxPoints(data) {
|
|
99
|
+
const xList = data.map(e => { return e.x })
|
|
100
|
+
const yList = data.map(e => { return e.y })
|
|
101
|
+
const minPoint = { x: Math.min(...xList), y: Math.min(...yList) }
|
|
102
|
+
const maxPoint = { x: Math.max(...xList), y: Math.max(...yList) }
|
|
103
|
+
return [minPoint, maxPoint]
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Get area relative to the image
|
|
108
|
+
*
|
|
109
|
+
* @param {Array} data Annotation data
|
|
110
|
+
* @param {*} scaledImg The scaled image object {width, height}
|
|
111
|
+
* @param {String} type Type of the annotation bBox, point, line, polygon
|
|
112
|
+
* @param {object} originalImg The original image
|
|
113
|
+
* @returns Area relative
|
|
114
|
+
*/
|
|
115
|
+
export function getArea(data, scaledImg, type, originalImg) {
|
|
116
|
+
const relData = toBackend(data, scaledImg, type)
|
|
117
|
+
switch (type) {
|
|
118
|
+
case 'bBox':
|
|
119
|
+
return Math.abs(relData.w * relData.h) * originalImg.width * originalImg.height
|
|
120
|
+
// return relData.w*relData.h
|
|
121
|
+
case 'line':
|
|
122
|
+
case 'point':
|
|
123
|
+
return undefined
|
|
124
|
+
case 'polygon':
|
|
125
|
+
let area = 0.0; // Accumulates area in the loop
|
|
126
|
+
if (relData.length > 2) {
|
|
127
|
+
let j = relData.length - 1; // The last vertex is the 'previous' one to the first
|
|
128
|
+
|
|
129
|
+
for (let i = 0; i < relData.length; i++) {
|
|
130
|
+
area = area + (relData[j].x + relData[i].x) * (relData[j].y - relData[i].y);
|
|
131
|
+
j = i; //j is previous vertex to i
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return Math.abs(area / 2) * originalImg.width * originalImg.height
|
|
135
|
+
default:
|
|
136
|
+
console.warn("Wrong annotation type!")
|
|
137
|
+
return undefined
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export function move(data, movementX, movementY) {
|
|
142
|
+
return data.map(e => {
|
|
143
|
+
return {
|
|
144
|
+
x: e.x + movementX,
|
|
145
|
+
y: e.y + movementY
|
|
146
|
+
}
|
|
147
|
+
})
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
export function getBox(data, type) {
|
|
152
|
+
|
|
153
|
+
switch (type) {
|
|
154
|
+
case 'bBox':
|
|
155
|
+
return data
|
|
156
|
+
case 'point':
|
|
157
|
+
case 'line':
|
|
158
|
+
case 'polygon':
|
|
159
|
+
let maxX = 0
|
|
160
|
+
let maxY = 0
|
|
161
|
+
let minX = Infinity
|
|
162
|
+
let minY = Infinity
|
|
163
|
+
data.forEach(el => {
|
|
164
|
+
if (el.x > maxX) maxX = el.x
|
|
165
|
+
if (el.y > maxY) maxY = el.y
|
|
166
|
+
if (el.x < minX) minX = el.x
|
|
167
|
+
if (el.y < minY) minY = el.y
|
|
168
|
+
})
|
|
169
|
+
return [
|
|
170
|
+
{ x: minX, y: minY }, { x: maxX, y: minY },
|
|
171
|
+
{ x: minX, y: maxY }, { x: maxX, y: maxY }
|
|
172
|
+
]
|
|
173
|
+
default:
|
|
174
|
+
break
|
|
175
|
+
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export function getCenter(data, type) {
|
|
180
|
+
let box = undefined
|
|
181
|
+
switch (type) {
|
|
182
|
+
case 'point':
|
|
183
|
+
return data[0]
|
|
184
|
+
case 'line':
|
|
185
|
+
case 'polygon':
|
|
186
|
+
case 'bBox':
|
|
187
|
+
box = getBox(data, type)
|
|
188
|
+
const w = box[1].x - box[0].x
|
|
189
|
+
const h = box[3].y - box[0].y
|
|
190
|
+
return {
|
|
191
|
+
x: box[0].x + w / 2.0,
|
|
192
|
+
y: box[0].y + h / 2.0
|
|
193
|
+
}
|
|
194
|
+
default:
|
|
195
|
+
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Get point that is closest to the left browser side.
|
|
201
|
+
*
|
|
202
|
+
* @param {object} data list of points {x,y}
|
|
203
|
+
* @returns {object} A list of point [{x,y}...]. Multiple points are
|
|
204
|
+
* returned when multiple points have the same distance to the left side.
|
|
205
|
+
*/
|
|
206
|
+
export function getMostLeftPoint(data) {
|
|
207
|
+
let minX = Infinity
|
|
208
|
+
let minXList = []
|
|
209
|
+
data.forEach(el => {
|
|
210
|
+
if (el.x < minX) {
|
|
211
|
+
minX = el.x
|
|
212
|
+
minXList = []
|
|
213
|
+
minXList.push(el)
|
|
214
|
+
} else if (el.x === minX) {
|
|
215
|
+
minXList.push(el)
|
|
216
|
+
}
|
|
217
|
+
})
|
|
218
|
+
return minXList
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Get point that is closest to the top of the browser.
|
|
223
|
+
*
|
|
224
|
+
* @param {object} data list of points {x,y}
|
|
225
|
+
* @returns {object} A list of point [{x,y}...]. Multiple points are
|
|
226
|
+
* returned when multiple points have the same distance to the top.
|
|
227
|
+
*/
|
|
228
|
+
export function getTopPoint(data) {
|
|
229
|
+
let minY = Infinity
|
|
230
|
+
let minYList = []
|
|
231
|
+
data.forEach(el => {
|
|
232
|
+
if (el.y < minY) {
|
|
233
|
+
minY = el.y
|
|
234
|
+
minYList = []
|
|
235
|
+
minYList.push(el)
|
|
236
|
+
} else if (el.y === minY) {
|
|
237
|
+
minYList.push(el)
|
|
238
|
+
}
|
|
239
|
+
})
|
|
240
|
+
return minYList
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Check if all nodes of an annotation are within the image. If not,
|
|
245
|
+
* correct the annotation
|
|
246
|
+
* @param {object} data
|
|
247
|
+
* @param {object} image
|
|
248
|
+
* @param {object} imageOffset
|
|
249
|
+
*/
|
|
250
|
+
export function correctAnnotation(data, image, imageOffset) {
|
|
251
|
+
const imgWidth = image.width - 2 * imageOffset.x
|
|
252
|
+
const imgHeight = image.height - 2 * imageOffset.y
|
|
253
|
+
const corrected = data.map(el => {
|
|
254
|
+
let x = el.x
|
|
255
|
+
let y = el.y
|
|
256
|
+
if (el.x <= imageOffset.x) {
|
|
257
|
+
x = imageOffset.x
|
|
258
|
+
} else if (el.x > (imgWidth + imageOffset.x)) {
|
|
259
|
+
x = imgWidth + imageOffset.x
|
|
260
|
+
}
|
|
261
|
+
if (el.y < imageOffset.y) {
|
|
262
|
+
y = imageOffset.y
|
|
263
|
+
} else if (el.y > (imgHeight + imageOffset.y)) {
|
|
264
|
+
y = imgHeight + imageOffset.y
|
|
265
|
+
}
|
|
266
|
+
return { x: x, y: y }
|
|
267
|
+
})
|
|
268
|
+
return corrected
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Rotate annotation around center.
|
|
273
|
+
* @param {*} data list of points {x:int,y:int}
|
|
274
|
+
* @param {*} center Center to rotate point
|
|
275
|
+
* @param {*} angle Rotation angle
|
|
276
|
+
*/
|
|
277
|
+
export function rotateAnnotation(data, center, angle) {
|
|
278
|
+
angle = (angle) * (Math.PI / 180); // Convert to radians
|
|
279
|
+
const rotated = data.map(point => {
|
|
280
|
+
return {
|
|
281
|
+
x: Math.round(Math.cos(angle) * (point.x - center.x) - Math.sin(angle) * (point.y - center.y) + center.x),
|
|
282
|
+
y: Math.round(Math.sin(angle) * (point.x - center.x) + Math.cos(angle) * (point.y - center.y) + center.y)
|
|
283
|
+
}
|
|
284
|
+
})
|
|
285
|
+
return rotated;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Resize annotation data in canvas format to new image size
|
|
290
|
+
* @param {*} data Annotation data in canvas format [{x:int, y:int},...]
|
|
291
|
+
* @param {*} sizeOld Size of old image {width:int, height:int}
|
|
292
|
+
* @param {*} sizeNew Size of new image {width:int, height:int}
|
|
293
|
+
*/
|
|
294
|
+
export function resizeAnnoData(data, sizeOld, sizeNew) {
|
|
295
|
+
const xRatio = sizeNew.width / sizeOld.width
|
|
296
|
+
const yRatio = sizeNew.height / sizeOld.height
|
|
297
|
+
return data.map(e => {
|
|
298
|
+
return {
|
|
299
|
+
x: parseInt(e.x * xRatio),
|
|
300
|
+
y: parseInt(e.y * yRatio)
|
|
301
|
+
}
|
|
302
|
+
})
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
export default {
|
|
306
|
+
toSia,
|
|
307
|
+
toBackend,
|
|
308
|
+
getMinMaxPoints,
|
|
309
|
+
getArea,
|
|
310
|
+
move,
|
|
311
|
+
getBox,
|
|
312
|
+
getCenter,
|
|
313
|
+
getMostLeftPoint,
|
|
314
|
+
getTopPoint,
|
|
315
|
+
correctAnnotation,
|
|
316
|
+
rotateAnnotation,
|
|
317
|
+
resizeAnnoData
|
|
318
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
export const SIA_INITIAL_UI_CONFIG = {
|
|
2
|
+
nodeRadius: 4,
|
|
3
|
+
strokeWidth: 4,
|
|
4
|
+
annoDetails: {
|
|
5
|
+
visible: false
|
|
6
|
+
},
|
|
7
|
+
labelInfo: {
|
|
8
|
+
visible: false
|
|
9
|
+
},
|
|
10
|
+
annoStats: {
|
|
11
|
+
visible: false
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// read sia-ui-config from localStorage
|
|
16
|
+
const iniFromStorage = localStorage.getItem('sia-ui-config') ? JSON.parse(localStorage.getItem('sia-ui-config')) : SIA_INITIAL_UI_CONFIG
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
// collect object keys and its type in order to describe the object
|
|
20
|
+
const collectDescription = (obj, array) => {
|
|
21
|
+
Object.keys(obj).forEach(key => {
|
|
22
|
+
|
|
23
|
+
const description = {
|
|
24
|
+
key: key,
|
|
25
|
+
type: typeof (obj[key])
|
|
26
|
+
}
|
|
27
|
+
array.push(description)
|
|
28
|
+
|
|
29
|
+
if (typeof obj[key] === 'object') {
|
|
30
|
+
collectDescription(obj[key], array)
|
|
31
|
+
}
|
|
32
|
+
})
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// collect object description for ini and storage ui-config
|
|
36
|
+
|
|
37
|
+
let iniObjectDescriptor = []
|
|
38
|
+
let storageObjectDescriptor = []
|
|
39
|
+
|
|
40
|
+
collectDescription(SIA_INITIAL_UI_CONFIG, iniObjectDescriptor)
|
|
41
|
+
collectDescription(iniFromStorage, storageObjectDescriptor)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
// compare both object descriptions
|
|
45
|
+
|
|
46
|
+
const getUiConfig = () => {
|
|
47
|
+
if (JSON.stringify(iniObjectDescriptor) === JSON.stringify(storageObjectDescriptor)) {
|
|
48
|
+
return iniFromStorage
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
// ini description dif from storage: send ini ui-config and store it to local storage
|
|
52
|
+
return SIA_INITIAL_UI_CONFIG
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export const uiConfig = getUiConfig()
|
|
57
|
+
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export function getViewportCoordinates(w, svg){
|
|
2
|
+
const window = {
|
|
3
|
+
xMin:-1*svg.translateX,
|
|
4
|
+
xMax: -1*svg.translateX + (svg.width)/svg.scale,
|
|
5
|
+
yMin: -1*svg.translateY,
|
|
6
|
+
yMax: -1*svg.translateY + (svg.height)/svg.scale
|
|
7
|
+
|
|
8
|
+
}
|
|
9
|
+
const viewport = {
|
|
10
|
+
xMin: 0,
|
|
11
|
+
xMax: svg.width,
|
|
12
|
+
yMin: 0,
|
|
13
|
+
yMax: svg.height
|
|
14
|
+
}
|
|
15
|
+
const scaleX = (viewport.xMax - viewport.xMin)/ (window.xMax - window.xMin)
|
|
16
|
+
const scaleY = (viewport.yMax - viewport.yMin)/ (window.yMax - window.yMin)
|
|
17
|
+
|
|
18
|
+
const vX = viewport.xMin + (w.x - window.xMin) * scaleX
|
|
19
|
+
const vY = viewport.yMin + (w.y - window.yMin) * scaleY
|
|
20
|
+
return {window, viewport, vX, vY, scaleX, scaleY}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
*
|
|
25
|
+
* @param {*} w0 Point in image coordinate system
|
|
26
|
+
* @param {*} svg Svg with old translation values and old scales
|
|
27
|
+
* @param {*} s1 New scale/zoom
|
|
28
|
+
*/
|
|
29
|
+
export function getZoomTranslation(w0, svg, s1){
|
|
30
|
+
const s0 = svg.scale
|
|
31
|
+
let translation = {x:0,y:0}
|
|
32
|
+
translation.x = (s0/s1) * (w0.x + svg.translateX) - w0.x
|
|
33
|
+
translation.y = (s0/s1) * (w0.y + svg.translateY) - w0.y
|
|
34
|
+
return translation
|
|
35
|
+
}
|
package/CHANGELOG.md
DELETED
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
All notable changes to this project will be documented in this file.
|
|
3
|
-
|
|
4
|
-
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
5
|
-
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
|
-
|
|
7
|
-
## [1.2.0] - 2022-05-12
|
|
8
|
-
### Added
|
|
9
|
-
- Added preventScrolling prop onMouseEnter in canvas
|
|
10
|
-
|
|
11
|
-
## [1.1.3] - 2022-05-12
|
|
12
|
-
### Changed
|
|
13
|
-
- Move import of semantic-ui-css into index js
|
|
14
|
-
|
|
15
|
-
## [1.1.2] - 2022-05-12
|
|
16
|
-
### Added
|
|
17
|
-
- Sia dummy data for quick testing
|
|
18
|
-
### Changed
|
|
19
|
-
- Moved semantic ui css into sia component
|
|
20
|
-
### Fixed
|
|
21
|
-
- Toolbar: Do not crash if no filter props is provided
|
|
22
|
-
|
|
23
|
-
## [1.1.1] - 2022-05-11
|
|
24
|
-
### Changed
|
|
25
|
-
- Update sematic-ui-react to version 2.0.3
|
|
26
|
-
|
|
27
|
-
## [1.1.0] - 2022-05-10
|
|
28
|
-
### Added
|
|
29
|
-
- More fine grained visibility level for toolbar elements
|
|
30
|
-
|
|
31
|
-
## [1.0.3] - 2022-05-10
|
|
32
|
-
### Fixed
|
|
33
|
-
- Export of toolbarEvents and tools
|
|
34
|
-
|
|
35
|
-
## [1.0.2] - 2022-05-09
|
|
36
|
-
### Fixed
|
|
37
|
-
- Improved internal uiConfig handling
|
|
38
|
-
|
|
39
|
-
## [1.0.1] - 2022-05-06
|
|
40
|
-
### Fixed
|
|
41
|
-
- Export of Sia and other components
|
|
42
|
-
|
|
43
|
-
## [1.0.0] - 2022-05-06
|
|
44
|
-
### Added
|
|
45
|
-
- Possibility to assign comments to 2D-Annotations
|
|
46
|
-
- InfoBox (AnnoStats) that shows the number of annotations per label (see https://github.com/l3p-cv/lost/issues/86 and https://github.com/l3p-cv/lost/issues/160)
|
|
47
|
-
- When clicking on a label in the InfoBox all annotations of this label will be hidden. Anothter click will show the annotations again. (see also https://github.com/l3p-cv/lost/issues/161)
|
|
48
|
-
- Added auto save feature
|
|
49
|
-
- Anno Example Viewer + Image Example in LabelInfo box
|
|
50
|
-
### Changed
|
|
51
|
-
- Move InfoBoxes to Canvas
|
|
52
|
-
### Breaking Change
|
|
53
|
-
- Restructured props and event handling for canvas and toolbar
|
|
54
|
-
- Created new Sia component
|
|
55
|
-
### Fixed
|
|
56
|
-
- Fixed correctAnnotation method to work correctly in maxCanvas mode
|
|
57
|
-
- Will prevent annotations from being created outside of the image
|
|
58
|
-
|
|
59
|
-
## [0.9.0] - 2021-12-23
|
|
60
|
-
### Added
|
|
61
|
-
- Delete annotation in creation mode when hitting *Escape*-Key
|
|
62
|
-
- Show img description in ImgBar if available
|
|
63
|
-
- Max canvas size mode. Where canvas takes the maximum container size and is not
|
|
64
|
-
image oriented as before. Add prop *maxCanvas={true}* to canvas in order to enable.
|
|
65
|
-
### Changed
|
|
66
|
-
- Be able to deal with mixed color possible labels -> where a part of labels
|
|
67
|
-
will have a specified color and the other part has no provided color
|
|
68
|
-
|
|
69
|
-
## [0.8.0] - 2021-10-14
|
|
70
|
-
### Added
|
|
71
|
-
- Added lockedAnnos prop for Canvas in order to lock annos by id. Locked annos
|
|
72
|
-
can not be edited
|
|
73
|
-
|
|
74
|
-
## [0.7.0] - 2021-10-13
|
|
75
|
-
### Added
|
|
76
|
-
- Update annotations on **annos**-prob change
|
|
77
|
-
|
|
78
|
-
## [0.6.0] - 2021-09-28
|
|
79
|
-
### Added
|
|
80
|
-
- Edit mode for Polygons -> Edit polygons again that already have been created
|
|
81
|
-
|
|
82
|
-
## [0.5.2] - 2021-07-22
|
|
83
|
-
### Changed
|
|
84
|
-
- do not spam logs with toSia function
|
|
85
|
-
## [0.5.1] - 2021-04-17
|
|
86
|
-
### Fixed
|
|
87
|
-
- Prevent to crash when hitting delete and no annotation was selected
|
|
88
|
-
- Prevent to crash when no AnnoRef was found
|
|
89
|
-
|
|
90
|
-
## [0.5.0] - 2021-01-04
|
|
91
|
-
### Added
|
|
92
|
-
- Added onAnnoPerformedAction callback to canvas
|
|
93
|
-
### Changed
|
|
94
|
-
- Removed all logs
|
|
95
|
-
|
|
96
|
-
## [0.4.1] - 2020-12-16
|
|
97
|
-
### Changed
|
|
98
|
-
- Do not unload image when props.annos change
|
|
99
|
-
|
|
100
|
-
## [0.4.0] - 2020-12-16
|
|
101
|
-
### Added
|
|
102
|
-
- A possible label can now be selected as default label by id
|
|
103
|
-
- Added maxAnnos to canvasConfig. This allows to define a maximum number of annotations that are allowed per image.
|
|
104
|
-
|
|
105
|
-
## [0.3.0] - 2020-12-11
|
|
106
|
-
### Added
|
|
107
|
-
- Frontend annotation time measurement
|
|
108
|
-
* Annotation time is now measured in frontend, based on user events. For each annotation individual user interaction time is measured.
|
|
109
|
-
- Delete last node of polygon/ line when hitting delete key in create mode
|
|
110
|
-
- Added copy & paste for annotations
|
|
111
|
-
- Added prop to block canvas
|
|
112
|
-
### Fixed
|
|
113
|
-
- Do not lose polygon annotation when hitting enter in create mode
|
|
114
|
-
- Do not allow to draw a polygon consisting of two points
|
|
115
|
-
- Do not collapse line with two points, when confirming with enter
|
|
116
|
-
|
|
117
|
-
## [0.2.2] - 2020-08-06
|
|
118
|
-
### Fixed
|
|
119
|
-
- Do not clutter background through sia css file, when importing sia canvas component
|
|
120
|
-
|
|
121
|
-
## [0.2.1] - 2020-06-20
|
|
122
|
-
### Fixed
|
|
123
|
-
- Fixed multiple image load events for the same image, that lead to wrong svg sizes
|
|
124
|
-
|
|
125
|
-
## [0.2.0] - 2020-06-05
|
|
126
|
-
### Fixed
|
|
127
|
-
- Added camera move on wasd keys
|
|
128
|
-
- Provide canvas key events via prop callback
|
|
129
|
-
### Changed
|
|
130
|
-
- Show annotation nodes in foreground and label above annotation to prevent that nodes are not accessible by the annotator (see https://github.com/l3p-cv/lost/issues/74)
|
|
131
|
-
|
|
132
|
-
## [0.1.2] - 2020-04-06
|
|
133
|
-
### Removed
|
|
134
|
-
- Removed most sia logs that clutter the console
|
|
135
|
-
|
|
136
|
-
## [0.1.1] - 2020-04-06
|
|
137
|
-
### Fixed
|
|
138
|
-
- Fixed undefined possible labels in canvas
|
|
139
|
-
|
|
140
|
-
## [0.1.0] - 2020-04-06
|
|
141
|
-
### Added
|
|
142
|
-
- Always reset annotation mode to *view* when getAnnoBackendFormat is called
|
|
143
|
-
- Delete annotation in sia canvas correctly, when they are moved out of the image.
|
|
144
|
-
- Prevent user from moving image out of canvas
|
|
145
|
-
- Confirm label in LabelInput by click on the respective label
|
|
146
|
-
- Configure name of the default Label by a prop
|
|
147
|
-
- Provide method to reset canvas zoom
|
|
148
|
-
- It is now possible to define custom label colors via canvas *possibleLabels* props
|
|
149
|
-
|
|
150
|
-
### Fixed
|
|
151
|
-
- Fixed jumping camera when zooming into the image
|
|
152
|
-
- Fixed LabelInput on wrong position when image was zoomed
|
|
153
|
-
|
|
154
|
-
## [0.0.2] - 2020-04-02
|
|
155
|
-
### Fixed
|
|
156
|
-
- Fixed crash on changing image when label input is active.
|
|
157
|
-
|
|
158
|
-
## [0.0.1] - 2020-04-01
|
|
159
|
-
### Fixed
|
|
160
|
-
- Fixed all annotations lost bug. (see also https://github.com/l3p-cv/lost/issues/51)
|
|
161
|
-
* When a new annotation was created and deleted before a backend update was performed, SIA sent this annotation to backend for an db update
|
|
162
|
-
* The backend then tried to update a db record that did not exists which caused an exception.
|
|
163
|
-
* The result was that all annotation where lost
|