npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

label-studio-converter

v1.6.1

Published

Convert between Label Studio OCR format and PPOCRLabelv2 format

Downloads

639

Readme

:notebook_with_decorative_cover: Table of Contents

:toolbox: Getting Started

:bangbang: Prerequisites

:package: Installation

As a CLI tool:

npm install -g label-studio-converter

As a library:

npm install label-studio-converter
# or
pnpm add label-studio-converter
# or
yarn add label-studio-converter

:running: Run Locally

Clone the project:

git clone https://github.com/DuckyMomo20012/label-studio-converter.git

Go to the project directory:

cd label-studio-converter

Install dependencies:

pnpm install

:eyes: Usage

[!IMPORTANT] This tool only supports conversion between PPOCRLabelv2 format and Label Studio "OCR" template. For setting up Label Studio for OCR tasks, please refer to the Using generated files with Label Studio section.

[!NOTE] This package can be used both as a CLI tool and as a library.

  • CLI: Run commands directly from the terminal
  • Library: Import and use functions in your TypeScript/JavaScript code

Library Usage

Conversion Functions:

import {
  fullLabelStudioToPPOCRConverters,
  minLabelStudioToPPOCRConverters,
  ppocrToLabelStudio
} from 'label-studio-converter'

// Convert Label Studio Full Format to PPOCRLabel
const fullData = [] // FullOCRLabelStudio type
const ppocrMap = await fullLabelStudioToPPOCRConverters(fullData, {
  baseImageDir: 'images/ch',
  normalizeShape: 'rectangle',
  widthIncrement: 5,
  heightIncrement: 5,
  precision: 0 // integers
})

// Convert Label Studio Min Format to PPOCRLabel
const minData = [] // MinOCRLabelStudio type
const ppocrMap2 = await minLabelStudioToPPOCRConverters(minData, {
  baseImageDir: 'images/ch',
  precision: 0
})

// Convert PPOCRLabel to Label Studio
const ppocrData = [] // PPOCRLabel type
const labelStudioData = await ppocrToLabelStudio(ppocrData, {
  imagePath: 'example.jpg',
  baseServerUrl: 'http://localhost:8081',
  inputDir: './images',
  toFullJson: true,
  labelName: 'Text',
  precision: -1 // full precision
})

Enhancement Functions:

import {
  enhanceLabelStudioData,
  enhancePPOCRLabel,
} from 'label-studio-converter'

// Enhance PPOCRLabel data
const enhanced = enhancePPOCRLabel(ppocrData, {
  sortVertical: 'top-bottom',
  sortHorizontal: 'ltr',
  normalizeShape: 'rectangle',
  widthIncrement: 10,
  heightIncrement: 5,
  precision: 0,
})

// Enhance Label Studio data (Full or Min format)
const enhancedLS = await enhanceLabelStudioData(
  labelStudioData,
  true, // isFull: true for Full format, false for Min format
  {
    sortVertical: 'top-bottom',
    normalizeShape: 'rectangle',
    precision: 2,
  },
)

Utility Functions:

import {
  normalizeShape,
  resizeBoundingBox,
  sortBoundingBoxes,
  transformPoints,
} from 'label-studio-converter'

// Transform points (normalize + resize)
const transformed = transformPoints(points, {
  normalizeShape: 'rectangle',
  widthIncrement: 10,
  heightIncrement: 5,
})

// Normalize diamond shapes to rectangles
const normalized = normalizeShape(points)

// Resize bounding box
const resized = resizeBoundingBox(points, 10, 5)

// Sort bounding boxes
const sorted = sortBoundingBoxes(annotations, 'top-bottom', 'ltr')

CLI Usage

Available Commands

label-studio-converter --help

Output:

USAGE
  label-studio-converter toLabelStudio [--outDir value] [--fileName value] [--backup] [--recursive] [--filePattern value] [--copyImages] [--imageBaseDir value] [--sortVertical value] [--sortHorizontal value] [--normalizeShape value] [--useOrientedBox] [--widthIncrement value] [--heightIncrement value] [--adaptResize] [--adaptResizeThreshold value] [--adaptResizeMargin value] [--adaptResizeMinComponentSize value] [--adaptResizeMaxComponentSize value] [--adaptResizeOutlierPercentile value] [--adaptResizeMorphologySize value] [--adaptResizeMaxHorizontalExpansion value] [--adaptResizePaddingCheckWidth value] [--adaptResizeMinPaddingBrightness value] [--adaptResizeMinPaddingRatio value] [--adaptResizeUseAdaptiveThreshold] [--adaptResizeAdaptiveBlockSize value] [--precision value] [--numPointCheck value] [--defaultLabelName value] [--toFullJson] [--createFilePerImage] [--createFileListForServing] [--fileListName value] [--baseServerUrl value] [--outputMode value] <args>...
  label-studio-converter toPPOCR [--outDir value] [--fileName value] [--backup] [--recursive] [--filePattern value] [--copyImages] [--imageBaseDir value] [--sortVertical value] [--sortHorizontal value] [--normalizeShape value] [--useOrientedBox] [--widthIncrement value] [--heightIncrement value] [--adaptResize] [--adaptResizeThreshold value] [--adaptResizeMargin value] [--adaptResizeMinComponentSize value] [--adaptResizeMaxComponentSize value] [--adaptResizeOutlierPercentile value] [--adaptResizeMorphologySize value] [--adaptResizeMaxHorizontalExpansion value] [--adaptResizePaddingCheckWidth value] [--adaptResizeMinPaddingBrightness value] [--adaptResizeMinPaddingRatio value] [--adaptResizeUseAdaptiveThreshold] [--adaptResizeAdaptiveBlockSize value] [--precision value] [--numPointCheck value] [--baseImageDir value] [--generateFileState] <args>...
  label-studio-converter enhance-labelstudio [--outDir value] [--fileName value] [--backup] [--recursive] [--filePattern value] [--copyImages] [--imageBaseDir value] [--sortVertical value] [--sortHorizontal value] [--normalizeShape value] [--useOrientedBox] [--widthIncrement value] [--heightIncrement value] [--adaptResize] [--adaptResizeThreshold value] [--adaptResizeMargin value] [--adaptResizeMinComponentSize value] [--adaptResizeMaxComponentSize value] [--adaptResizeOutlierPercentile value] [--adaptResizeMorphologySize value] [--adaptResizeMaxHorizontalExpansion value] [--adaptResizePaddingCheckWidth value] [--adaptResizeMinPaddingBrightness value] [--adaptResizeMinPaddingRatio value] [--adaptResizeUseAdaptiveThreshold] [--adaptResizeAdaptiveBlockSize value] [--precision value] [--numPointCheck value] [--outputMode value] <args>...
  label-studio-converter enhance-ppocr [--outDir value] [--fileName value] [--backup] [--recursive] [--filePattern value] [--copyImages] [--imageBaseDir value] [--sortVertical value] [--sortHorizontal value] [--normalizeShape value] [--useOrientedBox] [--widthIncrement value] [--heightIncrement value] [--adaptResize] [--adaptResizeThreshold value] [--adaptResizeMargin value] [--adaptResizeMinComponentSize value] [--adaptResizeMaxComponentSize value] [--adaptResizeOutlierPercentile value] [--adaptResizeMorphologySize value] [--adaptResizeMaxHorizontalExpansion value] [--adaptResizePaddingCheckWidth value] [--adaptResizeMinPaddingBrightness value] [--adaptResizeMinPaddingRatio value] [--adaptResizeUseAdaptiveThreshold] [--adaptResizeAdaptiveBlockSize value] [--precision value] [--numPointCheck value] <args>...
  label-studio-converter label-studio-output-to-ppocr [--recursive] [--backup] [--filePattern value] [--numPointCheck value] (--outDir value) [--fileName value] [--removeBaseImageDir value] [--generateFileState] <args>...
  label-studio-converter --help
  label-studio-converter --version

