label-studio-converter 1.3.0 → 1.4.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
@@ -21,8 +21,29 @@
21
21
  - [Usage](#eyes-usage)
22
22
  - [Library Usage](#library-usage)
23
23
  - [CLI Usage](#cli-usage)
24
+ - [Available Commands](#available-commands)
25
+ - [Command Flags Reference](#command-flags-reference)
26
+ - [Flags Available for All Commands](#flags-available-for-all-commands)
27
+ - [Flags Specific to toLabelStudio Command](#flags-specific-to-tolabelstudio-command)
28
+ - [Flags Specific to toPPOCR Command](#flags-specific-to-toppocr-command)
29
+ - [Flags Specific to enhance-labelstudio Command](#flags-specific-to-enhance-labelstudio-command)
30
+ - [Image Path Resolution Logic](#image-path-resolution-logic)
31
+ - [Image Path Resolution Logic](#image-path-resolution-logic)
32
+ - [toLabelStudio: PPOCRLabel → Label Studio](#tolabelstudio-ppocrlabel--label-studio)
33
+ - [toPPOCR: Label Studio → PPOCRLabel](#toppocr-label-studio--ppocrlabel)
34
+ - [enhance-labelstudio: Label Studio Enhancement](#enhance-labelstudio-label-studio--label-studio-enhanced)
35
+ - [enhance-ppocr: PPOCRLabel Enhancement](#enhance-ppocr-ppocrlabel--ppocrlabel-enhanced)
36
+ - [Adaptive Resize Feature](#adaptive-resize-feature)
37
+ - [Detailed Command Help](#detailed-command-help)
38
+ - [toLabelStudio Command](#tolabelstudio-command)
39
+ - [toPPOCR Command](#toppocr-command)
40
+ - [enhance-labelstudio Command](#enhance-labelstudio-command)
41
+ - [enhance-ppocr Command](#enhance-ppocr-command)
24
42
  - [Examples](#examples)
25
- - [Enhancement Features](#enhancement-features)
43
+ - [Basic Conversion](#basic-conversion)
44
+ - [Enhancement Pipeline](#enhancement-pipeline)
45
+ - [File Organization](#file-organization)
46
+ - [Shape Normalization](#shape-normalization)
26
47
  - [Using generated files with Label Studio](#using-generated-files-with-label-studio)
27
48
  - [Interface setup](#interface-setup)
28
49
  - [Serving annotation files locally](#serving-annotation-files-locally)
@@ -124,14 +145,14 @@ pnpm install
124
145
 
125
146
  ```ts
126
147
  import {
127
- labelStudioToPPOCR,
128
- minLabelStudioToPPOCR,
148
+ fullLabelStudioToPPOCRConverters,
149
+ minLabelStudioToPPOCRConverters,
129
150
  ppocrToLabelStudio
130
151
  } from 'label-studio-converter';
131
152
 
132
153
  // Convert Label Studio Full Format to PPOCRLabel
133
154
  const fullData = [...]; // FullOCRLabelStudio type
134
- const ppocrMap = await labelStudioToPPOCR(fullData, {
155
+ const ppocrMap = await fullLabelStudioToPPOCRConverters(fullData, {
135
156
  baseImageDir: 'images/ch',
136
157
  normalizeShape: 'rectangle',
137
158
  widthIncrement: 5,
@@ -141,7 +162,7 @@ const ppocrMap = await labelStudioToPPOCR(fullData, {
141
162
 
142
163
  // Convert Label Studio Min Format to PPOCRLabel
143
164
  const minData = [...]; // MinOCRLabelStudio type
144
- const ppocrMap2 = await minLabelStudioToPPOCR(minData, {
165
+ const ppocrMap2 = await minLabelStudioToPPOCRConverters(minData, {
145
166
  baseImageDir: 'images/ch',
146
167
  precision: 0
147
168
  });
@@ -217,13 +238,15 @@ const sorted = sortBoundingBoxes(annotations, 'top-bottom', 'ltr');
217
238
 
218
239
  ### CLI Usage
219
240
 
220
- **Available Commands:**
241
+ #### Available Commands
221
242
 
222
243
  ```bash
223
244
  label-studio-converter --help
224
245
  ```
225
246
 
226
- ```bash
247
+ **Output:**
248
+
249
+ ```
227
250
  USAGE
228
251
  label-studio-converter toLabelStudio [--outDir value] [--fileName value] [--backup] [--defaultLabelName value] [--toFullJson] [--createFilePerImage] [--createFileListForServing] [--fileListName value] [--baseServerUrl value] [--sortVertical value] [--sortHorizontal value] [--normalizeShape value] [--widthIncrement value] [--heightIncrement value] [--precision value] [--recursive] [--filePattern value] [--outputMode value] <args>...
229
252
  label-studio-converter toPPOCR [--outDir value] [--fileName value] [--backup] [--baseImageDir value] [--sortVertical value] [--sortHorizontal value] [--normalizeShape value] [--widthIncrement value] [--heightIncrement value] [--precision value] [--recursive] [--filePattern value] <args>...
@@ -245,11 +268,576 @@ COMMANDS
245
268
  enhance-ppocr Enhance PPOCRLabel files with sorting, normalization, and resizing
246
269
  ```
247
270
 
248
- **Commands:**
271
+ #### Command Flags Reference
272
+
273
+ ##### Flags Available for All Commands
274
+
275
+ **File I/O Flags:**
276
+
277
+ - `--outDir <path>`: Output directory path
278
+ - **Behavior**: Saves converted/enhanced files to specified directory
279
+ - **Default**: Same directory as input files
280
+ - **Example**: `--outDir ./output` saves all files to `./output/`
281
+
282
+ - `--fileName <name>`: Custom output filename
283
+ - **Behavior**: Renames output file (without extension for JSON, with extension for txt)
284
+ - **Default**:
285
+ - toLabelStudio: `{source}_full.json` or `{source}_min.json`
286
+ - toPPOCR: `Label.txt`
287
+ - enhance commands: Same as input filename
288
+ - **Example**: `--fileName MyLabels.txt` creates `MyLabels.txt` instead of `Label.txt`
289
+
290
+ - `--backup` / `--noBackup`: Create backup before overwriting
291
+ - **Behavior**: Copies existing file to `{filename}.backup` before overwriting
292
+ - **Default**: `false` (no backup)
293
+ - **Example**: `--backup` creates `Label.txt.backup` if `Label.txt` exists
294
+
295
+ - `--recursive` / `--noRecursive`: Search subdirectories
296
+ - **Behavior**: Processes files in all subdirectories recursively
297
+ - **Default**: `false` (current directory only)
298
+ - **Example**: `--recursive` processes `./data/train/Label.txt` and `./data/test/Label.txt`
299
+
300
+ - `--filePattern <regex>`: Pattern to match input files
301
+ - **Behavior**: Only processes files matching regex pattern
302
+ - **Default**:
303
+ - PPOCRLabel commands: `.*\.txt$` (all .txt files)
304
+ - Label Studio commands: `.*\.json$` (all .json files)
305
+ - **Example**: `--filePattern "train_.*\.txt$"` only processes files starting with `train_`
306
+
307
+ - `--copyImages` / `--noCopyImages`: Copy images when using --outDir
308
+ - **Behavior**: When --outDir is specified, automatically copies/moves images to output directory alongside converted files
309
+ - **Default**: `true` (copy images)
310
+ - **Example**: `--noCopyImages` keeps images in original location, only copies task files
311
+ - **Note**: Only applies to toLabelStudio and toPPOCR converters when --outDir is used
312
+
313
+ **Enhancement Flags:**
314
+
315
+ - `--sortVertical <order>`: Vertical sorting order
316
+ - **Behavior**: Sorts bounding boxes by vertical position
317
+ - **Options**: `none`, `top-bottom`, `bottom-top`
318
+ - **Default**: `none` (no sorting)
319
+ - **Example**: `--sortVertical top-bottom` sorts boxes from top to bottom
320
+
321
+ - `--sortHorizontal <order>`: Horizontal sorting order
322
+ - **Behavior**: Sorts bounding boxes by horizontal position (applied after vertical sort)
323
+ - **Options**: `none`, `ltr` (left-to-right), `rtl` (right-to-left)
324
+ - **Default**: `none` (no sorting)
325
+ - **Example**: `--sortHorizontal rtl` sorts boxes right-to-left (for vertical text)
326
+
327
+ - `--normalizeShape <option>`: Shape normalization
328
+ - **Behavior**: Converts diamond/rotated shapes to axis-aligned rectangles
329
+ - **Options**: `none`, `rectangle`
330
+ - **Default**: `none` (preserve original shapes)
331
+ - **Example**: `--normalizeShape rectangle` converts all polygons to rectangles
332
+
333
+ - `--widthIncrement <pixels>`: Adjust box width
334
+ - **Behavior**: Adds pixels to box width (can be negative to shrink)
335
+ - **Default**: `0` (no change)
336
+ - **Example**: `--widthIncrement 5` expands boxes by 5px horizontally
337
+
338
+ - `--heightIncrement <pixels>`: Adjust box height
339
+ - **Behavior**: Adds pixels to box height (can be negative to shrink)
340
+ - **Default**: `0` (no change)
341
+ - **Example**: `--heightIncrement -3` shrinks boxes by 3px vertically
342
+
343
+ - `--precision <decimals>`: Coordinate precision
344
+ - **Behavior**: Number of decimal places for coordinates
345
+ - **Default**:
346
+ - toLabelStudio: `-1` (full precision, no rounding)
347
+ - toPPOCR: `0` (integers only)
348
+ - enhance-labelstudio: `-1` (full precision)
349
+ - enhance-ppocr: `0` (integers)
350
+ - **Example**: `--precision 2` rounds to 2 decimal places (e.g., 123.45)
351
+
352
+ **Adaptive Resize Flags (Advanced):**
353
+
354
+ - `--adaptResize` / `--noAdaptResize`: Enable intelligent box resizing
355
+ - **Behavior**: Uses image analysis to shrink oversized boxes to fit actual text
356
+ - **Default**: `false` (disabled)
357
+ - **Use Case**: Sino-Nom OCR datasets with excessive padding
358
+ - **Example**: `--adaptResize` enables feature with default parameters
359
+
360
+ - `--adaptResizeThreshold <0-255>`: Grayscale threshold
361
+ - **Behavior**: Pixels ≥ threshold are considered text (white), < threshold are background (black)
362
+ - **Default**: `128`
363
+ - **Example**: `--adaptResizeThreshold 140` for darker text on light background
364
+
365
+ - `--adaptResizeMargin <pixels>`: Padding around detected content
366
+ - **Behavior**: Additional pixels added on all sides after detection
367
+ - **Default**: `5`
368
+ - **Example**: `--adaptResizeMargin 8` adds 8px padding
369
+
370
+ - `--adaptResizeMinComponentSize <pixels>`: Noise filter
371
+ - **Behavior**: Regions smaller than this are ignored (filters dirt dots)
372
+ - **Default**: `10`
373
+ - **Example**: `--adaptResizeMinComponentSize 15` filters more aggressively
374
+
375
+ - `--adaptResizeMaxComponentSize <pixels>`: Artifact filter
376
+ - **Behavior**: Regions larger than this are ignored (filters huge artifacts)
377
+ - **Default**: `100000`
378
+ - **Example**: `--adaptResizeMaxComponentSize 50000` for smaller characters
379
+
380
+ - `--adaptResizeOutlierPercentile <%>`: Outlier removal
381
+ - **Behavior**: Ignores this % of smallest and largest pixels when calculating boundaries
382
+ - **Default**: `2` (ignore 2% on each end)
383
+ - **Example**: `--adaptResizeOutlierPercentile 3` for more aggressive outlier removal
384
+
385
+ - `--adaptResizeMorphologySize <pixels>`: Stroke connection
386
+ - **Behavior**: Kernel size for connecting broken character strokes
387
+ - **Default**: `2`
388
+ - **Example**: `--adaptResizeMorphologySize 3` connects larger gaps
389
+
390
+ - `--adaptResizeMaxHorizontalExpansion <pixels>`: Column overlap prevention
391
+ - **Behavior**: Maximum pixels boxes can expand horizontally (CRITICAL for vertical text)
392
+ - **Default**: `50`
393
+ - **Example**: `--adaptResizeMaxHorizontalExpansion 30` for closely-spaced columns
394
+
395
+ ##### Flags Specific to toLabelStudio Command
396
+
397
+ - `--defaultLabelName <name>`: Default label for annotations
398
+ - **Behavior**: Label assigned to all text regions
399
+ - **Default**: `"Text"`
400
+ - **Example**: `--defaultLabelName "Handwriting"` labels all regions as Handwriting
401
+
402
+ - `--toFullJson` / `--noToFullJson`: Output format
403
+ - **Behavior**: `true` = Full format (more metadata), `false` = Min format (compact)
404
+ - **Default**: `true` (Full format)
405
+ - **Example**: `--noToFullJson` creates minimal format files
406
+
407
+ - `--createFilePerImage` / `--noCreateFilePerImage`: File splitting
408
+ - **Behavior**: `true` = one JSON per image, `false` = all tasks in one file
409
+ - **Default**: `false` (single file)
410
+ - **Example**: `--createFilePerImage` creates `image1.json`, `image2.json`, etc.
411
+
412
+ - `--createFileListForServing` / `--noCreateFileListForServing`: Generate file list
413
+ - **Behavior**: Creates `files.txt` with image URLs for Label Studio import
414
+ - **Default**: `true` (create file list)
415
+ - **Example**: `--noCreateFileListForServing` skips file list creation
416
+
417
+ - `--fileListName <name>`: File list filename
418
+ - **Behavior**: Name of the file containing image URLs for serving
419
+ - **Default**: `"files.txt"`
420
+ - **Example**: `--fileListName "images.txt"` creates `images.txt` instead
421
+
422
+ - `--baseServerUrl <url>`: Base URL for images
423
+ - **Behavior**: Prepended to image paths in output JSON (e.g., for local HTTP server)
424
+ - **Default**: `"http://localhost:8081"`
425
+ - **Example**: `--baseServerUrl "http://192.168.1.100:8080"` for network access
426
+
427
+ - `--outputMode <mode>`: Annotation mode
428
+ - **Behavior**:
429
+ - `annotations` = editable ground truth annotations
430
+ - `predictions` = read-only pre-annotations
431
+ - **Default**: `"annotations"`
432
+ - **Example**: `--outputMode predictions` for model predictions import
433
+
434
+ ##### Flags Specific to toPPOCR Command
435
+
436
+ - `--baseImageDir <path>`: Image directory prefix
437
+ - **Behavior**: Prepended to image filenames in output `Label.txt`
438
+ - **Default**: Empty string (no prefix)
439
+ - **Example**: `--baseImageDir "images/ch"` writes `images/ch/example.jpg` in Label.txt
440
+
441
+ ##### Flags Specific to enhance-labelstudio Command
442
+
443
+ - `--outputMode <mode>`: Same as toLabelStudio command
444
+ - See toLabelStudio flags section above
445
+
446
+ #### Image Path Resolution Logic
447
+
448
+ Understanding how image paths are resolved is critical for organizing your files before conversion. The key is knowing **where you run the command** and **what input parameter you provide**.
449
+
450
+ ##### toLabelStudio: PPOCRLabel → Label Studio
451
+
452
+ **INPUT Resolution (Reading PPOCRLabel files):**
453
+
454
+ **Command Execution Context:**
455
+
456
+ - You run: `cd project && label-studio-converter toLabelStudio data/`
457
+ - Current working directory (CWD): `project/`
458
+ - Input parameter: `data/` (directory to search for Label.txt files)
459
+ - Converter finds: `project/data/Label.txt` (and other Label.txt files in subdirectories if --recursive)
460
+ - Task file being processed: `project/data/Label.txt`
461
+
462
+ **How Resolvers Work:**
463
+
464
+ 1. **What's in the Label.txt file**:
465
+ - Path format: `data/example.jpg` (PPOCRLabel standard: folder/filename)
466
+ - PPOCRLabel was opened on `data/` folder, so paths use `data/` prefix
467
+
468
+ 2. **How input resolver finds images**:
469
+ - Reads path from Label.txt: `data/example.jpg`
470
+ - Task file is at: `project/data/Label.txt`
471
+ - Task directory: `project/data/`
472
+ - Check if path starts with task folder name (`data/`):
473
+ - YES → resolve from parent: `dirname(project/data/) + data/example.jpg` = `project/data/example.jpg`
474
+ - NO → resolve from task dir: `project/data/ + example.jpg` = `project/data/example.jpg`
475
+
476
+ 3. **What the processor receives**:
477
+ - Path relative to CWD: `data/example.jpg`
478
+ - (This is `relative(project/, project/data/example.jpg)` = `data/example.jpg`)
479
+
480
+ **OUTPUT Resolution (Writing Label Studio JSON):**
481
+
482
+ **Command Execution Context:**
483
+
484
+ - Output location: Same as task file location (no --outDir specified)
485
+ - Output file: `project/data/Label_full.json`
486
+
487
+ **How Resolvers Work:**
488
+
489
+ 1. **What the processor has**:
490
+ - Path relative to CWD: `data/example.jpg`
491
+ - (From input resolution step)
492
+
493
+ 2. **How output resolver formats paths**:
494
+ - No --outDir: Compute relative path from output JSON to image
495
+ - Output JSON at: `project/data/Label_full.json`
496
+ - Image at: `project/data/example.jpg`
497
+ - Relative path: `relative(project/data/, project/data/example.jpg)` = `example.jpg`
498
+ - Apply baseServerUrl: `http://localhost:8081/example.jpg`
499
+
500
+ 3. **What goes in the output file**:
501
+ - Label Studio JSON: `"ocr": "http://localhost:8081/example.jpg"`
502
+
503
+ **File Organization Examples:**
504
+
505
+ <details>
506
+ <summary><b>Example 1: Default Location (No --outDir)</b></summary>
507
+
508
+ **Setup**: Images and output in same place as task file
509
+
510
+ ```
511
+ project/
512
+ └── data/
513
+ ├── Label.txt # Contains: data/example.jpg [...]
514
+ └── example.jpg
515
+ ```
516
+
517
+ **Command:**
518
+
519
+ ```bash
520
+ cd project
521
+ label-studio-converter toLabelStudio data/
522
+ ```
523
+
524
+ **Result:**
525
+
526
+ ```
527
+ project/
528
+ └── data/
529
+ ├── Label.txt # Original task file
530
+ ├── Label_full.json # NEW: Generated output
531
+ ├── files.txt # NEW: File list for serving
532
+ └── example.jpg # Original image (unchanged)
533
+ ```
534
+
535
+ **Generated Label_full.json contains:**
536
+
537
+ ```json
538
+ {
539
+ "data": {
540
+ "ocr": "http://localhost:8081/example.jpg"
541
+ }
542
+ }
543
+ ```
544
+
545
+ **Image Path Flow:**
546
+
547
+ - Input path in Label.txt: `data/example.jpg`
548
+ - Resolved path: `data/example.jpg` (relative to CWD)
549
+ - Output saved in: `data/` (same as task)
550
+ - Relative to output: `example.jpg`
551
+ - Final URL: `http://localhost:8081/example.jpg`
552
+
553
+ </details>
554
+
555
+ <details>
556
+ <summary><b>Example 2: With --outDir Configuration</b></summary>
557
+
558
+ **Setup**: Separate output directory for organized export
559
+
560
+ ```
561
+ project/
562
+ ├── data/
563
+ │ ├── Label.txt # Contains: data/example.jpg [...]
564
+ │ └── example.jpg
565
+ └── output/ # Target output directory
566
+ ```
567
+
568
+ **Command:**
569
+
570
+ ```bash
571
+ cd project
572
+ label-studio-converter toLabelStudio data/ \
573
+ --outDir output \
574
+ --baseServerUrl http://localhost:8081
575
+ ```
576
+
577
+ **Result:**
578
+
579
+ ```
580
+ project/
581
+ ├── data/
582
+ │ ├── Label.txt # Original (unchanged)
583
+ │ └── example.jpg # Original (unchanged)
584
+ └── output/ # NEW: All outputs here
585
+ ├── Label_full.json # NEW: Generated tasks
586
+ ├── files.txt # NEW: File list
587
+ └── example.jpg # NEW: Copied from source
588
+ ```
589
+
590
+ **Generated Label_full.json contains:**
591
+
592
+ ```json
593
+ {
594
+ "data": {
595
+ "ocr": "http://localhost:8081/example.jpg"
596
+ }
597
+ }
598
+ ```
599
+
600
+ **Image Path Flow:**
601
+
602
+ - Input path in Label.txt: `data/example.jpg`
603
+ - Resolved path: `data/example.jpg` (relative to CWD)
604
+ - Copied to: `output/example.jpg`
605
+ - Relative to output: `example.jpg`
606
+ - Final URL: `http://localhost:8081/example.jpg`
607
+
608
+ </details>
609
+
610
+ ##### toPPOCR: Label Studio → PPOCRLabel
611
+
612
+ **INPUT Resolution (Reading Label Studio JSON):**
613
+
614
+ **Command Execution Context:**
615
+
616
+ - You run: `cd project && label-studio-converter toPPOCR data/`
617
+ - Current working directory (CWD): `project/`
618
+ - Input parameter: `data/` (directory to search for JSON files)
619
+ - Converter finds: `project/data/export.json` (and other JSON files in subdirectories if --recursive)
620
+ - Task file being processed: `project/data/export.json`
621
+
622
+ **How Resolvers Work:**
623
+
624
+ 1. **What's in the JSON file**:
625
+ - Local path: `"ocr": "/example.jpg"` or `"ocr": "example.jpg"`
626
+ - OR Remote URL: `"ocr": "http://localhost:8081/example.jpg"`
627
+
628
+ 2. **How input resolver finds/downloads images**:
629
+ - **Local path** (`/example.jpg` or `example.jpg`):
630
+ - Strip leading slashes: `/example.jpg` → `example.jpg`
631
+ - Task directory: `project/data/`
632
+ - Resolve: `project/data/ + example.jpg` = `project/data/example.jpg`
633
+ - **Remote URL** (`http://localhost:8081/example.jpg`):
634
+ - Extract filename: `basename(URL)` = `example.jpg`
635
+ - Download to task directory: `project/data/example.jpg`
636
+
637
+ 3. **What the processor receives**:
638
+ - Path relative to CWD: `data/example.jpg`
639
+ - (This is `relative(project/, project/data/example.jpg)` = `data/example.jpg`)
640
+
641
+ **OUTPUT Resolution (Writing PPOCRLabel Label.txt):**
642
+
643
+ **Command Execution Context:**
644
+
645
+ - No --outDir specified: Output at task file location
646
+ - Output file: `project/data/Label.txt`
647
+
648
+ **How Resolvers Work:**
649
+
650
+ 1. **What the processor has**:
651
+ - Path relative to CWD: `data/example.jpg`
652
+ - (From input resolution step)
653
+
654
+ 2. **How output resolver formats paths**:
655
+ - Extract filename: `basename(data/example.jpg)` = `example.jpg`
656
+ - Determine folder prefix:
657
+ - No --baseImageDir: Use output directory basename
658
+ - Output at: `project/data/Label.txt` → folder is `data`
659
+ - Result: `data/example.jpg`
660
+ - With --baseImageDir="images": Result would be `images/example.jpg`
661
+
662
+ 3. **What goes in the output file**:
663
+ - PPOCRLabel Label.txt: `data/example.jpg [{"transcription":"Text",...}]`
664
+ - **Important**: Path in Label.txt is a reference format, NOT the physical location
665
+ - Physical images stay in task directory (`data/`), but Label.txt uses folder prefix
666
+
667
+ **File Organization Examples:**
668
+
669
+ <details>
670
+ <summary><b>Example 1: Default Location (No --outDir)</b></summary>
671
+
672
+ **Setup**: Export Label.txt to same directory as task
673
+
674
+ ```
675
+ project/
676
+ └── data/
677
+ └── export.json # Contains: "ocr": "http://localhost:8081/example.jpg"
678
+ ```
679
+
680
+ **Command:**
681
+
682
+ ```bash
683
+ cd project
684
+ label-studio-converter toPPOCR data/ \
685
+ --baseImageDir data
686
+ ```
687
+
688
+ **Result:**
689
+
690
+ ```
691
+ project/
692
+ └── data/
693
+ ├── export.json # Original (unchanged)
694
+ ├── Label.txt # NEW: Generated PPOCR file
695
+ └── example.jpg # NEW: Downloaded from server
696
+ ```
697
+
698
+ **Generated Label.txt contains:**
699
+
700
+ ```
701
+ data/example.jpg [{"transcription":"Text","points":[[...]],"dt_score":1}]
702
+ ```
703
+
704
+ **Image Path Flow:**
705
+
706
+ - Input URL in JSON: `http://localhost:8081/example.jpg`
707
+ - **Downloaded to**: `data/example.jpg` (task file directory)
708
+ - Resolved path: `data/example.jpg` (relative to CWD)
709
+ - Extracted filename: `example.jpg`
710
+ - baseImageDir: `data`
711
+ - Output in Label.txt: `data/example.jpg`
712
+
713
+ </details>
714
+
715
+ <details>
716
+ <summary><b>Example 2: With --outDir Configuration</b></summary>
717
+
718
+ **Setup**: Organize output in separate directory
719
+
720
+ ```
721
+ project/
722
+ ├── data/
723
+ │ └── export.json # Contains: "ocr": "http://localhost:8081/example.jpg"
724
+ └── output/ # Target output directory
725
+ ```
249
726
 
250
- - `toLabelStudio` - Convert PPOCRLabel files to Label Studio format
727
+ **Command:**
251
728
 
252
729
  ```bash
730
+ cd project
731
+ label-studio-converter toPPOCR data/ \
732
+ --outDir output
733
+ ```
734
+
735
+ **Result:**
736
+
737
+ ```
738
+ project/
739
+ ├── data/
740
+ │ ├── export.json # Original (unchanged)
741
+ │ └── example.jpg # Downloaded, then copied to output
742
+ └── output/
743
+ ├── Label.txt # NEW: Generated PPOCR file
744
+ └── example.jpg # NEW: Copied from data/
745
+ ```
746
+
747
+ **Generated Label.txt contains:**
748
+
749
+ ```
750
+ output/example.jpg [{"transcription":"Text","points":[[...]],"dt_score":1}]
751
+ ```
752
+
753
+ **Image Path Flow:**
754
+
755
+ - Input URL in JSON: `http://localhost:8081/example.jpg`
756
+ - **Downloaded to**: `data/example.jpg` (task file directory)
757
+ - **Copied to**: `output/example.jpg` (because --outDir specified)
758
+ - Resolved path: `data/example.jpg` (relative to CWD)
759
+ - Output dir: `output/`
760
+ - Extracted filename: `example.jpg`
761
+ - Output folder name: `output`
762
+ - Output in Label.txt: `output/example.jpg`
763
+
764
+ **Note**: Images are automatically copied to output directory. Use `--noCopyImages` to skip copying.
765
+
766
+ </details>
767
+
768
+ ##### enhance-labelstudio: Label Studio → Label Studio (Enhanced)
769
+
770
+ **INPUT Resolution**: Same as `toPPOCR` converter
771
+
772
+ - Reads Label Studio JSON files
773
+ - Resolves local paths relative to task file
774
+ - Downloads remote URLs to task file directory
775
+
776
+ **OUTPUT Resolution**: Same as `toLabelStudio` converter
777
+
778
+ - Generates Label Studio JSON with `data.ocr` URLs
779
+ - Applies `baseServerUrl` formatting
780
+ - Computes relative paths from output location to images
781
+
782
+ ##### enhance-ppocr: PPOCRLabel → PPOCRLabel (Enhanced)
783
+
784
+ **INPUT Resolution**: Same as `toLabelStudio` converter
785
+
786
+ - Reads PPOCRLabel Label.txt files
787
+ - Resolves paths with folder pattern (`folder/file.jpg`)
788
+ - Detects folder name and resolves from parent directory
789
+
790
+ **OUTPUT Resolution**: Same as `toPPOCR` converter
791
+
792
+ - Generates PPOCRLabel Label.txt with `folder/filename.jpg` format
793
+ - Uses `baseImageDir` or output directory basename as folder prefix
794
+ - Extracts filename from resolved path, prepends folder name
795
+
796
+ ---
797
+
798
+ **Key Concepts:**
799
+
800
+ 1. **Path Resolution Flow**:
801
+ - Input converters resolve paths to **task-relative paths** (relative to task file location)
802
+ - Processor receives and operates on these **task-relative paths**
803
+ - Output converters format these paths for the target system
804
+
805
+ 2. **Remote Image Handling**:
806
+ - URLs (`http://` or `https://`) are downloaded to **task file directory**
807
+ - Only filename is extracted from URL (path structure ignored)
808
+ - Example: `http://server.com/deep/path/example.jpg` → saved as `task-dir/example.jpg`
809
+
810
+ 3. **Image Organization** (toLabelStudio & toPPOCR):
811
+ - **No --outDir**: Output files created in task directory, images stay in place
812
+ - **With --outDir**: Output files go to outDir, **images automatically copied** to outDir (unless --noCopyImages)
813
+ - **--noCopyImages**: Skip image copying, only create task files in outDir
814
+ - **enhance commands**: Images always stay in original location
815
+
816
+ 4. **Output Path Format**:
817
+ - **toLabelStudio**: `${baseServerUrl}/${relativePath}` where relativePath is from output JSON to image
818
+ - **toPPOCR**: `${folder}/${filename}` where folder is `baseImageDir` or output directory name
819
+
820
+ #### Adaptive Resize Feature
821
+
822
+ For detailed algorithm documentation and tuning guide, see [ADAPTIVE_RESIZE.md](docs/ADAPTIVE_RESIZE.md).
823
+
824
+ **Quick Overview:**
825
+
826
+ - **Purpose**: Shrinks oversized boxes to fit actual text content (essential for Sino-Nom OCR with excessive padding)
827
+ - **Algorithm**: Morphological operations + connected component analysis + percentile-based outlier removal
828
+ - **Usage**: Enable with `--adaptResize` flag, tune with 7 parameters documented above
829
+
830
+ #### Detailed Command Help
831
+
832
+ ##### toLabelStudio Command
833
+
834
+ ```bash
835
+ label-studio-converter toLabelStudio --help
836
+ ```
837
+
838
+ **Output:**
839
+
840
+ ```
253
841
  USAGE
254
842
  label-studio-converter toLabelStudio [--outDir value] [--fileName value] [--backup] [--defaultLabelName value] [--toFullJson] [--createFilePerImage] [--createFileListForServing] [--fileListName value] [--baseServerUrl value] [--sortVertical value] [--sortHorizontal value] [--normalizeShape value] [--widthIncrement value] [--heightIncrement value] [--precision value] [--recursive] [--filePattern value] [--outputMode value] <args>...
255
843
  label-studio-converter toLabelStudio --help
@@ -281,9 +869,15 @@ ARGUMENTS
281
869
  args... Input directories containing PPOCRLabel files
282
870
  ```
283
871
 
284
- - `toPPOCR` - Convert Label Studio files to PPOCRLabel format
872
+ ##### toPPOCR Command
285
873
 
286
874
  ```bash
875
+ label-studio-converter toPPOCR --help
876
+ ```
877
+
878
+ **Output:**
879
+
880
+ ```
287
881
  USAGE
288
882
  label-studio-converter toPPOCR [--outDir value] [--fileName value] [--backup] [--baseImageDir value] [--sortVertical value] [--sortHorizontal value] [--normalizeShape value] [--widthIncrement value] [--heightIncrement value] [--precision value] [--recursive] [--filePattern value] <args>...
289
883
  label-studio-converter toPPOCR --help
@@ -309,10 +903,15 @@ ARGUMENTS
309
903
  args... Input directories containing Label Studio files
310
904
  ```
311
905
 
312
- - `enhance-labelstudio` - Enhance Label Studio files with sorting,
313
- normalization, and resizing
906
+ ##### enhance-labelstudio Command
314
907
 
315
908
  ```bash
909
+ label-studio-converter enhance-labelstudio --help
910
+ ```
911
+
912
+ **Output:**
913
+
914
+ ```
316
915
  USAGE
317
916
  label-studio-converter enhance-labelstudio [--outDir value] [--fileName value] [--backup] [--sortVertical value] [--sortHorizontal value] [--normalizeShape value] [--widthIncrement value] [--heightIncrement value] [--precision value] [--recursive] [--filePattern value] [--outputMode value] <args>...
318
917
  label-studio-converter enhance-labelstudio --help
@@ -338,9 +937,15 @@ ARGUMENTS
338
937
  args... Input directories containing Label Studio JSON files
339
938
  ```
340
939
 
341
- - `enhance-ppocr` - Enhance PPOCRLabel files with sorting, normalization, and resizing
940
+ ##### enhance-ppocr Command
342
941
 
343
942
  ```bash
943
+ label-studio-converter enhance-ppocr --help
944
+ ```
945
+
946
+ **Output:**
947
+
948
+ ```
344
949
  USAGE
345
950
  label-studio-converter enhance-ppocr [--outDir value] [--fileName value] [--backup] [--sortVertical value] [--sortHorizontal value] [--normalizeShape value] [--widthIncrement value] [--heightIncrement value] [--precision value] [--recursive] [--filePattern value] <args>...
346
951
  label-studio-converter enhance-ppocr --help
@@ -365,348 +970,103 @@ ARGUMENTS
365
970
  args... Input directories containing PPOCRLabel files
366
971
  ```
367
972
 
368
- **Error Handling:**
369
-
370
- The `toLabelStudio` command handles missing or unreadable image files gracefully:
371
-
372
- - If an image file referenced in PPOCRLabel cannot be found or read, a warning is logged
373
- - Default dimensions of **1920×1080** are used as fallback
374
- - Conversion continues for remaining images without interruption
375
-
376
- This allows the conversion process to complete even when some image files are missing from the dataset.
377
-
378
973
  #### Examples
379
974
 
380
- **Basic Conversions:**
975
+ ##### Basic Conversion
381
976
 
382
977
  ```bash
383
- # Convert PPOCRLabel files to full Label Studio format
384
- label-studio-converter toLabelStudio ./input-ppocr --outDir ./output-label-studio
385
-
386
- # Convert Label Studio files to PPOCRLabel format
387
- label-studio-converter toPPOCR ./input-label-studio --outDir ./output-ppocr
388
-
389
- # Convert with custom output filename for PPOCR
390
- label-studio-converter toPPOCR ./input-label-studio --outDir ./output-ppocr --fileName MyLabels.txt
391
-
392
- # Convert with base image directory path
393
- label-studio-converter toPPOCR ./input-label-studio --baseImageDir images/ch
394
- ```
395
-
396
- > [!NOTE]
397
- > By default, all PPOCRLabel positions are treated as **polygons** in Label Studio.
398
-
399
- **toLabelStudio Options:**
400
-
401
- ```bash
402
- # Create separate JSON file for each image
403
- label-studio-converter toLabelStudio ./input-ppocr \
404
- --outDir ./output \
405
- --createFilePerImage
406
-
407
- # Specify custom label name (default is "Text")
408
- label-studio-converter toLabelStudio ./input-ppocr \
409
- --outDir ./output \
410
- --defaultLabelName Handwriting
411
-
412
- # Convert to minimal format (without serving support)
413
- label-studio-converter toLabelStudio ./input-ppocr \
414
- --outDir ./output \
415
- --noToFullJson
978
+ # PPOCRLabel Label Studio
979
+ label-studio-converter toLabelStudio ./input-ppocr --outDir ./output
416
980
 
417
- # Disable file list creation for serving
418
- label-studio-converter toLabelStudio ./input-ppocr \
419
- --outDir ./output \
420
- --noCreateFileListForServing
981
+ # Label Studio PPOCRLabel
982
+ label-studio-converter toPPOCR ./input-label-studio --outDir ./output --baseImageDir images/ch
421
983
 
422
- # Custom file list name and server URL
984
+ # File-per-image + custom server URL
423
985
  label-studio-converter toLabelStudio ./input-ppocr \
424
986
  --outDir ./output \
425
- --fileListName my-images.txt \
987
+ --createFilePerImage \
426
988
  --baseServerUrl http://192.168.1.100:8080
427
989
 
428
- # Convert to predictions format (pre-annotations) instead of annotations
429
- # Predictions are read-only and useful for pre-annotated data
430
- label-studio-converter toLabelStudio ./input-ppocr \
431
- --outDir ./output \
432
- --outputMode predictions
433
-
434
- # Convert to annotations format (default, editable ground truth)
435
- label-studio-converter toLabelStudio ./input-ppocr \
436
- --outDir ./output \
437
- --outputMode annotations
438
- ```
439
-
440
- > [!IMPORTANT]
441
- > **Output Mode Restrictions:**
442
- >
443
- > - The `--outputMode` flag is only available for:
444
- > - `toLabelStudio` command (when using `--toFullJson`)
445
- > - `enhance-labelstudio` command (for Full JSON format files only)
446
- > - **Not available** for:
447
- > - `toPPOCR` command (PPOCR format doesn't distinguish annotations/predictions)
448
- > - `enhance-ppocr` command (PPOCR format doesn't distinguish annotations/predictions)
449
- > - Min JSON Label Studio format (doesn't support annotations/predictions)
450
- >
451
- > **Prediction Scores:**
452
- >
453
- > - When converting from PPOCRLabel to Label Studio with `--outputMode predictions`, the `dt_score` field from PPOCRLabel is automatically mapped to the prediction `score` field in Label Studio
454
- > - This allows pre-annotation confidence scores to be preserved and displayed in Label Studio
455
- > - Score values should be between 0.0 and 1.0 (confidence percentage)
456
-
457
- **toPPOCR Options:**
458
-
459
- ```bash
460
- # Basic conversion with output directory
461
- label-studio-converter toPPOCR ./input-label-studio \
462
- --outDir ./output
463
-
464
- # Custom output filename
465
- label-studio-converter toPPOCR ./input-label-studio \
466
- --outDir ./output \
467
- --fileName CustomLabel.txt
468
-
469
- # Add base image directory to paths
470
- label-studio-converter toPPOCR ./input-label-studio \
471
- --outDir ./output \
472
- --baseImageDir dataset/images
990
+ # Predictions format (read-only pre-annotations)
991
+ label-studio-converter toLabelStudio ./input-ppocr --outputMode predictions
473
992
  ```
474
993
 
475
- **Recursive Search and Pattern Matching:**
994
+ ##### Enhancement Pipeline
476
995
 
477
996
  ```bash
478
- # Recursively search all subdirectories for .txt files
479
- label-studio-converter toLabelStudio ./data --recursive
480
-
481
- # Search with custom pattern (only files starting with "Label")
482
- label-studio-converter toLabelStudio ./data \
483
- --recursive \
484
- --filePattern "Label.*\.txt$"
485
-
486
- # Convert only specific JSON files (e.g., final annotations)
487
- label-studio-converter toPPOCR ./annotations \
488
- --recursive \
489
- --filePattern ".*_final\.json$"
490
-
491
- # Enhance only specific files matching pattern
492
- label-studio-converter enhance-ppocr ./dataset \
493
- --recursive \
494
- --filePattern "train_.*\.txt$"
495
- ```
496
-
497
- > [!NOTE]
498
- >
499
- > - `--recursive`: Searches all subdirectories for matching files
500
- > - `--filePattern`: Regex pattern to filter files (default: `.*\.txt$` for PPOCR, `.*\.json$` for Label Studio)
501
- > - Patterns are flexible - use any regex, but ensure they match appropriate file types (.txt for PPOCR, .json for Label Studio)
502
-
503
- ### Enhancement Features
504
-
505
- The tool provides powerful enhancement capabilities that can be used standalone or integrated with conversion:
506
-
507
- **Enhance PPOCRLabel files:**
508
-
509
- ```bash
510
- # Sort annotations from top to bottom, left to right
511
- label-studio-converter enhance-ppocr ./data --sortVertical top-bottom --sortHorizontal ltr
512
-
513
- # Normalize diamond shapes to rectangles and resize
514
- label-studio-converter enhance-ppocr ./data --normalizeShape rectangle --widthIncrement 10 --heightIncrement 5
515
-
516
- # Apply all enhancements
997
+ # Sort + normalize + resize
517
998
  label-studio-converter enhance-ppocr ./data \
518
999
  --sortVertical top-bottom \
519
1000
  --sortHorizontal ltr \
520
1001
  --normalizeShape rectangle \
521
1002
  --widthIncrement 5 \
522
- --heightIncrement 5 \
523
- --precision 0
524
- ```
525
-
526
- **Enhance Label Studio files:**
527
-
528
- ```bash
529
- # Sort and normalize Label Studio annotations
530
- label-studio-converter enhance-labelstudio ./data \
531
- --sortVertical top-bottom \
532
- --normalizeShape rectangle \
533
- --precision 2
534
-
535
- # Works with both Full and Min formats automatically
536
- label-studio-converter enhance-labelstudio ./label-studio-files --outDir ./enhanced
537
- ```
1003
+ --heightIncrement 5
538
1004
 
539
- **Enhancement Options:**
540
-
541
- - `--sortVertical`: Sort bounding boxes vertically
542
- - `none` (default): No sorting
543
- - `top-bottom`: Sort from top to bottom
544
- - `bottom-top`: Sort from bottom to top
545
- - Example:
546
- ```bash
547
- # Sort annotations from top to bottom
548
- label-studio-converter enhance-ppocr ./data --sortVertical top-bottom
549
- ```
550
-
551
- - `--sortHorizontal`: Sort bounding boxes horizontally
552
- - `none` (default): No sorting
553
- - `ltr`: Sort left to right (useful for English, most European languages)
554
- - `rtl`: Sort right to left (useful for Arabic, Hebrew)
555
- - Example:
556
-
557
- ```bash
558
- # Sort annotations left to right
559
- label-studio-converter enhance-ppocr ./data --sortHorizontal ltr
560
-
561
- # Sort annotations right to left
562
- label-studio-converter enhance-ppocr ./data --sortHorizontal rtl
563
- ```
564
-
565
- - `--normalizeShape`: Normalize shapes
566
- - `none` (default): Keep original shape
567
- - `rectangle`: Convert diamond-like or rotated shapes to axis-aligned rectangles
568
- - Example:
569
- ```bash
570
- # Convert irregular shapes to clean rectangles
571
- label-studio-converter enhance-ppocr ./data --normalizeShape rectangle
572
- ```
573
-
574
- - `--widthIncrement`: Increase/decrease width (pixels, can be negative)
575
- - Default: `0`
576
- - Examples:
577
-
578
- ```bash
579
- # Increase width by 10 pixels
580
- label-studio-converter enhance-ppocr ./data --widthIncrement 10
581
-
582
- # Decrease width by 5 pixels
583
- label-studio-converter enhance-ppocr ./data --widthIncrement -5
584
- ```
585
-
586
- - `--heightIncrement`: Increase/decrease height (pixels, can be negative)
587
- - Default: `0`
588
- - Examples:
589
-
590
- ```bash
591
- # Increase height by 15 pixels
592
- label-studio-converter enhance-ppocr ./data --heightIncrement 15
593
-
594
- # Decrease height by 3 pixels
595
- label-studio-converter enhance-ppocr ./data --heightIncrement -3
596
- ```
597
-
598
- - `--precision`: Control the number of decimal places for coordinate values
599
- - `-1`: Full precision - no rounding, keeps all decimal places (default for Label Studio output)
600
- - Example output: `27.44656917885264`
601
- - `0`: Round to integers (default for PPOCR output)
602
- - Example output: `27`
603
- - `1`: Round to 1 decimal place
604
- - Example output: `27.4`
605
- - `2`: Round to 2 decimal places
606
- - Example output: `27.45`
607
- - Any positive integer for that many decimal places
608
- - Examples:
609
-
610
- ```bash
611
- # Use full precision
612
- label-studio-converter toLabelStudio ./data --precision -1
613
-
614
- # Use integer coordinates
615
- label-studio-converter toPPOCR ./data --precision 0
616
-
617
- # Use 2 decimal places
618
- label-studio-converter enhance-labelstudio ./data --precision 2
619
- ```
620
-
621
- **Conversion with Enhancement:**
622
-
623
- All enhancement options are available in conversion commands:
1005
+ # Adaptive resize for Sino-Nom OCR (shrinks oversized boxes)
1006
+ label-studio-converter enhance-ppocr ./sinonom-data \
1007
+ --adaptResize \
1008
+ --adaptResizeThreshold 128 \
1009
+ --adaptResizeMargin 8 \
1010
+ --adaptResizeMaxHorizontalExpansion 50 \
1011
+ --sortHorizontal rtl
624
1012
 
625
- ```bash
626
- # Convert with enhancements applied during conversion
1013
+ # Convert with full enhancement pipeline
627
1014
  label-studio-converter toLabelStudio ./input-ppocr \
628
1015
  --outDir ./output \
629
- --sortVertical top-bottom \
630
1016
  --normalizeShape rectangle \
631
- --widthIncrement 10
632
-
633
- label-studio-converter toPPOCR ./input-label-studio \
634
- --outDir ./output \
635
- --sortVertical top-bottom \
636
- --sortHorizontal ltr \
637
- --normalizeShape rectangle
1017
+ --adaptResize \
1018
+ --sortVertical top-bottom
638
1019
  ```
639
1020
 
640
- **Convert PPOCRLabel files to Label Studio format with one file per image:**
1021
+ ##### File Organization
641
1022
 
642
1023
  ```bash
643
- label-studio-converter toLabelStudio ./input-ppocr --outDir ./output-label-studio --defaultLabelName Text --toFullJson --createFilePerImage --sortVertical none --sortHorizontal none
644
- ```
645
-
646
- **Convert PPOCRLabel files to minimal Label Studio format (cannot be used for serving):**
1024
+ # Recursive search with pattern matching
1025
+ label-studio-converter toLabelStudio ./dataset \
1026
+ --recursive \
1027
+ --filePattern "train_.*\.txt$"
647
1028
 
648
- ```bash
649
- label-studio-converter toLabelStudio ./input-ppocr --outDir ./output-label-studio --defaultLabelName Text --noToFullJson --sortVertical none --sortHorizontal none
1029
+ # Custom output filenames
1030
+ label-studio-converter toPPOCR ./data \
1031
+ --outDir ./output \
1032
+ --fileName MyLabels.txt
650
1033
  ```
651
1034
 
652
- > [!IMPORTANT]
653
- > Minimal Label Studio format cannot be used for serving in Label Studio, as it
654
- > lacks necessary fields such as `id` and `data`. So you can only use minimal
655
- > format for conversion back to PPOCRLabelv2 format or other purposes.
656
-
657
- **Shape Normalization**
1035
+ ##### Shape Normalization
658
1036
 
659
- Convert diamond-like or irregular quadrilateral shapes to axis-aligned
660
- rectangles. This is useful when your annotations have irregular shapes that you
661
- want to normalize to clean, horizontal/vertical bounding boxes:
1037
+ Diamond/rotated shapes axis-aligned rectangles:
662
1038
 
663
1039
  ```bash
664
- # Convert to axis-aligned rectangles
665
- label-studio-converter toLabelStudio ./input-ppocr --outDir ./output --normalizeShape rectangle
666
-
667
- # For toPPOCR command
668
- label-studio-converter toPPOCR ./input-label-studio --outDir ./output --normalizeShape rectangle
1040
+ label-studio-converter enhance-ppocr ./data \
1041
+ --normalizeShape rectangle \
1042
+ --outDir ./normalized
669
1043
  ```
670
1044
 
671
1045
  <details>
672
- <summary>
673
- <b>Before normalization</b> (diamond-like shapes):
674
- </summary>
1046
+ <summary>Visual comparison</summary>
675
1047
 
676
- ![Before normalization](./docs/images/label-studio-original-diamond.png)
1048
+ **Before:** Diamond-like shapes
677
1049
 
678
- </details>
1050
+ ![Before normalization](./docs/images/label-studio-original-diamond.png)
679
1051
 
680
- <details>
681
- <summary>
682
- <b>After normalization</b> (axis-aligned rectangles):
683
- </summary>
684
-
685
- Command:
686
-
687
- ```bash
688
- ./dist/cli.js toPPOCR ./tmp --baseImageDir output --normalizeShape rectangle
689
- ```
1052
+ **After:** Axis-aligned rectangles
690
1053
 
691
1054
  ![After normalization](./docs/images/label-studio-converted-diamond.png)
692
1055
 
693
- </details>
694
-
695
- <details>
696
- <summary>
697
- <b>Before normalization</b> (diamond-like vertical shapes):
698
- </summary>
1056
+ **Vertical text example:**
699
1057
 
700
- ![Before normalization (vert)](./docs/images/label-studio-original-diamond-vert.png)
1058
+ ![Before (vertical)](./docs/images/label-studio-original-diamond-vert.png)
1059
+ ![After (vertical)](./docs/images/label-studio-converted-diamond-vert.png)
701
1060
 
702
1061
  </details>
703
1062
 
704
- <details>
705
- <summary>
706
- <b>After normalization</b> (axis-aligned vertical rectangles):
707
- </summary>
708
-
709
- Command:
1063
+ > [!NOTE]
1064
+ > **Key Behaviors:**
1065
+ >
1066
+ > - Remote images (`http://`, `https://`) are automatically downloaded
1067
+ > - Path resolution: `${baseServerUrl}/${relativeToOutDir}/image.jpg`
1068
+ > - All PPOCRLabel positions treated as polygons in Label Studio
1069
+ > - Missing images use fallback dimensions (1920×1080) and log warning
710
1070
 
711
1071
  ```bash
712
1072
  ./dist/cli.js toPPOCR ./tmp --baseImageDir output --normalizeShape rectangle
@@ -716,61 +1076,6 @@ Command:
716
1076
 
717
1077
  </details>
718
1078
 
719
- **Bounding Box Resizing**
720
-
721
- Increase or decrease bounding box dimensions while keeping them centered. This
722
- is useful for adjusting annotation margins:
723
-
724
- ```bash
725
- # Increase width by 10 pixels and height by 20 pixels
726
- label-studio-converter toLabelStudio ./input-ppocr --outDir ./output --widthIncrement 10 --heightIncrement 20
727
-
728
- # Decrease width by 5 pixels (negative increment)
729
- label-studio-converter toLabelStudio ./input-ppocr --outDir ./output --widthIncrement -5
730
-
731
- # Works with toPPOCR as well
732
- label-studio-converter toPPOCR ./input-label-studio --outDir ./output --widthIncrement 10 --heightIncrement 10
733
- ```
734
-
735
- **Combining Features**
736
-
737
- You can combine shape normalization and resizing:
738
-
739
- ```bash
740
- # Normalize to rectangle and increase size
741
- label-studio-converter toLabelStudio ./input-ppocr --outDir ./output --normalizeShape rectangle --widthIncrement 5 --heightIncrement 5
742
-
743
- # Also works with sorting
744
- label-studio-converter toLabelStudio ./input-ppocr --outDir ./output --normalizeShape rectangle --widthIncrement 10 --sortVertical top-bottom --sortHorizontal ltr
745
- ```
746
-
747
- **Number Precision Control**
748
-
749
- Control the precision of coordinate values in the output. This is useful for
750
- matching format expectations or reducing file size:
751
-
752
- ```bash
753
- # Convert to Label Studio with full precision (default: -1)
754
- label-studio-converter toLabelStudio ./input-ppocr --outDir ./output --precision -1
755
-
756
- # Convert to PPOCR with integer coordinates (default: 0)
757
- label-studio-converter toPPOCR ./input-label-studio --outDir ./output --precision 0
758
-
759
- # Use 2 decimal places for more compact but still precise coordinates
760
- label-studio-converter toLabelStudio ./input-ppocr --outDir ./output --precision 2
761
- ```
762
-
763
- Precision values:
764
-
765
- - `-1`: Full floating-point precision (default for Label Studio output)
766
- - `0`: Round to integers (default for PPOCR output)
767
- - `1+`: Round to specified number of decimal places
768
-
769
- > [!NOTE]
770
- > The default precision matches typical format conventions: Label Studio uses
771
- > full precision for percentage-based coordinates, while PPOCR format typically
772
- > uses integer pixel coordinates.
773
-
774
1079
  ### Using generated files with Label Studio
775
1080
 
776
1081
  #### Interface setup
@@ -1099,10 +1404,10 @@ Converted back to Label Studio annotation:
1099
1404
  "last_created_by": null
1100
1405
  }
1101
1406
  ],
1102
- "file_upload": "5b1e3483-example.jpg",
1407
+ "file_upload": "example.jpg",
1103
1408
  "drafts": [],
1104
1409
  "predictions": [],
1105
- "data": { "ocr": "\/data\/upload\/2\/5b1e3483-example.jpg" },
1410
+ "data": { "ocr": "\/example.jpg" },
1106
1411
  "meta": {},
1107
1412
  "created_at": "2026-01-07T03:13:41.175183Z",
1108
1413
  "updated_at": "2026-01-10T03:21:09.923449Z",
@@ -1137,7 +1442,7 @@ Command:
1137
1442
  Output:
1138
1443
 
1139
1444
  ```
1140
- 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}]
1445
+ data/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}]
1141
1446
  ```
1142
1447
 
1143
1448
  </details>
@@ -1363,11 +1668,11 @@ Output:
1363
1668
  "last_created_by": null
1364
1669
  }
1365
1670
  ],
1366
- "file_upload": "5b1e3483-example.jpg",
1671
+ "file_upload": "example.jpg",
1367
1672
  "drafts": [],
1368
1673
  "predictions": [],
1369
1674
  "data": {
1370
- "ocr": "http://localhost:8081/output/5b1e3483-example.jpg"
1675
+ "ocr": "http://localhost:8081/output/example.jpg"
1371
1676
  },
1372
1677
  "meta": {},
1373
1678
  "created_at": "2026-01-10T03:25:05.530Z",
@@ -1419,7 +1724,8 @@ commands:
1419
1724
  rm -rf ./output-label-studio
1420
1725
  ```
1421
1726
 
1422
- - When you did not specify an output directory (default: files are saved in the same directory as the source files):
1727
+ - When you did not specify an output directory (default: files are saved in the
1728
+ same directory as the source files):
1423
1729
 
1424
1730
  **For default output file names:**
1425
1731
 
@@ -1452,7 +1758,8 @@ commands:
1452
1758
  Remove-Item -Path ".\output-label-studio" -Recurse -Force
1453
1759
  ```
1454
1760
 
1455
- - When you did not specify an output directory (default: files are saved in the same directory as the source files):
1761
+ - When you did not specify an output directory (default: files are saved in the
1762
+ same directory as the source files):
1456
1763
 
1457
1764
  **For default output file names:**
1458
1765