label-studio-converter 1.0.0 → 1.1.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/README.md +580 -20
- package/dist/bash-complete.cjs +316 -74
- package/dist/bash-complete.cjs.map +1 -1
- package/dist/bash-complete.js +316 -74
- package/dist/bash-complete.js.map +1 -1
- package/dist/cli.cjs +316 -74
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +316 -74
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +199 -49
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +31 -16
- package/dist/index.d.ts +31 -16
- package/dist/index.js +199 -49
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/bash-complete.js
CHANGED
|
@@ -19,7 +19,7 @@ var init_esm_shims = __esm({
|
|
|
19
19
|
});
|
|
20
20
|
|
|
21
21
|
// src/constants.ts
|
|
22
|
-
var OUTPUT_BASE_DIR, DEFAULT_LABEL_NAME, DEFAULT_LABEL_STUDIO_FULL_JSON, DEFAULT_CREATE_FILE_PER_IMAGE, DEFAULT_CREATE_FILE_LIST_FOR_SERVING, DEFAULT_FILE_LIST_NAME, DEFAULT_BASE_SERVER_URL, DEFAULT_PPOCR_FILE_NAME, SORT_VERTICAL_NONE, SORT_VERTICAL_TOP_BOTTOM, SORT_VERTICAL_BOTTOM_TOP, DEFAULT_SORT_VERTICAL, SORT_HORIZONTAL_NONE, SORT_HORIZONTAL_LTR, SORT_HORIZONTAL_RTL, DEFAULT_SORT_HORIZONTAL;
|
|
22
|
+
var OUTPUT_BASE_DIR, DEFAULT_LABEL_NAME, DEFAULT_LABEL_STUDIO_FULL_JSON, DEFAULT_CREATE_FILE_PER_IMAGE, DEFAULT_CREATE_FILE_LIST_FOR_SERVING, DEFAULT_FILE_LIST_NAME, DEFAULT_BASE_SERVER_URL, DEFAULT_PPOCR_FILE_NAME, SORT_VERTICAL_NONE, SORT_VERTICAL_TOP_BOTTOM, SORT_VERTICAL_BOTTOM_TOP, DEFAULT_SORT_VERTICAL, SORT_HORIZONTAL_NONE, SORT_HORIZONTAL_LTR, SORT_HORIZONTAL_RTL, DEFAULT_SORT_HORIZONTAL, SHAPE_NORMALIZE_NONE, SHAPE_NORMALIZE_RECTANGLE, DEFAULT_SHAPE_NORMALIZE, DEFAULT_WIDTH_INCREMENT, DEFAULT_HEIGHT_INCREMENT, DEFAULT_LABEL_STUDIO_PRECISION, DEFAULT_PPOCR_PRECISION;
|
|
23
23
|
var init_constants = __esm({
|
|
24
24
|
"src/constants.ts"() {
|
|
25
25
|
"use strict";
|
|
@@ -40,6 +40,99 @@ var init_constants = __esm({
|
|
|
40
40
|
SORT_HORIZONTAL_LTR = "ltr";
|
|
41
41
|
SORT_HORIZONTAL_RTL = "rtl";
|
|
42
42
|
DEFAULT_SORT_HORIZONTAL = SORT_HORIZONTAL_NONE;
|
|
43
|
+
SHAPE_NORMALIZE_NONE = "none";
|
|
44
|
+
SHAPE_NORMALIZE_RECTANGLE = "rectangle";
|
|
45
|
+
DEFAULT_SHAPE_NORMALIZE = SHAPE_NORMALIZE_NONE;
|
|
46
|
+
DEFAULT_WIDTH_INCREMENT = 0;
|
|
47
|
+
DEFAULT_HEIGHT_INCREMENT = 0;
|
|
48
|
+
DEFAULT_LABEL_STUDIO_PRECISION = -1;
|
|
49
|
+
DEFAULT_PPOCR_PRECISION = 0;
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// src/lib/geometry.ts
|
|
54
|
+
function roundToPrecision(value, precision) {
|
|
55
|
+
if (precision < 0) {
|
|
56
|
+
return value;
|
|
57
|
+
}
|
|
58
|
+
const multiplier = Math.pow(10, precision);
|
|
59
|
+
return Math.round(value * multiplier) / multiplier;
|
|
60
|
+
}
|
|
61
|
+
function roundPoints(points, precision) {
|
|
62
|
+
if (precision < 0) {
|
|
63
|
+
return points;
|
|
64
|
+
}
|
|
65
|
+
return points.map(
|
|
66
|
+
([x, y]) => [roundToPrecision(x, precision), roundToPrecision(y, precision)]
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
function calculateCenter(points) {
|
|
70
|
+
const sum = points.reduce((acc, [x, y]) => [acc[0] + x, acc[1] + y], [
|
|
71
|
+
0,
|
|
72
|
+
0
|
|
73
|
+
]);
|
|
74
|
+
return [sum[0] / points.length, sum[1] / points.length];
|
|
75
|
+
}
|
|
76
|
+
function getMinimumBoundingRect(points) {
|
|
77
|
+
const minX = Math.min(...points.map(([x]) => x));
|
|
78
|
+
const maxX = Math.max(...points.map(([x]) => x));
|
|
79
|
+
const minY = Math.min(...points.map(([, y]) => y));
|
|
80
|
+
const maxY = Math.max(...points.map(([, y]) => y));
|
|
81
|
+
return {
|
|
82
|
+
minX,
|
|
83
|
+
minY,
|
|
84
|
+
maxX,
|
|
85
|
+
maxY,
|
|
86
|
+
width: maxX - minX,
|
|
87
|
+
height: maxY - minY
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
function normalizeShape(points) {
|
|
91
|
+
if (points.length < 3) {
|
|
92
|
+
return points;
|
|
93
|
+
}
|
|
94
|
+
const { minX, minY, maxX, maxY } = getMinimumBoundingRect(points);
|
|
95
|
+
return [
|
|
96
|
+
[minX, minY],
|
|
97
|
+
[maxX, minY],
|
|
98
|
+
[maxX, maxY],
|
|
99
|
+
[minX, maxY]
|
|
100
|
+
];
|
|
101
|
+
}
|
|
102
|
+
function resizeBoundingBox(points, widthIncrement, heightIncrement) {
|
|
103
|
+
if (points.length === 0) {
|
|
104
|
+
return points;
|
|
105
|
+
}
|
|
106
|
+
const center = calculateCenter(points);
|
|
107
|
+
const bbox = getMinimumBoundingRect(points);
|
|
108
|
+
const newWidth = Math.max(1, bbox.width + widthIncrement);
|
|
109
|
+
const newHeight = Math.max(1, bbox.height + heightIncrement);
|
|
110
|
+
const scaleX = newWidth / bbox.width;
|
|
111
|
+
const scaleY = newHeight / bbox.height;
|
|
112
|
+
return points.map(([x, y]) => {
|
|
113
|
+
const relX = x - center[0];
|
|
114
|
+
const relY = y - center[1];
|
|
115
|
+
return [center[0] + relX * scaleX, center[1] + relY * scaleY];
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
function transformPoints(points, options) {
|
|
119
|
+
let result = points;
|
|
120
|
+
if (options.normalizeShape && options.normalizeShape === "rectangle") {
|
|
121
|
+
result = normalizeShape(result);
|
|
122
|
+
}
|
|
123
|
+
if (options.widthIncrement !== void 0 || options.heightIncrement !== void 0) {
|
|
124
|
+
result = resizeBoundingBox(
|
|
125
|
+
result,
|
|
126
|
+
options.widthIncrement ?? 0,
|
|
127
|
+
options.heightIncrement ?? 0
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
return result;
|
|
131
|
+
}
|
|
132
|
+
var init_geometry = __esm({
|
|
133
|
+
"src/lib/geometry.ts"() {
|
|
134
|
+
"use strict";
|
|
135
|
+
init_esm_shims();
|
|
43
136
|
}
|
|
44
137
|
});
|
|
45
138
|
|
|
@@ -54,6 +147,7 @@ var init_ppocr_label = __esm({
|
|
|
54
147
|
"use strict";
|
|
55
148
|
init_esm_shims();
|
|
56
149
|
init_constants();
|
|
150
|
+
init_geometry();
|
|
57
151
|
ppocrToLabelStudio = async (data, options) => {
|
|
58
152
|
const {
|
|
59
153
|
imagePath,
|
|
@@ -61,7 +155,11 @@ var init_ppocr_label = __esm({
|
|
|
61
155
|
inputDir,
|
|
62
156
|
toFullJson = true,
|
|
63
157
|
taskId = 1,
|
|
64
|
-
labelName = DEFAULT_LABEL_NAME
|
|
158
|
+
labelName = DEFAULT_LABEL_NAME,
|
|
159
|
+
normalizeShape: normalizeShape2,
|
|
160
|
+
widthIncrement = 0,
|
|
161
|
+
heightIncrement = 0,
|
|
162
|
+
precision = DEFAULT_LABEL_STUDIO_PRECISION
|
|
65
163
|
} = options || {};
|
|
66
164
|
if (toFullJson) {
|
|
67
165
|
return ppocrToFullLabelStudio(
|
|
@@ -70,7 +168,11 @@ var init_ppocr_label = __esm({
|
|
|
70
168
|
baseServerUrl,
|
|
71
169
|
inputDir,
|
|
72
170
|
taskId,
|
|
73
|
-
labelName
|
|
171
|
+
labelName,
|
|
172
|
+
normalizeShape2,
|
|
173
|
+
widthIncrement,
|
|
174
|
+
heightIncrement,
|
|
175
|
+
precision
|
|
74
176
|
);
|
|
75
177
|
} else {
|
|
76
178
|
return ppocrToMinLabelStudio(
|
|
@@ -78,11 +180,15 @@ var init_ppocr_label = __esm({
|
|
|
78
180
|
imagePath,
|
|
79
181
|
baseServerUrl,
|
|
80
182
|
inputDir,
|
|
81
|
-
labelName
|
|
183
|
+
labelName,
|
|
184
|
+
normalizeShape2,
|
|
185
|
+
widthIncrement,
|
|
186
|
+
heightIncrement,
|
|
187
|
+
precision
|
|
82
188
|
);
|
|
83
189
|
}
|
|
84
190
|
};
|
|
85
|
-
ppocrToFullLabelStudio = (data, imagePath, baseServerUrl, inputDir, taskId = 1, labelName = DEFAULT_LABEL_NAME) => {
|
|
191
|
+
ppocrToFullLabelStudio = (data, imagePath, baseServerUrl, inputDir, taskId = 1, labelName = DEFAULT_LABEL_NAME, normalizeShape2, widthIncrement = 0, heightIncrement = 0, precision = DEFAULT_LABEL_STUDIO_PRECISION) => {
|
|
86
192
|
const newBaseServerUrl = baseServerUrl.replace(/\/+$/, "") + (baseServerUrl === "" ? "" : "/");
|
|
87
193
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
88
194
|
let original_width = 1920;
|
|
@@ -109,11 +215,16 @@ var init_ppocr_label = __esm({
|
|
|
109
215
|
id: taskId,
|
|
110
216
|
completed_by: 1,
|
|
111
217
|
result: data.map((item) => {
|
|
112
|
-
|
|
218
|
+
let { points } = item;
|
|
219
|
+
points = transformPoints(points, {
|
|
220
|
+
normalizeShape: normalizeShape2,
|
|
221
|
+
widthIncrement,
|
|
222
|
+
heightIncrement
|
|
223
|
+
});
|
|
113
224
|
const annotationId = randomUUID().slice(0, 10);
|
|
114
225
|
const polygonPoints = points.map(([x, y]) => [
|
|
115
|
-
(x ?? 0) / original_width * 100,
|
|
116
|
-
(y ?? 0) / original_height * 100
|
|
226
|
+
roundToPrecision((x ?? 0) / original_width * 100, precision),
|
|
227
|
+
roundToPrecision((y ?? 0) / original_height * 100, precision)
|
|
117
228
|
]);
|
|
118
229
|
return [
|
|
119
230
|
// 1. Polygon geometry only
|
|
@@ -207,7 +318,7 @@ var init_ppocr_label = __esm({
|
|
|
207
318
|
];
|
|
208
319
|
return result;
|
|
209
320
|
};
|
|
210
|
-
ppocrToMinLabelStudio = (data, imagePath, baseServerUrl, inputDir, labelName = "text") => {
|
|
321
|
+
ppocrToMinLabelStudio = (data, imagePath, baseServerUrl, inputDir, labelName = "text", normalizeShape2, widthIncrement = 0, heightIncrement = 0, precision = DEFAULT_LABEL_STUDIO_PRECISION) => {
|
|
211
322
|
const newBaseServerUrl = baseServerUrl.replace(/\/+$/, "") + (baseServerUrl === "" ? "" : "/");
|
|
212
323
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
213
324
|
let original_width = 1920;
|
|
@@ -226,12 +337,23 @@ var init_ppocr_label = __esm({
|
|
|
226
337
|
original_width = dimensions.width;
|
|
227
338
|
original_height = dimensions.height;
|
|
228
339
|
return data.map((item, index) => {
|
|
229
|
-
|
|
340
|
+
let { points } = item;
|
|
341
|
+
points = transformPoints(points, {
|
|
342
|
+
normalizeShape: normalizeShape2,
|
|
343
|
+
widthIncrement,
|
|
344
|
+
heightIncrement
|
|
345
|
+
});
|
|
346
|
+
const roundedPoints = points.map(
|
|
347
|
+
([x, y]) => [
|
|
348
|
+
roundToPrecision(x ?? 0, precision),
|
|
349
|
+
roundToPrecision(y ?? 0, precision)
|
|
350
|
+
]
|
|
351
|
+
);
|
|
230
352
|
let minX = Infinity;
|
|
231
353
|
let minY = Infinity;
|
|
232
354
|
let maxX = -Infinity;
|
|
233
355
|
let maxY = -Infinity;
|
|
234
|
-
for (const point of
|
|
356
|
+
for (const point of roundedPoints) {
|
|
235
357
|
const [x, y] = point;
|
|
236
358
|
if (x !== void 0 && y !== void 0) {
|
|
237
359
|
minX = Math.min(minX, x);
|
|
@@ -258,7 +380,7 @@ var init_ppocr_label = __esm({
|
|
|
258
380
|
],
|
|
259
381
|
label: [
|
|
260
382
|
{
|
|
261
|
-
points,
|
|
383
|
+
points: roundedPoints,
|
|
262
384
|
closed: true,
|
|
263
385
|
labels: [labelName],
|
|
264
386
|
original_width,
|
|
@@ -268,7 +390,7 @@ var init_ppocr_label = __esm({
|
|
|
268
390
|
transcription: [item.transcription],
|
|
269
391
|
poly: [
|
|
270
392
|
{
|
|
271
|
-
points,
|
|
393
|
+
points: roundedPoints,
|
|
272
394
|
closed: true,
|
|
273
395
|
original_width,
|
|
274
396
|
original_height
|
|
@@ -301,6 +423,7 @@ var init_schema = __esm({
|
|
|
301
423
|
completed_by: z.number(),
|
|
302
424
|
result: z.array(
|
|
303
425
|
z.union([
|
|
426
|
+
// Most specific rectangle variants first (with text or labels)
|
|
304
427
|
z.object({
|
|
305
428
|
original_width: z.number(),
|
|
306
429
|
original_height: z.number(),
|
|
@@ -310,7 +433,8 @@ var init_schema = __esm({
|
|
|
310
433
|
y: z.number(),
|
|
311
434
|
width: z.number(),
|
|
312
435
|
height: z.number(),
|
|
313
|
-
rotation: z.number()
|
|
436
|
+
rotation: z.number(),
|
|
437
|
+
text: z.array(z.string())
|
|
314
438
|
}),
|
|
315
439
|
id: z.string(),
|
|
316
440
|
from_name: z.string(),
|
|
@@ -336,6 +460,7 @@ var init_schema = __esm({
|
|
|
336
460
|
type: z.string(),
|
|
337
461
|
origin: z.string()
|
|
338
462
|
}),
|
|
463
|
+
// Base rectangle without text or labels
|
|
339
464
|
z.object({
|
|
340
465
|
original_width: z.number(),
|
|
341
466
|
original_height: z.number(),
|
|
@@ -345,8 +470,7 @@ var init_schema = __esm({
|
|
|
345
470
|
y: z.number(),
|
|
346
471
|
width: z.number(),
|
|
347
472
|
height: z.number(),
|
|
348
|
-
rotation: z.number()
|
|
349
|
-
text: z.array(z.string())
|
|
473
|
+
rotation: z.number()
|
|
350
474
|
}),
|
|
351
475
|
id: z.string(),
|
|
352
476
|
from_name: z.string(),
|
|
@@ -354,13 +478,15 @@ var init_schema = __esm({
|
|
|
354
478
|
type: z.string(),
|
|
355
479
|
origin: z.string()
|
|
356
480
|
}),
|
|
481
|
+
// Most specific polygon variants first (with text or labels)
|
|
357
482
|
z.object({
|
|
358
483
|
original_width: z.number(),
|
|
359
484
|
original_height: z.number(),
|
|
360
485
|
image_rotation: z.number(),
|
|
361
486
|
value: z.object({
|
|
362
487
|
points: z.array(z.array(z.number())),
|
|
363
|
-
closed: z.boolean()
|
|
488
|
+
closed: z.boolean(),
|
|
489
|
+
text: z.array(z.string())
|
|
364
490
|
}),
|
|
365
491
|
id: z.string(),
|
|
366
492
|
from_name: z.string(),
|
|
@@ -383,14 +509,14 @@ var init_schema = __esm({
|
|
|
383
509
|
type: z.string(),
|
|
384
510
|
origin: z.string()
|
|
385
511
|
}),
|
|
512
|
+
// Base polygon without text or labels
|
|
386
513
|
z.object({
|
|
387
514
|
original_width: z.number(),
|
|
388
515
|
original_height: z.number(),
|
|
389
516
|
image_rotation: z.number(),
|
|
390
517
|
value: z.object({
|
|
391
518
|
points: z.array(z.array(z.number())),
|
|
392
|
-
closed: z.boolean()
|
|
393
|
-
text: z.array(z.string())
|
|
519
|
+
closed: z.boolean()
|
|
394
520
|
}),
|
|
395
521
|
id: z.string(),
|
|
396
522
|
from_name: z.string(),
|
|
@@ -429,6 +555,7 @@ var init_schema = __esm({
|
|
|
429
555
|
created_ago: z.string(),
|
|
430
556
|
result: z.array(
|
|
431
557
|
z.union([
|
|
558
|
+
// Most specific rectangle variants first (with text or labels)
|
|
432
559
|
z.object({
|
|
433
560
|
original_width: z.number(),
|
|
434
561
|
original_height: z.number(),
|
|
@@ -438,7 +565,8 @@ var init_schema = __esm({
|
|
|
438
565
|
y: z.number(),
|
|
439
566
|
width: z.number(),
|
|
440
567
|
height: z.number(),
|
|
441
|
-
rotation: z.number()
|
|
568
|
+
rotation: z.number(),
|
|
569
|
+
text: z.array(z.string())
|
|
442
570
|
}),
|
|
443
571
|
id: z.string(),
|
|
444
572
|
from_name: z.string(),
|
|
@@ -464,6 +592,7 @@ var init_schema = __esm({
|
|
|
464
592
|
type: z.string(),
|
|
465
593
|
origin: z.string()
|
|
466
594
|
}),
|
|
595
|
+
// Base rectangle without text or labels
|
|
467
596
|
z.object({
|
|
468
597
|
original_width: z.number(),
|
|
469
598
|
original_height: z.number(),
|
|
@@ -473,8 +602,7 @@ var init_schema = __esm({
|
|
|
473
602
|
y: z.number(),
|
|
474
603
|
width: z.number(),
|
|
475
604
|
height: z.number(),
|
|
476
|
-
rotation: z.number()
|
|
477
|
-
text: z.array(z.string())
|
|
605
|
+
rotation: z.number()
|
|
478
606
|
}),
|
|
479
607
|
id: z.string(),
|
|
480
608
|
from_name: z.string(),
|
|
@@ -482,13 +610,15 @@ var init_schema = __esm({
|
|
|
482
610
|
type: z.string(),
|
|
483
611
|
origin: z.string()
|
|
484
612
|
}),
|
|
613
|
+
// Most specific polygon variants first (with text or labels)
|
|
485
614
|
z.object({
|
|
486
615
|
original_width: z.number(),
|
|
487
616
|
original_height: z.number(),
|
|
488
617
|
image_rotation: z.number(),
|
|
489
618
|
value: z.object({
|
|
490
619
|
points: z.array(z.array(z.number())),
|
|
491
|
-
closed: z.boolean()
|
|
620
|
+
closed: z.boolean(),
|
|
621
|
+
text: z.array(z.string())
|
|
492
622
|
}),
|
|
493
623
|
id: z.string(),
|
|
494
624
|
from_name: z.string(),
|
|
@@ -511,14 +641,14 @@ var init_schema = __esm({
|
|
|
511
641
|
type: z.string(),
|
|
512
642
|
origin: z.string()
|
|
513
643
|
}),
|
|
644
|
+
// Base polygon without text or labels
|
|
514
645
|
z.object({
|
|
515
646
|
original_width: z.number(),
|
|
516
647
|
original_height: z.number(),
|
|
517
648
|
image_rotation: z.number(),
|
|
518
649
|
value: z.object({
|
|
519
650
|
points: z.array(z.array(z.number())),
|
|
520
|
-
closed: z.boolean()
|
|
521
|
-
text: z.array(z.string())
|
|
651
|
+
closed: z.boolean()
|
|
522
652
|
}),
|
|
523
653
|
id: z.string(),
|
|
524
654
|
from_name: z.string(),
|
|
@@ -569,7 +699,7 @@ var init_schema = __esm({
|
|
|
569
699
|
original_width: z.number(),
|
|
570
700
|
original_height: z.number()
|
|
571
701
|
})
|
|
572
|
-
),
|
|
702
|
+
).optional().default([]),
|
|
573
703
|
label: z.array(
|
|
574
704
|
z.union([
|
|
575
705
|
z.object({
|
|
@@ -590,8 +720,11 @@ var init_schema = __esm({
|
|
|
590
720
|
original_height: z.number()
|
|
591
721
|
})
|
|
592
722
|
])
|
|
593
|
-
),
|
|
594
|
-
transcription: z.array(z.string())
|
|
723
|
+
).optional().default([]),
|
|
724
|
+
transcription: z.union([z.string(), z.array(z.string())]).optional().transform((val) => {
|
|
725
|
+
if (!val) return [];
|
|
726
|
+
return Array.isArray(val) ? val : [val];
|
|
727
|
+
}),
|
|
595
728
|
poly: z.array(
|
|
596
729
|
z.object({
|
|
597
730
|
points: z.array(z.array(z.number())),
|
|
@@ -599,7 +732,7 @@ var init_schema = __esm({
|
|
|
599
732
|
original_width: z.number(),
|
|
600
733
|
original_height: z.number()
|
|
601
734
|
})
|
|
602
|
-
),
|
|
735
|
+
).optional().default([]),
|
|
603
736
|
annotator: z.number(),
|
|
604
737
|
annotation_id: z.number(),
|
|
605
738
|
created_at: z.string(),
|
|
@@ -726,7 +859,11 @@ async function convertToLabelStudio(flags, ...inputDirs) {
|
|
|
726
859
|
fileListName = DEFAULT_FILE_LIST_NAME,
|
|
727
860
|
baseServerUrl = DEFAULT_BASE_SERVER_URL,
|
|
728
861
|
sortVertical = DEFAULT_SORT_VERTICAL,
|
|
729
|
-
sortHorizontal = DEFAULT_SORT_HORIZONTAL
|
|
862
|
+
sortHorizontal = DEFAULT_SORT_HORIZONTAL,
|
|
863
|
+
normalizeShape: normalizeShape2 = DEFAULT_SHAPE_NORMALIZE,
|
|
864
|
+
widthIncrement = DEFAULT_WIDTH_INCREMENT,
|
|
865
|
+
heightIncrement = DEFAULT_HEIGHT_INCREMENT,
|
|
866
|
+
precision = DEFAULT_LABEL_STUDIO_PRECISION
|
|
730
867
|
} = flags;
|
|
731
868
|
const newBaseServerUrl = baseServerUrl.replace(/\/+$/, "") + (baseServerUrl === "" ? "" : "/");
|
|
732
869
|
await mkdir(outDir, { recursive: true });
|
|
@@ -769,7 +906,11 @@ async function convertToLabelStudio(flags, ...inputDirs) {
|
|
|
769
906
|
baseServerUrl: newBaseServerUrl,
|
|
770
907
|
inputDir,
|
|
771
908
|
taskId,
|
|
772
|
-
labelName: defaultLabelName
|
|
909
|
+
labelName: defaultLabelName,
|
|
910
|
+
normalizeShape: normalizeShape2 !== SHAPE_NORMALIZE_NONE ? normalizeShape2 : void 0,
|
|
911
|
+
widthIncrement,
|
|
912
|
+
heightIncrement,
|
|
913
|
+
precision
|
|
773
914
|
});
|
|
774
915
|
if (toFullJson) {
|
|
775
916
|
allLabelStudioData.push(labelStudioData[0]);
|
|
@@ -850,7 +991,15 @@ var init_label_studio = __esm({
|
|
|
850
991
|
"src/lib/label-studio.ts"() {
|
|
851
992
|
"use strict";
|
|
852
993
|
init_esm_shims();
|
|
853
|
-
|
|
994
|
+
init_geometry();
|
|
995
|
+
labelStudioToPPOCR = async (data, options) => {
|
|
996
|
+
const {
|
|
997
|
+
baseImageDir,
|
|
998
|
+
normalizeShape: normalizeShape2,
|
|
999
|
+
widthIncrement = 0,
|
|
1000
|
+
heightIncrement = 0,
|
|
1001
|
+
precision = 0
|
|
1002
|
+
} = options || {};
|
|
854
1003
|
const resultMap = /* @__PURE__ */ new Map();
|
|
855
1004
|
for (const task of data) {
|
|
856
1005
|
let imagePath = task.file_upload || "";
|
|
@@ -901,6 +1050,12 @@ var init_label_studio = __esm({
|
|
|
901
1050
|
}
|
|
902
1051
|
}
|
|
903
1052
|
if (points && points.length > 0) {
|
|
1053
|
+
points = transformPoints(points, {
|
|
1054
|
+
normalizeShape: normalizeShape2,
|
|
1055
|
+
widthIncrement,
|
|
1056
|
+
heightIncrement
|
|
1057
|
+
});
|
|
1058
|
+
points = roundPoints(points, precision);
|
|
904
1059
|
let dt_score = 1;
|
|
905
1060
|
try {
|
|
906
1061
|
const firstPoint = points[0];
|
|
@@ -926,7 +1081,14 @@ var init_label_studio = __esm({
|
|
|
926
1081
|
}
|
|
927
1082
|
return resultMap;
|
|
928
1083
|
};
|
|
929
|
-
minLabelStudioToPPOCR = async (data,
|
|
1084
|
+
minLabelStudioToPPOCR = async (data, options) => {
|
|
1085
|
+
const {
|
|
1086
|
+
baseImageDir,
|
|
1087
|
+
normalizeShape: normalizeShape2,
|
|
1088
|
+
widthIncrement = 0,
|
|
1089
|
+
heightIncrement = 0,
|
|
1090
|
+
precision = 0
|
|
1091
|
+
} = options || {};
|
|
930
1092
|
const resultMap = /* @__PURE__ */ new Map();
|
|
931
1093
|
for (const item of data) {
|
|
932
1094
|
let imagePath = item.ocr || "";
|
|
@@ -938,43 +1100,62 @@ var init_label_studio = __esm({
|
|
|
938
1100
|
if (baseImageDir) {
|
|
939
1101
|
imagePath = `${baseImageDir}/${imagePath.split("/").pop() || imagePath}`;
|
|
940
1102
|
}
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
[
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
1103
|
+
const numAnnotations = Math.max(
|
|
1104
|
+
item.poly?.length || 0,
|
|
1105
|
+
item.bbox?.length || 0,
|
|
1106
|
+
item.transcription?.length || 0
|
|
1107
|
+
);
|
|
1108
|
+
for (let i = 0; i < numAnnotations; i++) {
|
|
1109
|
+
let points;
|
|
1110
|
+
if (item.poly && item.poly.length > i && item.poly[i]) {
|
|
1111
|
+
const poly = item.poly[i];
|
|
1112
|
+
if (poly) {
|
|
1113
|
+
const { points: polyPoints } = poly;
|
|
1114
|
+
points = polyPoints;
|
|
1115
|
+
}
|
|
1116
|
+
} else if (item.bbox && item.bbox.length > i && item.bbox[i]) {
|
|
1117
|
+
const bbox = item.bbox[i];
|
|
1118
|
+
if (bbox) {
|
|
1119
|
+
const { x, y, width, height } = bbox;
|
|
1120
|
+
points = [
|
|
1121
|
+
[x, y],
|
|
1122
|
+
[x + width, y],
|
|
1123
|
+
[x + width, y + height],
|
|
1124
|
+
[x, y + height]
|
|
1125
|
+
];
|
|
1126
|
+
}
|
|
965
1127
|
}
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
1128
|
+
if (!points) {
|
|
1129
|
+
continue;
|
|
1130
|
+
}
|
|
1131
|
+
points = transformPoints(points, {
|
|
1132
|
+
normalizeShape: normalizeShape2,
|
|
1133
|
+
widthIncrement,
|
|
1134
|
+
heightIncrement
|
|
1135
|
+
});
|
|
1136
|
+
points = roundPoints(points, precision);
|
|
1137
|
+
const transcription = item.transcription && item.transcription.length > i ? item.transcription[i] : "";
|
|
1138
|
+
let dt_score = 1;
|
|
1139
|
+
try {
|
|
1140
|
+
const firstPoint = points[0];
|
|
1141
|
+
if (firstPoint) {
|
|
1142
|
+
const polygon2 = turf.polygon([points.concat([firstPoint])]);
|
|
1143
|
+
const area2 = turf.area(polygon2);
|
|
1144
|
+
dt_score = Math.min(1, Math.max(0.5, area2 / 1e4));
|
|
1145
|
+
}
|
|
1146
|
+
} catch {
|
|
1147
|
+
dt_score = 0.8;
|
|
1148
|
+
}
|
|
1149
|
+
const annotation = {
|
|
1150
|
+
transcription: transcription ?? "",
|
|
1151
|
+
points,
|
|
1152
|
+
dt_score
|
|
1153
|
+
};
|
|
1154
|
+
if (!resultMap.has(imagePath)) {
|
|
1155
|
+
resultMap.set(imagePath, []);
|
|
1156
|
+
}
|
|
1157
|
+
resultMap.get(imagePath).push(annotation);
|
|
976
1158
|
}
|
|
977
|
-
resultMap.get(imagePath).push(annotation);
|
|
978
1159
|
}
|
|
979
1160
|
return resultMap;
|
|
980
1161
|
};
|
|
@@ -995,7 +1176,11 @@ async function convertToPPOCR(flags, ...inputDirs) {
|
|
|
995
1176
|
fileName = DEFAULT_PPOCR_FILE_NAME,
|
|
996
1177
|
baseImageDir,
|
|
997
1178
|
sortVertical = DEFAULT_SORT_VERTICAL,
|
|
998
|
-
sortHorizontal = DEFAULT_SORT_HORIZONTAL
|
|
1179
|
+
sortHorizontal = DEFAULT_SORT_HORIZONTAL,
|
|
1180
|
+
normalizeShape: normalizeShape2 = DEFAULT_SHAPE_NORMALIZE,
|
|
1181
|
+
widthIncrement = DEFAULT_WIDTH_INCREMENT,
|
|
1182
|
+
heightIncrement = DEFAULT_HEIGHT_INCREMENT,
|
|
1183
|
+
precision = DEFAULT_PPOCR_PRECISION
|
|
999
1184
|
} = flags;
|
|
1000
1185
|
await mkdir2(outDir, { recursive: true });
|
|
1001
1186
|
for (const inputDir of inputDirs) {
|
|
@@ -1011,10 +1196,19 @@ async function convertToPPOCR(flags, ...inputDirs) {
|
|
|
1011
1196
|
const fileData = await readFile2(filePath, "utf-8");
|
|
1012
1197
|
const labelStudioData = JSON.parse(fileData);
|
|
1013
1198
|
const { data, isFull } = isLabelStudioFullJSON(labelStudioData);
|
|
1014
|
-
const ppocrDataMap = isFull ? await labelStudioToPPOCR(data,
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1199
|
+
const ppocrDataMap = isFull ? await labelStudioToPPOCR(data, {
|
|
1200
|
+
baseImageDir,
|
|
1201
|
+
normalizeShape: normalizeShape2 !== SHAPE_NORMALIZE_NONE ? normalizeShape2 : void 0,
|
|
1202
|
+
widthIncrement,
|
|
1203
|
+
heightIncrement,
|
|
1204
|
+
precision
|
|
1205
|
+
}) : await minLabelStudioToPPOCR(data, {
|
|
1206
|
+
baseImageDir,
|
|
1207
|
+
normalizeShape: normalizeShape2 !== SHAPE_NORMALIZE_NONE ? normalizeShape2 : void 0,
|
|
1208
|
+
widthIncrement,
|
|
1209
|
+
heightIncrement,
|
|
1210
|
+
precision
|
|
1211
|
+
});
|
|
1018
1212
|
const outputLines = [];
|
|
1019
1213
|
for (const [imagePath, annotations] of ppocrDataMap.entries()) {
|
|
1020
1214
|
const sortedAnnotations = sortBoundingBoxes(
|
|
@@ -1082,7 +1276,7 @@ import {
|
|
|
1082
1276
|
import { buildApplication, buildRouteMap } from "@stricli/core";
|
|
1083
1277
|
|
|
1084
1278
|
// package.json
|
|
1085
|
-
var version = "1.
|
|
1279
|
+
var version = "1.1.0";
|
|
1086
1280
|
var description = "Convert between Label Studio OCR format and PPOCRLabelv2 format";
|
|
1087
1281
|
|
|
1088
1282
|
// src/commands/toLabelStudio/command.ts
|
|
@@ -1154,6 +1348,30 @@ var toLabelStudioCommand = buildCommand({
|
|
|
1154
1348
|
brief: `Sort bounding boxes horizontally. Options: "${SORT_HORIZONTAL_NONE}" (default), "${SORT_HORIZONTAL_LTR}", "${SORT_HORIZONTAL_RTL}"`,
|
|
1155
1349
|
parse: String,
|
|
1156
1350
|
optional: true
|
|
1351
|
+
},
|
|
1352
|
+
normalizeShape: {
|
|
1353
|
+
kind: "parsed",
|
|
1354
|
+
brief: `Normalize diamond-like shapes to axis-aligned rectangles. Options: "${SHAPE_NORMALIZE_NONE}" (default), "${SHAPE_NORMALIZE_RECTANGLE}"`,
|
|
1355
|
+
parse: String,
|
|
1356
|
+
optional: true
|
|
1357
|
+
},
|
|
1358
|
+
widthIncrement: {
|
|
1359
|
+
kind: "parsed",
|
|
1360
|
+
brief: `Increase bounding box width by this amount (in pixels). Can be negative to decrease. Default: ${DEFAULT_WIDTH_INCREMENT}`,
|
|
1361
|
+
parse: Number,
|
|
1362
|
+
optional: true
|
|
1363
|
+
},
|
|
1364
|
+
heightIncrement: {
|
|
1365
|
+
kind: "parsed",
|
|
1366
|
+
brief: `Increase bounding box height by this amount (in pixels). Can be negative to decrease. Default: ${DEFAULT_HEIGHT_INCREMENT}`,
|
|
1367
|
+
parse: Number,
|
|
1368
|
+
optional: true
|
|
1369
|
+
},
|
|
1370
|
+
precision: {
|
|
1371
|
+
kind: "parsed",
|
|
1372
|
+
brief: `Number of decimal places for coordinates. Use -1 for full precision (no rounding). Default: ${DEFAULT_LABEL_STUDIO_PRECISION}`,
|
|
1373
|
+
parse: Number,
|
|
1374
|
+
optional: true
|
|
1157
1375
|
}
|
|
1158
1376
|
}
|
|
1159
1377
|
},
|
|
@@ -1210,6 +1428,30 @@ var toPPOCRCommand = buildCommand2({
|
|
|
1210
1428
|
brief: `Sort bounding boxes horizontally. Options: "${SORT_HORIZONTAL_NONE}" (default), "${SORT_HORIZONTAL_LTR}", "${SORT_HORIZONTAL_RTL}"`,
|
|
1211
1429
|
parse: String,
|
|
1212
1430
|
optional: true
|
|
1431
|
+
},
|
|
1432
|
+
normalizeShape: {
|
|
1433
|
+
kind: "parsed",
|
|
1434
|
+
brief: `Normalize diamond-like shapes to axis-aligned rectangles. Options: "${SHAPE_NORMALIZE_NONE}" (default), "${SHAPE_NORMALIZE_RECTANGLE}"`,
|
|
1435
|
+
parse: String,
|
|
1436
|
+
optional: true
|
|
1437
|
+
},
|
|
1438
|
+
widthIncrement: {
|
|
1439
|
+
kind: "parsed",
|
|
1440
|
+
brief: `Increase bounding box width by this amount (in pixels). Can be negative to decrease. Default: ${DEFAULT_WIDTH_INCREMENT}`,
|
|
1441
|
+
parse: Number,
|
|
1442
|
+
optional: true
|
|
1443
|
+
},
|
|
1444
|
+
heightIncrement: {
|
|
1445
|
+
kind: "parsed",
|
|
1446
|
+
brief: `Increase bounding box height by this amount (in pixels). Can be negative to decrease. Default: ${DEFAULT_HEIGHT_INCREMENT}`,
|
|
1447
|
+
parse: Number,
|
|
1448
|
+
optional: true
|
|
1449
|
+
},
|
|
1450
|
+
precision: {
|
|
1451
|
+
kind: "parsed",
|
|
1452
|
+
brief: `Number of decimal places for coordinates. Use -1 for full precision (no rounding). Default: ${DEFAULT_PPOCR_PRECISION} (integers)`,
|
|
1453
|
+
parse: Number,
|
|
1454
|
+
optional: true
|
|
1213
1455
|
}
|
|
1214
1456
|
}
|
|
1215
1457
|
},
|