Convert between Label Studio OCR format and PPOCRLabelv2 format

FLAGS
  -h --help     Print help information and exit
  -v --version  Print version information and exit

COMMANDS
  toLabelStudio                 Convert PPOCRLabel files to Label Studio format
  toPPOCR                       Convert Label Studio files to PPOCRLabel format
  enhance-labelstudio           Enhance Label Studio files with sorting, normalization, and resizing
  enhance-ppocr                 Enhance PPOCRLabel files with sorting, normalization, and resizing
  label-studio-output-to-ppocr  Convert Label Studio output files to PPOCRLabel format

Command Flags Reference

Flags Available for All Commands

File I/O Flags:

  • --outDir <path>: Output directory path

    • Behavior: Saves converted/enhanced files to specified directory
    • Default: Same directory as input files
    • Example: --outDir ./output saves all files to ./output/
  • --fileName <name>: Custom output filename

    • Behavior: Renames output file (without extension for JSON, with extension for txt)
    • Default:
      • toLabelStudio: {source}_full.json or {source}_min.json
      • toPPOCR: Label.txt
      • enhance commands: Same as input filename
    • Example: --fileName MyLabels.txt creates MyLabels.txt instead of Label.txt
  • --backup / --noBackup: Create backup before overwriting

    • Behavior: Copies existing file to {filename}.backup before overwriting
    • Default: false (no backup)
    • Example: --backup creates Label.txt.backup if Label.txt exists
  • --recursive / --noRecursive: Search subdirectories

    • Behavior: Processes files in all subdirectories recursively
    • Default: false (current directory only)
    • Example: --recursive processes ./data/train/Label.txt and ./data/test/Label.txt
  • --filePattern <regex>: Pattern to match input files

    • Behavior: Only processes files matching regex pattern
    • Default:
      • PPOCRLabel commands: .*\.txt$ (all .txt files)
      • Label Studio commands: .*\.json$ (all .json files)
    • Example: --filePattern "train_.*\.txt$" only processes files starting with train_
  • --copyImages / --noCopyImages: Copy images when using --outDir

    • Behavior: When --outDir is specified, automatically copies/moves images to output directory alongside converted files
    • Default: true (copy images)
    • Example: --noCopyImages keeps images in original location, only copies task files
    • Note: Only applies to toLabelStudio and toPPOCR converters when --outDir is used
    • Note: Not available for label-studio-output-to-ppocr command since it only processes Label Studio output files which have no image paths
  • --imageBaseDir <dir>: Controls output directory structure when copying images

    • Behavior: Determines how the directory structure is preserved when copying images to output directory
    • Options: task-file (relative to task file), input-dir (relative to input directory)
    • Default: task-file
    • Example: --imageBaseDir input-dir --copyImages preserves full path structure from input directory
    • Use case: Control whether copied images maintain full path from input directory or relative to task file
    • Note: Only affects output when --copyImages is used with --outDir
    • Note: Not available for label-studio-output-to-ppocr command since it only processes Label Studio output files which have no image paths

Enhancement Flags:

  • --sortVertical <order>: Vertical sorting order

    • Behavior: Sorts bounding boxes by vertical position
    • Options: none, top-bottom, bottom-top
    • Default: none (no sorting)
    • Example: --sortVertical top-bottom sorts boxes from top to bottom
  • --sortHorizontal <order>: Horizontal sorting order

    • Behavior: Sorts bounding boxes by horizontal position (applied after vertical sort)
    • Options: none, ltr (left-to-right), rtl (right-to-left)
    • Default: none (no sorting)
    • Example: --sortHorizontal rtl sorts boxes right-to-left (for vertical text)
  • --normalizeShape <option>: Shape normalization

    • Behavior: Converts diamond/rotated shapes to axis-aligned rectangles
    • Options: none, rectangle
    • Default: none (preserve original shapes)
    • Example: --normalizeShape rectangle converts all polygons to rectangles
  • --widthIncrement <pixels>: Adjust box width

    • Behavior: Adds pixels to box width (can be negative to shrink)
    • Default: 0 (no change)
    • Example: --widthIncrement 5 expands boxes by 5px horizontally
  • --heightIncrement <pixels>: Adjust box height

    • Behavior: Adds pixels to box height (can be negative to shrink)
    • Default: 0 (no change)
    • Example: --heightIncrement -3 shrinks boxes by 3px vertically
  • --precision <decimals>: Coordinate precision

    • Behavior: Number of decimal places for coordinates
    • Default:
      • toLabelStudio: -1 (full precision, no rounding)
      • toPPOCR: 0 (integers only)
      • enhance-labelstudio: -1 (full precision)
      • enhance-ppocr: 0 (integers)
    • Example: --precision 2 rounds to 2 decimal places (e.g., 123.45)

Check Flags:

  • --numPointCheck <number>: Check number of points in each annotation
    • Behavior: Validates that each annotation has exactly this number of points
    • Example: --numPointCheck 4 ensures all boxes are quadrilaterals

