label-studio-converter 1.1.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 CHANGED
@@ -16,10 +16,12 @@
16
16
 
17
17
  - [Getting Started](#toolbox-getting-started)
18
18
  - [Prerequisites](#bangbang-prerequisites)
19
+ - [Installation](#package-installation)
19
20
  - [Run Locally](#running-run-locally)
20
21
  - [Usage](#eyes-usage)
21
- - [Basic Usage](#basic-usage)
22
+ - [Library Usage](#library-usage)
22
23
  - [CLI Usage](#cli-usage)
24
+ - [Enhancement Features](#enhancement-features)
23
25
  - [Using generated files with Label Studio](#using-generated-files-with-label-studio)
24
26
  - [Interface setup](#interface-setup)
25
27
  - [Serving annotation files locally](#serving-annotation-files-locally)
@@ -54,6 +56,27 @@
54
56
  [04928bf](https://github.com/PFCCLab/PPOCRLabel/tree/04928bf015656e41ba5569877df9b0666ca90f89)
55
57
 
56
58
  - [Node.js](https://nodejs.org/): Tested with version `22.x` and above.
59
+
60
+ <!-- Installation -->
61
+
62
+ ### :package: Installation
63
+
64
+ **As a CLI tool:**
65
+
66
+ ```bash
67
+ npm install -g label-studio-converter
68
+ ```
69
+
70
+ **As a library:**
71
+
72
+ ```bash
73
+ npm install label-studio-converter
74
+ # or
75
+ pnpm add label-studio-converter
76
+ # or
77
+ yarn add label-studio-converter
78
+ ```
79
+
57
80
  <!-- Run Locally -->
58
81
 
59
82
  ### :running: Run Locally
@@ -87,50 +110,123 @@ pnpm install
87
110
  > setting up Label Studio for OCR tasks, please refer to the [Using generated
88
111
  > files with Label Studio](#using-generated-files-with-label-studio) section.
89
112
 
90
- ### Basic Usage
113
+ > [!NOTE]
114
+ > **This package can be used both as a CLI tool and as a library.**
115
+ >
116
+ > - **CLI**: Run commands directly from the terminal
117
+ > - **Library**: Import and use functions in your TypeScript/JavaScript code
118
+
119
+ ### Library Usage
120
+
121
+ **Conversion Functions:**
91
122
 
92
123
  ```ts
93
- import { toLabelStudio, toPPOCR } from 'label-studio-converter';
124
+ import {
125
+ labelStudioToPPOCR,
126
+ minLabelStudioToPPOCR,
127
+ ppocrToLabelStudio
128
+ } from 'label-studio-converter';
129
+
130
+ // Convert Label Studio Full Format to PPOCRLabel
131
+ const fullData = [...]; // FullOCRLabelStudio type
132
+ const ppocrMap = await labelStudioToPPOCR(fullData, {
133
+ baseImageDir: 'images/ch',
134
+ normalizeShape: 'rectangle',
135
+ widthIncrement: 5,
136
+ heightIncrement: 5,
137
+ precision: 0 // integers
138
+ });
94
139
 
95
- // Convert PPOCRLabel files to Label Studio format
96
- await toLabelStudio({
97
- inputDirs: ['./input-ppocr'],
98
- outDir: './output-label-studio',
99
- defaultLabelName: 'Text',
100
- toFullJson: true,
101
- createFilePerImage: false,
102
- createFileListForServing: true,
103
- fileListName: 'files.txt',
140
+ // Convert Label Studio Min Format to PPOCRLabel
141
+ const minData = [...]; // MinOCRLabelStudio type
142
+ const ppocrMap2 = await minLabelStudioToPPOCR(minData, {
143
+ baseImageDir: 'images/ch',
144
+ precision: 0
145
+ });
146
+
147
+ // Convert PPOCRLabel to Label Studio
148
+ const ppocrData = [...]; // PPOCRLabel type
149
+ const labelStudioData = await ppocrToLabelStudio(ppocrData, {
150
+ imagePath: 'example.jpg',
104
151
  baseServerUrl: 'http://localhost:8081',
105
- sortVertical: 'none',
106
- sortHorizontal: 'none',
107
- normalizeShape: 'none', // Options: 'none', 'rectangle'
108
- widthIncrement: 0, // Increase width in pixels (can be negative)
109
- heightIncrement: 0, // Increase height in pixels (can be negative)
110
- precision: -1, // Number precision: -1 = full precision (default for Label Studio)
152
+ inputDir: './images',
153
+ toFullJson: true,
154
+ labelName: 'Text',
155
+ precision: -1 // full precision
111
156
  });
157
+ ```
112
158
 
113
- // Convert Label Studio files to PPOCRLabel format
114
- await toPPOCR({
115
- inputDirs: ['./input-label-studio'],
116
- outDir: './output-ppocr',
117
- fileName: 'Label.txt',
118
- baseImageDir: 'images/ch',
119
- sortVertical: 'none',
120
- sortHorizontal: 'none',
121
- normalizeShape: 'none', // Options: 'none', 'rectangle'
122
- widthIncrement: 0, // Increase width in pixels (can be negative)
123
- heightIncrement: 0, // Increase height in pixels (can be negative)
124
- precision: 0, // Number precision: 0 = integers (default for PPOCR)
159
+ **Enhancement Functions:**
160
+
161
+ ```ts
162
+ import {
163
+ enhancePPOCRLabel,
164
+ enhanceLabelStudioData,
165
+ } from 'label-studio-converter';
166
+
167
+ // Enhance PPOCRLabel data
168
+ const enhanced = enhancePPOCRLabel(ppocrData, {
169
+ sortVertical: 'top-bottom',
170
+ sortHorizontal: 'ltr',
171
+ normalizeShape: 'rectangle',
172
+ widthIncrement: 10,
173
+ heightIncrement: 5,
174
+ precision: 0,
175
+ });
176
+
177
+ // Enhance Label Studio data (Full or Min format)
178
+ const enhancedLS = await enhanceLabelStudioData(
179
+ labelStudioData,
180
+ true, // isFull: true for Full format, false for Min format
181
+ {
182
+ sortVertical: 'top-bottom',
183
+ normalizeShape: 'rectangle',
184
+ precision: 2,
185
+ },
186
+ );
187
+ ```
188
+
189
+ **Utility Functions:**
190
+
191
+ ```ts
192
+ import {
193
+ transformPoints,
194
+ normalizeShape,
195
+ resizeBoundingBox,
196
+ sortBoundingBoxes,
197
+ } from 'label-studio-converter';
198
+
199
+ // Transform points (normalize + resize)
200
+ const transformed = transformPoints(points, {
201
+ normalizeShape: 'rectangle',
202
+ widthIncrement: 10,
203
+ heightIncrement: 5,
125
204
  });
205
+
206
+ // Normalize diamond shapes to rectangles
207
+ const normalized = normalizeShape(points);
208
+
209
+ // Resize bounding box
210
+ const resized = resizeBoundingBox(points, 10, 5);
211
+
212
+ // Sort bounding boxes
213
+ const sorted = sortBoundingBoxes(annotations, 'top-bottom', 'ltr');
126
214
  ```
127
215
 
128
216
  ### CLI Usage
129
217
 
218
+ **Available Commands:**
219
+
220
+ ```bash
221
+ label-studio-converter --help
222
+ ```
223
+
130
224
  ```bash
131
225
  USAGE
132
226
  label-studio-converter toLabelStudio [--outDir value] [--defaultLabelName value] [--toFullJson] [--createFilePerImage] [--createFileListForServing] [--fileListName value] [--baseServerUrl value] [--sortVertical value] [--sortHorizontal value] [--normalizeShape value] [--widthIncrement value] [--heightIncrement value] [--precision value] <args>...
133
227
  label-studio-converter toPPOCR [--outDir value] [--fileName value] [--baseImageDir value] [--sortVertical value] [--sortHorizontal value] [--normalizeShape value] [--widthIncrement value] [--heightIncrement value] [--precision value] <args>...
228
+ label-studio-converter enhance-labelstudio [--outDir value] [--sortVertical value] [--sortHorizontal value] [--normalizeShape value] [--widthIncrement value] [--heightIncrement value] [--precision value] <args>...
229
+ label-studio-converter enhance-ppocr [--outDir value] [--sortVertical value] [--sortHorizontal value] [--normalizeShape value] [--widthIncrement value] [--heightIncrement value] [--precision value] <args>...
134
230
  label-studio-converter --help
135
231
  label-studio-converter --version
136
232
 
@@ -141,13 +237,15 @@ FLAGS
141
237
  -v --version Print version information and exit
142
238
 
143
239
  COMMANDS
144
- toLabelStudio Convert PPOCRLabel files to Label Studio format
145
- toPPOCR Convert Label Studio files to PPOCRLabel format
240
+ toLabelStudio Convert PPOCRLabel files to Label Studio format
241
+ toPPOCR Convert Label Studio files to PPOCRLabel format
242
+ enhance-labelstudio Enhance Label Studio files with sorting, normalization, and resizing
243
+ enhance-ppocr Enhance PPOCRLabel files with sorting, normalization, and resizing
146
244
  ```
147
245
 
148
- Subcommands:
246
+ **Commands:**
149
247
 
150
- **toLabelStudio**:
248
+ - `toLabelStudio` - Convert PPOCRLabel files to Label Studio format
151
249
 
152
250
  ```bash
153
251
  USAGE
@@ -157,13 +255,13 @@ USAGE
157
255
  Convert PPOCRLabel files to Label Studio format
158
256
 
159
257
  FLAGS
160
- [--outDir] Output directory. Default to "./output"
161
- [--defaultLabelName] Default label name for text annotations. Default to "Text"
162
- [--toFullJson/--noToFullJson] Convert to Full OCR Label Studio format. Default to "true"
163
- [--createFilePerImage/--noCreateFilePerImage] Create a separate Label Studio JSON file for each image. Default to "false"
164
- [--createFileListForServing/--noCreateFileListForServing] Create a file list for serving in Label Studio. Default to "true"
165
- [--fileListName] Name of the file list for serving. Default to "files.txt"
166
- [--baseServerUrl] Base server URL for constructing image URLs in the file list. Default to "http://localhost:8081"
258
+ [--outDir] Output directory. Default: "./output"
259
+ [--defaultLabelName] Default label name for text annotations. Default: "Text"
260
+ [--toFullJson/--noToFullJson] Convert to Full OCR Label Studio format. Default: "true"
261
+ [--createFilePerImage/--noCreateFilePerImage] Create a separate Label Studio JSON file for each image. Default: "false"
262
+ [--createFileListForServing/--noCreateFileListForServing] Create a file list for serving in Label Studio. Default: "true"
263
+ [--fileListName] Name of the file list for serving. Default: "files.txt"
264
+ [--baseServerUrl] Base server URL for constructing image URLs in the file list. Default: "http://localhost:8081"
167
265
  [--sortVertical] Sort bounding boxes vertically. Options: "none" (default), "top-bottom", "bottom-top"
168
266
  [--sortHorizontal] Sort bounding boxes horizontally. Options: "none" (default), "ltr", "rtl"
169
267
  [--normalizeShape] Normalize diamond-like shapes to axis-aligned rectangles. Options: "none" (default), "rectangle"
@@ -176,7 +274,7 @@ ARGUMENTS
176
274
  args... Input directories containing PPOCRLabel files
177
275
  ```
178
276
 
179
- **toPPOCR**:
277
+ - `toPPOCR` - Convert Label Studio files to PPOCRLabel format
180
278
 
181
279
  ```bash
182
280
  USAGE
@@ -186,8 +284,8 @@ USAGE
186
284
  Convert Label Studio files to PPOCRLabel format
187
285
 
188
286
  FLAGS
189
- [--outDir] Output directory. Default to "./output"
190
- [--fileName] Output PPOCR file name. Default to "Label.txt"
287
+ [--outDir] Output directory. Default: "./output"
288
+ [--fileName] Output PPOCR file name. Default: "Label.txt"
191
289
  [--baseImageDir] Base directory path to prepend to image filenames in output (e.g., "ch" or "images/ch")
192
290
  [--sortVertical] Sort bounding boxes vertically. Options: "none" (default), "top-bottom", "bottom-top"
193
291
  [--sortHorizontal] Sort bounding boxes horizontally. Options: "none" (default), "ltr", "rtl"
@@ -201,21 +299,257 @@ ARGUMENTS
201
299
  args... Input directories containing Label Studio files
202
300
  ```
203
301
 
302
+ - `enhance-labelstudio` - Enhance Label Studio files with sorting,
303
+ normalization, and resizing
304
+
305
+ ```bash
306
+ USAGE
307
+ label-studio-converter enhance-labelstudio [--outDir value] [--sortVertical value] [--sortHorizontal value] [--normalizeShape value] [--widthIncrement value] [--heightIncrement value] [--precision value] <args>...
308
+ label-studio-converter enhance-labelstudio --help
309
+
310
+ Enhance Label Studio files with sorting, normalization, and resizing
311
+
312
+ FLAGS
313
+ [--outDir] Output directory. Default: "./output"
314
+ [--sortVertical] Sort bounding boxes vertically. Options: "none" (default), "top-bottom", "bottom-top"
315
+ [--sortHorizontal] Sort bounding boxes horizontally. Options: "none" (default), "ltr", "rtl"
316
+ [--normalizeShape] Normalize diamond-like shapes to axis-aligned rectangles. Options: "none" (default), "rectangle"
317
+ [--widthIncrement] Increase bounding box width by this amount (in pixels). Can be negative to decrease. Default: 0
318
+ [--heightIncrement] Increase bounding box height by this amount (in pixels). Can be negative to decrease. Default: 0
319
+ [--precision] Number of decimal places for coordinates. Use -1 for full precision (no rounding). Default: -1
320
+ -h --help Print help information and exit
321
+
322
+ ARGUMENTS
323
+ args... Input directories containing Label Studio JSON files
324
+ ```
325
+
326
+ - `enhance-ppocr` - Enhance PPOCRLabel files with sorting, normalization, and resizing
327
+
328
+ ```bash
329
+ USAGE
330
+ label-studio-converter enhance-ppocr [--outDir value] [--sortVertical value] [--sortHorizontal value] [--normalizeShape value] [--widthIncrement value] [--heightIncrement value] [--precision value] <args>...
331
+ label-studio-converter enhance-ppocr --help
332
+
333
+ Enhance PPOCRLabel files with sorting, normalization, and resizing
334
+
335
+ FLAGS
336
+ [--outDir] Output directory. Default: "./output"
337
+ [--sortVertical] Sort bounding boxes vertically. Options: "none" (default), "top-bottom", "bottom-top"
338
+ [--sortHorizontal] Sort bounding boxes horizontally. Options: "none" (default), "ltr", "rtl"
339
+ [--normalizeShape] Normalize diamond-like shapes to axis-aligned rectangles. Options: "none" (default), "rectangle"
340
+ [--widthIncrement] Increase bounding box width by this amount (in pixels). Can be negative to decrease. Default: 0
341
+ [--heightIncrement] Increase bounding box height by this amount (in pixels). Can be negative to decrease. Default: 0
342
+ [--precision] Number of decimal places for coordinates. Use -1 for full precision (no rounding). Default: 0 (integers)
343
+ -h --help Print help information and exit
344
+
345
+ ARGUMENTS
346
+ args... Input directories containing PPOCRLabel files
347
+ ```
348
+
204
349
  #### Examples
205
350
 
206
- **Convert PPOCRLabel files to full Label Studio format:**
351
+ **Basic Conversions:**
207
352
 
208
353
  ```bash
209
- label-studio-converter toLabelStudio ./input-ppocr --outDir ./output-label-studio --defaultLabelName Text --toFullJson --createFileListForServing --fileListName files.txt --baseServerUrl http://localhost:8081 --sortVertical none --sortHorizontal none
354
+ # Convert PPOCRLabel files to full Label Studio format
355
+ label-studio-converter toLabelStudio ./input-ppocr --outDir ./output-label-studio
356
+
357
+ # Convert Label Studio files to PPOCRLabel format
358
+ label-studio-converter toPPOCR ./input-label-studio --outDir ./output-ppocr
359
+
360
+ # Convert with custom output filename for PPOCR
361
+ label-studio-converter toPPOCR ./input-label-studio --outDir ./output-ppocr --fileName MyLabels.txt
362
+
363
+ # Convert with base image directory path
364
+ label-studio-converter toPPOCR ./input-label-studio --baseImageDir images/ch
210
365
  ```
211
366
 
212
367
  > [!NOTE]
213
368
  > By default, all PPOCRLabel positions are treated as **polygons** in Label Studio.
214
369
 
215
- **Convert Label Studio files to PPOCRLabel format:**
370
+ **toLabelStudio Options:**
371
+
372
+ ```bash
373
+ # Create separate JSON file for each image
374
+ label-studio-converter toLabelStudio ./input-ppocr \
375
+ --outDir ./output \
376
+ --createFilePerImage
377
+
378
+ # Specify custom label name (default is "Text")
379
+ label-studio-converter toLabelStudio ./input-ppocr \
380
+ --outDir ./output \
381
+ --defaultLabelName Handwriting
382
+
383
+ # Convert to minimal format (without serving support)
384
+ label-studio-converter toLabelStudio ./input-ppocr \
385
+ --outDir ./output \
386
+ --noToFullJson
387
+
388
+ # Disable file list creation for serving
389
+ label-studio-converter toLabelStudio ./input-ppocr \
390
+ --outDir ./output \
391
+ --noCreateFileListForServing
392
+
393
+ # Custom file list name and server URL
394
+ label-studio-converter toLabelStudio ./input-ppocr \
395
+ --outDir ./output \
396
+ --fileListName my-images.txt \
397
+ --baseServerUrl http://192.168.1.100:8080
398
+ ```
399
+
400
+ **toPPOCR Options:**
216
401
 
217
402
  ```bash
218
- label-studio-converter toPPOCR ./input-label-studio --outDir ./output-ppocr --fileName Label.txt --baseImageDir images/ch --sortVertical none --sortHorizontal none
403
+ # Basic conversion with output directory
404
+ label-studio-converter toPPOCR ./input-label-studio \
405
+ --outDir ./output
406
+
407
+ # Custom output filename
408
+ label-studio-converter toPPOCR ./input-label-studio \
409
+ --outDir ./output \
410
+ --fileName CustomLabel.txt
411
+
412
+ # Add base image directory to paths
413
+ label-studio-converter toPPOCR ./input-label-studio \
414
+ --outDir ./output \
415
+ --baseImageDir dataset/images
416
+ ```
417
+
418
+ ### Enhancement Features
419
+
420
+ The tool provides powerful enhancement capabilities that can be used standalone or integrated with conversion:
421
+
422
+ **Enhance PPOCRLabel files:**
423
+
424
+ ```bash
425
+ # Sort annotations from top to bottom, left to right
426
+ label-studio-converter enhance-ppocr ./data --sortVertical top-bottom --sortHorizontal ltr
427
+
428
+ # Normalize diamond shapes to rectangles and resize
429
+ label-studio-converter enhance-ppocr ./data --normalizeShape rectangle --widthIncrement 10 --heightIncrement 5
430
+
431
+ # Apply all enhancements
432
+ label-studio-converter enhance-ppocr ./data \
433
+ --sortVertical top-bottom \
434
+ --sortHorizontal ltr \
435
+ --normalizeShape rectangle \
436
+ --widthIncrement 5 \
437
+ --heightIncrement 5 \
438
+ --precision 0
439
+ ```
440
+
441
+ **Enhance Label Studio files:**
442
+
443
+ ```bash
444
+ # Sort and normalize Label Studio annotations
445
+ label-studio-converter enhance-labelstudio ./data \
446
+ --sortVertical top-bottom \
447
+ --normalizeShape rectangle \
448
+ --precision 2
449
+
450
+ # Works with both Full and Min formats automatically
451
+ label-studio-converter enhance-labelstudio ./label-studio-files --outDir ./enhanced
452
+ ```
453
+
454
+ **Enhancement Options:**
455
+
456
+ - `--sortVertical`: Sort bounding boxes vertically
457
+ - `none` (default): No sorting
458
+ - `top-bottom`: Sort from top to bottom
459
+ - `bottom-top`: Sort from bottom to top
460
+ - Example:
461
+ ```bash
462
+ # Sort annotations from top to bottom
463
+ label-studio-converter enhance-ppocr ./data --sortVertical top-bottom
464
+ ```
465
+
466
+ - `--sortHorizontal`: Sort bounding boxes horizontally
467
+ - `none` (default): No sorting
468
+ - `ltr`: Sort left to right (useful for English, most European languages)
469
+ - `rtl`: Sort right to left (useful for Arabic, Hebrew)
470
+ - Example:
471
+
472
+ ```bash
473
+ # Sort annotations left to right
474
+ label-studio-converter enhance-ppocr ./data --sortHorizontal ltr
475
+
476
+ # Sort annotations right to left
477
+ label-studio-converter enhance-ppocr ./data --sortHorizontal rtl
478
+ ```
479
+
480
+ - `--normalizeShape`: Normalize shapes
481
+ - `none` (default): Keep original shape
482
+ - `rectangle`: Convert diamond-like or rotated shapes to axis-aligned rectangles
483
+ - Example:
484
+ ```bash
485
+ # Convert irregular shapes to clean rectangles
486
+ label-studio-converter enhance-ppocr ./data --normalizeShape rectangle
487
+ ```
488
+
489
+ - `--widthIncrement`: Increase/decrease width (pixels, can be negative)
490
+ - Default: `0`
491
+ - Examples:
492
+
493
+ ```bash
494
+ # Increase width by 10 pixels
495
+ label-studio-converter enhance-ppocr ./data --widthIncrement 10
496
+
497
+ # Decrease width by 5 pixels
498
+ label-studio-converter enhance-ppocr ./data --widthIncrement -5
499
+ ```
500
+
501
+ - `--heightIncrement`: Increase/decrease height (pixels, can be negative)
502
+ - Default: `0`
503
+ - Examples:
504
+
505
+ ```bash
506
+ # Increase height by 15 pixels
507
+ label-studio-converter enhance-ppocr ./data --heightIncrement 15
508
+
509
+ # Decrease height by 3 pixels
510
+ label-studio-converter enhance-ppocr ./data --heightIncrement -3
511
+ ```
512
+
513
+ - `--precision`: Control the number of decimal places for coordinate values
514
+ - `-1`: Full precision - no rounding, keeps all decimal places (default for Label Studio output)
515
+ - Example output: `27.44656917885264`
516
+ - `0`: Round to integers (default for PPOCR output)
517
+ - Example output: `27`
518
+ - `1`: Round to 1 decimal place
519
+ - Example output: `27.4`
520
+ - `2`: Round to 2 decimal places
521
+ - Example output: `27.45`
522
+ - Any positive integer for that many decimal places
523
+ - Examples:
524
+
525
+ ```bash
526
+ # Use full precision
527
+ label-studio-converter toLabelStudio ./data --precision -1
528
+
529
+ # Use integer coordinates
530
+ label-studio-converter toPPOCR ./data --precision 0
531
+
532
+ # Use 2 decimal places
533
+ label-studio-converter enhance-labelstudio ./data --precision 2
534
+ ```
535
+
536
+ **Conversion with Enhancement:**
537
+
538
+ All enhancement options are available in conversion commands:
539
+
540
+ ```bash
541
+ # Convert with enhancements applied during conversion
542
+ label-studio-converter toLabelStudio ./input-ppocr \
543
+ --outDir ./output \
544
+ --sortVertical top-bottom \
545
+ --normalizeShape rectangle \
546
+ --widthIncrement 10
547
+
548
+ label-studio-converter toPPOCR ./input-label-studio \
549
+ --outDir ./output \
550
+ --sortVertical top-bottom \
551
+ --sortHorizontal ltr \
552
+ --normalizeShape rectangle
219
553
  ```
220
554
 
221
555
  **Convert PPOCRLabel files to Label Studio format with one file per image:**
@@ -254,7 +588,7 @@ label-studio-converter toPPOCR ./input-label-studio --outDir ./output --normaliz
254
588
  <b>Before normalization</b> (diamond-like shapes):
255
589
  </summary>
256
590
 
257
- ![Before normalization](./docs/images/LabelStudio_original_diamond.png)
591
+ ![Before normalization](./docs/images/label-studio-original-diamond.png)
258
592
 
259
593
  </details>
260
594
 
@@ -269,7 +603,7 @@ Command:
269
603
  ./dist/cli.js toPPOCR ./tmp --baseImageDir output --normalizeShape rectangle
270
604
  ```
271
605
 
272
- ![After normalization](./docs/images/LabelStudio_converted_diamond.png)
606
+ ![After normalization](./docs/images/label-studio-converted-diamond.png)
273
607
 
274
608
  </details>
275
609
 
@@ -278,7 +612,7 @@ Command:
278
612
  <b>Before normalization</b> (diamond-like vertical shapes):
279
613
  </summary>
280
614
 
281
- ![Before normalization (vert)](./docs/images/LabelStudio_original_diamond_vert.png)
615
+ ![Before normalization (vert)](./docs/images/label-studio-original-diamond-vert.png)
282
616
 
283
617
  </details>
284
618
 
@@ -293,7 +627,7 @@ Command:
293
627
  ./dist/cli.js toPPOCR ./tmp --baseImageDir output --normalizeShape rectangle
294
628
  ```
295
629
 
296
- ![After normalization (vert)](./docs/images/LabelStudio_converted_diamond_vert.png)
630
+ ![After normalization (vert)](./docs/images/label-studio-converted-diamond-vert.png)
297
631
 
298
632
  </details>
299
633
 
@@ -470,19 +804,19 @@ aspects of the data.
470
804
 
471
805
  Label Studio annotation:
472
806
 
473
- ![Label Studio annotation](./docs/images/LabelStudio_original_example.png)
807
+ ![Label Studio annotation](./docs/images/label-studio-original-example.png)
474
808
 
475
809
  Generated PPOCRLabelv2 annotation:
476
810
 
477
- ![PPOCRLabelv2 annotation](./docs/images/PPOCRLabel_converted_example.png)
811
+ ![PPOCRLabelv2 annotation](./docs/images/ppocr-label-converted-example.png)
478
812
 
479
813
  Converted back to Label Studio annotation:
480
814
 
481
- ![Converted back to Label Studio annotation](./docs/images/LabelStudio_converted_back_example.png)
815
+ ![Converted back to Label Studio annotation](./docs/images/label-studio-converted-back-example.png)
482
816
 
483
817
  <details>
484
818
  <summary>
485
- <b>Original data</b> (<code>full_label_studio.json</code>):
819
+ <b>Original data</b>:
486
820
  </summary>
487
821
 
488
822
  ```json
@@ -499,13 +833,13 @@ Converted back to Label Studio annotation:
499
833
  "original_height": 520,
500
834
  "image_rotation": 0,
501
835
  "value": {
502
- "x": 27.44656917885264,
503
- "y": 58.07692307692308,
504
- "width": 42.63217097862767,
505
- "height": 5.961538461538453,
836
+ "x": 27.691012033297714,
837
+ "y": 58.08133472367049,
838
+ "width": 42.14645223570203,
839
+ "height": 5.4223149113660085,
506
840
  "rotation": 0
507
841
  },
508
- "id": "JQAipC-2LH",
842
+ "id": "pa6F68vZpa",
509
843
  "from_name": "bbox",
510
844
  "to_name": "image",
511
845
  "type": "rectangle",
@@ -516,14 +850,14 @@ Converted back to Label Studio annotation:
516
850
  "original_height": 520,
517
851
  "image_rotation": 0,
518
852
  "value": {
519
- "x": 27.44656917885264,
520
- "y": 58.07692307692308,
521
- "width": 42.63217097862767,
522
- "height": 5.961538461538453,
853
+ "x": 27.691012033297714,
854
+ "y": 58.08133472367049,
855
+ "width": 42.14645223570203,
856
+ "height": 5.4223149113660085,
523
857
  "rotation": 0,
524
858
  "labels": ["Text"]
525
859
  },
526
- "id": "JQAipC-2LH",
860
+ "id": "pa6F68vZpa",
527
861
  "from_name": "label",
528
862
  "to_name": "image",
529
863
  "type": "labels",
@@ -534,14 +868,14 @@ Converted back to Label Studio annotation:
534
868
  "original_height": 520,
535
869
  "image_rotation": 0,
536
870
  "value": {
537
- "x": 27.44656917885264,
538
- "y": 58.07692307692308,
539
- "width": 42.63217097862767,
540
- "height": 5.961538461538453,
871
+ "x": 27.691012033297714,
872
+ "y": 58.08133472367049,
873
+ "width": 42.14645223570203,
874
+ "height": 5.4223149113660085,
541
875
  "rotation": 0,
542
876
  "text": ["ACUTE CORONARY SYNDROME"]
543
877
  },
544
- "id": "JQAipC-2LH",
878
+ "id": "pa6F68vZpa",
545
879
  "from_name": "transcription",
546
880
  "to_name": "image",
547
881
  "type": "textarea",
@@ -552,13 +886,13 @@ Converted back to Label Studio annotation:
552
886
  "original_height": 520,
553
887
  "image_rotation": 0,
554
888
  "value": {
555
- "x": 27.559055118110237,
556
- "y": 64.8076923076923,
557
- "width": 26.884374807767497,
558
- "height": 4.423038206853052,
559
- "rotation": 359.76027010391914
889
+ "x": 27.569025196146622,
890
+ "y": 70.38581856100105,
891
+ "width": 49.03965680633165,
892
+ "height": 4.788140385599174,
893
+ "rotation": 359.64368755661553
560
894
  },
561
- "id": "gydCl1Q9Nt",
895
+ "id": "iIfXbvxhFx",
562
896
  "from_name": "bbox",
563
897
  "to_name": "image",
564
898
  "type": "rectangle",
@@ -569,14 +903,71 @@ Converted back to Label Studio annotation:
569
903
  "original_height": 520,
570
904
  "image_rotation": 0,
571
905
  "value": {
572
- "x": 27.559055118110237,
573
- "y": 64.8076923076923,
574
- "width": 26.884374807767497,
575
- "height": 4.423038206853052,
576
- "rotation": 359.76027010391914,
906
+ "x": 27.569025196146622,
907
+ "y": 70.38581856100105,
908
+ "width": 49.03965680633165,
909
+ "height": 4.788140385599174,
910
+ "rotation": 359.64368755661553,
911
+ "labels": ["Text"]
912
+ },
913
+ "id": "iIfXbvxhFx",
914
+ "from_name": "label",
915
+ "to_name": "image",
916
+ "type": "labels",
917
+ "origin": "manual"
918
+ },
919
+ {
920
+ "original_width": 889,
921
+ "original_height": 520,
922
+ "image_rotation": 0,
923
+ "value": {
924
+ "x": 27.569025196146622,
925
+ "y": 70.38581856100105,
926
+ "width": 49.03965680633165,
927
+ "height": 4.788140385599174,
928
+ "rotation": 359.64368755661553,
929
+ "text": ["MILD CORONARY ARTERY DISEASE"]
930
+ },
931
+ "id": "iIfXbvxhFx",
932
+ "from_name": "transcription",
933
+ "to_name": "image",
934
+ "type": "textarea",
935
+ "origin": "manual"
936
+ },
937
+ {
938
+ "original_width": 889,
939
+ "original_height": 520,
940
+ "image_rotation": 0,
941
+ "value": {
942
+ "points": [
943
+ [27.630018614722168, 81.85610010427528],
944
+ [61.66434617987663, 80.8133472367049],
945
+ [61.969313272754356, 85.71428571428571],
946
+ [28.239952800477624, 86.44421272158499]
947
+ ],
948
+ "closed": true
949
+ },
950
+ "id": "mpqixNR8uh",
951
+ "from_name": "poly",
952
+ "to_name": "image",
953
+ "type": "polygon",
954
+ "origin": "manual"
955
+ },
956
+ {
957
+ "original_width": 889,
958
+ "original_height": 520,
959
+ "image_rotation": 0,
960
+ "value": {
961
+ "points": [
962
+ [27.630018614722168, 81.85610010427528],
963
+ [61.66434617987663, 80.8133472367049],
964
+ [61.969313272754356, 85.71428571428571],
965
+ [28.239952800477624, 86.44421272158499]
966
+ ],
967
+ "closed": true,
577
968
  "labels": ["Handwriting"]
578
969
  },
579
- "id": "gydCl1Q9Nt",
970
+ "id": "mpqixNR8uh",
580
971
  "from_name": "label",
581
972
  "to_name": "image",
582
973
  "type": "labels",
@@ -587,14 +978,16 @@ Converted back to Label Studio annotation:
587
978
  "original_height": 520,
588
979
  "image_rotation": 0,
589
980
  "value": {
590
- "x": 27.559055118110237,
591
- "y": 64.8076923076923,
592
- "width": 26.884374807767497,
593
- "height": 4.423038206853052,
594
- "rotation": 359.76027010391914,
595
- "text": ["UNSTABLE ANGINA"]
981
+ "points": [
982
+ [27.630018614722168, 81.85610010427528],
983
+ [61.66434617987663, 80.8133472367049],
984
+ [61.969313272754356, 85.71428571428571],
985
+ [28.239952800477624, 86.44421272158499]
986
+ ],
987
+ "closed": true,
988
+ "text": ["MEDICAL MANAGEMENT"]
596
989
  },
597
- "id": "gydCl1Q9Nt",
990
+ "id": "mpqixNR8uh",
598
991
  "from_name": "transcription",
599
992
  "to_name": "image",
600
993
  "type": "textarea",
@@ -604,11 +997,11 @@ Converted back to Label Studio annotation:
604
997
  "was_cancelled": false,
605
998
  "ground_truth": false,
606
999
  "created_at": "2026-01-07T03:14:39.424067Z",
607
- "updated_at": "2026-01-07T03:14:39.424096Z",
1000
+ "updated_at": "2026-01-10T03:21:09.833576Z",
608
1001
  "draft_created_at": "2026-01-07T03:14:04.596361Z",
609
- "lead_time": 56.087,
1002
+ "lead_time": 2686.9700000000003,
610
1003
  "prediction": {},
611
- "result_count": 2,
1004
+ "result_count": 3,
612
1005
  "unique_id": "7e8c79f1-49ce-471c-8b26-8b8c6f9c3401",
613
1006
  "import_id": null,
614
1007
  "last_action": null,
@@ -627,7 +1020,7 @@ Converted back to Label Studio annotation:
627
1020
  "data": { "ocr": "\/data\/upload\/2\/5b1e3483-example.jpg" },
628
1021
  "meta": {},
629
1022
  "created_at": "2026-01-07T03:13:41.175183Z",
630
- "updated_at": "2026-01-07T03:14:39.478016Z",
1023
+ "updated_at": "2026-01-10T03:21:09.923449Z",
631
1024
  "allow_skip": true,
632
1025
  "inner_id": 1,
633
1026
  "total_annotations": 1,
@@ -647,7 +1040,7 @@ Converted back to Label Studio annotation:
647
1040
 
648
1041
  <details>
649
1042
  <summary>
650
- <b>Converted data</b> (<code>output/Label.txt</code>):
1043
+ <b>Converted data</b>:
651
1044
  </summary>
652
1045
 
653
1046
  Command:
@@ -659,14 +1052,14 @@ Command:
659
1052
  Output:
660
1053
 
661
1054
  ```
662
- output/5b1e3483-example.jpg [{"transcription":"ACUTE CORONARY SYNDROME","points":[[243.99999999999997,302],[623,302],[623,332.99999999999994],[243.99999999999997,332.99999999999994]],"dt_score":1},{"transcription":"UNSTABLE ANGINA","points":[[245,337],[484.00209204105306,337],[484.00209204105306,359.9997986756359],[245,359.9997986756359]],"dt_score":1}]
1055
+ output/example.jpg [{"transcription":"ACUTE CORONARY SYNDROME","points":[[246,302],[621,302],[621,330],[246,330]],"dt_score":1},{"transcription":"MILD CORONARY ARTERY DISEASE","points":[[245,366],[681,366],[681,391],[245,391]],"dt_score":1},{"transcription":"MEDICAL MANAGEMENT","points":[[246,426],[548,420],[551,446],[251,450]],"dt_score":1}]
663
1056
  ```
664
1057
 
665
1058
  </details>
666
1059
 
667
1060
  <details>
668
1061
  <summary>
669
- <b>Convert back to Label Studio</b> (<code>output/Label_full.json</code>):
1062
+ <b>Convert back to Label Studio</b>:
670
1063
  </summary>
671
1064
 
672
1065
  Command:
@@ -679,178 +1072,248 @@ Output:
679
1072
 
680
1073
  ```json
681
1074
  [
682
- {
683
- "id": 1,
684
- "annotations": [
685
- {
686
- "id": 1,
687
- "completed_by": 1,
688
- "result": [
689
- {
690
- "original_width": 889,
691
- "original_height": 520,
692
- "image_rotation": 0,
693
- "value": {
694
- "points": [
695
- [27.44656917885264, 58.07692307692308],
696
- [70.07874015748031, 58.07692307692308],
697
- [70.07874015748031, 64.03846153846153],
698
- [27.44656917885264, 64.03846153846153]
699
- ],
700
- "closed": true
1075
+ [
1076
+ {
1077
+ "id": 1,
1078
+ "annotations": [
1079
+ {
1080
+ "id": 1,
1081
+ "completed_by": 1,
1082
+ "result": [
1083
+ {
1084
+ "original_width": 889,
1085
+ "original_height": 520,
1086
+ "image_rotation": 0,
1087
+ "value": {
1088
+ "points": [
1089
+ [27.671541057367826, 58.07692307692308],
1090
+ [69.85376827896513, 58.07692307692308],
1091
+ [69.85376827896513, 63.46153846153846],
1092
+ [27.671541057367826, 63.46153846153846]
1093
+ ],
1094
+ "closed": true
1095
+ },
1096
+ "id": "fce62949-7",
1097
+ "from_name": "poly",
1098
+ "to_name": "image",
1099
+ "type": "polygon",
1100
+ "origin": "manual"
701
1101
  },
702
- "id": "4ebb52a4-d",
703
- "from_name": "poly",
704
- "to_name": "image",
705
- "type": "polygon",
706
- "origin": "manual"
707
- },
708
- {
709
- "original_width": 889,
710
- "original_height": 520,
711
- "image_rotation": 0,
712
- "value": {
713
- "points": [
714
- [27.44656917885264, 58.07692307692308],
715
- [70.07874015748031, 58.07692307692308],
716
- [70.07874015748031, 64.03846153846153],
717
- [27.44656917885264, 64.03846153846153]
718
- ],
719
- "closed": true,
720
- "labels": ["Text"]
1102
+ {
1103
+ "original_width": 889,
1104
+ "original_height": 520,
1105
+ "image_rotation": 0,
1106
+ "value": {
1107
+ "points": [
1108
+ [27.671541057367826, 58.07692307692308],
1109
+ [69.85376827896513, 58.07692307692308],
1110
+ [69.85376827896513, 63.46153846153846],
1111
+ [27.671541057367826, 63.46153846153846]
1112
+ ],
1113
+ "closed": true,
1114
+ "labels": ["Text"]
1115
+ },
1116
+ "id": "fce62949-7",
1117
+ "from_name": "label",
1118
+ "to_name": "image",
1119
+ "type": "labels",
1120
+ "origin": "manual"
721
1121
  },
722
- "id": "4ebb52a4-d",
723
- "from_name": "label",
724
- "to_name": "image",
725
- "type": "labels",
726
- "origin": "manual"
727
- },
728
- {
729
- "original_width": 889,
730
- "original_height": 520,
731
- "image_rotation": 0,
732
- "value": {
733
- "points": [
734
- [27.44656917885264, 58.07692307692308],
735
- [70.07874015748031, 58.07692307692308],
736
- [70.07874015748031, 64.03846153846153],
737
- [27.44656917885264, 64.03846153846153]
738
- ],
739
- "closed": true,
740
- "text": ["ACUTE CORONARY SYNDROME"]
1122
+ {
1123
+ "original_width": 889,
1124
+ "original_height": 520,
1125
+ "image_rotation": 0,
1126
+ "value": {
1127
+ "points": [
1128
+ [27.671541057367826, 58.07692307692308],
1129
+ [69.85376827896513, 58.07692307692308],
1130
+ [69.85376827896513, 63.46153846153846],
1131
+ [27.671541057367826, 63.46153846153846]
1132
+ ],
1133
+ "closed": true,
1134
+ "text": ["ACUTE CORONARY SYNDROME"]
1135
+ },
1136
+ "id": "fce62949-7",
1137
+ "from_name": "transcription",
1138
+ "to_name": "image",
1139
+ "type": "textarea",
1140
+ "origin": "manual"
741
1141
  },
742
- "id": "4ebb52a4-d",
743
- "from_name": "transcription",
744
- "to_name": "image",
745
- "type": "textarea",
746
- "origin": "manual"
747
- },
748
- {
749
- "original_width": 889,
750
- "original_height": 520,
751
- "image_rotation": 0,
752
- "value": {
753
- "points": [
754
- [27.559055118110237, 64.8076923076923],
755
- [54.44342992587774, 64.8076923076923],
756
- [54.44342992587774, 69.23073051454536],
757
- [27.559055118110237, 69.23073051454536]
758
- ],
759
- "closed": true
1142
+ {
1143
+ "original_width": 889,
1144
+ "original_height": 520,
1145
+ "image_rotation": 0,
1146
+ "value": {
1147
+ "points": [
1148
+ [27.559055118110237, 70.38461538461539],
1149
+ [76.6029246344207, 70.38461538461539],
1150
+ [76.6029246344207, 75.1923076923077],
1151
+ [27.559055118110237, 75.1923076923077]
1152
+ ],
1153
+ "closed": true
1154
+ },
1155
+ "id": "9d9389a6-f",
1156
+ "from_name": "poly",
1157
+ "to_name": "image",
1158
+ "type": "polygon",
1159
+ "origin": "manual"
760
1160
  },
761
- "id": "06aa0669-d",
762
- "from_name": "poly",
763
- "to_name": "image",
764
- "type": "polygon",
765
- "origin": "manual"
766
- },
767
- {
768
- "original_width": 889,
769
- "original_height": 520,
770
- "image_rotation": 0,
771
- "value": {
772
- "points": [
773
- [27.559055118110237, 64.8076923076923],
774
- [54.44342992587774, 64.8076923076923],
775
- [54.44342992587774, 69.23073051454536],
776
- [27.559055118110237, 69.23073051454536]
777
- ],
778
- "closed": true,
779
- "labels": ["Text"]
1161
+ {
1162
+ "original_width": 889,
1163
+ "original_height": 520,
1164
+ "image_rotation": 0,
1165
+ "value": {
1166
+ "points": [
1167
+ [27.559055118110237, 70.38461538461539],
1168
+ [76.6029246344207, 70.38461538461539],
1169
+ [76.6029246344207, 75.1923076923077],
1170
+ [27.559055118110237, 75.1923076923077]
1171
+ ],
1172
+ "closed": true,
1173
+ "labels": ["Text"]
1174
+ },
1175
+ "id": "9d9389a6-f",
1176
+ "from_name": "label",
1177
+ "to_name": "image",
1178
+ "type": "labels",
1179
+ "origin": "manual"
780
1180
  },
781
- "id": "06aa0669-d",
782
- "from_name": "label",
783
- "to_name": "image",
784
- "type": "labels",
785
- "origin": "manual"
786
- },
787
- {
788
- "original_width": 889,
789
- "original_height": 520,
790
- "image_rotation": 0,
791
- "value": {
792
- "points": [
793
- [27.559055118110237, 64.8076923076923],
794
- [54.44342992587774, 64.8076923076923],
795
- [54.44342992587774, 69.23073051454536],
796
- [27.559055118110237, 69.23073051454536]
797
- ],
798
- "closed": true,
799
- "text": ["UNSTABLE ANGINA"]
1181
+ {
1182
+ "original_width": 889,
1183
+ "original_height": 520,
1184
+ "image_rotation": 0,
1185
+ "value": {
1186
+ "points": [
1187
+ [27.559055118110237, 70.38461538461539],
1188
+ [76.6029246344207, 70.38461538461539],
1189
+ [76.6029246344207, 75.1923076923077],
1190
+ [27.559055118110237, 75.1923076923077]
1191
+ ],
1192
+ "closed": true,
1193
+ "text": ["MILD CORONARY ARTERY DISEASE"]
1194
+ },
1195
+ "id": "9d9389a6-f",
1196
+ "from_name": "transcription",
1197
+ "to_name": "image",
1198
+ "type": "textarea",
1199
+ "origin": "manual"
800
1200
  },
801
- "id": "06aa0669-d",
802
- "from_name": "transcription",
803
- "to_name": "image",
804
- "type": "textarea",
805
- "origin": "manual"
806
- }
807
- ],
808
- "was_cancelled": false,
809
- "ground_truth": false,
810
- "created_at": "2026-01-07T04:16:31.329Z",
811
- "updated_at": "2026-01-07T04:16:31.329Z",
812
- "draft_created_at": "2026-01-07T04:16:31.329Z",
813
- "lead_time": 0,
814
- "prediction": {},
815
- "result_count": 6,
816
- "unique_id": "b471a896-b002-4b52-b3a4-36f810c3ca16",
817
- "import_id": null,
818
- "last_action": null,
819
- "bulk_created": false,
820
- "task": 1,
821
- "project": 1,
822
- "updated_by": 1,
823
- "parent_prediction": null,
824
- "parent_annotation": null,
825
- "last_created_by": null
826
- }
827
- ],
828
- "file_upload": "5b1e3483-example.jpg",
829
- "drafts": [],
830
- "predictions": [],
831
- "data": {
832
- "ocr": "http://localhost:8081/output/5b1e3483-example.jpg"
833
- },
834
- "meta": {},
835
- "created_at": "2026-01-07T04:16:31.329Z",
836
- "updated_at": "2026-01-07T04:16:31.329Z",
837
- "allow_skip": false,
838
- "inner_id": 1,
839
- "total_annotations": 1,
840
- "cancelled_annotations": 0,
841
- "total_predictions": 0,
842
- "comment_count": 0,
843
- "unresolved_comment_count": 0,
844
- "last_comment_updated_at": null,
845
- "project": 1,
846
- "updated_by": 1,
847
- "comment_authors": []
848
- }
1201
+ {
1202
+ "original_width": 889,
1203
+ "original_height": 520,
1204
+ "image_rotation": 0,
1205
+ "value": {
1206
+ "points": [
1207
+ [27.671541057367826, 81.92307692307692],
1208
+ [61.64229471316085, 80.76923076923077],
1209
+ [61.97975253093363, 85.76923076923076],
1210
+ [28.23397075365579, 86.53846153846155]
1211
+ ],
1212
+ "closed": true
1213
+ },
1214
+ "id": "4f2e63fc-b",
1215
+ "from_name": "poly",
1216
+ "to_name": "image",
1217
+ "type": "polygon",
1218
+ "origin": "manual"
1219
+ },
1220
+ {
1221
+ "original_width": 889,
1222
+ "original_height": 520,
1223
+ "image_rotation": 0,
1224
+ "value": {
1225
+ "points": [
1226
+ [27.671541057367826, 81.92307692307692],
1227
+ [61.64229471316085, 80.76923076923077],
1228
+ [61.97975253093363, 85.76923076923076],
1229
+ [28.23397075365579, 86.53846153846155]
1230
+ ],
1231
+ "closed": true,
1232
+ "labels": ["Text"]
1233
+ },
1234
+ "id": "4f2e63fc-b",
1235
+ "from_name": "label",
1236
+ "to_name": "image",
1237
+ "type": "labels",
1238
+ "origin": "manual"
1239
+ },
1240
+ {
1241
+ "original_width": 889,
1242
+ "original_height": 520,
1243
+ "image_rotation": 0,
1244
+ "value": {
1245
+ "points": [
1246
+ [27.671541057367826, 81.92307692307692],
1247
+ [61.64229471316085, 80.76923076923077],
1248
+ [61.97975253093363, 85.76923076923076],
1249
+ [28.23397075365579, 86.53846153846155]
1250
+ ],
1251
+ "closed": true,
1252
+ "text": ["MEDICAL MANAGEMENT"]
1253
+ },
1254
+ "id": "4f2e63fc-b",
1255
+ "from_name": "transcription",
1256
+ "to_name": "image",
1257
+ "type": "textarea",
1258
+ "origin": "manual"
1259
+ }
1260
+ ],
1261
+ "was_cancelled": false,
1262
+ "ground_truth": false,
1263
+ "created_at": "2026-01-10T03:25:05.530Z",
1264
+ "updated_at": "2026-01-10T03:25:05.530Z",
1265
+ "draft_created_at": "2026-01-10T03:25:05.530Z",
1266
+ "lead_time": 0,
1267
+ "prediction": {},
1268
+ "result_count": 9,
1269
+ "unique_id": "e17b1920-022b-4e48-9207-f9904a42e840",
1270
+ "import_id": null,
1271
+ "last_action": null,
1272
+ "bulk_created": false,
1273
+ "task": 1,
1274
+ "project": 1,
1275
+ "updated_by": 1,
1276
+ "parent_prediction": null,
1277
+ "parent_annotation": null,
1278
+ "last_created_by": null
1279
+ }
1280
+ ],
1281
+ "file_upload": "5b1e3483-example.jpg",
1282
+ "drafts": [],
1283
+ "predictions": [],
1284
+ "data": {
1285
+ "ocr": "http://localhost:8081/output/5b1e3483-example.jpg"
1286
+ },
1287
+ "meta": {},
1288
+ "created_at": "2026-01-10T03:25:05.530Z",
1289
+ "updated_at": "2026-01-10T03:25:05.530Z",
1290
+ "allow_skip": false,
1291
+ "inner_id": 1,
1292
+ "total_annotations": 1,
1293
+ "cancelled_annotations": 0,
1294
+ "total_predictions": 0,
1295
+ "comment_count": 0,
1296
+ "unresolved_comment_count": 0,
1297
+ "last_comment_updated_at": null,
1298
+ "project": 1,
1299
+ "updated_by": 1,
1300
+ "comment_authors": []
1301
+ }
1302
+ ]
849
1303
  ]
850
1304
  ```
851
1305
 
852
1306
  </details>
853
1307
 
1308
+ **Comparison of bounding box positions:**
1309
+
1310
+ | Original Label Studio (polygon) | Label Studio to PPOCRLabel | PPOCRLabel -> Label Studio (polygon) | Margin (Converted Back − Original) |
1311
+ | :--------------------------------------: | -------------------------- | ---------------------------------------- | --------------------------------------- |
1312
+ | \[27.630018614722168, 81.85610010427528] | \[246,426] | \[27.671541057367826, 81.92307692307692] | \[0.04152244264566, 0.06697681880164] |
1313
+ | \[61.66434617987663, 80.8133472367049] | \[548,420] | \[61.64229471316085, 80.76923076923077] | \[-0.02205146671578, -0.04411646747413] |
1314
+ | \[61.969313272754356, 85.71428571428571] | \[551,446] | \[61.97975253093363, 85.76923076923076] | \[0.01043925817927, 0.05494505494505] |
1315
+ | \[28.239952800477624, 86.44421272158499] | \[251,450] | \[28.23397075365579, 86.53846153846155] | \[-0.00598204682183, 0.09424881687656] |
1316
+
854
1317
  > [!IMPORTANT]
855
1318
  > So as you can see, after converting from Label Studio to PPOCRLabelv2 and then
856
1319
  > back to Label Studio, the positions of the bounding boxes have slight