label-studio-converter 1.0.0 → 1.2.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 +1076 -53
- package/dist/bash-complete.cjs +1285 -530
- package/dist/bash-complete.cjs.map +1 -1
- package/dist/bash-complete.js +1278 -524
- package/dist/bash-complete.js.map +1 -1
- package/dist/cli.cjs +1284 -529
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +1278 -524
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +864 -56
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +136 -17
- package/dist/index.d.ts +136 -17
- package/dist/index.js +849 -55
- package/dist/index.js.map +1 -1
- package/package.json +6 -3
package/dist/bash-complete.cjs
CHANGED
|
@@ -38,7 +38,7 @@ var init_cjs_shims = __esm({
|
|
|
38
38
|
});
|
|
39
39
|
|
|
40
40
|
// src/constants.ts
|
|
41
|
-
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;
|
|
41
|
+
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;
|
|
42
42
|
var init_constants = __esm({
|
|
43
43
|
"src/constants.ts"() {
|
|
44
44
|
"use strict";
|
|
@@ -59,247 +59,578 @@ var init_constants = __esm({
|
|
|
59
59
|
SORT_HORIZONTAL_LTR = "ltr";
|
|
60
60
|
SORT_HORIZONTAL_RTL = "rtl";
|
|
61
61
|
DEFAULT_SORT_HORIZONTAL = SORT_HORIZONTAL_NONE;
|
|
62
|
+
SHAPE_NORMALIZE_NONE = "none";
|
|
63
|
+
SHAPE_NORMALIZE_RECTANGLE = "rectangle";
|
|
64
|
+
DEFAULT_SHAPE_NORMALIZE = SHAPE_NORMALIZE_NONE;
|
|
65
|
+
DEFAULT_WIDTH_INCREMENT = 0;
|
|
66
|
+
DEFAULT_HEIGHT_INCREMENT = 0;
|
|
67
|
+
DEFAULT_LABEL_STUDIO_PRECISION = -1;
|
|
68
|
+
DEFAULT_PPOCR_PRECISION = 0;
|
|
62
69
|
}
|
|
63
70
|
});
|
|
64
71
|
|
|
65
|
-
// src/lib/
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
72
|
+
// src/lib/geometry.ts
|
|
73
|
+
function roundToPrecision(value, precision) {
|
|
74
|
+
if (precision < 0) {
|
|
75
|
+
return value;
|
|
76
|
+
}
|
|
77
|
+
const multiplier = Math.pow(10, precision);
|
|
78
|
+
return Math.round(value * multiplier) / multiplier;
|
|
79
|
+
}
|
|
80
|
+
function roundPoints(points, precision) {
|
|
81
|
+
if (precision < 0) {
|
|
82
|
+
return points;
|
|
83
|
+
}
|
|
84
|
+
return points.map(
|
|
85
|
+
([x, y]) => [roundToPrecision(x, precision), roundToPrecision(y, precision)]
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
function calculateCenter(points) {
|
|
89
|
+
const sum = points.reduce((acc, [x, y]) => [acc[0] + x, acc[1] + y], [
|
|
90
|
+
0,
|
|
91
|
+
0
|
|
92
|
+
]);
|
|
93
|
+
return [sum[0] / points.length, sum[1] / points.length];
|
|
94
|
+
}
|
|
95
|
+
function getMinimumBoundingRect(points) {
|
|
96
|
+
const minX = Math.min(...points.map(([x]) => x));
|
|
97
|
+
const maxX = Math.max(...points.map(([x]) => x));
|
|
98
|
+
const minY = Math.min(...points.map(([, y]) => y));
|
|
99
|
+
const maxY = Math.max(...points.map(([, y]) => y));
|
|
100
|
+
return {
|
|
101
|
+
minX,
|
|
102
|
+
minY,
|
|
103
|
+
maxX,
|
|
104
|
+
maxY,
|
|
105
|
+
width: maxX - minX,
|
|
106
|
+
height: maxY - minY
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
function normalizeShape(points) {
|
|
110
|
+
if (points.length < 3) {
|
|
111
|
+
return points;
|
|
112
|
+
}
|
|
113
|
+
const { minX, minY, maxX, maxY } = getMinimumBoundingRect(points);
|
|
114
|
+
return [
|
|
115
|
+
[minX, minY],
|
|
116
|
+
[maxX, minY],
|
|
117
|
+
[maxX, maxY],
|
|
118
|
+
[minX, maxY]
|
|
119
|
+
];
|
|
120
|
+
}
|
|
121
|
+
function resizeBoundingBox(points, widthIncrement, heightIncrement) {
|
|
122
|
+
if (points.length === 0) {
|
|
123
|
+
return points;
|
|
124
|
+
}
|
|
125
|
+
const center = calculateCenter(points);
|
|
126
|
+
const bbox = getMinimumBoundingRect(points);
|
|
127
|
+
const newWidth = Math.max(1, bbox.width + widthIncrement);
|
|
128
|
+
const newHeight = Math.max(1, bbox.height + heightIncrement);
|
|
129
|
+
const scaleX = newWidth / bbox.width;
|
|
130
|
+
const scaleY = newHeight / bbox.height;
|
|
131
|
+
return points.map(([x, y]) => {
|
|
132
|
+
const relX = x - center[0];
|
|
133
|
+
const relY = y - center[1];
|
|
134
|
+
return [center[0] + relX * scaleX, center[1] + relY * scaleY];
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
function transformPoints(points, options) {
|
|
138
|
+
let result = points;
|
|
139
|
+
if (options.normalizeShape && options.normalizeShape === "rectangle") {
|
|
140
|
+
result = normalizeShape(result);
|
|
141
|
+
}
|
|
142
|
+
if (options.widthIncrement !== void 0 || options.heightIncrement !== void 0) {
|
|
143
|
+
result = resizeBoundingBox(
|
|
144
|
+
result,
|
|
145
|
+
options.widthIncrement ?? 0,
|
|
146
|
+
options.heightIncrement ?? 0
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
return result;
|
|
150
|
+
}
|
|
151
|
+
var init_geometry = __esm({
|
|
152
|
+
"src/lib/geometry.ts"() {
|
|
69
153
|
"use strict";
|
|
70
154
|
init_cjs_shims();
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
// src/lib/sort.ts
|
|
159
|
+
function getBoundingBoxCenter(points) {
|
|
160
|
+
let minX = Infinity;
|
|
161
|
+
let minY = Infinity;
|
|
162
|
+
let maxX = -Infinity;
|
|
163
|
+
let maxY = -Infinity;
|
|
164
|
+
for (const [x, y] of points) {
|
|
165
|
+
if (x !== void 0 && y !== void 0) {
|
|
166
|
+
minX = Math.min(minX, x);
|
|
167
|
+
minY = Math.min(minY, y);
|
|
168
|
+
maxX = Math.max(maxX, x);
|
|
169
|
+
maxY = Math.max(maxY, y);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return {
|
|
173
|
+
x: (minX + maxX) / 2,
|
|
174
|
+
y: (minY + maxY) / 2,
|
|
175
|
+
width: maxX - minX,
|
|
176
|
+
height: maxY - minY
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
function sortBoundingBoxes(annotations, verticalSort, horizontalSort) {
|
|
180
|
+
if (verticalSort === SORT_VERTICAL_NONE && horizontalSort === SORT_HORIZONTAL_NONE) {
|
|
181
|
+
return annotations;
|
|
182
|
+
}
|
|
183
|
+
const sorted = [...annotations];
|
|
184
|
+
const isVerticalText = sorted.length > 0 && (() => {
|
|
185
|
+
const verticalCount = sorted.filter((ann) => {
|
|
186
|
+
const center = getBoundingBoxCenter(ann.points);
|
|
187
|
+
return center.height > center.width * 1.5;
|
|
188
|
+
}).length;
|
|
189
|
+
return verticalCount > sorted.length / 2;
|
|
190
|
+
})();
|
|
191
|
+
if (horizontalSort === SORT_HORIZONTAL_RTL && verticalSort !== SORT_VERTICAL_NONE && isVerticalText) {
|
|
192
|
+
const annotationsWithCenters = sorted.map((ann) => ({
|
|
193
|
+
annotation: ann,
|
|
194
|
+
center: getBoundingBoxCenter(ann.points)
|
|
195
|
+
}));
|
|
196
|
+
const columns = [];
|
|
197
|
+
for (const item of annotationsWithCenters) {
|
|
198
|
+
let addedToColumn = false;
|
|
199
|
+
for (const column of columns) {
|
|
200
|
+
const avgX = column.reduce((sum, c) => sum + c.center.x, 0) / column.length;
|
|
201
|
+
if (Math.abs(item.center.x - avgX) < GROUPING_TOLERANCE) {
|
|
202
|
+
column.push(item);
|
|
203
|
+
addedToColumn = true;
|
|
204
|
+
break;
|
|
205
|
+
}
|
|
102
206
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
const newBaseServerUrl = baseServerUrl.replace(/\/+$/, "") + (baseServerUrl === "" ? "" : "/");
|
|
106
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
107
|
-
let original_width = 1920;
|
|
108
|
-
let original_height = 1080;
|
|
109
|
-
const resolvedImagePath = inputDir ? (0, import_node_path.join)(inputDir, imagePath) : imagePath;
|
|
110
|
-
if (!(0, import_node_fs.existsSync)(resolvedImagePath)) {
|
|
111
|
-
throw new Error(`Image file not found: ${resolvedImagePath}`);
|
|
207
|
+
if (!addedToColumn) {
|
|
208
|
+
columns.push([item]);
|
|
112
209
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
210
|
+
}
|
|
211
|
+
columns.sort((colA, colB) => {
|
|
212
|
+
const avgXA = colA.reduce((sum, c) => sum + c.center.x, 0) / colA.length;
|
|
213
|
+
const avgXB = colB.reduce((sum, c) => sum + c.center.x, 0) / colB.length;
|
|
214
|
+
return avgXB - avgXA;
|
|
215
|
+
});
|
|
216
|
+
for (const column of columns) {
|
|
217
|
+
column.sort((a, b) => {
|
|
218
|
+
return verticalSort === SORT_VERTICAL_TOP_BOTTOM ? a.center.y - b.center.y : b.center.y - a.center.y;
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
return columns.flat().map((item) => item.annotation);
|
|
222
|
+
}
|
|
223
|
+
sorted.sort((a, b) => {
|
|
224
|
+
const centerA = getBoundingBoxCenter(a.points);
|
|
225
|
+
const centerB = getBoundingBoxCenter(b.points);
|
|
226
|
+
if (verticalSort !== SORT_VERTICAL_NONE) {
|
|
227
|
+
const yDiff = verticalSort === SORT_VERTICAL_TOP_BOTTOM ? centerA.y - centerB.y : centerB.y - centerA.y;
|
|
228
|
+
if (Math.abs(yDiff) > GROUPING_TOLERANCE) {
|
|
229
|
+
return yDiff;
|
|
119
230
|
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
231
|
+
}
|
|
232
|
+
if (horizontalSort !== SORT_HORIZONTAL_NONE) {
|
|
233
|
+
return horizontalSort === SORT_HORIZONTAL_LTR ? centerA.x - centerB.x : centerB.x - centerA.x;
|
|
234
|
+
}
|
|
235
|
+
return 0;
|
|
236
|
+
});
|
|
237
|
+
return sorted;
|
|
238
|
+
}
|
|
239
|
+
var GROUPING_TOLERANCE;
|
|
240
|
+
var init_sort = __esm({
|
|
241
|
+
"src/lib/sort.ts"() {
|
|
242
|
+
"use strict";
|
|
243
|
+
init_cjs_shims();
|
|
244
|
+
init_constants();
|
|
245
|
+
GROUPING_TOLERANCE = 50;
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
// src/lib/enhance.ts
|
|
250
|
+
function enhancePPOCRLabel(data, options) {
|
|
251
|
+
const {
|
|
252
|
+
sortVertical,
|
|
253
|
+
sortHorizontal,
|
|
254
|
+
normalizeShape: normalizeShape2,
|
|
255
|
+
widthIncrement = 0,
|
|
256
|
+
heightIncrement = 0,
|
|
257
|
+
precision = 0
|
|
258
|
+
} = options;
|
|
259
|
+
let enhanced = data;
|
|
260
|
+
if (sortVertical && sortHorizontal) {
|
|
261
|
+
enhanced = sortBoundingBoxes(enhanced, sortVertical, sortHorizontal);
|
|
262
|
+
}
|
|
263
|
+
if (normalizeShape2 || widthIncrement !== 0 || heightIncrement !== 0) {
|
|
264
|
+
enhanced = enhanced.map((annotation) => {
|
|
265
|
+
let points = transformPoints(annotation.points, {
|
|
266
|
+
normalizeShape: normalizeShape2,
|
|
267
|
+
widthIncrement,
|
|
268
|
+
heightIncrement
|
|
269
|
+
});
|
|
270
|
+
points = roundPoints(points, precision);
|
|
271
|
+
return {
|
|
272
|
+
...annotation,
|
|
273
|
+
points
|
|
274
|
+
};
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
return enhanced;
|
|
278
|
+
}
|
|
279
|
+
var init_enhance = __esm({
|
|
280
|
+
"src/lib/enhance.ts"() {
|
|
281
|
+
"use strict";
|
|
282
|
+
init_cjs_shims();
|
|
283
|
+
init_geometry();
|
|
284
|
+
init_sort();
|
|
285
|
+
}
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
// src/lib/label-studio.ts
|
|
289
|
+
var turf, labelStudioToPPOCR, minLabelStudioToPPOCR, enhanceLabelStudioData;
|
|
290
|
+
var init_label_studio = __esm({
|
|
291
|
+
"src/lib/label-studio.ts"() {
|
|
292
|
+
"use strict";
|
|
293
|
+
init_cjs_shims();
|
|
294
|
+
turf = __toESM(require("@turf/turf"), 1);
|
|
295
|
+
init_enhance();
|
|
296
|
+
init_geometry();
|
|
297
|
+
labelStudioToPPOCR = async (data, options) => {
|
|
298
|
+
const {
|
|
299
|
+
baseImageDir,
|
|
300
|
+
normalizeShape: normalizeShape2,
|
|
301
|
+
widthIncrement = 0,
|
|
302
|
+
heightIncrement = 0,
|
|
303
|
+
precision = 0
|
|
304
|
+
} = options || {};
|
|
305
|
+
const resultMap = /* @__PURE__ */ new Map();
|
|
306
|
+
for (const task of data) {
|
|
307
|
+
let imagePath = task.file_upload || "";
|
|
308
|
+
if (task.data.ocr) {
|
|
309
|
+
const urlPath = task.data.ocr.replace(/^https?:\/\/[^/]+\//, "");
|
|
310
|
+
imagePath = decodeURIComponent(urlPath);
|
|
311
|
+
}
|
|
312
|
+
if (baseImageDir) {
|
|
313
|
+
imagePath = `${baseImageDir}/${task.file_upload || imagePath.split("/").pop() || imagePath}`;
|
|
314
|
+
}
|
|
315
|
+
const imageAnnotations = [];
|
|
316
|
+
for (const annotation of task.annotations) {
|
|
317
|
+
const groupedById = /* @__PURE__ */ new Map();
|
|
318
|
+
for (const resultItem of annotation.result) {
|
|
319
|
+
const { id } = resultItem;
|
|
320
|
+
if (!groupedById.has(id)) {
|
|
321
|
+
groupedById.set(id, []);
|
|
322
|
+
}
|
|
323
|
+
groupedById.get(id).push(resultItem);
|
|
324
|
+
}
|
|
325
|
+
for (const [_, resultItems] of groupedById) {
|
|
326
|
+
let points;
|
|
327
|
+
let transcription = "";
|
|
328
|
+
for (const resultItem of resultItems) {
|
|
329
|
+
if ("points" in resultItem.value && resultItem.value.points) {
|
|
330
|
+
const { points: valuePoints } = resultItem.value;
|
|
331
|
+
const { original_width, original_height } = resultItem;
|
|
332
|
+
points = valuePoints.map(([x, y]) => [
|
|
333
|
+
(x ?? 0) * original_width / 100,
|
|
334
|
+
(y ?? 0) * original_height / 100
|
|
136
335
|
]);
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
to_name: "image",
|
|
150
|
-
type: "polygon",
|
|
151
|
-
origin: "manual"
|
|
152
|
-
},
|
|
153
|
-
// 2. Labels with polygon geometry
|
|
154
|
-
{
|
|
155
|
-
original_width,
|
|
156
|
-
original_height,
|
|
157
|
-
image_rotation: 0,
|
|
158
|
-
value: {
|
|
159
|
-
points: polygonPoints,
|
|
160
|
-
closed: true,
|
|
161
|
-
labels: [labelName]
|
|
162
|
-
},
|
|
163
|
-
id: annotationId,
|
|
164
|
-
from_name: "label",
|
|
165
|
-
to_name: "image",
|
|
166
|
-
type: "labels",
|
|
167
|
-
origin: "manual"
|
|
168
|
-
},
|
|
169
|
-
// 3. Textarea with polygon geometry and text
|
|
170
|
-
{
|
|
171
|
-
original_width,
|
|
172
|
-
original_height,
|
|
173
|
-
image_rotation: 0,
|
|
174
|
-
value: {
|
|
175
|
-
points: polygonPoints,
|
|
176
|
-
closed: true,
|
|
177
|
-
text: [item.transcription]
|
|
178
|
-
},
|
|
179
|
-
id: annotationId,
|
|
180
|
-
from_name: "transcription",
|
|
181
|
-
to_name: "image",
|
|
182
|
-
type: "textarea",
|
|
183
|
-
origin: "manual"
|
|
184
|
-
}
|
|
336
|
+
} else if ("x" in resultItem.value && "y" in resultItem.value && "width" in resultItem.value && "height" in resultItem.value) {
|
|
337
|
+
const { x, y, width, height } = resultItem.value;
|
|
338
|
+
const { original_width, original_height } = resultItem;
|
|
339
|
+
const absX = x * original_width / 100;
|
|
340
|
+
const absY = y * original_height / 100;
|
|
341
|
+
const absWidth = width * original_width / 100;
|
|
342
|
+
const absHeight = height * original_height / 100;
|
|
343
|
+
points = [
|
|
344
|
+
[absX, absY],
|
|
345
|
+
[absX + absWidth, absY],
|
|
346
|
+
[absX + absWidth, absY + absHeight],
|
|
347
|
+
[absX, absY + absHeight]
|
|
185
348
|
];
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
updated_at: now,
|
|
191
|
-
draft_created_at: now,
|
|
192
|
-
lead_time: 0,
|
|
193
|
-
prediction: {},
|
|
194
|
-
result_count: data.length * 3,
|
|
195
|
-
unique_id: (0, import_node_crypto.randomUUID)(),
|
|
196
|
-
import_id: null,
|
|
197
|
-
last_action: null,
|
|
198
|
-
bulk_created: false,
|
|
199
|
-
task: taskId,
|
|
200
|
-
project: 1,
|
|
201
|
-
updated_by: 1,
|
|
202
|
-
parent_prediction: null,
|
|
203
|
-
parent_annotation: null,
|
|
204
|
-
last_created_by: null
|
|
349
|
+
}
|
|
350
|
+
if ("text" in resultItem.value && Array.isArray(resultItem.value.text)) {
|
|
351
|
+
transcription = resultItem.value.text[0] || "";
|
|
352
|
+
}
|
|
205
353
|
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
354
|
+
if (points && points.length > 0) {
|
|
355
|
+
points = transformPoints(points, {
|
|
356
|
+
normalizeShape: normalizeShape2,
|
|
357
|
+
widthIncrement,
|
|
358
|
+
heightIncrement
|
|
359
|
+
});
|
|
360
|
+
points = roundPoints(points, precision);
|
|
361
|
+
let dt_score = 1;
|
|
362
|
+
try {
|
|
363
|
+
const firstPoint = points[0];
|
|
364
|
+
if (firstPoint) {
|
|
365
|
+
const polygon2 = turf.polygon([points.concat([firstPoint])]);
|
|
366
|
+
const area2 = turf.area(polygon2);
|
|
367
|
+
dt_score = Math.min(1, Math.max(0.5, area2 / 1e4));
|
|
368
|
+
}
|
|
369
|
+
} catch {
|
|
370
|
+
dt_score = 0.8;
|
|
371
|
+
}
|
|
372
|
+
imageAnnotations.push({
|
|
373
|
+
transcription,
|
|
374
|
+
points,
|
|
375
|
+
dt_score
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
if (imageAnnotations.length > 0) {
|
|
381
|
+
resultMap.set(imagePath, imageAnnotations);
|
|
225
382
|
}
|
|
226
|
-
];
|
|
227
|
-
return result;
|
|
228
|
-
};
|
|
229
|
-
ppocrToMinLabelStudio = (data, imagePath, baseServerUrl, inputDir, labelName = "text") => {
|
|
230
|
-
const newBaseServerUrl = baseServerUrl.replace(/\/+$/, "") + (baseServerUrl === "" ? "" : "/");
|
|
231
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
232
|
-
let original_width = 1920;
|
|
233
|
-
let original_height = 1080;
|
|
234
|
-
const resolvedImagePath = inputDir ? (0, import_node_path.join)(inputDir, imagePath) : imagePath;
|
|
235
|
-
if (!(0, import_node_fs.existsSync)(resolvedImagePath)) {
|
|
236
|
-
throw new Error(`Image file not found: ${resolvedImagePath}`);
|
|
237
383
|
}
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
384
|
+
return resultMap;
|
|
385
|
+
};
|
|
386
|
+
minLabelStudioToPPOCR = async (data, options) => {
|
|
387
|
+
const {
|
|
388
|
+
baseImageDir,
|
|
389
|
+
normalizeShape: normalizeShape2,
|
|
390
|
+
widthIncrement = 0,
|
|
391
|
+
heightIncrement = 0,
|
|
392
|
+
precision = 0
|
|
393
|
+
} = options || {};
|
|
394
|
+
const resultMap = /* @__PURE__ */ new Map();
|
|
395
|
+
for (const item of data) {
|
|
396
|
+
let imagePath = item.ocr || "";
|
|
397
|
+
if (imagePath) {
|
|
398
|
+
imagePath = decodeURIComponent(
|
|
399
|
+
imagePath.replace(/^https?:\/\/[^/]+\//, "")
|
|
400
|
+
);
|
|
401
|
+
}
|
|
402
|
+
if (baseImageDir) {
|
|
403
|
+
imagePath = `${baseImageDir}/${imagePath.split("/").pop() || imagePath}`;
|
|
404
|
+
}
|
|
405
|
+
const numAnnotations = Math.max(
|
|
406
|
+
item.poly?.length || 0,
|
|
407
|
+
item.bbox?.length || 0,
|
|
408
|
+
item.transcription?.length || 0
|
|
243
409
|
);
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
410
|
+
for (let i = 0; i < numAnnotations; i++) {
|
|
411
|
+
let points;
|
|
412
|
+
if (item.poly && item.poly.length > i && item.poly[i]) {
|
|
413
|
+
const poly = item.poly[i];
|
|
414
|
+
if (poly) {
|
|
415
|
+
const { points: polyPoints } = poly;
|
|
416
|
+
points = polyPoints;
|
|
417
|
+
}
|
|
418
|
+
} else if (item.bbox && item.bbox.length > i && item.bbox[i]) {
|
|
419
|
+
const bbox = item.bbox[i];
|
|
420
|
+
if (bbox) {
|
|
421
|
+
const { x, y, width, height } = bbox;
|
|
422
|
+
points = [
|
|
423
|
+
[x, y],
|
|
424
|
+
[x + width, y],
|
|
425
|
+
[x + width, y + height],
|
|
426
|
+
[x, y + height]
|
|
427
|
+
];
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
if (!points) {
|
|
431
|
+
continue;
|
|
432
|
+
}
|
|
433
|
+
points = transformPoints(points, {
|
|
434
|
+
normalizeShape: normalizeShape2,
|
|
435
|
+
widthIncrement,
|
|
436
|
+
heightIncrement
|
|
437
|
+
});
|
|
438
|
+
points = roundPoints(points, precision);
|
|
439
|
+
const transcription = item.transcription && item.transcription.length > i ? item.transcription[i] : "";
|
|
440
|
+
let dt_score = 1;
|
|
441
|
+
try {
|
|
442
|
+
const firstPoint = points[0];
|
|
443
|
+
if (firstPoint) {
|
|
444
|
+
const polygon2 = turf.polygon([points.concat([firstPoint])]);
|
|
445
|
+
const area2 = turf.area(polygon2);
|
|
446
|
+
dt_score = Math.min(1, Math.max(0.5, area2 / 1e4));
|
|
447
|
+
}
|
|
448
|
+
} catch {
|
|
449
|
+
dt_score = 0.8;
|
|
260
450
|
}
|
|
451
|
+
const annotation = {
|
|
452
|
+
transcription: transcription ?? "",
|
|
453
|
+
points,
|
|
454
|
+
dt_score
|
|
455
|
+
};
|
|
456
|
+
if (!resultMap.has(imagePath)) {
|
|
457
|
+
resultMap.set(imagePath, []);
|
|
458
|
+
}
|
|
459
|
+
resultMap.get(imagePath).push(annotation);
|
|
261
460
|
}
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
461
|
+
}
|
|
462
|
+
return resultMap;
|
|
463
|
+
};
|
|
464
|
+
enhanceLabelStudioData = async (data, isFull, options) => {
|
|
465
|
+
const {
|
|
466
|
+
sortVertical,
|
|
467
|
+
sortHorizontal,
|
|
468
|
+
normalizeShape: normalizeShape2,
|
|
469
|
+
widthIncrement = 0,
|
|
470
|
+
heightIncrement = 0,
|
|
471
|
+
precision = 0
|
|
472
|
+
} = options;
|
|
473
|
+
if (isFull) {
|
|
474
|
+
const fullData = data;
|
|
475
|
+
return fullData.map((task) => ({
|
|
476
|
+
...task,
|
|
477
|
+
annotations: task.annotations.map((annotation) => {
|
|
478
|
+
const groupedById = /* @__PURE__ */ new Map();
|
|
479
|
+
for (const resultItem of annotation.result) {
|
|
480
|
+
const { id } = resultItem;
|
|
481
|
+
if (!groupedById.has(id)) {
|
|
482
|
+
groupedById.set(id, []);
|
|
483
|
+
}
|
|
484
|
+
groupedById.get(id).push(resultItem);
|
|
276
485
|
}
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
486
|
+
const enhancedResult = [];
|
|
487
|
+
for (const [_, resultItems] of groupedById) {
|
|
488
|
+
let ppocrAnnotations = [];
|
|
489
|
+
for (const resultItem of resultItems) {
|
|
490
|
+
let points;
|
|
491
|
+
if ("points" in resultItem.value && resultItem.value.points) {
|
|
492
|
+
const { points: valuePoints } = resultItem.value;
|
|
493
|
+
const { original_width, original_height } = resultItem;
|
|
494
|
+
points = valuePoints.map(([x, y]) => [
|
|
495
|
+
(x ?? 0) * original_width / 100,
|
|
496
|
+
(y ?? 0) * original_height / 100
|
|
497
|
+
]);
|
|
498
|
+
} else if ("x" in resultItem.value && "y" in resultItem.value && "width" in resultItem.value && "height" in resultItem.value) {
|
|
499
|
+
const { x, y, width, height } = resultItem.value;
|
|
500
|
+
const { original_width, original_height } = resultItem;
|
|
501
|
+
const absX = x * original_width / 100;
|
|
502
|
+
const absY = y * original_height / 100;
|
|
503
|
+
const absWidth = width * original_width / 100;
|
|
504
|
+
const absHeight = height * original_height / 100;
|
|
505
|
+
points = [
|
|
506
|
+
[absX, absY],
|
|
507
|
+
[absX + absWidth, absY],
|
|
508
|
+
[absX + absWidth, absY + absHeight],
|
|
509
|
+
[absX, absY + absHeight]
|
|
510
|
+
];
|
|
511
|
+
}
|
|
512
|
+
if (points) {
|
|
513
|
+
ppocrAnnotations.push({
|
|
514
|
+
transcription: "",
|
|
515
|
+
points,
|
|
516
|
+
dt_score: 1
|
|
517
|
+
});
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
if (ppocrAnnotations.length > 0) {
|
|
521
|
+
ppocrAnnotations = enhancePPOCRLabel(ppocrAnnotations, {
|
|
522
|
+
sortVertical,
|
|
523
|
+
sortHorizontal,
|
|
524
|
+
normalizeShape: normalizeShape2,
|
|
525
|
+
widthIncrement,
|
|
526
|
+
heightIncrement,
|
|
527
|
+
precision
|
|
528
|
+
});
|
|
529
|
+
for (let i = 0; i < resultItems.length; i++) {
|
|
530
|
+
const resultItem = resultItems[i];
|
|
531
|
+
const enhanced = ppocrAnnotations[i];
|
|
532
|
+
if (!enhanced) {
|
|
533
|
+
enhancedResult.push(resultItem);
|
|
534
|
+
continue;
|
|
535
|
+
}
|
|
536
|
+
if ("points" in resultItem.value && resultItem.value.points) {
|
|
537
|
+
const { original_width, original_height } = resultItem;
|
|
538
|
+
enhancedResult.push({
|
|
539
|
+
...resultItem,
|
|
540
|
+
value: {
|
|
541
|
+
...resultItem.value,
|
|
542
|
+
points: enhanced.points.map(
|
|
543
|
+
([x, y]) => [
|
|
544
|
+
(x ?? 0) / original_width * 100,
|
|
545
|
+
(y ?? 0) / original_height * 100
|
|
546
|
+
]
|
|
547
|
+
)
|
|
548
|
+
}
|
|
549
|
+
});
|
|
550
|
+
} else if ("x" in resultItem.value && "y" in resultItem.value && "width" in resultItem.value && "height" in resultItem.value) {
|
|
551
|
+
const { original_width, original_height } = resultItem;
|
|
552
|
+
const xs = enhanced.points.map(([x]) => x ?? 0);
|
|
553
|
+
const ys = enhanced.points.map(([, y]) => y ?? 0);
|
|
554
|
+
const minX = Math.min(...xs);
|
|
555
|
+
const maxX = Math.max(...xs);
|
|
556
|
+
const minY = Math.min(...ys);
|
|
557
|
+
const maxY = Math.max(...ys);
|
|
558
|
+
enhancedResult.push({
|
|
559
|
+
...resultItem,
|
|
560
|
+
value: {
|
|
561
|
+
...resultItem.value,
|
|
562
|
+
x: minX / original_width * 100,
|
|
563
|
+
y: minY / original_height * 100,
|
|
564
|
+
width: (maxX - minX) / original_width * 100,
|
|
565
|
+
height: (maxY - minY) / original_height * 100
|
|
566
|
+
}
|
|
567
|
+
});
|
|
568
|
+
} else {
|
|
569
|
+
enhancedResult.push(resultItem);
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
} else {
|
|
573
|
+
enhancedResult.push(...resultItems);
|
|
574
|
+
}
|
|
285
575
|
}
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
576
|
+
return {
|
|
577
|
+
...annotation,
|
|
578
|
+
result: enhancedResult
|
|
579
|
+
};
|
|
580
|
+
})
|
|
581
|
+
}));
|
|
582
|
+
} else {
|
|
583
|
+
const minData = data;
|
|
584
|
+
return minData.map((item) => {
|
|
585
|
+
let ppocrAnnotations = [];
|
|
586
|
+
const numAnnotations = Math.max(
|
|
587
|
+
item.poly?.length || 0,
|
|
588
|
+
item.bbox?.length || 0,
|
|
589
|
+
item.transcription?.length || 0
|
|
590
|
+
);
|
|
591
|
+
for (let i = 0; i < numAnnotations; i++) {
|
|
592
|
+
let points;
|
|
593
|
+
if (item.poly && item.poly.length > i && item.poly[i]) {
|
|
594
|
+
const { points: polyPoints } = item.poly[i];
|
|
595
|
+
points = polyPoints;
|
|
596
|
+
} else if (item.bbox && item.bbox.length > i && item.bbox[i]) {
|
|
597
|
+
const { x, y, width, height } = item.bbox[i];
|
|
598
|
+
points = [
|
|
599
|
+
[x, y],
|
|
600
|
+
[x + width, y],
|
|
601
|
+
[x + width, y + height],
|
|
602
|
+
[x, y + height]
|
|
603
|
+
];
|
|
294
604
|
}
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
605
|
+
if (points) {
|
|
606
|
+
ppocrAnnotations.push({
|
|
607
|
+
transcription: item.transcription && item.transcription.length > i ? item.transcription[i] ?? "" : "",
|
|
608
|
+
points,
|
|
609
|
+
dt_score: 1
|
|
610
|
+
});
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
if (ppocrAnnotations.length > 0) {
|
|
614
|
+
ppocrAnnotations = enhancePPOCRLabel(ppocrAnnotations, {
|
|
615
|
+
sortVertical,
|
|
616
|
+
sortHorizontal,
|
|
617
|
+
normalizeShape: normalizeShape2,
|
|
618
|
+
widthIncrement,
|
|
619
|
+
heightIncrement,
|
|
620
|
+
precision
|
|
621
|
+
});
|
|
622
|
+
const newPoly = ppocrAnnotations.map((ann) => ({
|
|
623
|
+
points: ann.points
|
|
624
|
+
}));
|
|
625
|
+
const { bbox: _, ...itemWithoutBbox } = item;
|
|
626
|
+
return {
|
|
627
|
+
...itemWithoutBbox,
|
|
628
|
+
poly: newPoly
|
|
629
|
+
};
|
|
630
|
+
}
|
|
631
|
+
return item;
|
|
632
|
+
});
|
|
633
|
+
}
|
|
303
634
|
};
|
|
304
635
|
}
|
|
305
636
|
});
|
|
@@ -320,6 +651,7 @@ var init_schema = __esm({
|
|
|
320
651
|
completed_by: import_zod.default.number(),
|
|
321
652
|
result: import_zod.default.array(
|
|
322
653
|
import_zod.default.union([
|
|
654
|
+
// Most specific rectangle variants first (with text or labels)
|
|
323
655
|
import_zod.default.object({
|
|
324
656
|
original_width: import_zod.default.number(),
|
|
325
657
|
original_height: import_zod.default.number(),
|
|
@@ -329,7 +661,8 @@ var init_schema = __esm({
|
|
|
329
661
|
y: import_zod.default.number(),
|
|
330
662
|
width: import_zod.default.number(),
|
|
331
663
|
height: import_zod.default.number(),
|
|
332
|
-
rotation: import_zod.default.number()
|
|
664
|
+
rotation: import_zod.default.number(),
|
|
665
|
+
text: import_zod.default.array(import_zod.default.string())
|
|
333
666
|
}),
|
|
334
667
|
id: import_zod.default.string(),
|
|
335
668
|
from_name: import_zod.default.string(),
|
|
@@ -355,6 +688,7 @@ var init_schema = __esm({
|
|
|
355
688
|
type: import_zod.default.string(),
|
|
356
689
|
origin: import_zod.default.string()
|
|
357
690
|
}),
|
|
691
|
+
// Base rectangle without text or labels
|
|
358
692
|
import_zod.default.object({
|
|
359
693
|
original_width: import_zod.default.number(),
|
|
360
694
|
original_height: import_zod.default.number(),
|
|
@@ -364,8 +698,7 @@ var init_schema = __esm({
|
|
|
364
698
|
y: import_zod.default.number(),
|
|
365
699
|
width: import_zod.default.number(),
|
|
366
700
|
height: import_zod.default.number(),
|
|
367
|
-
rotation: import_zod.default.number()
|
|
368
|
-
text: import_zod.default.array(import_zod.default.string())
|
|
701
|
+
rotation: import_zod.default.number()
|
|
369
702
|
}),
|
|
370
703
|
id: import_zod.default.string(),
|
|
371
704
|
from_name: import_zod.default.string(),
|
|
@@ -373,13 +706,15 @@ var init_schema = __esm({
|
|
|
373
706
|
type: import_zod.default.string(),
|
|
374
707
|
origin: import_zod.default.string()
|
|
375
708
|
}),
|
|
709
|
+
// Most specific polygon variants first (with text or labels)
|
|
376
710
|
import_zod.default.object({
|
|
377
711
|
original_width: import_zod.default.number(),
|
|
378
712
|
original_height: import_zod.default.number(),
|
|
379
713
|
image_rotation: import_zod.default.number(),
|
|
380
714
|
value: import_zod.default.object({
|
|
381
715
|
points: import_zod.default.array(import_zod.default.array(import_zod.default.number())),
|
|
382
|
-
closed: import_zod.default.boolean()
|
|
716
|
+
closed: import_zod.default.boolean(),
|
|
717
|
+
text: import_zod.default.array(import_zod.default.string())
|
|
383
718
|
}),
|
|
384
719
|
id: import_zod.default.string(),
|
|
385
720
|
from_name: import_zod.default.string(),
|
|
@@ -402,14 +737,14 @@ var init_schema = __esm({
|
|
|
402
737
|
type: import_zod.default.string(),
|
|
403
738
|
origin: import_zod.default.string()
|
|
404
739
|
}),
|
|
740
|
+
// Base polygon without text or labels
|
|
405
741
|
import_zod.default.object({
|
|
406
742
|
original_width: import_zod.default.number(),
|
|
407
743
|
original_height: import_zod.default.number(),
|
|
408
744
|
image_rotation: import_zod.default.number(),
|
|
409
745
|
value: import_zod.default.object({
|
|
410
746
|
points: import_zod.default.array(import_zod.default.array(import_zod.default.number())),
|
|
411
|
-
closed: import_zod.default.boolean()
|
|
412
|
-
text: import_zod.default.array(import_zod.default.string())
|
|
747
|
+
closed: import_zod.default.boolean()
|
|
413
748
|
}),
|
|
414
749
|
id: import_zod.default.string(),
|
|
415
750
|
from_name: import_zod.default.string(),
|
|
@@ -448,6 +783,7 @@ var init_schema = __esm({
|
|
|
448
783
|
created_ago: import_zod.default.string(),
|
|
449
784
|
result: import_zod.default.array(
|
|
450
785
|
import_zod.default.union([
|
|
786
|
+
// Most specific rectangle variants first (with text or labels)
|
|
451
787
|
import_zod.default.object({
|
|
452
788
|
original_width: import_zod.default.number(),
|
|
453
789
|
original_height: import_zod.default.number(),
|
|
@@ -457,7 +793,8 @@ var init_schema = __esm({
|
|
|
457
793
|
y: import_zod.default.number(),
|
|
458
794
|
width: import_zod.default.number(),
|
|
459
795
|
height: import_zod.default.number(),
|
|
460
|
-
rotation: import_zod.default.number()
|
|
796
|
+
rotation: import_zod.default.number(),
|
|
797
|
+
text: import_zod.default.array(import_zod.default.string())
|
|
461
798
|
}),
|
|
462
799
|
id: import_zod.default.string(),
|
|
463
800
|
from_name: import_zod.default.string(),
|
|
@@ -483,6 +820,7 @@ var init_schema = __esm({
|
|
|
483
820
|
type: import_zod.default.string(),
|
|
484
821
|
origin: import_zod.default.string()
|
|
485
822
|
}),
|
|
823
|
+
// Base rectangle without text or labels
|
|
486
824
|
import_zod.default.object({
|
|
487
825
|
original_width: import_zod.default.number(),
|
|
488
826
|
original_height: import_zod.default.number(),
|
|
@@ -492,8 +830,7 @@ var init_schema = __esm({
|
|
|
492
830
|
y: import_zod.default.number(),
|
|
493
831
|
width: import_zod.default.number(),
|
|
494
832
|
height: import_zod.default.number(),
|
|
495
|
-
rotation: import_zod.default.number()
|
|
496
|
-
text: import_zod.default.array(import_zod.default.string())
|
|
833
|
+
rotation: import_zod.default.number()
|
|
497
834
|
}),
|
|
498
835
|
id: import_zod.default.string(),
|
|
499
836
|
from_name: import_zod.default.string(),
|
|
@@ -501,13 +838,15 @@ var init_schema = __esm({
|
|
|
501
838
|
type: import_zod.default.string(),
|
|
502
839
|
origin: import_zod.default.string()
|
|
503
840
|
}),
|
|
841
|
+
// Most specific polygon variants first (with text or labels)
|
|
504
842
|
import_zod.default.object({
|
|
505
843
|
original_width: import_zod.default.number(),
|
|
506
844
|
original_height: import_zod.default.number(),
|
|
507
845
|
image_rotation: import_zod.default.number(),
|
|
508
846
|
value: import_zod.default.object({
|
|
509
847
|
points: import_zod.default.array(import_zod.default.array(import_zod.default.number())),
|
|
510
|
-
closed: import_zod.default.boolean()
|
|
848
|
+
closed: import_zod.default.boolean(),
|
|
849
|
+
text: import_zod.default.array(import_zod.default.string())
|
|
511
850
|
}),
|
|
512
851
|
id: import_zod.default.string(),
|
|
513
852
|
from_name: import_zod.default.string(),
|
|
@@ -530,14 +869,14 @@ var init_schema = __esm({
|
|
|
530
869
|
type: import_zod.default.string(),
|
|
531
870
|
origin: import_zod.default.string()
|
|
532
871
|
}),
|
|
872
|
+
// Base polygon without text or labels
|
|
533
873
|
import_zod.default.object({
|
|
534
874
|
original_width: import_zod.default.number(),
|
|
535
875
|
original_height: import_zod.default.number(),
|
|
536
876
|
image_rotation: import_zod.default.number(),
|
|
537
877
|
value: import_zod.default.object({
|
|
538
878
|
points: import_zod.default.array(import_zod.default.array(import_zod.default.number())),
|
|
539
|
-
closed: import_zod.default.boolean()
|
|
540
|
-
text: import_zod.default.array(import_zod.default.string())
|
|
879
|
+
closed: import_zod.default.boolean()
|
|
541
880
|
}),
|
|
542
881
|
id: import_zod.default.string(),
|
|
543
882
|
from_name: import_zod.default.string(),
|
|
@@ -588,7 +927,7 @@ var init_schema = __esm({
|
|
|
588
927
|
original_width: import_zod.default.number(),
|
|
589
928
|
original_height: import_zod.default.number()
|
|
590
929
|
})
|
|
591
|
-
),
|
|
930
|
+
).optional().default([]),
|
|
592
931
|
label: import_zod.default.array(
|
|
593
932
|
import_zod.default.union([
|
|
594
933
|
import_zod.default.object({
|
|
@@ -609,8 +948,11 @@ var init_schema = __esm({
|
|
|
609
948
|
original_height: import_zod.default.number()
|
|
610
949
|
})
|
|
611
950
|
])
|
|
612
|
-
),
|
|
613
|
-
transcription: import_zod.default.array(import_zod.default.string())
|
|
951
|
+
).optional().default([]),
|
|
952
|
+
transcription: import_zod.default.union([import_zod.default.string(), import_zod.default.array(import_zod.default.string())]).optional().transform((val) => {
|
|
953
|
+
if (!val) return [];
|
|
954
|
+
return Array.isArray(val) ? val : [val];
|
|
955
|
+
}),
|
|
614
956
|
poly: import_zod.default.array(
|
|
615
957
|
import_zod.default.object({
|
|
616
958
|
points: import_zod.default.array(import_zod.default.array(import_zod.default.number())),
|
|
@@ -618,7 +960,7 @@ var init_schema = __esm({
|
|
|
618
960
|
original_width: import_zod.default.number(),
|
|
619
961
|
original_height: import_zod.default.number()
|
|
620
962
|
})
|
|
621
|
-
),
|
|
963
|
+
).optional().default([]),
|
|
622
964
|
annotator: import_zod.default.number(),
|
|
623
965
|
annotation_id: import_zod.default.number(),
|
|
624
966
|
created_at: import_zod.default.string(),
|
|
@@ -630,106 +972,450 @@ var init_schema = __esm({
|
|
|
630
972
|
import_zod.default.object({
|
|
631
973
|
transcription: import_zod.default.string(),
|
|
632
974
|
points: import_zod.default.array(import_zod.default.array(import_zod.default.number())),
|
|
633
|
-
dt_score: import_zod.default.number()
|
|
975
|
+
dt_score: import_zod.default.number().optional(),
|
|
976
|
+
// Detection score (from PaddleOCR)
|
|
977
|
+
difficult: import_zod.default.boolean().optional()
|
|
978
|
+
// Difficult flag (from PPOCRLabel tool)
|
|
634
979
|
})
|
|
635
980
|
);
|
|
636
981
|
}
|
|
637
982
|
});
|
|
638
983
|
|
|
639
|
-
// src/
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
984
|
+
// src/commands/enhance-labelstudio/impl.ts
|
|
985
|
+
var impl_exports = {};
|
|
986
|
+
__export(impl_exports, {
|
|
987
|
+
enhanceLabelStudio: () => enhanceLabelStudio
|
|
988
|
+
});
|
|
989
|
+
async function enhanceLabelStudio(flags, ...inputDirs) {
|
|
990
|
+
const {
|
|
991
|
+
outDir = OUTPUT_BASE_DIR,
|
|
992
|
+
sortVertical = DEFAULT_SORT_VERTICAL,
|
|
993
|
+
sortHorizontal = DEFAULT_SORT_HORIZONTAL,
|
|
994
|
+
normalizeShape: normalizeShape2 = DEFAULT_SHAPE_NORMALIZE,
|
|
995
|
+
widthIncrement = DEFAULT_WIDTH_INCREMENT,
|
|
996
|
+
heightIncrement = DEFAULT_HEIGHT_INCREMENT,
|
|
997
|
+
precision = DEFAULT_LABEL_STUDIO_PRECISION
|
|
998
|
+
} = flags;
|
|
999
|
+
await (0, import_promises.mkdir)(outDir, { recursive: true });
|
|
1000
|
+
for (const inputDir of inputDirs) {
|
|
1001
|
+
console.log(import_chalk.default.blue(`Processing input directory: ${inputDir}`));
|
|
1002
|
+
const files = await (0, import_promises.readdir)(inputDir);
|
|
1003
|
+
for (const file of files) {
|
|
1004
|
+
if (!file.endsWith(".json")) {
|
|
1005
|
+
continue;
|
|
1006
|
+
}
|
|
1007
|
+
const filePath = (0, import_path.join)(inputDir, file);
|
|
1008
|
+
console.log(import_chalk.default.gray(`Processing file: ${file}`));
|
|
1009
|
+
try {
|
|
1010
|
+
const fileData = await (0, import_promises.readFile)(filePath, "utf-8");
|
|
1011
|
+
const labelStudioData = JSON.parse(fileData);
|
|
1012
|
+
const { data, isFull } = isLabelStudioFullJSON(labelStudioData);
|
|
1013
|
+
const enhanced = await enhanceLabelStudioData(data, isFull, {
|
|
1014
|
+
sortVertical,
|
|
1015
|
+
sortHorizontal,
|
|
1016
|
+
normalizeShape: normalizeShape2 !== SHAPE_NORMALIZE_NONE ? normalizeShape2 : void 0,
|
|
1017
|
+
widthIncrement,
|
|
1018
|
+
heightIncrement,
|
|
1019
|
+
precision
|
|
1020
|
+
});
|
|
1021
|
+
const outputFilePath = (0, import_path.join)(outDir, file);
|
|
1022
|
+
await (0, import_promises.writeFile)(
|
|
1023
|
+
outputFilePath,
|
|
1024
|
+
JSON.stringify(enhanced, null, 2),
|
|
1025
|
+
"utf-8"
|
|
1026
|
+
);
|
|
1027
|
+
console.log(import_chalk.default.green(`\u2713 Enhanced file saved: ${outputFilePath}`));
|
|
1028
|
+
} catch (error) {
|
|
1029
|
+
console.error(
|
|
1030
|
+
import_chalk.default.red(`Error processing file ${file}:`),
|
|
1031
|
+
error instanceof Error ? error.message : String(error)
|
|
1032
|
+
);
|
|
1033
|
+
}
|
|
651
1034
|
}
|
|
652
1035
|
}
|
|
653
|
-
|
|
654
|
-
x: (minX + maxX) / 2,
|
|
655
|
-
y: (minY + maxY) / 2,
|
|
656
|
-
width: maxX - minX,
|
|
657
|
-
height: maxY - minY
|
|
658
|
-
};
|
|
1036
|
+
console.log(import_chalk.default.green("\n\u2713 Enhancement complete!"));
|
|
659
1037
|
}
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
for (const column of columns) {
|
|
681
|
-
const avgX = column.reduce((sum, c) => sum + c.center.x, 0) / column.length;
|
|
682
|
-
if (Math.abs(item.center.x - avgX) < GROUPING_TOLERANCE) {
|
|
683
|
-
column.push(item);
|
|
684
|
-
addedToColumn = true;
|
|
685
|
-
break;
|
|
1038
|
+
var import_promises, import_path, import_chalk, isLabelStudioFullJSON;
|
|
1039
|
+
var init_impl = __esm({
|
|
1040
|
+
"src/commands/enhance-labelstudio/impl.ts"() {
|
|
1041
|
+
"use strict";
|
|
1042
|
+
init_cjs_shims();
|
|
1043
|
+
import_promises = require("fs/promises");
|
|
1044
|
+
import_path = require("path");
|
|
1045
|
+
import_chalk = __toESM(require("chalk"), 1);
|
|
1046
|
+
init_constants();
|
|
1047
|
+
init_label_studio();
|
|
1048
|
+
init_schema();
|
|
1049
|
+
isLabelStudioFullJSON = (data) => {
|
|
1050
|
+
const parsedFull = FullOCRLabelStudioSchema.safeParse(data);
|
|
1051
|
+
if (parsedFull.success) {
|
|
1052
|
+
return { isFull: true, data: parsedFull.data };
|
|
1053
|
+
}
|
|
1054
|
+
if (!Array.isArray(data) && typeof data === "object" && data !== null) {
|
|
1055
|
+
const parsedSingleFull = FullOCRLabelStudioSchema.safeParse([data]);
|
|
1056
|
+
if (parsedSingleFull.success) {
|
|
1057
|
+
return { isFull: true, data: parsedSingleFull.data };
|
|
686
1058
|
}
|
|
687
1059
|
}
|
|
688
|
-
|
|
689
|
-
|
|
1060
|
+
const parsedMin = MinOCRLabelStudioSchema.safeParse(data);
|
|
1061
|
+
if (parsedMin.success) {
|
|
1062
|
+
return { isFull: false, data: parsedMin.data };
|
|
690
1063
|
}
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
const avgXA = colA.reduce((sum, c) => sum + c.center.x, 0) / colA.length;
|
|
694
|
-
const avgXB = colB.reduce((sum, c) => sum + c.center.x, 0) / colB.length;
|
|
695
|
-
return avgXB - avgXA;
|
|
696
|
-
});
|
|
697
|
-
for (const column of columns) {
|
|
698
|
-
column.sort((a, b) => {
|
|
699
|
-
return verticalSort === SORT_VERTICAL_TOP_BOTTOM ? a.center.y - b.center.y : b.center.y - a.center.y;
|
|
700
|
-
});
|
|
701
|
-
}
|
|
702
|
-
return columns.flat().map((item) => item.annotation);
|
|
1064
|
+
throw new Error("Input data is not valid Label Studio JSON format.");
|
|
1065
|
+
};
|
|
703
1066
|
}
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
1067
|
+
});
|
|
1068
|
+
|
|
1069
|
+
// src/commands/enhance-ppocr/impl.ts
|
|
1070
|
+
var impl_exports2 = {};
|
|
1071
|
+
__export(impl_exports2, {
|
|
1072
|
+
enhancePPOCR: () => enhancePPOCR
|
|
1073
|
+
});
|
|
1074
|
+
async function enhancePPOCR(flags, ...inputDirs) {
|
|
1075
|
+
const {
|
|
1076
|
+
outDir = OUTPUT_BASE_DIR,
|
|
1077
|
+
sortVertical = DEFAULT_SORT_VERTICAL,
|
|
1078
|
+
sortHorizontal = DEFAULT_SORT_HORIZONTAL,
|
|
1079
|
+
normalizeShape: normalizeShape2 = DEFAULT_SHAPE_NORMALIZE,
|
|
1080
|
+
widthIncrement = DEFAULT_WIDTH_INCREMENT,
|
|
1081
|
+
heightIncrement = DEFAULT_HEIGHT_INCREMENT,
|
|
1082
|
+
precision = DEFAULT_PPOCR_PRECISION
|
|
1083
|
+
} = flags;
|
|
1084
|
+
await (0, import_promises2.mkdir)(outDir, { recursive: true });
|
|
1085
|
+
for (const inputDir of inputDirs) {
|
|
1086
|
+
console.log(import_chalk2.default.blue(`Processing input directory: ${inputDir}`));
|
|
1087
|
+
const files = await (0, import_promises2.readdir)(inputDir);
|
|
1088
|
+
for (const file of files) {
|
|
1089
|
+
if (!file.endsWith(".txt")) {
|
|
1090
|
+
continue;
|
|
1091
|
+
}
|
|
1092
|
+
const filePath = (0, import_path2.join)(inputDir, file);
|
|
1093
|
+
console.log(import_chalk2.default.gray(`Processing file: ${file}`));
|
|
1094
|
+
try {
|
|
1095
|
+
const fileData = await (0, import_promises2.readFile)(filePath, "utf-8");
|
|
1096
|
+
const lines = fileData.trim().split("\n");
|
|
1097
|
+
const enhancedLines = [];
|
|
1098
|
+
for (const line of lines) {
|
|
1099
|
+
const parts = line.split(" ");
|
|
1100
|
+
if (parts.length !== 2) {
|
|
1101
|
+
throw new Error(`Invalid PPOCRLabelV2 format in line: ${line}`);
|
|
1102
|
+
}
|
|
1103
|
+
const [imagePath, annotationsStr] = parts;
|
|
1104
|
+
const annotations = JSON.parse(annotationsStr);
|
|
1105
|
+
PPOCRLabelSchema.parse(annotations);
|
|
1106
|
+
const enhanced = enhancePPOCRLabel(annotations, {
|
|
1107
|
+
sortVertical,
|
|
1108
|
+
sortHorizontal,
|
|
1109
|
+
normalizeShape: normalizeShape2 !== SHAPE_NORMALIZE_NONE ? normalizeShape2 : void 0,
|
|
1110
|
+
widthIncrement,
|
|
1111
|
+
heightIncrement,
|
|
1112
|
+
precision
|
|
1113
|
+
});
|
|
1114
|
+
PPOCRLabelSchema.parse(enhanced);
|
|
1115
|
+
const jsonArray = JSON.stringify(enhanced);
|
|
1116
|
+
enhancedLines.push(`${imagePath} ${jsonArray}`);
|
|
1117
|
+
}
|
|
1118
|
+
const outputFilePath = (0, import_path2.join)(outDir, file);
|
|
1119
|
+
await (0, import_promises2.writeFile)(outputFilePath, enhancedLines.join("\n"), "utf-8");
|
|
1120
|
+
console.log(import_chalk2.default.green(`\u2713 Enhanced file saved: ${outputFilePath}`));
|
|
1121
|
+
} catch (error) {
|
|
1122
|
+
console.error(
|
|
1123
|
+
import_chalk2.default.red(`Error processing file ${file}:`),
|
|
1124
|
+
error instanceof Error ? error.message : String(error)
|
|
1125
|
+
);
|
|
711
1126
|
}
|
|
712
1127
|
}
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
}
|
|
716
|
-
return 0;
|
|
717
|
-
});
|
|
718
|
-
return sorted;
|
|
1128
|
+
}
|
|
1129
|
+
console.log(import_chalk2.default.green("\n\u2713 Enhancement complete!"));
|
|
719
1130
|
}
|
|
720
|
-
var
|
|
721
|
-
var
|
|
722
|
-
"src/
|
|
1131
|
+
var import_promises2, import_path2, import_chalk2;
|
|
1132
|
+
var init_impl2 = __esm({
|
|
1133
|
+
"src/commands/enhance-ppocr/impl.ts"() {
|
|
723
1134
|
"use strict";
|
|
724
1135
|
init_cjs_shims();
|
|
1136
|
+
import_promises2 = require("fs/promises");
|
|
1137
|
+
import_path2 = require("path");
|
|
1138
|
+
import_chalk2 = __toESM(require("chalk"), 1);
|
|
725
1139
|
init_constants();
|
|
726
|
-
|
|
1140
|
+
init_enhance();
|
|
1141
|
+
init_schema();
|
|
1142
|
+
}
|
|
1143
|
+
});
|
|
1144
|
+
|
|
1145
|
+
// src/lib/ppocr-label.ts
|
|
1146
|
+
var import_node_crypto, import_node_fs, import_node_path, import_image_size, ppocrToLabelStudio, ppocrToFullLabelStudio, ppocrToMinLabelStudio;
|
|
1147
|
+
var init_ppocr_label = __esm({
|
|
1148
|
+
"src/lib/ppocr-label.ts"() {
|
|
1149
|
+
"use strict";
|
|
1150
|
+
init_cjs_shims();
|
|
1151
|
+
import_node_crypto = require("crypto");
|
|
1152
|
+
import_node_fs = require("fs");
|
|
1153
|
+
import_node_path = require("path");
|
|
1154
|
+
import_image_size = __toESM(require("image-size"), 1);
|
|
1155
|
+
init_constants();
|
|
1156
|
+
init_geometry();
|
|
1157
|
+
ppocrToLabelStudio = async (data, options) => {
|
|
1158
|
+
const {
|
|
1159
|
+
imagePath,
|
|
1160
|
+
baseServerUrl,
|
|
1161
|
+
inputDir,
|
|
1162
|
+
toFullJson = true,
|
|
1163
|
+
taskId = 1,
|
|
1164
|
+
labelName = DEFAULT_LABEL_NAME,
|
|
1165
|
+
normalizeShape: normalizeShape2,
|
|
1166
|
+
widthIncrement = 0,
|
|
1167
|
+
heightIncrement = 0,
|
|
1168
|
+
precision = DEFAULT_LABEL_STUDIO_PRECISION
|
|
1169
|
+
} = options || {};
|
|
1170
|
+
if (toFullJson) {
|
|
1171
|
+
return ppocrToFullLabelStudio(
|
|
1172
|
+
data,
|
|
1173
|
+
imagePath,
|
|
1174
|
+
baseServerUrl,
|
|
1175
|
+
inputDir,
|
|
1176
|
+
taskId,
|
|
1177
|
+
labelName,
|
|
1178
|
+
normalizeShape2,
|
|
1179
|
+
widthIncrement,
|
|
1180
|
+
heightIncrement,
|
|
1181
|
+
precision
|
|
1182
|
+
);
|
|
1183
|
+
} else {
|
|
1184
|
+
return ppocrToMinLabelStudio(
|
|
1185
|
+
data,
|
|
1186
|
+
imagePath,
|
|
1187
|
+
baseServerUrl,
|
|
1188
|
+
inputDir,
|
|
1189
|
+
labelName,
|
|
1190
|
+
normalizeShape2,
|
|
1191
|
+
widthIncrement,
|
|
1192
|
+
heightIncrement,
|
|
1193
|
+
precision
|
|
1194
|
+
);
|
|
1195
|
+
}
|
|
1196
|
+
};
|
|
1197
|
+
ppocrToFullLabelStudio = (data, imagePath, baseServerUrl, inputDir, taskId = 1, labelName = DEFAULT_LABEL_NAME, normalizeShape2, widthIncrement = 0, heightIncrement = 0, precision = DEFAULT_LABEL_STUDIO_PRECISION) => {
|
|
1198
|
+
const newBaseServerUrl = baseServerUrl.replace(/\/+$/, "") + (baseServerUrl === "" ? "" : "/");
|
|
1199
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1200
|
+
let original_width = 1920;
|
|
1201
|
+
let original_height = 1080;
|
|
1202
|
+
const resolvedImagePath = inputDir ? (0, import_node_path.join)(inputDir, imagePath) : imagePath;
|
|
1203
|
+
if (!(0, import_node_fs.existsSync)(resolvedImagePath)) {
|
|
1204
|
+
throw new Error(`Image file not found: ${resolvedImagePath}`);
|
|
1205
|
+
}
|
|
1206
|
+
const buffer = (0, import_node_fs.readFileSync)(resolvedImagePath);
|
|
1207
|
+
const dimensions = (0, import_image_size.default)(buffer);
|
|
1208
|
+
if (!dimensions.width || !dimensions.height) {
|
|
1209
|
+
throw new Error(
|
|
1210
|
+
`Failed to read image dimensions from: ${resolvedImagePath}`
|
|
1211
|
+
);
|
|
1212
|
+
}
|
|
1213
|
+
original_width = dimensions.width;
|
|
1214
|
+
original_height = dimensions.height;
|
|
1215
|
+
const fileName = imagePath.split("/").pop() || imagePath;
|
|
1216
|
+
const result = [
|
|
1217
|
+
{
|
|
1218
|
+
id: taskId,
|
|
1219
|
+
annotations: [
|
|
1220
|
+
{
|
|
1221
|
+
id: taskId,
|
|
1222
|
+
completed_by: 1,
|
|
1223
|
+
result: data.map((item) => {
|
|
1224
|
+
let { points } = item;
|
|
1225
|
+
points = transformPoints(points, {
|
|
1226
|
+
normalizeShape: normalizeShape2,
|
|
1227
|
+
widthIncrement,
|
|
1228
|
+
heightIncrement
|
|
1229
|
+
});
|
|
1230
|
+
const annotationId = (0, import_node_crypto.randomUUID)().slice(0, 10);
|
|
1231
|
+
const polygonPoints = points.map(([x, y]) => [
|
|
1232
|
+
roundToPrecision((x ?? 0) / original_width * 100, precision),
|
|
1233
|
+
roundToPrecision((y ?? 0) / original_height * 100, precision)
|
|
1234
|
+
]);
|
|
1235
|
+
return [
|
|
1236
|
+
// 1. Polygon geometry only
|
|
1237
|
+
{
|
|
1238
|
+
original_width,
|
|
1239
|
+
original_height,
|
|
1240
|
+
image_rotation: 0,
|
|
1241
|
+
value: {
|
|
1242
|
+
points: polygonPoints,
|
|
1243
|
+
closed: true
|
|
1244
|
+
},
|
|
1245
|
+
id: annotationId,
|
|
1246
|
+
from_name: "poly",
|
|
1247
|
+
to_name: "image",
|
|
1248
|
+
type: "polygon",
|
|
1249
|
+
origin: "manual"
|
|
1250
|
+
},
|
|
1251
|
+
// 2. Labels with polygon geometry
|
|
1252
|
+
{
|
|
1253
|
+
original_width,
|
|
1254
|
+
original_height,
|
|
1255
|
+
image_rotation: 0,
|
|
1256
|
+
value: {
|
|
1257
|
+
points: polygonPoints,
|
|
1258
|
+
closed: true,
|
|
1259
|
+
labels: [labelName]
|
|
1260
|
+
},
|
|
1261
|
+
id: annotationId,
|
|
1262
|
+
from_name: "label",
|
|
1263
|
+
to_name: "image",
|
|
1264
|
+
type: "labels",
|
|
1265
|
+
origin: "manual"
|
|
1266
|
+
},
|
|
1267
|
+
// 3. Textarea with polygon geometry and text
|
|
1268
|
+
{
|
|
1269
|
+
original_width,
|
|
1270
|
+
original_height,
|
|
1271
|
+
image_rotation: 0,
|
|
1272
|
+
value: {
|
|
1273
|
+
points: polygonPoints,
|
|
1274
|
+
closed: true,
|
|
1275
|
+
text: [item.transcription]
|
|
1276
|
+
},
|
|
1277
|
+
id: annotationId,
|
|
1278
|
+
from_name: "transcription",
|
|
1279
|
+
to_name: "image",
|
|
1280
|
+
type: "textarea",
|
|
1281
|
+
origin: "manual"
|
|
1282
|
+
}
|
|
1283
|
+
];
|
|
1284
|
+
}).flat(),
|
|
1285
|
+
was_cancelled: false,
|
|
1286
|
+
ground_truth: false,
|
|
1287
|
+
created_at: now,
|
|
1288
|
+
updated_at: now,
|
|
1289
|
+
draft_created_at: now,
|
|
1290
|
+
lead_time: 0,
|
|
1291
|
+
prediction: {},
|
|
1292
|
+
result_count: data.length * 3,
|
|
1293
|
+
unique_id: (0, import_node_crypto.randomUUID)(),
|
|
1294
|
+
import_id: null,
|
|
1295
|
+
last_action: null,
|
|
1296
|
+
bulk_created: false,
|
|
1297
|
+
task: taskId,
|
|
1298
|
+
project: 1,
|
|
1299
|
+
updated_by: 1,
|
|
1300
|
+
parent_prediction: null,
|
|
1301
|
+
parent_annotation: null,
|
|
1302
|
+
last_created_by: null
|
|
1303
|
+
}
|
|
1304
|
+
],
|
|
1305
|
+
file_upload: fileName,
|
|
1306
|
+
drafts: [],
|
|
1307
|
+
predictions: [],
|
|
1308
|
+
data: { ocr: `${newBaseServerUrl}${imagePath}` },
|
|
1309
|
+
meta: {},
|
|
1310
|
+
created_at: now,
|
|
1311
|
+
updated_at: now,
|
|
1312
|
+
allow_skip: false,
|
|
1313
|
+
inner_id: taskId,
|
|
1314
|
+
total_annotations: 1,
|
|
1315
|
+
cancelled_annotations: 0,
|
|
1316
|
+
total_predictions: 0,
|
|
1317
|
+
comment_count: 0,
|
|
1318
|
+
unresolved_comment_count: 0,
|
|
1319
|
+
last_comment_updated_at: null,
|
|
1320
|
+
project: 1,
|
|
1321
|
+
updated_by: 1,
|
|
1322
|
+
comment_authors: []
|
|
1323
|
+
}
|
|
1324
|
+
];
|
|
1325
|
+
return result;
|
|
1326
|
+
};
|
|
1327
|
+
ppocrToMinLabelStudio = (data, imagePath, baseServerUrl, inputDir, labelName = "text", normalizeShape2, widthIncrement = 0, heightIncrement = 0, precision = DEFAULT_LABEL_STUDIO_PRECISION) => {
|
|
1328
|
+
const newBaseServerUrl = baseServerUrl.replace(/\/+$/, "") + (baseServerUrl === "" ? "" : "/");
|
|
1329
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1330
|
+
let original_width = 1920;
|
|
1331
|
+
let original_height = 1080;
|
|
1332
|
+
const resolvedImagePath = inputDir ? (0, import_node_path.join)(inputDir, imagePath) : imagePath;
|
|
1333
|
+
if (!(0, import_node_fs.existsSync)(resolvedImagePath)) {
|
|
1334
|
+
throw new Error(`Image file not found: ${resolvedImagePath}`);
|
|
1335
|
+
}
|
|
1336
|
+
const buffer = (0, import_node_fs.readFileSync)(resolvedImagePath);
|
|
1337
|
+
const dimensions = (0, import_image_size.default)(buffer);
|
|
1338
|
+
if (!dimensions.width || !dimensions.height) {
|
|
1339
|
+
throw new Error(
|
|
1340
|
+
`Failed to read image dimensions from: ${resolvedImagePath}`
|
|
1341
|
+
);
|
|
1342
|
+
}
|
|
1343
|
+
original_width = dimensions.width;
|
|
1344
|
+
original_height = dimensions.height;
|
|
1345
|
+
return data.map((item, index) => {
|
|
1346
|
+
let { points } = item;
|
|
1347
|
+
points = transformPoints(points, {
|
|
1348
|
+
normalizeShape: normalizeShape2,
|
|
1349
|
+
widthIncrement,
|
|
1350
|
+
heightIncrement
|
|
1351
|
+
});
|
|
1352
|
+
const roundedPoints = points.map(
|
|
1353
|
+
([x, y]) => [
|
|
1354
|
+
roundToPrecision(x ?? 0, precision),
|
|
1355
|
+
roundToPrecision(y ?? 0, precision)
|
|
1356
|
+
]
|
|
1357
|
+
);
|
|
1358
|
+
let minX = Infinity;
|
|
1359
|
+
let minY = Infinity;
|
|
1360
|
+
let maxX = -Infinity;
|
|
1361
|
+
let maxY = -Infinity;
|
|
1362
|
+
for (const point of roundedPoints) {
|
|
1363
|
+
const [x, y] = point;
|
|
1364
|
+
if (x !== void 0 && y !== void 0) {
|
|
1365
|
+
minX = Math.min(minX, x);
|
|
1366
|
+
minY = Math.min(minY, y);
|
|
1367
|
+
maxX = Math.max(maxX, x);
|
|
1368
|
+
maxY = Math.max(maxY, y);
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1371
|
+
const width = maxX - minX;
|
|
1372
|
+
const height = maxY - minY;
|
|
1373
|
+
return {
|
|
1374
|
+
ocr: encodeURI(`${newBaseServerUrl}${imagePath}`),
|
|
1375
|
+
id: index + 1,
|
|
1376
|
+
bbox: [
|
|
1377
|
+
{
|
|
1378
|
+
x: minX,
|
|
1379
|
+
y: minY,
|
|
1380
|
+
width,
|
|
1381
|
+
height,
|
|
1382
|
+
rotation: 0,
|
|
1383
|
+
original_width,
|
|
1384
|
+
original_height
|
|
1385
|
+
}
|
|
1386
|
+
],
|
|
1387
|
+
label: [
|
|
1388
|
+
{
|
|
1389
|
+
points: roundedPoints,
|
|
1390
|
+
closed: true,
|
|
1391
|
+
labels: [labelName],
|
|
1392
|
+
original_width,
|
|
1393
|
+
original_height
|
|
1394
|
+
}
|
|
1395
|
+
],
|
|
1396
|
+
transcription: [item.transcription],
|
|
1397
|
+
poly: [
|
|
1398
|
+
{
|
|
1399
|
+
points: roundedPoints,
|
|
1400
|
+
closed: true,
|
|
1401
|
+
original_width,
|
|
1402
|
+
original_height
|
|
1403
|
+
}
|
|
1404
|
+
],
|
|
1405
|
+
annotator: 1,
|
|
1406
|
+
annotation_id: index + 1,
|
|
1407
|
+
created_at: now,
|
|
1408
|
+
updated_at: now,
|
|
1409
|
+
lead_time: 0
|
|
1410
|
+
};
|
|
1411
|
+
});
|
|
1412
|
+
};
|
|
727
1413
|
}
|
|
728
1414
|
});
|
|
729
1415
|
|
|
730
1416
|
// src/commands/toLabelStudio/impl.ts
|
|
731
|
-
var
|
|
732
|
-
__export(
|
|
1417
|
+
var impl_exports3 = {};
|
|
1418
|
+
__export(impl_exports3, {
|
|
733
1419
|
convertToLabelStudio: () => convertToLabelStudio
|
|
734
1420
|
});
|
|
735
1421
|
async function convertToLabelStudio(flags, ...inputDirs) {
|
|
@@ -742,21 +1428,25 @@ async function convertToLabelStudio(flags, ...inputDirs) {
|
|
|
742
1428
|
fileListName = DEFAULT_FILE_LIST_NAME,
|
|
743
1429
|
baseServerUrl = DEFAULT_BASE_SERVER_URL,
|
|
744
1430
|
sortVertical = DEFAULT_SORT_VERTICAL,
|
|
745
|
-
sortHorizontal = DEFAULT_SORT_HORIZONTAL
|
|
1431
|
+
sortHorizontal = DEFAULT_SORT_HORIZONTAL,
|
|
1432
|
+
normalizeShape: normalizeShape2 = DEFAULT_SHAPE_NORMALIZE,
|
|
1433
|
+
widthIncrement = DEFAULT_WIDTH_INCREMENT,
|
|
1434
|
+
heightIncrement = DEFAULT_HEIGHT_INCREMENT,
|
|
1435
|
+
precision = DEFAULT_LABEL_STUDIO_PRECISION
|
|
746
1436
|
} = flags;
|
|
747
1437
|
const newBaseServerUrl = baseServerUrl.replace(/\/+$/, "") + (baseServerUrl === "" ? "" : "/");
|
|
748
|
-
await (0,
|
|
1438
|
+
await (0, import_promises3.mkdir)(outDir, { recursive: true });
|
|
749
1439
|
for (const inputDir of inputDirs) {
|
|
750
|
-
console.log(
|
|
751
|
-
const files = await (0,
|
|
1440
|
+
console.log(import_chalk3.default.blue(`Processing input directory: ${inputDir}`));
|
|
1441
|
+
const files = await (0, import_promises3.readdir)(inputDir);
|
|
752
1442
|
for (const file of files) {
|
|
753
1443
|
if (!file.endsWith(".txt")) {
|
|
754
1444
|
continue;
|
|
755
1445
|
}
|
|
756
|
-
const filePath = (0,
|
|
757
|
-
console.log(
|
|
1446
|
+
const filePath = (0, import_path3.join)(inputDir, file);
|
|
1447
|
+
console.log(import_chalk3.default.gray(`Processing file: ${file}`));
|
|
758
1448
|
try {
|
|
759
|
-
const fileData = await (0,
|
|
1449
|
+
const fileData = await (0, import_promises3.readFile)(filePath, "utf-8");
|
|
760
1450
|
const lines = fileData.trim().split("\n");
|
|
761
1451
|
const imageDataMap = /* @__PURE__ */ new Map();
|
|
762
1452
|
for (const line of lines) {
|
|
@@ -785,7 +1475,11 @@ async function convertToLabelStudio(flags, ...inputDirs) {
|
|
|
785
1475
|
baseServerUrl: newBaseServerUrl,
|
|
786
1476
|
inputDir,
|
|
787
1477
|
taskId,
|
|
788
|
-
labelName: defaultLabelName
|
|
1478
|
+
labelName: defaultLabelName,
|
|
1479
|
+
normalizeShape: normalizeShape2 !== SHAPE_NORMALIZE_NONE ? normalizeShape2 : void 0,
|
|
1480
|
+
widthIncrement,
|
|
1481
|
+
heightIncrement,
|
|
1482
|
+
precision
|
|
789
1483
|
});
|
|
790
1484
|
if (toFullJson) {
|
|
791
1485
|
allLabelStudioData.push(labelStudioData[0]);
|
|
@@ -794,11 +1488,11 @@ async function convertToLabelStudio(flags, ...inputDirs) {
|
|
|
794
1488
|
}
|
|
795
1489
|
if (createFilePerImage) {
|
|
796
1490
|
const imageBaseName = imagePath.replace(/\//g, "_").replace(/\.[^.]+$/, "");
|
|
797
|
-
const individualOutputPath = (0,
|
|
1491
|
+
const individualOutputPath = (0, import_path3.join)(
|
|
798
1492
|
outDir,
|
|
799
1493
|
`${imageBaseName}_${toFullJson ? "full" : "min"}.json`
|
|
800
1494
|
);
|
|
801
|
-
await (0,
|
|
1495
|
+
await (0, import_promises3.writeFile)(
|
|
802
1496
|
individualOutputPath,
|
|
803
1497
|
JSON.stringify(
|
|
804
1498
|
toFullJson ? labelStudioData[0] : labelStudioData,
|
|
@@ -808,7 +1502,7 @@ async function convertToLabelStudio(flags, ...inputDirs) {
|
|
|
808
1502
|
"utf-8"
|
|
809
1503
|
);
|
|
810
1504
|
console.log(
|
|
811
|
-
|
|
1505
|
+
import_chalk3.default.gray(
|
|
812
1506
|
` \u2713 Created individual file: ${individualOutputPath}`
|
|
813
1507
|
)
|
|
814
1508
|
);
|
|
@@ -819,43 +1513,43 @@ async function convertToLabelStudio(flags, ...inputDirs) {
|
|
|
819
1513
|
taskId++;
|
|
820
1514
|
}
|
|
821
1515
|
const baseName = file.replace(".txt", "");
|
|
822
|
-
const outputPath = (0,
|
|
1516
|
+
const outputPath = (0, import_path3.join)(
|
|
823
1517
|
outDir,
|
|
824
1518
|
`${baseName}_${toFullJson ? "full" : "min"}.json`
|
|
825
1519
|
);
|
|
826
|
-
await (0,
|
|
1520
|
+
await (0, import_promises3.writeFile)(
|
|
827
1521
|
outputPath,
|
|
828
1522
|
JSON.stringify(allLabelStudioData, null, 2),
|
|
829
1523
|
"utf-8"
|
|
830
1524
|
);
|
|
831
|
-
console.log(
|
|
1525
|
+
console.log(import_chalk3.default.green(`\u2713 Converted ${file} -> ${outputPath}`));
|
|
832
1526
|
if (createFileListForServing && fileList.length > 0) {
|
|
833
|
-
const fileListPath = (0,
|
|
834
|
-
await (0,
|
|
1527
|
+
const fileListPath = (0, import_path3.join)(outDir, fileListName);
|
|
1528
|
+
await (0, import_promises3.writeFile)(fileListPath, fileList.join("\n"), "utf-8");
|
|
835
1529
|
console.log(
|
|
836
|
-
|
|
1530
|
+
import_chalk3.default.green(
|
|
837
1531
|
`\u2713 Created file list: ${fileListPath} (${fileList.length} files)`
|
|
838
1532
|
)
|
|
839
1533
|
);
|
|
840
1534
|
}
|
|
841
1535
|
} catch (error) {
|
|
842
1536
|
console.error(
|
|
843
|
-
|
|
1537
|
+
import_chalk3.default.red(`\u2717 Failed to process ${file}:`),
|
|
844
1538
|
error instanceof Error ? error.message : error
|
|
845
1539
|
);
|
|
846
1540
|
}
|
|
847
1541
|
}
|
|
848
1542
|
}
|
|
849
|
-
console.log(
|
|
1543
|
+
console.log(import_chalk3.default.green("\n\u2713 Conversion completed!"));
|
|
850
1544
|
}
|
|
851
|
-
var
|
|
852
|
-
var
|
|
1545
|
+
var import_promises3, import_path3, import_chalk3;
|
|
1546
|
+
var init_impl3 = __esm({
|
|
853
1547
|
"src/commands/toLabelStudio/impl.ts"() {
|
|
854
1548
|
"use strict";
|
|
855
1549
|
init_cjs_shims();
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
1550
|
+
import_promises3 = require("fs/promises");
|
|
1551
|
+
import_path3 = require("path");
|
|
1552
|
+
import_chalk3 = __toESM(require("chalk"), 1);
|
|
859
1553
|
init_constants();
|
|
860
1554
|
init_ppocr_label();
|
|
861
1555
|
init_schema();
|
|
@@ -863,147 +1557,9 @@ var init_impl = __esm({
|
|
|
863
1557
|
}
|
|
864
1558
|
});
|
|
865
1559
|
|
|
866
|
-
// src/lib/label-studio.ts
|
|
867
|
-
var turf, labelStudioToPPOCR, minLabelStudioToPPOCR;
|
|
868
|
-
var init_label_studio = __esm({
|
|
869
|
-
"src/lib/label-studio.ts"() {
|
|
870
|
-
"use strict";
|
|
871
|
-
init_cjs_shims();
|
|
872
|
-
turf = __toESM(require("@turf/turf"), 1);
|
|
873
|
-
labelStudioToPPOCR = async (data, baseImageDir) => {
|
|
874
|
-
const resultMap = /* @__PURE__ */ new Map();
|
|
875
|
-
for (const task of data) {
|
|
876
|
-
let imagePath = task.file_upload || "";
|
|
877
|
-
if (task.data.ocr) {
|
|
878
|
-
const urlPath = task.data.ocr.replace(/^https?:\/\/[^/]+\//, "");
|
|
879
|
-
imagePath = decodeURIComponent(urlPath);
|
|
880
|
-
}
|
|
881
|
-
if (baseImageDir) {
|
|
882
|
-
imagePath = `${baseImageDir}/${task.file_upload || imagePath.split("/").pop() || imagePath}`;
|
|
883
|
-
}
|
|
884
|
-
const imageAnnotations = [];
|
|
885
|
-
for (const annotation of task.annotations) {
|
|
886
|
-
const groupedById = /* @__PURE__ */ new Map();
|
|
887
|
-
for (const resultItem of annotation.result) {
|
|
888
|
-
const { id } = resultItem;
|
|
889
|
-
if (!groupedById.has(id)) {
|
|
890
|
-
groupedById.set(id, []);
|
|
891
|
-
}
|
|
892
|
-
groupedById.get(id).push(resultItem);
|
|
893
|
-
}
|
|
894
|
-
for (const [_, resultItems] of groupedById) {
|
|
895
|
-
let points;
|
|
896
|
-
let transcription = "";
|
|
897
|
-
for (const resultItem of resultItems) {
|
|
898
|
-
if ("points" in resultItem.value && resultItem.value.points) {
|
|
899
|
-
const { points: valuePoints } = resultItem.value;
|
|
900
|
-
const { original_width, original_height } = resultItem;
|
|
901
|
-
points = valuePoints.map(([x, y]) => [
|
|
902
|
-
(x ?? 0) * original_width / 100,
|
|
903
|
-
(y ?? 0) * original_height / 100
|
|
904
|
-
]);
|
|
905
|
-
} else if ("x" in resultItem.value && "y" in resultItem.value && "width" in resultItem.value && "height" in resultItem.value) {
|
|
906
|
-
const { x, y, width, height } = resultItem.value;
|
|
907
|
-
const { original_width, original_height } = resultItem;
|
|
908
|
-
const absX = x * original_width / 100;
|
|
909
|
-
const absY = y * original_height / 100;
|
|
910
|
-
const absWidth = width * original_width / 100;
|
|
911
|
-
const absHeight = height * original_height / 100;
|
|
912
|
-
points = [
|
|
913
|
-
[absX, absY],
|
|
914
|
-
[absX + absWidth, absY],
|
|
915
|
-
[absX + absWidth, absY + absHeight],
|
|
916
|
-
[absX, absY + absHeight]
|
|
917
|
-
];
|
|
918
|
-
}
|
|
919
|
-
if ("text" in resultItem.value && Array.isArray(resultItem.value.text)) {
|
|
920
|
-
transcription = resultItem.value.text[0] || "";
|
|
921
|
-
}
|
|
922
|
-
}
|
|
923
|
-
if (points && points.length > 0) {
|
|
924
|
-
let dt_score = 1;
|
|
925
|
-
try {
|
|
926
|
-
const firstPoint = points[0];
|
|
927
|
-
if (firstPoint) {
|
|
928
|
-
const polygon2 = turf.polygon([points.concat([firstPoint])]);
|
|
929
|
-
const area2 = turf.area(polygon2);
|
|
930
|
-
dt_score = Math.min(1, Math.max(0.5, area2 / 1e4));
|
|
931
|
-
}
|
|
932
|
-
} catch {
|
|
933
|
-
dt_score = 0.8;
|
|
934
|
-
}
|
|
935
|
-
imageAnnotations.push({
|
|
936
|
-
transcription,
|
|
937
|
-
points,
|
|
938
|
-
dt_score
|
|
939
|
-
});
|
|
940
|
-
}
|
|
941
|
-
}
|
|
942
|
-
}
|
|
943
|
-
if (imageAnnotations.length > 0) {
|
|
944
|
-
resultMap.set(imagePath, imageAnnotations);
|
|
945
|
-
}
|
|
946
|
-
}
|
|
947
|
-
return resultMap;
|
|
948
|
-
};
|
|
949
|
-
minLabelStudioToPPOCR = async (data, baseImageDir) => {
|
|
950
|
-
const resultMap = /* @__PURE__ */ new Map();
|
|
951
|
-
for (const item of data) {
|
|
952
|
-
let imagePath = item.ocr || "";
|
|
953
|
-
if (imagePath) {
|
|
954
|
-
imagePath = decodeURIComponent(
|
|
955
|
-
imagePath.replace(/^https?:\/\/[^/]+\//, "")
|
|
956
|
-
);
|
|
957
|
-
}
|
|
958
|
-
if (baseImageDir) {
|
|
959
|
-
imagePath = `${baseImageDir}/${imagePath.split("/").pop() || imagePath}`;
|
|
960
|
-
}
|
|
961
|
-
let points;
|
|
962
|
-
if (item.poly.length > 0 && item.poly[0]) {
|
|
963
|
-
const { points: polyPoints } = item.poly[0];
|
|
964
|
-
points = polyPoints;
|
|
965
|
-
} else if (item.bbox.length > 0 && item.bbox[0]) {
|
|
966
|
-
const bbox = item.bbox[0];
|
|
967
|
-
const { x, y, width, height } = bbox;
|
|
968
|
-
points = [
|
|
969
|
-
[x, y],
|
|
970
|
-
[x + width, y],
|
|
971
|
-
[x + width, y + height],
|
|
972
|
-
[x, y + height]
|
|
973
|
-
];
|
|
974
|
-
} else {
|
|
975
|
-
continue;
|
|
976
|
-
}
|
|
977
|
-
const transcription = item.transcription.length > 0 ? item.transcription[0] : "";
|
|
978
|
-
let dt_score = 1;
|
|
979
|
-
try {
|
|
980
|
-
const firstPoint = points[0];
|
|
981
|
-
if (firstPoint) {
|
|
982
|
-
const polygon2 = turf.polygon([points.concat([firstPoint])]);
|
|
983
|
-
const area2 = turf.area(polygon2);
|
|
984
|
-
dt_score = Math.min(1, Math.max(0.5, area2 / 1e4));
|
|
985
|
-
}
|
|
986
|
-
} catch {
|
|
987
|
-
dt_score = 0.8;
|
|
988
|
-
}
|
|
989
|
-
const annotation = {
|
|
990
|
-
transcription: transcription ?? "",
|
|
991
|
-
points,
|
|
992
|
-
dt_score
|
|
993
|
-
};
|
|
994
|
-
if (!resultMap.has(imagePath)) {
|
|
995
|
-
resultMap.set(imagePath, []);
|
|
996
|
-
}
|
|
997
|
-
resultMap.get(imagePath).push(annotation);
|
|
998
|
-
}
|
|
999
|
-
return resultMap;
|
|
1000
|
-
};
|
|
1001
|
-
}
|
|
1002
|
-
});
|
|
1003
|
-
|
|
1004
1560
|
// src/commands/toPPOCR/impl.ts
|
|
1005
|
-
var
|
|
1006
|
-
__export(
|
|
1561
|
+
var impl_exports4 = {};
|
|
1562
|
+
__export(impl_exports4, {
|
|
1007
1563
|
convertToPPOCR: () => convertToPPOCR
|
|
1008
1564
|
});
|
|
1009
1565
|
async function convertToPPOCR(flags, ...inputDirs) {
|
|
@@ -1012,26 +1568,39 @@ async function convertToPPOCR(flags, ...inputDirs) {
|
|
|
1012
1568
|
fileName = DEFAULT_PPOCR_FILE_NAME,
|
|
1013
1569
|
baseImageDir,
|
|
1014
1570
|
sortVertical = DEFAULT_SORT_VERTICAL,
|
|
1015
|
-
sortHorizontal = DEFAULT_SORT_HORIZONTAL
|
|
1571
|
+
sortHorizontal = DEFAULT_SORT_HORIZONTAL,
|
|
1572
|
+
normalizeShape: normalizeShape2 = DEFAULT_SHAPE_NORMALIZE,
|
|
1573
|
+
widthIncrement = DEFAULT_WIDTH_INCREMENT,
|
|
1574
|
+
heightIncrement = DEFAULT_HEIGHT_INCREMENT,
|
|
1575
|
+
precision = DEFAULT_PPOCR_PRECISION
|
|
1016
1576
|
} = flags;
|
|
1017
|
-
await (0,
|
|
1577
|
+
await (0, import_promises4.mkdir)(outDir, { recursive: true });
|
|
1018
1578
|
for (const inputDir of inputDirs) {
|
|
1019
|
-
console.log(
|
|
1020
|
-
const files = await (0,
|
|
1579
|
+
console.log(import_chalk4.default.blue(`Processing input directory: ${inputDir}`));
|
|
1580
|
+
const files = await (0, import_promises4.readdir)(inputDir);
|
|
1021
1581
|
for (const file of files) {
|
|
1022
1582
|
if (!file.endsWith(".json")) {
|
|
1023
1583
|
continue;
|
|
1024
1584
|
}
|
|
1025
|
-
const filePath = (0,
|
|
1026
|
-
console.log(
|
|
1585
|
+
const filePath = (0, import_path4.join)(inputDir, file);
|
|
1586
|
+
console.log(import_chalk4.default.gray(`Processing file: ${file}`));
|
|
1027
1587
|
try {
|
|
1028
|
-
const fileData = await (0,
|
|
1588
|
+
const fileData = await (0, import_promises4.readFile)(filePath, "utf-8");
|
|
1029
1589
|
const labelStudioData = JSON.parse(fileData);
|
|
1030
|
-
const { data, isFull } =
|
|
1031
|
-
const ppocrDataMap = isFull ? await labelStudioToPPOCR(data,
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1590
|
+
const { data, isFull } = isLabelStudioFullJSON2(labelStudioData);
|
|
1591
|
+
const ppocrDataMap = isFull ? await labelStudioToPPOCR(data, {
|
|
1592
|
+
baseImageDir,
|
|
1593
|
+
normalizeShape: normalizeShape2 !== SHAPE_NORMALIZE_NONE ? normalizeShape2 : void 0,
|
|
1594
|
+
widthIncrement,
|
|
1595
|
+
heightIncrement,
|
|
1596
|
+
precision
|
|
1597
|
+
}) : await minLabelStudioToPPOCR(data, {
|
|
1598
|
+
baseImageDir,
|
|
1599
|
+
normalizeShape: normalizeShape2 !== SHAPE_NORMALIZE_NONE ? normalizeShape2 : void 0,
|
|
1600
|
+
widthIncrement,
|
|
1601
|
+
heightIncrement,
|
|
1602
|
+
precision
|
|
1603
|
+
});
|
|
1035
1604
|
const outputLines = [];
|
|
1036
1605
|
for (const [imagePath, annotations] of ppocrDataMap.entries()) {
|
|
1037
1606
|
const sortedAnnotations = sortBoundingBoxes(
|
|
@@ -1044,32 +1613,32 @@ async function convertToPPOCR(flags, ...inputDirs) {
|
|
|
1044
1613
|
outputLines.push(`${imagePath} ${jsonArray}`);
|
|
1045
1614
|
}
|
|
1046
1615
|
const baseName = file.replace(".json", "");
|
|
1047
|
-
const outputPath = (0,
|
|
1048
|
-
await (0,
|
|
1049
|
-
console.log(
|
|
1616
|
+
const outputPath = (0, import_path4.join)(outDir, `${baseName}_${fileName}`);
|
|
1617
|
+
await (0, import_promises4.writeFile)(outputPath, outputLines.join("\n"), "utf-8");
|
|
1618
|
+
console.log(import_chalk4.default.green(`\u2713 Converted ${file} -> ${outputPath}`));
|
|
1050
1619
|
} catch (error) {
|
|
1051
1620
|
console.error(
|
|
1052
|
-
|
|
1621
|
+
import_chalk4.default.red(`\u2717 Failed to process ${file}:`),
|
|
1053
1622
|
error instanceof Error ? error.message : error
|
|
1054
1623
|
);
|
|
1055
1624
|
}
|
|
1056
1625
|
}
|
|
1057
1626
|
}
|
|
1058
|
-
console.log(
|
|
1627
|
+
console.log(import_chalk4.default.green("\n\u2713 Conversion completed!"));
|
|
1059
1628
|
}
|
|
1060
|
-
var
|
|
1061
|
-
var
|
|
1629
|
+
var import_promises4, import_path4, import_chalk4, isLabelStudioFullJSON2;
|
|
1630
|
+
var init_impl4 = __esm({
|
|
1062
1631
|
"src/commands/toPPOCR/impl.ts"() {
|
|
1063
1632
|
"use strict";
|
|
1064
1633
|
init_cjs_shims();
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1634
|
+
import_promises4 = require("fs/promises");
|
|
1635
|
+
import_path4 = require("path");
|
|
1636
|
+
import_chalk4 = __toESM(require("chalk"), 1);
|
|
1068
1637
|
init_constants();
|
|
1069
1638
|
init_label_studio();
|
|
1070
1639
|
init_schema();
|
|
1071
1640
|
init_sort();
|
|
1072
|
-
|
|
1641
|
+
isLabelStudioFullJSON2 = (data) => {
|
|
1073
1642
|
const parsedFull = FullOCRLabelStudioSchema.safeParse(data);
|
|
1074
1643
|
if (parsedFull.success) {
|
|
1075
1644
|
return { isFull: true, data: parsedFull.data };
|
|
@@ -1091,24 +1660,160 @@ var init_impl2 = __esm({
|
|
|
1091
1660
|
|
|
1092
1661
|
// src/bin/bash-complete.ts
|
|
1093
1662
|
init_cjs_shims();
|
|
1094
|
-
var
|
|
1663
|
+
var import_core6 = require("@stricli/core");
|
|
1095
1664
|
|
|
1096
1665
|
// src/app.ts
|
|
1097
1666
|
init_cjs_shims();
|
|
1098
1667
|
var import_auto_complete = require("@stricli/auto-complete");
|
|
1099
|
-
var
|
|
1668
|
+
var import_core5 = require("@stricli/core");
|
|
1100
1669
|
|
|
1101
1670
|
// package.json
|
|
1102
|
-
var version = "1.
|
|
1671
|
+
var version = "1.2.0";
|
|
1103
1672
|
var description = "Convert between Label Studio OCR format and PPOCRLabelv2 format";
|
|
1104
1673
|
|
|
1105
|
-
// src/commands/
|
|
1674
|
+
// src/commands/enhance-labelstudio/command.ts
|
|
1106
1675
|
init_cjs_shims();
|
|
1107
1676
|
var import_core = require("@stricli/core");
|
|
1108
1677
|
init_constants();
|
|
1109
|
-
var
|
|
1678
|
+
var enhanceLabelStudioCommand = (0, import_core.buildCommand)({
|
|
1679
|
+
loader: async () => {
|
|
1680
|
+
const { enhanceLabelStudio: enhanceLabelStudio2 } = await Promise.resolve().then(() => (init_impl(), impl_exports));
|
|
1681
|
+
return enhanceLabelStudio2;
|
|
1682
|
+
},
|
|
1683
|
+
parameters: {
|
|
1684
|
+
positional: {
|
|
1685
|
+
kind: "array",
|
|
1686
|
+
parameter: {
|
|
1687
|
+
brief: "Input directories containing Label Studio JSON files",
|
|
1688
|
+
parse: String
|
|
1689
|
+
},
|
|
1690
|
+
minimum: 1
|
|
1691
|
+
},
|
|
1692
|
+
flags: {
|
|
1693
|
+
outDir: {
|
|
1694
|
+
kind: "parsed",
|
|
1695
|
+
brief: `Output directory. Default: "${OUTPUT_BASE_DIR}"`,
|
|
1696
|
+
parse: String,
|
|
1697
|
+
optional: true
|
|
1698
|
+
},
|
|
1699
|
+
sortVertical: {
|
|
1700
|
+
kind: "parsed",
|
|
1701
|
+
brief: `Sort bounding boxes vertically. Options: "${SORT_VERTICAL_NONE}", "${SORT_VERTICAL_TOP_BOTTOM}", "${SORT_VERTICAL_BOTTOM_TOP}". Default: "${DEFAULT_SORT_VERTICAL}"`,
|
|
1702
|
+
parse: String,
|
|
1703
|
+
optional: true
|
|
1704
|
+
},
|
|
1705
|
+
sortHorizontal: {
|
|
1706
|
+
kind: "parsed",
|
|
1707
|
+
brief: `Sort bounding boxes horizontally. Options: "${SORT_HORIZONTAL_NONE}", "${SORT_HORIZONTAL_LTR}", "${SORT_HORIZONTAL_RTL}". Default: "${DEFAULT_SORT_HORIZONTAL}"`,
|
|
1708
|
+
parse: String,
|
|
1709
|
+
optional: true
|
|
1710
|
+
},
|
|
1711
|
+
normalizeShape: {
|
|
1712
|
+
kind: "parsed",
|
|
1713
|
+
brief: `Normalize diamond-like shapes to axis-aligned rectangles. Options: "${SHAPE_NORMALIZE_NONE}", "${SHAPE_NORMALIZE_RECTANGLE}". Default: "${DEFAULT_SHAPE_NORMALIZE}"`,
|
|
1714
|
+
parse: String,
|
|
1715
|
+
optional: true
|
|
1716
|
+
},
|
|
1717
|
+
widthIncrement: {
|
|
1718
|
+
kind: "parsed",
|
|
1719
|
+
brief: `Increase bounding box width by this amount (in pixels). Can be negative to decrease. Default: ${DEFAULT_WIDTH_INCREMENT}`,
|
|
1720
|
+
parse: Number,
|
|
1721
|
+
optional: true
|
|
1722
|
+
},
|
|
1723
|
+
heightIncrement: {
|
|
1724
|
+
kind: "parsed",
|
|
1725
|
+
brief: `Increase bounding box height by this amount (in pixels). Can be negative to decrease. Default: ${DEFAULT_HEIGHT_INCREMENT}`,
|
|
1726
|
+
parse: Number,
|
|
1727
|
+
optional: true
|
|
1728
|
+
},
|
|
1729
|
+
precision: {
|
|
1730
|
+
kind: "parsed",
|
|
1731
|
+
brief: `Number of decimal places for coordinates. Use -1 for full precision (no rounding). Default: ${DEFAULT_LABEL_STUDIO_PRECISION}`,
|
|
1732
|
+
parse: Number,
|
|
1733
|
+
optional: true
|
|
1734
|
+
}
|
|
1735
|
+
}
|
|
1736
|
+
},
|
|
1737
|
+
docs: {
|
|
1738
|
+
brief: "Enhance Label Studio files with sorting, normalization, and resizing"
|
|
1739
|
+
}
|
|
1740
|
+
});
|
|
1741
|
+
|
|
1742
|
+
// src/commands/enhance-ppocr/command.ts
|
|
1743
|
+
init_cjs_shims();
|
|
1744
|
+
var import_core2 = require("@stricli/core");
|
|
1745
|
+
init_constants();
|
|
1746
|
+
var enhancePPOCRCommand = (0, import_core2.buildCommand)({
|
|
1747
|
+
loader: async () => {
|
|
1748
|
+
const { enhancePPOCR: enhancePPOCR2 } = await Promise.resolve().then(() => (init_impl2(), impl_exports2));
|
|
1749
|
+
return enhancePPOCR2;
|
|
1750
|
+
},
|
|
1751
|
+
parameters: {
|
|
1752
|
+
positional: {
|
|
1753
|
+
kind: "array",
|
|
1754
|
+
parameter: {
|
|
1755
|
+
brief: "Input directories containing PPOCRLabel files",
|
|
1756
|
+
parse: String
|
|
1757
|
+
},
|
|
1758
|
+
minimum: 1
|
|
1759
|
+
},
|
|
1760
|
+
flags: {
|
|
1761
|
+
outDir: {
|
|
1762
|
+
kind: "parsed",
|
|
1763
|
+
brief: `Output directory. Default: "${OUTPUT_BASE_DIR}"`,
|
|
1764
|
+
parse: String,
|
|
1765
|
+
optional: true
|
|
1766
|
+
},
|
|
1767
|
+
sortVertical: {
|
|
1768
|
+
kind: "parsed",
|
|
1769
|
+
brief: `Sort bounding boxes vertically. Options: "${SORT_VERTICAL_NONE}", "${SORT_VERTICAL_TOP_BOTTOM}", "${SORT_VERTICAL_BOTTOM_TOP}". Default: "${DEFAULT_SORT_VERTICAL}"`,
|
|
1770
|
+
parse: String,
|
|
1771
|
+
optional: true
|
|
1772
|
+
},
|
|
1773
|
+
sortHorizontal: {
|
|
1774
|
+
kind: "parsed",
|
|
1775
|
+
brief: `Sort bounding boxes horizontally. Options: "${SORT_HORIZONTAL_NONE}", "${SORT_HORIZONTAL_LTR}", "${SORT_HORIZONTAL_RTL}". Default: "${DEFAULT_SORT_HORIZONTAL}"`,
|
|
1776
|
+
parse: String,
|
|
1777
|
+
optional: true
|
|
1778
|
+
},
|
|
1779
|
+
normalizeShape: {
|
|
1780
|
+
kind: "parsed",
|
|
1781
|
+
brief: `Normalize diamond-like shapes to axis-aligned rectangles. Options: "${SHAPE_NORMALIZE_NONE}", "${SHAPE_NORMALIZE_RECTANGLE}". Default: "${DEFAULT_SHAPE_NORMALIZE}"`,
|
|
1782
|
+
parse: String,
|
|
1783
|
+
optional: true
|
|
1784
|
+
},
|
|
1785
|
+
widthIncrement: {
|
|
1786
|
+
kind: "parsed",
|
|
1787
|
+
brief: `Increase bounding box width by this amount (in pixels). Can be negative to decrease. Default: ${DEFAULT_WIDTH_INCREMENT}`,
|
|
1788
|
+
parse: Number,
|
|
1789
|
+
optional: true
|
|
1790
|
+
},
|
|
1791
|
+
heightIncrement: {
|
|
1792
|
+
kind: "parsed",
|
|
1793
|
+
brief: `Increase bounding box height by this amount (in pixels). Can be negative to decrease. Default: ${DEFAULT_HEIGHT_INCREMENT}`,
|
|
1794
|
+
parse: Number,
|
|
1795
|
+
optional: true
|
|
1796
|
+
},
|
|
1797
|
+
precision: {
|
|
1798
|
+
kind: "parsed",
|
|
1799
|
+
brief: `Number of decimal places for coordinates. Use -1 for full precision (no rounding). Default: ${DEFAULT_PPOCR_PRECISION} (integers)`,
|
|
1800
|
+
parse: Number,
|
|
1801
|
+
optional: true
|
|
1802
|
+
}
|
|
1803
|
+
}
|
|
1804
|
+
},
|
|
1805
|
+
docs: {
|
|
1806
|
+
brief: "Enhance PPOCRLabel files with sorting, normalization, and resizing"
|
|
1807
|
+
}
|
|
1808
|
+
});
|
|
1809
|
+
|
|
1810
|
+
// src/commands/toLabelStudio/command.ts
|
|
1811
|
+
init_cjs_shims();
|
|
1812
|
+
var import_core3 = require("@stricli/core");
|
|
1813
|
+
init_constants();
|
|
1814
|
+
var toLabelStudioCommand = (0, import_core3.buildCommand)({
|
|
1110
1815
|
loader: async () => {
|
|
1111
|
-
const { convertToLabelStudio: convertToLabelStudio2 } = await Promise.resolve().then(() => (
|
|
1816
|
+
const { convertToLabelStudio: convertToLabelStudio2 } = await Promise.resolve().then(() => (init_impl3(), impl_exports3));
|
|
1112
1817
|
return convertToLabelStudio2;
|
|
1113
1818
|
},
|
|
1114
1819
|
parameters: {
|
|
@@ -1123,54 +1828,78 @@ var toLabelStudioCommand = (0, import_core.buildCommand)({
|
|
|
1123
1828
|
flags: {
|
|
1124
1829
|
outDir: {
|
|
1125
1830
|
kind: "parsed",
|
|
1126
|
-
brief: `Output directory. Default
|
|
1831
|
+
brief: `Output directory. Default: "${OUTPUT_BASE_DIR}"`,
|
|
1127
1832
|
parse: String,
|
|
1128
1833
|
optional: true
|
|
1129
1834
|
},
|
|
1130
1835
|
defaultLabelName: {
|
|
1131
1836
|
kind: "parsed",
|
|
1132
|
-
brief: `Default label name for text annotations. Default
|
|
1837
|
+
brief: `Default label name for text annotations. Default: "${DEFAULT_LABEL_NAME}"`,
|
|
1133
1838
|
parse: String,
|
|
1134
1839
|
optional: true
|
|
1135
1840
|
},
|
|
1136
1841
|
toFullJson: {
|
|
1137
1842
|
kind: "boolean",
|
|
1138
|
-
brief: `Convert to Full OCR Label Studio format. Default
|
|
1843
|
+
brief: `Convert to Full OCR Label Studio format. Default: "${DEFAULT_LABEL_STUDIO_FULL_JSON}"`,
|
|
1139
1844
|
optional: true
|
|
1140
1845
|
},
|
|
1141
1846
|
createFilePerImage: {
|
|
1142
1847
|
kind: "boolean",
|
|
1143
|
-
brief: `Create a separate Label Studio JSON file for each image. Default
|
|
1848
|
+
brief: `Create a separate Label Studio JSON file for each image. Default: "${DEFAULT_CREATE_FILE_PER_IMAGE}"`,
|
|
1144
1849
|
optional: true
|
|
1145
1850
|
},
|
|
1146
1851
|
createFileListForServing: {
|
|
1147
1852
|
kind: "boolean",
|
|
1148
|
-
brief: `Create a file list for serving in Label Studio. Default
|
|
1853
|
+
brief: `Create a file list for serving in Label Studio. Default: "${DEFAULT_CREATE_FILE_LIST_FOR_SERVING}"`,
|
|
1149
1854
|
optional: true
|
|
1150
1855
|
},
|
|
1151
1856
|
fileListName: {
|
|
1152
1857
|
kind: "parsed",
|
|
1153
|
-
brief: `Name of the file list for serving. Default
|
|
1858
|
+
brief: `Name of the file list for serving. Default: "${DEFAULT_FILE_LIST_NAME}"`,
|
|
1154
1859
|
parse: String,
|
|
1155
1860
|
optional: true
|
|
1156
1861
|
},
|
|
1157
1862
|
baseServerUrl: {
|
|
1158
1863
|
kind: "parsed",
|
|
1159
|
-
brief: `Base server URL for constructing image URLs in the file list. Default
|
|
1864
|
+
brief: `Base server URL for constructing image URLs in the file list. Default: "${DEFAULT_BASE_SERVER_URL}"`,
|
|
1160
1865
|
parse: String,
|
|
1161
1866
|
optional: true
|
|
1162
1867
|
},
|
|
1163
1868
|
sortVertical: {
|
|
1164
1869
|
kind: "parsed",
|
|
1165
|
-
brief: `Sort bounding boxes vertically. Options: "${SORT_VERTICAL_NONE}"
|
|
1870
|
+
brief: `Sort bounding boxes vertically. Options: "${SORT_VERTICAL_NONE}", "${SORT_VERTICAL_TOP_BOTTOM}", "${SORT_VERTICAL_BOTTOM_TOP}". Default: "${DEFAULT_SORT_VERTICAL}"`,
|
|
1166
1871
|
parse: String,
|
|
1167
1872
|
optional: true
|
|
1168
1873
|
},
|
|
1169
1874
|
sortHorizontal: {
|
|
1170
1875
|
kind: "parsed",
|
|
1171
|
-
brief: `Sort bounding boxes horizontally. Options: "${SORT_HORIZONTAL_NONE}"
|
|
1876
|
+
brief: `Sort bounding boxes horizontally. Options: "${SORT_HORIZONTAL_NONE}", "${SORT_HORIZONTAL_LTR}", "${SORT_HORIZONTAL_RTL}". Default: "${DEFAULT_SORT_HORIZONTAL}"`,
|
|
1877
|
+
parse: String,
|
|
1878
|
+
optional: true
|
|
1879
|
+
},
|
|
1880
|
+
normalizeShape: {
|
|
1881
|
+
kind: "parsed",
|
|
1882
|
+
brief: `Normalize diamond-like shapes to axis-aligned rectangles. Options: "${SHAPE_NORMALIZE_NONE}", "${SHAPE_NORMALIZE_RECTANGLE}". Default: "${DEFAULT_SHAPE_NORMALIZE}"`,
|
|
1172
1883
|
parse: String,
|
|
1173
1884
|
optional: true
|
|
1885
|
+
},
|
|
1886
|
+
widthIncrement: {
|
|
1887
|
+
kind: "parsed",
|
|
1888
|
+
brief: `Increase bounding box width by this amount (in pixels). Can be negative to decrease. Default: ${DEFAULT_WIDTH_INCREMENT}`,
|
|
1889
|
+
parse: Number,
|
|
1890
|
+
optional: true
|
|
1891
|
+
},
|
|
1892
|
+
heightIncrement: {
|
|
1893
|
+
kind: "parsed",
|
|
1894
|
+
brief: `Increase bounding box height by this amount (in pixels). Can be negative to decrease. Default: ${DEFAULT_HEIGHT_INCREMENT}`,
|
|
1895
|
+
parse: Number,
|
|
1896
|
+
optional: true
|
|
1897
|
+
},
|
|
1898
|
+
precision: {
|
|
1899
|
+
kind: "parsed",
|
|
1900
|
+
brief: `Number of decimal places for coordinates. Use -1 for full precision (no rounding). Default: ${DEFAULT_LABEL_STUDIO_PRECISION}`,
|
|
1901
|
+
parse: Number,
|
|
1902
|
+
optional: true
|
|
1174
1903
|
}
|
|
1175
1904
|
}
|
|
1176
1905
|
},
|
|
@@ -1181,11 +1910,11 @@ var toLabelStudioCommand = (0, import_core.buildCommand)({
|
|
|
1181
1910
|
|
|
1182
1911
|
// src/commands/toPPOCR/commands.ts
|
|
1183
1912
|
init_cjs_shims();
|
|
1184
|
-
var
|
|
1913
|
+
var import_core4 = require("@stricli/core");
|
|
1185
1914
|
init_constants();
|
|
1186
|
-
var toPPOCRCommand = (0,
|
|
1915
|
+
var toPPOCRCommand = (0, import_core4.buildCommand)({
|
|
1187
1916
|
loader: async () => {
|
|
1188
|
-
const { convertToPPOCR: convertToPPOCR2 } = await Promise.resolve().then(() => (
|
|
1917
|
+
const { convertToPPOCR: convertToPPOCR2 } = await Promise.resolve().then(() => (init_impl4(), impl_exports4));
|
|
1189
1918
|
return convertToPPOCR2;
|
|
1190
1919
|
},
|
|
1191
1920
|
parameters: {
|
|
@@ -1200,13 +1929,13 @@ var toPPOCRCommand = (0, import_core2.buildCommand)({
|
|
|
1200
1929
|
flags: {
|
|
1201
1930
|
outDir: {
|
|
1202
1931
|
kind: "parsed",
|
|
1203
|
-
brief: `Output directory. Default
|
|
1932
|
+
brief: `Output directory. Default: "${OUTPUT_BASE_DIR}"`,
|
|
1204
1933
|
parse: String,
|
|
1205
1934
|
optional: true
|
|
1206
1935
|
},
|
|
1207
1936
|
fileName: {
|
|
1208
1937
|
kind: "parsed",
|
|
1209
|
-
brief: `Output PPOCR file name. Default
|
|
1938
|
+
brief: `Output PPOCR file name. Default: "${DEFAULT_PPOCR_FILE_NAME}"`,
|
|
1210
1939
|
parse: String,
|
|
1211
1940
|
optional: true
|
|
1212
1941
|
},
|
|
@@ -1218,15 +1947,39 @@ var toPPOCRCommand = (0, import_core2.buildCommand)({
|
|
|
1218
1947
|
},
|
|
1219
1948
|
sortVertical: {
|
|
1220
1949
|
kind: "parsed",
|
|
1221
|
-
brief: `Sort bounding boxes vertically. Options: "${SORT_VERTICAL_NONE}"
|
|
1950
|
+
brief: `Sort bounding boxes vertically. Options: "${SORT_VERTICAL_NONE}", "${SORT_VERTICAL_TOP_BOTTOM}", "${SORT_VERTICAL_BOTTOM_TOP}". Default: "${DEFAULT_SORT_VERTICAL}"`,
|
|
1222
1951
|
parse: String,
|
|
1223
1952
|
optional: true
|
|
1224
1953
|
},
|
|
1225
1954
|
sortHorizontal: {
|
|
1226
1955
|
kind: "parsed",
|
|
1227
|
-
brief: `Sort bounding boxes horizontally. Options: "${SORT_HORIZONTAL_NONE}"
|
|
1956
|
+
brief: `Sort bounding boxes horizontally. Options: "${SORT_HORIZONTAL_NONE}", "${SORT_HORIZONTAL_LTR}", "${SORT_HORIZONTAL_RTL}". Default: "${DEFAULT_SORT_HORIZONTAL}"`,
|
|
1957
|
+
parse: String,
|
|
1958
|
+
optional: true
|
|
1959
|
+
},
|
|
1960
|
+
normalizeShape: {
|
|
1961
|
+
kind: "parsed",
|
|
1962
|
+
brief: `Normalize diamond-like shapes to axis-aligned rectangles. Options: "${SHAPE_NORMALIZE_NONE}", "${SHAPE_NORMALIZE_RECTANGLE}". Default: "${DEFAULT_SHAPE_NORMALIZE}"`,
|
|
1228
1963
|
parse: String,
|
|
1229
1964
|
optional: true
|
|
1965
|
+
},
|
|
1966
|
+
widthIncrement: {
|
|
1967
|
+
kind: "parsed",
|
|
1968
|
+
brief: `Increase bounding box width by this amount (in pixels). Can be negative to decrease. Default: ${DEFAULT_WIDTH_INCREMENT}`,
|
|
1969
|
+
parse: Number,
|
|
1970
|
+
optional: true
|
|
1971
|
+
},
|
|
1972
|
+
heightIncrement: {
|
|
1973
|
+
kind: "parsed",
|
|
1974
|
+
brief: `Increase bounding box height by this amount (in pixels). Can be negative to decrease. Default: ${DEFAULT_HEIGHT_INCREMENT}`,
|
|
1975
|
+
parse: Number,
|
|
1976
|
+
optional: true
|
|
1977
|
+
},
|
|
1978
|
+
precision: {
|
|
1979
|
+
kind: "parsed",
|
|
1980
|
+
brief: `Number of decimal places for coordinates. Use -1 for full precision (no rounding). Default: ${DEFAULT_PPOCR_PRECISION} (integers)`,
|
|
1981
|
+
parse: Number,
|
|
1982
|
+
optional: true
|
|
1230
1983
|
}
|
|
1231
1984
|
}
|
|
1232
1985
|
},
|
|
@@ -1236,10 +1989,12 @@ var toPPOCRCommand = (0, import_core2.buildCommand)({
|
|
|
1236
1989
|
});
|
|
1237
1990
|
|
|
1238
1991
|
// src/app.ts
|
|
1239
|
-
var routes = (0,
|
|
1992
|
+
var routes = (0, import_core5.buildRouteMap)({
|
|
1240
1993
|
routes: {
|
|
1241
1994
|
toLabelStudio: toLabelStudioCommand,
|
|
1242
1995
|
toPPOCR: toPPOCRCommand,
|
|
1996
|
+
"enhance-labelstudio": enhanceLabelStudioCommand,
|
|
1997
|
+
"enhance-ppocr": enhancePPOCRCommand,
|
|
1243
1998
|
install: (0, import_auto_complete.buildInstallCommand)("label-studio-converter", {
|
|
1244
1999
|
bash: "__label-studio-converter_bash_complete"
|
|
1245
2000
|
}),
|
|
@@ -1253,7 +2008,7 @@ var routes = (0, import_core3.buildRouteMap)({
|
|
|
1253
2008
|
}
|
|
1254
2009
|
}
|
|
1255
2010
|
});
|
|
1256
|
-
var app = (0,
|
|
2011
|
+
var app = (0, import_core5.buildApplication)(routes, {
|
|
1257
2012
|
name: "label-studio-converter",
|
|
1258
2013
|
versionInfo: {
|
|
1259
2014
|
currentVersion: version
|
|
@@ -1280,9 +2035,9 @@ function buildContext(process2) {
|
|
|
1280
2035
|
if (process.env.COMP_LINE?.endsWith(" ")) {
|
|
1281
2036
|
inputs.push("");
|
|
1282
2037
|
}
|
|
1283
|
-
await (0,
|
|
2038
|
+
await (0, import_core6.proposeCompletions)(app, inputs, buildContext(process));
|
|
1284
2039
|
try {
|
|
1285
|
-
for (const { completion } of await (0,
|
|
2040
|
+
for (const { completion } of await (0, import_core6.proposeCompletions)(
|
|
1286
2041
|
app,
|
|
1287
2042
|
inputs,
|
|
1288
2043
|
buildContext(process)
|