Adaptive Resize Flags (Advanced):

  • --adaptResize / --noAdaptResize: Enable intelligent box resizing

    • Behavior: Uses image analysis to shrink oversized boxes to fit actual text
    • Default: false (disabled)
    • Use Case: Sino-Nom OCR datasets with excessive padding
    • Example: --adaptResize enables feature with default parameters
  • --adaptResizeThreshold <0-255>: Grayscale threshold

    • Behavior: Pixels ≥ threshold are considered text (white), < threshold are background (black)
    • Default: 128
    • Example: --adaptResizeThreshold 140 for darker text on light background
  • --adaptResizeMargin <pixels>: Padding around detected content

    • Behavior: Additional pixels added on all sides after detection
    • Default: 5
    • Example: --adaptResizeMargin 8 adds 8px padding
  • --adaptResizeMinComponentSize <pixels>: Noise filter

    • Behavior: Regions smaller than this are ignored (filters dirt dots)
    • Default: 10
    • Example: --adaptResizeMinComponentSize 15 filters more aggressively
  • --adaptResizeMaxComponentSize <pixels>: Artifact filter

    • Behavior: Regions larger than this are ignored (filters huge artifacts)
    • Default: 100000
    • Example: --adaptResizeMaxComponentSize 50000 for smaller characters
  • --adaptResizeOutlierPercentile <%>: Outlier removal

    • Behavior: Ignores this % of smallest and largest pixels when calculating boundaries
    • Default: 2 (ignore 2% on each end)
    • Example: --adaptResizeOutlierPercentile 3 for more aggressive outlier removal
  • --adaptResizeMorphologySize <pixels>: Stroke connection

    • Behavior: Kernel size for connecting broken character strokes
    • Default: 2
    • Example: --adaptResizeMorphologySize 3 connects larger gaps
  • --adaptResizeMaxHorizontalExpansion <pixels>: Column overlap prevention

    • Behavior: Maximum pixels boxes can expand horizontally (CRITICAL for vertical text)
    • Default: 50
    • Example: --adaptResizeMaxHorizontalExpansion 30 for closely-spaced columns
Flags Specific to toLabelStudio Command
  • --defaultLabelName <name>: Default label for annotations

    • Behavior: Label assigned to all text regions
    • Default: "Text"
    • Example: --defaultLabelName "Handwriting" labels all regions as Handwriting
  • --toFullJson / --noToFullJson: Output format

    • Behavior: true = Full format (more metadata), false = Min format (compact)
    • Default: true (Full format)
    • Example: --noToFullJson creates minimal format files
  • --createFilePerImage / --noCreateFilePerImage: File splitting

    • Behavior: true = one JSON per image, false = all tasks in one file
    • Default: false (single file)
    • Example: --createFilePerImage creates image1.json, image2.json, etc.
  • --createFileListForServing / --noCreateFileListForServing: Generate file list

    • Behavior: Creates files.txt with image URLs for Label Studio import
    • Default: true (create file list)
    • Example: --noCreateFileListForServing skips file list creation
  • --fileListName <name>: File list filename

    • Behavior: Name of the file containing image URLs for serving
    • Default: "files.txt"
    • Example: --fileListName "images.txt" creates images.txt instead
  • --baseServerUrl <url>: Base URL for images

    • Behavior: Prepended to image paths in output JSON (e.g., for local HTTP server)
    • Default: "http://localhost:8081"
    • Example: --baseServerUrl "http://192.168.1.100:8080" for network access
  • --outputMode <mode>: Annotation mode

    • Behavior:
      • annotations = editable ground truth annotations
      • predictions = read-only pre-annotations
    • Default: "annotations"
    • Example: --outputMode predictions for model predictions import
Flags Specific to toPPOCR Command
  • --baseImageDir <path>: Image directory prefix

    • Behavior: Prepended to image filenames in output Label.txt
    • Default: Empty string (no prefix)
    • Example: --baseImageDir "images/ch" writes images/ch/example.jpg in Label.txt
  • --generateFileState / --noGenerateFileState: Generate file state

    • Behavior: Creates fileState.txt for each input directory, listing all processed files
    • Default: true
    • Example: --generateFileState creates fileState.txt in each input directory
Flags Specific to enhance-labelstudio Command
  • --outputMode <mode>: Same as toLabelStudio command
    • See toLabelStudio flags section above
Flags Specific to label-studio-output-to-ppocr Command
  • --removeBaseImageDir <dir>: Remove base directory from image paths

    • Behavior: Strips specified base directory from image paths in output Label.txt
    • Default: "/data/local-files/?d=" (removes Label Studio's default local file prefix)
    • Example: --removeBaseImageDir "data/" converts data/example.jpg to example.jpg in Label.txt
  • --generateFileState / --noGenerateFileState: Generate file state

    • Behavior: Creates fileState.txt for each input directory, listing all processed files
    • Default: true
    • Example: --generateFileState creates fileState.txt in each input directory

Image Path Resolution Logic

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.

New in v1.5.0: The --imageBaseDir flag controls the output directory structure when copying images. It determines whether copied images maintain their path relative to the task file (task-file, default) or the input directory (input-dir).

toLabelStudio: PPOCRLabel → Label Studio

INPUT Resolution (Reading PPOCRLabel files):

Command Execution Context:

  • You run: cd project && label-studio-converter toLabelStudio data/
  • Current working directory (CWD): project/
  • Input parameter: data/ (directory to search for Label.txt files)
  • Converter finds: project/data/Label.txt (and other Label.txt files in subdirectories if --recursive)
  • Task file being processed: project/data/Label.txt

How Image Paths Are Read:

  1. What's in the Label.txt file:

    • Path format: data/example.jpg (PPOCRLabel standard: folder/filename)
    • PPOCRLabel was opened on data/ folder, so paths use data/ prefix
  2. How input resolver finds images:

    • Reads path from Label.txt: data/example.jpg
    • Task file is at: project/data/Label.txt
    • Task directory: project/data/
    • Check if path starts with task folder name (data/):
      • YES → resolve from parent: dirname(project/data/) + data/example.jpg = project/data/example.jpg
      • NO → resolve from task dir: project/data/ + example.jpg = project/data/example.jpg

OUTPUT Resolution (Copying images with --copyImages --outDir):

With --imageBaseDir task-file (default):

When copying images to output directory, paths are maintained relative to the task file location:

  • Input directory: project/data/ (provided to command)
  • Source image: project/data/foo/bar/baz/example.jpg
  • Task file: project/data/Label.txt
  • Output dir: project/output/
  • Relative from task: relative(project/data/, project/data/foo/bar/baz/example.jpg) = foo/bar/baz/example.jpg
  • Destination: project/output/data/foo/bar/baz/example.jpg (maintains structure relative to task file)

With --imageBaseDir input-dir:

When copying images to output directory, paths are maintained relative to input directory:

  • Input directory: project/data/ (provided to command)
  • Source image: project/data/foo/bar/baz/example.jpg
  • Output dir: project/output/
  • Relative from input: relative(project/data/, project/data/foo/bar/baz/example.jpg) = foo/bar/baz/example.jpg
  • Destination: project/output/foo/bar/baz/example.jpg (maintains path from input directory)
    • Path relative to CWD: data/example.jpg
    • (From input resolution step)
  1. How output resolver formats paths:

    • No --outDir: Compute relative path from output JSON to image
    • Output JSON at: project/data/Label_full.json
    • Image at: project/data/example.jpg
    • Relative path: relative(project/data/, project/data/example.jpg) = example.jpg
    • Apply baseServerUrl: http://localhost:8081/example.jpg
  2. What goes in the output file:

    • Label Studio JSON: "ocr": "http://localhost:8081/example.jpg"

File Organization Examples:

Setup: Images and output in same place as task file

project/
└── data/
    ├── Label.txt              # Contains: data/example.jpg	[...]
    └── example.jpg

Command:

cd project
label-studio-converter toLabelStudio data/

Result:

project/
└── data/
    ├── Label.txt              # Original task file
    ├── Label_full.json        # NEW: Generated output
    ├── files.txt              # NEW: File list for serving
    └── example.jpg            # Original image (unchanged)

Generated Label_full.json contains:

{
  "data": {
    "ocr": "http://localhost:8081/example.jpg"
  }
}

Image Path Flow:

  • Input path in Label.txt: data/example.jpg
  • Resolved path: data/example.jpg (relative to CWD)
  • Output saved in: data/ (same as task)
  • Relative to output: example.jpg
  • Final URL: http://localhost:8081/example.jpg

Setup: Separate output directory for organized export

project/
├── data/
│   ├── Label.txt              # Contains: data/example.jpg	[...]
│   └── example.jpg
└── output/                    # Target output directory

Command:

cd project
label-studio-converter toLabelStudio data/ \
  --outDir output \
  --baseServerUrl http://localhost:8081

Result:

project/
├── data/
│   ├── Label.txt              # Original (unchanged)
│   └── example.jpg            # Original (unchanged)
└── output/                    # NEW: All outputs here
    ├── Label_full.json        # NEW: Generated tasks
    ├── files.txt              # NEW: File list
    └── example.jpg            # NEW: Copied from source

Generated Label_full.json contains:

{
  "data": {
    "ocr": "http://localhost:8081/example.jpg"
  }
}

Image Path Flow:

  • Input path in Label.txt: data/example.jpg
  • Resolved path: data/example.jpg (relative to CWD)
  • Copied to: output/example.jpg
  • Relative to output: example.jpg
  • Final URL: http://localhost:8081/example.jpg
toPPOCR: Label Studio → PPOCRLabel

INPUT Resolution (Reading Label Studio JSON):

Command Execution Context:

  • You run: cd project && label-studio-converter toPPOCR data/
  • Current working directory (CWD): project/
  • Input parameter: data/ (directory to search for JSON files)
  • Converter finds: project/data/export.json (and other JSON files in subdirectories if --recursive)
  • Task file being processed: project/data/export.json

How Image Paths Are Read:

  1. What's in the JSON file:

    • Local path: "ocr": "/example.jpg" or "ocr": "example.jpg"
    • OR Remote URL: "ocr": "http://localhost:8081/example.jpg"
  2. How input resolver finds/downloads images:

    • Local path (/example.jpg or example.jpg):
      • Strip leading slashes: /example.jpgexample.jpg
      • Task directory: project/data/
      • Resolve: project/data/ + example.jpg = project/data/example.jpg
    • Remote URL (http://localhost:8081/example.jpg):
      • Extract filename: basename(URL) = example.jpg
      • Download to task directory: project/data/example.jpg

OUTPUT Resolution (Copying images with --copyImages --outDir):

With --imageBaseDir task-file (default):

When copying images to output directory, paths are maintained relative to the task file location:

  • Input directory: project/data/ (provided to command)
  • Source image: project/data/foo/bar/baz/example.jpg
  • Task file: project/data/export.json
  • Output dir: project/output/
  • Relative from task: relative(project/data/, project/data/foo/bar/baz/example.jpg) = foo/bar/baz/example.jpg
  • Destination: project/output/data/foo/bar/baz/example.jpg (maintains structure relative to task file)

With --imageBaseDir input-dir:

When copying images to output directory, paths are maintained relative to input directory:

  • Input directory: project/data/ (provided to command)
  • Source image: project/data/foo/bar/baz/example.jpg
  • Output dir: project/output/
  • Relative from input: relative(project/data/, project/data/foo/bar/baz/example.jpg) = foo/bar/baz/example.jpg
  • Destination: project/output/foo/bar/baz/example.jpg (maintains path from input directory)

How Resolvers Work:

  1. What the processor has:

    • Path relative to CWD: data/example.jpg
    • (From input resolution step)
  2. How output resolver formats paths:

    • Extract filename: basename(data/example.jpg) = example.jpg
    • Determine folder prefix:
      • No --baseImageDir: Use output directory basename
      • Output at: project/data/Label.txt → folder is data
      • Result: data/example.jpg
    • With --baseImageDir="images": Result would be images/example.jpg
  3. What goes in the output file:

    • PPOCRLabel Label.txt: data/example.jpg [{"transcription":"Text",...}]
    • Important: Path in Label.txt is a reference format, NOT the physical location
    • Physical images stay in task directory (data/), but Label.txt uses folder prefix

File Organization Examples:

Setup: Export Label.txt to same directory as task

project/
└── data/
    └── export.json            # Contains: "ocr": "http://localhost:8081/example.jpg"

Command:

cd project
label-studio-converter toPPOCR data/ \
  --baseImageDir data

Result:

project/
└── data/
    ├── export.json            # Original (unchanged)
    ├── Label.txt              # NEW: Generated PPOCR file
    └── example.jpg            # NEW: Downloaded from server

Generated Label.txt contains:

data/example.jpg	[{"transcription":"Text","points":[[...]],"dt_score":1}]

Image Path Flow:

  • Input URL in JSON: http://localhost:8081/example.jpg
  • Downloaded to: data/example.jpg (task file directory)
  • Resolved path: data/example.jpg (relative to CWD)
  • Extracted filename: example.jpg
  • baseImageDir: data
  • Output in Label.txt: data/example.jpg

Setup: Organize output in separate directory

project/
├── data/
│   └── export.json            # Contains: "ocr": "http://localhost:8081/example.jpg"
└── output/                    # Target output directory

Command:

cd project
label-studio-converter toPPOCR data/ \
  --outDir output

Result:

project/
├── data/
│   ├── export.json            # Original (unchanged)
│   └── example.jpg            # Downloaded, then copied to output
└── output/
    ├── Label.txt              # NEW: Generated PPOCR file
    └── example.jpg            # NEW: Copied from data/

Generated Label.txt contains:

output/example.jpg	[{"transcription":"Text","points":[[...]],"dt_score":1}]

Image Path Flow:

  • Input URL in JSON: http://localhost:8081/example.jpg
  • Downloaded to: data/example.jpg (task file directory)
  • Copied to: output/example.jpg (because --outDir specified)
  • Resolved path: data/example.jpg (relative to CWD)
  • Output dir: output/
  • Extracted filename: example.jpg
  • Output folder name: output
  • Output in Label.txt: output/example.jpg

Note: Images are automatically copied to output directory. Use --noCopyImages to skip copying.

enhance-labelstudio: Label Studio → Label Studio (Enhanced)

INPUT Resolution: Same as toPPOCR converter

  • Reads Label Studio JSON files
  • Resolves local paths relative to task file
  • Downloads remote URLs to task file directory

OUTPUT Resolution: Same as toLabelStudio converter

  • Generates Label Studio JSON with data.ocr URLs
  • Applies baseServerUrl formatting
  • Computes relative paths from output location to images
enhance-ppocr: PPOCRLabel → PPOCRLabel (Enhanced)

INPUT Resolution: Same as toLabelStudio converter

  • Reads PPOCRLabel Label.txt files
  • Resolves paths with folder pattern (folder/file.jpg)
  • Detects folder name and resolves from parent directory

OUTPUT Resolution: Same as toPPOCR converter

  • Generates PPOCRLabel Label.txt with folder/filename.jpg format
  • Uses baseImageDir or output directory basename as folder prefix
  • Extracts filename from resolved path, prepends folder name
label-studio-output-to-ppocr: Label Studio Output → PPOCRLabel

INPUT Resolution:

  • Reads Label Studio output JSON files
  • Strips removeBaseImageDir prefix from image paths (e.g., data/local-files/?d=example.jpgexample.jpg)

OUTPUT Resolution:

  • Generates PPOCRLabel Label.txt with folder/filename.jpg format
  • Generates fileState.txt if --generateFileState is specified

Key Concepts:

  1. Path Resolution Flow:

    • Input converters resolve paths to task-relative paths (relative to task file location)
    • Processor receives and operates on these task-relative paths
    • Output converters format these paths for the target system
  2. Remote Image Handling:

    • URLs (http:// or https://) are downloaded to task file directory
    • Only filename is extracted from URL (path structure ignored)
    • Example: http://server.com/deep/path/example.jpg → saved as task-dir/example.jpg
  3. Image Organization (toLabelStudio & toPPOCR):

    • No --outDir: Output files created in task directory, images stay in place
    • With --outDir: Output files go to outDir, images automatically copied to outDir (unless --noCopyImages)
    • --noCopyImages: Skip image copying, only create task files in outDir
    • enhance commands: Images always stay in original location
  4. Output Path Format:

    • toLabelStudio: ${baseServerUrl}/${relativePath} where relativePath is from output JSON to image
    • toPPOCR: ${folder}/${filename} where folder is baseImageDir or output directory name

Adaptive Resize Feature

For detailed algorithm documentation and tuning guide, see ADAPTIVE_RESIZE.md.

Quick Overview:

  • Purpose: Shrinks oversized boxes to fit actual text content (essential for Sino-Nom OCR with excessive padding)
  • Algorithm: Morphological operations + connected component analysis + percentile-based outlier removal
  • Usage: Enable with --adaptResize flag, tune with 7 parameters documented above

Detailed Command Help

toLabelStudio Command
label-studio-converter toLabelStudio --help

Output:

USAGE
  label-studio-converter toLabelStudio [--outDir value] [--fileName value] [--backup] [--recursive] [--filePattern value] [--copyImages] [--imageBaseDir value] [--sortVertical value] [--sortHorizontal value] [--normalizeShape value] [--useOrientedBox] [--widthIncrement value] [--heightIncrement value] [--adaptResize] [--adaptResizeThreshold value] [--adaptResizeMargin value] [--adaptResizeMinComponentSize value] [--adaptResizeMaxComponentSize value] [--adaptResizeOutlierPercentile value] [--adaptResizeMorphologySize value] [--adaptResizeMaxHorizontalExpansion value] [--adaptResizePaddingCheckWidth value] [--adaptResizeMinPaddingBrightness value] [--adaptResizeMinPaddingRatio value] [--adaptResizeUseAdaptiveThreshold] [--adaptResizeAdaptiveBlockSize value] [--precision value] [--numPointCheck value] [--defaultLabelName value] [--toFullJson] [--createFilePerImage] [--createFileListForServing] [--fileListName value] [--baseServerUrl value] [--outputMode value] <args>...
  label-studio-converter toLabelStudio --help

Convert PPOCRLabel files to Label Studio format

FLAGS
     [--outDir]                                                               Output directory. If not specified, files are saved in the same directory as the source files
     [--fileName]                                                             Custom output filename (without extension). If not specified, uses source filename with format suffix
     [--backup/--noBackup]                                                    Create backup of existing files before overwriting. Default: false
     [--recursive/--noRecursive]                                              Recursively search directories for files. Default: false
     [--filePattern]                                                          Regex pattern to match PPOCRLabel files (should match .txt files). Default: ".*\.txt$"
     [--copyImages/--noCopyImages]                                            Copy images to output directory when --outDir is specified. Only applies to toLabelStudio and toPPOCR commands. Default: true
     [--imageBaseDir]                                                         Base directory for resolving image paths. Options: "task-file" (relative to task file location), "input-dir" (relative to command execution directory). Default: "task-file"
     [--sortVertical]                                                         Sort bounding boxes vertically. Options: "none", "top-bottom", "bottom-top". Default: "none"
     [--sortHorizontal]                                                       Sort bounding boxes horizontally. Options: "none", "ltr", "rtl". Default: "none"
     [--normalizeShape]                                                       Normalize diamond-like shapes to axis-aligned rectangles. Options: "none", "rectangle". Default: "none"
     [--useOrientedBox/--noUseOrientedBox]                                    Use oriented (rotated) bounding box when normalizing shapes. Useful for skewed text. Default: false
     [--widthIncrement]                                                       Increase bounding box width by this amount (in pixels). Can be negative to decrease. Default: 0
     [--heightIncrement]                                                      Increase bounding box height by this amount (in pixels). Can be negative to decrease. Default: 0
     [--adaptResize/--noAdaptResize]                                          Apply adaptive resize to automatically adjust bounding boxes based on image content. Default: false
     [--adaptResizeThreshold]                                                 Grayscale threshold for adaptive resize (0-255). Default: 128
     [--adaptResizeMargin]                                                    Margin pixels around detected content for adaptive resize. Default: 5
     [--adaptResizeMinComponentSize]                                          Minimum component size in pixels (filters dirt/noise). Default: 10
     [--adaptResizeMaxComponentSize]                                          Maximum component size in pixels (filters large artifacts). Default: 100000
     [--adaptResizeOutlierPercentile]                                         Percentile for outlier removal (0-100). Default: 2
     [--adaptResizeMorphologySize]                                            Morphological operation kernel size. Default: 2
     [--adaptResizeMaxHorizontalExpansion]                                    Maximum horizontal expansion in pixels (prevents column overlap). Default: 50
     [--adaptResizePaddingCheckWidth]                                         Width of padding strip to validate (in pixels). Default: 3
     [--adaptResizeMinPaddingBrightness]                                      Minimum brightness for white padding pixels (0-255). Default: 200
     [--adaptResizeMinPaddingRatio]                                           Minimum ratio of white pixels in padding strip (0-1). Default: 0.85
     [--adaptResizeUseAdaptiveThreshold/--noAdaptResizeUseAdaptiveThreshold]  Use adaptive thresholding based on image histogram (recommended). Default: true
     [--adaptResizeAdaptiveBlockSize]                                         Block size for adaptive thresholding. Default: 50
     [--precision]                                                            Number of decimal places for coordinates. Use -1 for full precision (no rounding). Default: 0 (integers)
     [--numPointCheck]                                                        Expected number of points in bounding boxes
     [--defaultLabelName]                                                     Default label name for text annotations. Default: "Text"
     [--toFullJson/--noToFullJson]                                            Convert to Full OCR Label Studio format. Default: "true"
     [--createFilePerImage/--noCreateFilePerImage]                            Create a separate Label Studio JSON file for each image. Default: "false"
     [--createFileListForServing/--noCreateFileListForServing]                Create a file list for serving in Label Studio. Default: "true"
     [--fileListName]                                                         Name of the file list for serving. Default: "files.txt"
     [--baseServerUrl]                                                        Base server URL for constructing image URLs in the file list. Default: "http://localhost:8081"
     [--outputMode]                                                           Output mode: "annotations" for editable annotations (ground truth) or "predictions" for read-only predictions (pre-annotations). Default: "annotations"
  -h  --help                                                                  Print help information and exit

ARGUMENTS
  args...  Input directories containing PPOCRLabel files
toPPOCR Command
label-studio-converter toPPOCR --help

Output:

USAGE
  label-studio-converter toPPOCR [--outDir value] [--fileName value] [--backup] [--recursive] [--filePattern value] [--copyImages] [--imageBaseDir value] [--sortVertical value] [--sortHorizontal value] [--normalizeShape value] [--useOrientedBox] [--widthIncrement value] [--heightIncrement value] [--adaptResize] [--adaptResizeThreshold value] [--adaptResizeMargin value] [--adaptResizeMinComponentSize value] [--adaptResizeMaxComponentSize value] [--adaptResizeOutlierPercentile value] [--adaptResizeMorphologySize value] [--adaptResizeMaxHorizontalExpansion value] [--adaptResizePaddingCheckWidth value] [--adaptResizeMinPaddingBrightness value] [--adaptResizeMinPaddingRatio value] [--adaptResizeUseAdaptiveThreshold] [--adaptResizeAdaptiveBlockSize value] [--precision value] [--numPointCheck value] [--baseImageDir value] [--generateFileState] <args>...
  label-studio-converter toPPOCR --help

Convert Label Studio files to PPOCRLabel format

FLAGS
     [--outDir]                                                               Output directory. If not specified, files are saved in the same directory as the source files
     [--fileName]                                                             Output PPOCR file name. Default: "Label.txt"
     [--backup/--noBackup]                                                    Create backup of existing files before overwriting. Default: false
     [--recursive/--noRecursive]                                              Recursively search directories for files. Default: false
     [--filePattern]                                                          Regex pattern to match Label Studio files (should match .json files). Default: ".*\.json$"
     [--copyImages/--noCopyImages]                                            Copy images to output directory when --outDir is specified. Only applies to toLabelStudio and toPPOCR commands. Default: true
     [--imageBaseDir]                                                         Base directory for resolving image paths. Options: "task-file" (relative to task file location), "input-dir" (relative to command execution directory). Default: "task-file"
     [--sortVertical]                                                         Sort bounding boxes vertically. Options: "none", "top-bottom", "bottom-top". Default: "none"
     [--sortHorizontal]                                                       Sort bounding boxes horizontally. Options: "none", "ltr", "rtl". Default: "none"
     [--normalizeShape]                                                       Normalize diamond-like shapes to axis-aligned rectangles. Options: "none", "rectangle". Default: "none"
     [--useOrientedBox/--noUseOrientedBox]                                    Use oriented (rotated) bounding box when normalizing shapes. Useful for skewed text. Default: false
     [--widthIncrement]                                                       Increase bounding box width by this amount (in pixels). Can be negative to decrease. Default: 0
     [--heightIncrement]                                                      Increase bounding box height by this amount (in pixels). Can be negative to decrease. Default: 0
     [--adaptResize/--noAdaptResize]                                          Apply adaptive resize to automatically adjust bounding boxes based on image content. Default: false
     [--adaptResizeThreshold]                                                 Grayscale threshold for adaptive resize (0-255). Default: 128
     [--adaptResizeMargin]                                                    Margin pixels around detected content for adaptive resize. Default: 5
     [--adaptResizeMinComponentSize]                                          Minimum component size in pixels (filters dirt/noise). Default: 10
     [--adaptResizeMaxComponentSize]                                          Maximum component size in pixels (filters large artifacts). Default: 100000
     [--adaptResizeOutlierPercentile]                                         Percentile for outlier removal (0-100). Default: 2
     [--adaptResizeMorphologySize]                                            Morphological operation kernel size. Default: 2
     [--adaptResizeMaxHorizontalExpansion]                                    Maximum horizontal expansion in pixels (prevents column overlap). Default: 50
     [--adaptResizePaddingCheckWidth]                                         Width of padding strip to validate (in pixels). Default: 3
     [--adaptResizeMinPaddingBrightness]                                      Minimum brightness for white padding pixels (0-255). Default: 200
     [--adaptResizeMinPaddingRatio]                                           Minimum ratio of white pixels in padding strip (0-1). Default: 0.85
     [--adaptResizeUseAdaptiveThreshold/--noAdaptResizeUseAdaptiveThreshold]  Use adaptive thresholding based on image histogram (recommended). Default: true
     [--adaptResizeAdaptiveBlockSize]                                         Block size for adaptive thresholding. Default: 50
     [--precision]                                                            Number of decimal places for coordinates. Use -1 for full precision (no rounding). Default: 0 (integers)
     [--numPointCheck]                                                        Expected number of points in bounding boxes
     [--baseImageDir]                                                         Base directory path to prepend to image filenames in output (e.g., "ch" or "images/ch")
     [--generateFileState/--noGenerateFileState]                              Generate a file state file for each input directory
  -h  --help                                                                  Print help information and exit

ARGUMENTS
  args...  Input directories containing Label Studio files
enhance-labelstudio Command
label-studio-converter enhance-labelstudio --help

Output:

USAGE
  label-studio-converter enhance-labelstudio [--outDir value] [--fileName value] [--backup] [--recursive] [--filePattern value] [--copyImages] [--imageBaseDir value] [--sortVertical value] [--sortHorizontal value] [--normalizeShape value] [--useOrientedBox] [--widthIncrement value] [--heightIncrement value] [--adaptResize] [--adaptResizeThreshold value] [--adaptResizeMargin value] [--adaptResizeMinComponentSize value] [--adaptResizeMaxComponentSize value] [--adaptResizeOutlierPercentile value] [--adaptResizeMorphologySize value] [--adaptResizeMaxHorizontalExpansion value] [--adaptResizePaddingCheckWidth value] [--adaptResizeMinPaddingBrightness value] [--adaptResizeMinPaddingRatio value] [--adaptResizeUseAdaptiveThreshold] [--adaptResizeAdaptiveBlockSize value] [--precision value] [--numPointCheck value] [--outputMode value] <args>...
  label-studio-converter enhance-labelstudio --help

Enhance Label Studio files with sorting, normalization, and resizing

FLAGS
     [--outDir]                                                               Output directory. If not specified, files are saved in the same directory as the source files
     [--fileName]                                                             Custom output filename. If not specified, uses the same name as the source file
     [--backup/--noBackup]                                                    Create backup of existing files before overwriting. Default: false
     [--recursive/--noRecursive]                                              Recursively search directories for files. Default: false
     [--filePattern]                                                          Regex pattern to match Label Studio files (should match .json files). Default: ".*\.json$"
     [--copyImages/--noCopyImages]                                            Copy images to output directory when --outDir is specified. Only applies to toLabelStudio and toPPOCR commands. Default: true
     [--imageBaseDir]                                                         Base directory for resolving image paths. Options: "task-file" (relative to task file location), "input-dir" (relative to command execution directory). Default: "task-file"
     [--sortVertical]                                                         Sort bounding boxes vertically. Options: "none", "top-bottom", "bottom-top". Default: "none"
     [--sortHorizontal]                                                       Sort bounding boxes horizontally. Options: "none", "ltr", "rtl". Default: "none"
     [--normalizeShape]                                                       Normalize diamond-like shapes to axis-aligned rectangles. Options: "none", "rectangle". Default: "none"
     [--useOrientedBox/--noUseOrientedBox]                                    Use oriented (rotated) bounding box when normalizing shapes. Useful for skewed text. Default: false
     [--widthIncrement]                                                       Increase bounding box width by this amount (in pixels). Can be negative to decrease. Default: 0
     [--heightIncrement]                                                      Increase bounding box height by this amount (in pixels). Can be negative to decrease. Default: 0
     [--adaptResize/--noAdaptResize]                                          Apply adaptive resize to automatically adjust bounding boxes based on image content. Default: false
     [--adaptResizeThreshold]                                                 Grayscale threshold for adaptive resize (0-255). Default: 128
     [--adaptResizeMargin]                                                    Margin pixels around detected content for adaptive resize. Default: 5
     [--adaptResizeMinComponentSize]                                          Minimum component size in pixels (filters dirt/noise). Default: 10
     [--adaptResizeMaxComponentSize]                                          Maximum component size in pixels (filters large artifacts). Default: 100000
     [--adaptResizeOutlierPercentile]                                         Percentile for outlier removal (0-100). Default: 2
     [--adaptResizeMorphologySize]                                            Morphological operation kernel size. Default: 2
     [--adaptResizeMaxHorizontalExpansion]                                    Maximum horizontal expansion in pixels (prevents column overlap). Default: 50
     [--adaptResizePaddingCheckWidth]                                         Width of padding strip to validate (in pixels). Default: 3
     [--adaptResizeMinPaddingBrightness]                                      Minimum brightness for white padding pixels (0-255). Default: 200
     [--adaptResizeMinPaddingRatio]                                           Minimum ratio of white pixels in padding strip (0-1). Default: 0.85
     [--adaptResizeUseAdaptiveThreshold/--noAdaptResizeUseAdaptiveThreshold]  Use adaptive thresholding based on image histogram (recommended). Default: true
     [--adaptResizeAdaptiveBlockSize]                                         Block size for adaptive thresholding. Default: 50
     [--precision]                                                            Number of decimal places for coordinates. Use -1 for full precision (no rounding). Default: 0 (integers)
     [--numPointCheck]                                                        Expected number of points in bounding boxes
     [--outputMode]                                                           Output mode: "annotations" for editable annotations (ground truth) or "predictions" for read-only predictions (pre-annotations). Default: "annotations"
  -h  --help                                                                  Print help information and exit

ARGUMENTS
  args...  Input directories containing Label Studio JSON files
enhance-ppocr Command
label-studio-converter enhance-ppocr --help

Output:

USAGE
  label-studio-converter enhance-ppocr [--outDir value] [--fileName value] [--backup] [--recursive] [--filePattern value] [--copyImages] [--imageBaseDir value] [--sortVertical value] [--sortHorizontal value] [--normalizeShape value] [--useOrientedBox] [--widthIncrement value] [--heightIncrement value] [--adaptResize] [--adaptResizeThreshold value] [--adaptResizeMargin value] [--adaptResizeMinComponentSize value] [--adaptResizeMaxComponentSize value] [--adaptResizeOutlierPercentile value] [--adaptResizeMorphologySize value] [--adaptResizeMaxHorizontalExpansion value] [--adaptResizePaddingCheckWidth value] [--adaptResizeMinPaddingBrightness value] [--adaptResizeMinPaddingRatio value] [--adaptResizeUseAdaptiveThreshold] [--adaptResizeAdaptiveBlockSize value] [--precision value] [--numPointCheck value] <args>...
  label-studio-converter enhance-ppocr --help

Enhance PPOCRLabel files with sorting, normalization, and resizing

FLAGS
     [--outDir]                                                               Output directory. If not specified, files are saved in the same directory as the source files
     [--fileName]                                                             Custom output filename. If not specified, uses the same name as the source file
     [--backup/--noBackup]                                                    Create backup of existing files before overwriting. Default: false
     [--recursive/--noRecursive]                                              Recursively search directories for files. Default: false
     [--filePattern]                                                          Regex pattern to match PPOCRLabel files (should match .txt files). Default: ".*\.txt$"
     [--copyImages/--noCopyImages]                                            Copy images to output directory when --outDir is specified. Only applies to toLabelStudio and toPPOCR commands. Default: true
     [--imageBaseDir]                                                         Base directory for resolving image paths. Options: "task-file" (relative to task file location), "input-dir" (relative to command execution directory). Default: "task-file"
     [--sortVertical]                                                         Sort bounding boxes vertically. Options: "none", "top-bottom", "bottom-top". Default: "none"
     [--sortHorizontal]                                                       Sort bounding boxes horizontally. Options: "none", "ltr", "rtl". Default: "none"
     [--normalizeShape]                                                       Normalize diamond-like shapes to axis-aligned rectangles. Options: "none", "rectangle". Default: "none"
     [--useOrientedBox/--noUseOrientedBox]                                    Use oriented (rotated) bounding box when normalizing shapes. Useful for skewed text. Default: false
     [--widthIncrement]                                                       Increase bounding box width by this amount (in pixels). Can be negative to decrease. Default: 0
     [--heightIncrement]                                                      Increase bounding box height by this amount (in pixels). Can be negative to decrease. Default: 0
     [--adaptResize/--noAdaptResize]                                          Apply adaptive resize to automatically adjust bounding boxes based on image content. Default: false
     [--adaptResizeThreshold]                                                 Grayscale threshold for adaptive resize (0-255). Default: 128
     [--adaptResizeMargin]                                                    Margin pixels around detected content for adaptive resize. Default: 5
     [--adaptResizeMinComponentSize]                                          Minimum component size in pixels (filters dirt/noise). Default: 10
     [--adaptResizeMaxComponentSize]                                          Maximum component size in pixels (filters large artifacts). Default: 100000
     [--adaptResizeOutlierPercentile]                                         Percentile for outlier removal (0-100). Default: 2
     [--adaptResizeMorphologySize]                                            Morphological operation kernel size. Default: 2
     [--adaptResizeMaxHorizontalExpansion]                                    Maximum horizontal expansion in pixels (prevents column overlap). Default: 50
     [--adaptResizePaddingCheckWidth]                                         Width of padding strip to validate (in pixels). Default: 3
     [--adaptResizeMinPaddingBrightness]                                      Minimum brightness for white padding pixels (0-255). Default: 200
     [--adaptResizeMinPaddingRatio]                                           Minimum ratio of white pixels in padding strip (0-1). Default: 0.85
     [--adaptResizeUseAdaptiveThreshold/--noAdaptResizeUseAdaptiveThreshold]  Use adaptive thresholding based on image histogram (recommended). Default: true
     [--adaptResizeAdaptiveBlockSize]                                         Block size for adaptive thresholding. Default: 50
     [--precision]                                                            Number of decimal places for coordinates. Use -1 for full precision (no rounding). Default: 0 (integers)
     [--numPointCheck]                                                        Expected number of points in bounding boxes
  -h  --help                                                                  Print help information and exit

ARGUMENTS
  args...  Input directories containing PPOCRLabel files
label-studio-output-to-ppocr Command
label-studio-converter label-studio-output-to-ppocr --help

Output:

USAGE
  label-studio-converter label-studio-output-to-ppocr [--recursive] [--backup] [--filePattern value] [--numPointCheck value] (--outDir value) [--fileName value] [--removeBaseImageDir value] [--generateFileState] <args>...
  label-studio-converter label-studio-output-to-ppocr --help

Convert Label Studio output files to PPOCRLabel format

FLAGS
     [--recursive/--noRecursive]                  Recursively search directories for files. Default: false
     [--backup/--noBackup]                        Create backup of existing files before overwriting. Default: false
     [--filePattern]                              Regex pattern to match input files
     [--numPointCheck]                            Expected number of points in bounding boxes
      --outDir                                    Output directory.
     [--fileName]                                 Output PPOCR file name. Default: "Label.txt"
     [--removeBaseImageDir]                       Remove base image directory from image paths in output. Default: "/data/local-files/?d="
     [--generateFileState/--noGenerateFileState]  Generate a file state file for each input directory
  -h  --help                                      Print help information and exit

ARGUMENTS
  args...  Input directories containing Label Studio files

Examples

Basic Conversion
# PPOCRLabel → Label Studio
label-studio-converter toLabelStudio ./input-ppocr --outDir ./output

# Label Studio → PPOCRLabel
label-studio-converter toPPOCR ./input-label-studio --outDir ./output --baseImageDir images/ch

# File-per-image + custom server URL
label-studio-converter toLabelStudio ./input-ppocr \
  --outDir ./output \
  --createFilePerImage \
  --baseServerUrl http://192.168.1.100:8080

# Predictions format (read-only pre-annotations)
label-studio-converter toLabelStudio ./input-ppocr --outputMode predictions
Enhancement Pipeline
# Sort + normalize + resize
label-studio-converter enhance-ppocr ./data \
  --sortVertical top-bottom \
  --sortHorizontal ltr \
  --normalizeShape rectangle \
  --widthIncrement 5 \
  --heightIncrement 5

# Adaptive resize for Sino-Nom OCR (shrinks oversized boxes)
label-studio-converter enhance-ppocr ./sinonom-data \
  --adaptResize \
  --adaptResizeThreshold 128 \
  --adaptResizeMargin 8 \
  --adaptResizeMaxHorizontalExpansion 50 \
  --sortHorizontal rtl

# Convert with full enhancement pipeline
label-studio-converter toLabelStudio ./input-ppocr \
  --outDir ./output \
  --normalizeShape rectangle \
  --adaptResize \
  --sortVertical top-bottom
File Organization
# Recursive search with pattern matching
label-studio-converter toLabelStudio ./dataset \
  --recursive \
  --filePattern "train_.*\.txt$"

# Custom output filenames
label-studio-converter toPPOCR ./data \
  --outDir ./output \
  --fileName MyLabels.txt

# Using imageBaseDir for flexible path resolution
# Default: resolve from task file location
label-studio-converter toLabelStudio ./annotations/

# Copy images maintaining full directory structure from execution directory
label-studio-converter toLabelStudio ./annotations/ \
  --copyImages \
  --imageBaseDir input-dir \
  --outDir ./output
Shape Normalization

Diamond/rotated shapes → axis-aligned rectangles:

label-studio-converter enhance-ppocr ./data \
  --normalizeShape rectangle \
  --outDir ./normalized

Before: Diamond-like shapes

Before normalization

After: Axis-aligned rectangles

After normalization

Vertical text example:

Before (vertical) After (vertical)

[!NOTE] Key Behaviors:

  • Remote images (http://, https://) are automatically downloaded
  • Path resolution: ${baseServerUrl}/${relativeToOutDir}/image.jpg
  • All PPOCRLabel positions treated as polygons in Label Studio
  • Missing images use fallback dimensions (1920×1080) and log warning
./dist/cli.js toPPOCR ./tmp --baseImageDir output --normalizeShape rectangle

After normalization (vert)

Using generated files with Label Studio

Interface setup

When creating a new labeling project in Label Studio, choose the "OCR" template. This will set up the appropriate interface for text recognition tasks.

This project uses the following Label Studio interface configuration:

<View>
	<Image name="image" value="$ocr" zoom="false" rotateControl="true" zoomControl="false"/>
	<Labels name="label" toName="image">
		<Label value="Text" background="green"/>
		<Label value="Handwriting" background="blue"/>
	</Labels>
	<Rectangle name="bbox" toName="image" strokeWidth="3"/>
	<Polygon name="poly" toName="image" strokeWidth="3"/>
	<TextArea name="transcription" toName="image" editable="true" perRegion="true" required="false" maxSubmissions="1" rows="5" placeholder="Recognized Text" displayMode="region-list"/>
</View>

This setup includes:

  • An Image tag to display the image to be annotated.
  • A Labels tag with two label options: Text and `Handwri