Ultralytics YOLO27: Iscriviti alla lista d'attesa.
Inizia

Dataset OBB per il testo in scena

Il dataset Scene Text OBB combina COCO-Text e HierText in un dataset a classe singola per il rilevamento di parole e l'addestramento con riquadri di delimitazione orientati (OBB). Contiene immagini di scene naturali e documenti con testo ruotato, curvo, disposto in modo fitto, scritto a mano e stampato.

Funzionalità principali#

  • 65.325 immagini e 1.288.991 annotazioni di parole leggibili dopo la conversione.
  • Una classe text con etichette poligonali normalizzate compatibili con i modelli Ultralytics YOLO OBB.
  • COCO-Text contribuisce con scene naturali varie; HierText con testo fitto proveniente da scene naturali e documenti.
  • Download automatico delle fonti, conversione delle annotazioni e collegamento delle immagini multipiattaforma tramite il file YAML del dataset.
  • I poligoni sorgente con più di quattro punti vengono mantenuti e ridotti a rettangoli di area minima dalla pipeline dati OBB.

Struttura del dataset#

Il dataset convertito presenta le seguenti suddivisioni. I conteggi includono solo le parole leggibili con un'area del contorno di almeno un pixel; le immagini prive dei relativi file sorgente sono escluse.

SubsetImmagini / parole COCO-TextImmagini / parole HierTextImmagini / parole combinate
Addestra43,686 / 65,9198,281 / 862,57751,967 / 928,496
Convalida4,927 / 7,2111,724 / 178,3826,651 / 185,593
Test5,073 / 7,7141,634 / 167,1886,707 / 174,902
Totale53,686 / 80,84411,639 / 1,208,14765,325 / 1,288,991

COCO-Text usa la suddivisione ufficiale di addestramento. Le immagini ufficiali di convalida vengono suddivise in modo deterministico, in sottoinsiemi di convalida e test approssimativamente bilanciati, usando l'ID dell'immagine. HierText mantiene le suddivisioni ufficiali di addestramento, convalida e test, rinominando validation in val.

Le immagini senza parole mantenute restano nel dataset con file di etichette vuoti e vengono usate come immagini di sfondo. Le directory convertite seguono questa struttura:

datasets/
└── scene-text-yolo/
    ├── coco-text/
    │   ├── train/
    │   │   ├── images/
    │   │   └── labels/
    │   ├── val/
    │   └── test/
    └── hiertext/
        ├── train/
        ├── val/
        └── test/

Ogni riga di etichetta contiene la classe 0 seguita dalle coordinate poligonali normalizzate. Le immagini vengono collegate tramite hard link quando il file system lo supporta e altrimenti copiate.

YAML del dataset#

La configurazione scene-text-obb.yaml fa riferimento a entrambi i dataset convertiti. Al primo utilizzo, scarica le immagini COCO 2017, le annotazioni COCO-Text, le annotazioni HierText e le immagini HierText prima di convertirle.

scene-text-obb.yaml
# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license

# Scene Text OBB dataset combining COCO-Text and HierText legible word annotations
# COCO-Text: https://bgshih.github.io/cocotext/ (annotations: CC BY 4.0; COCO image terms apply)
# HierText: https://github.com/google-research-datasets/hiertext (CC BY-SA 4.0; Open Images terms apply)
# Documentation: https://docs.ultralytics.com/datasets/obb/scene-text
# Example usage: yolo obb train data=scene-text-obb.yaml model=yolo26n-obb.pt imgsz=640
# parent
# ├── ultralytics
# └── datasets
#     ├── coco
#     ├── coco-text
#     ├── hiertext
#     └── scene-text-yolo

# Train/val/test sets as 1) dir: path/to/imgs, 2) file: path/to/imgs.txt, or 3) list: [path/to/imgs1, path/to/imgs2, ..]
path: scene-text-yolo # dataset root dir
train:
  - coco-text/train/images # 43686 images, 65919 words
  - hiertext/train/images # 8281 images, 862577 words
val:
  - coco-text/val/images # 4927 images, 7211 words
  - hiertext/val/images # 1724 images, 178382 words
test:
  - coco-text/test/images # 5073 images, 7714 words
  - hiertext/test/images # 1634 images, 167188 words

names:
  0: text

# Download COCO 2017 images and both annotation sources, then convert legible words to YOLO OBB format (~24 GB)
download: |
  import gzip
  import hashlib
  import json
  import os
  import shutil
  from pathlib import Path
  from tempfile import TemporaryDirectory

  import cv2
  import numpy as np

  from ultralytics.data.utils import check_det_dataset
  from ultralytics.utils import TQDM
  from ultralytics.utils.downloads import download

  def polygon_label(vertices, width, height):
      polygon = np.asarray(vertices, dtype=np.float32).reshape(-1, 2)
      if len(polygon) < 3 or cv2.contourArea(polygon) < 1:
          return ""
      polygon[:, 0] = polygon[:, 0].clip(0, width - 1)
      polygon[:, 1] = polygon[:, 1].clip(0, height - 1)
      polygon /= np.array([width, height], dtype=np.float32)
      return "0 " + " ".join(f"{x:.7f} {y:.7f}" for x, y in polygon)

  def link_image(source, destination):
      destination.parent.mkdir(parents=True, exist_ok=True)
      try:
          os.link(source, destination)
      except OSError:
          shutil.copy2(source, destination)

  def write_labels(label_dir, stem, labels):
      label_dir.mkdir(parents=True, exist_ok=True)
      (label_dir / f"{stem}.txt").write_text("\n".join(labels) + ("\n" if labels else ""), encoding="utf-8")

  def convert_coco_text(parent, destination):
      source_dir = parent / "coco-text"
      annotations = source_dir / "cocotext.v2.json"
      if not annotations.is_file():
          download(
              "https://github.com/bgshih/cocotext/releases/download/dl/cocotext.v2.zip",
              dir=source_dir,
              delete=True,
          )
      coco = check_det_dataset("coco.yaml")
      images = Path(coco["path"]) / "images"
      data = json.loads(annotations.read_text(encoding="utf-8"))
      for image_id, image in TQDM(data["imgs"].items(), desc="Converting COCO-Text"):
          split = (
              "train"
              if image["set"] == "train"
              else ("val" if hashlib.sha256(str(image["id"]).encode()).digest()[0] < 128 else "test")
          )
          filename = image["file_name"].replace("COCO_train2014_", "", 1)
          source = images / "train2017" / filename
          if not source.exists():
              source = images / "val2017" / filename
          if not source.exists():
              continue
          image_dir = destination / split / "images"
          link_image(source, image_dir / filename)
          im = cv2.imread(str(source))
          if im is None:
              raise ValueError(f"Unreadable image: {source}")
          height, width = im.shape[:2]
          labels = []
          for ann_id in data["imgToAnns"].get(image_id, []):
              ann = data["anns"][str(ann_id)]
              if ann["legibility"] == "legible" and (label := polygon_label(ann["mask"], width, height)):
                  labels.append(label)
          write_labels(destination / split / "labels", Path(filename).stem, labels)

  def convert_hiertext(parent, destination):
      source = parent / "hiertext" / "source"
      splits = {"train": "train", "validation": "val", "test": "test"}
      base = "https://raw.githubusercontent.com/google-research-datasets/hiertext/main"
      if not all((source / "gt" / f"{split}.jsonl.gz").is_file() for split in splits):
          download([f"{base}/gt/{split}.jsonl.gz" for split in splits], dir=source / "gt", unzip=False, threads=3)
      if not all((source / split).is_dir() for split in splits):
          download(
              [f"https://open-images-dataset.s3.amazonaws.com/ocr/{split}.tgz" for split in splits],
              dir=source,
              delete=True,
              threads=3,
          )
      for source_split, split in splits.items():
          with gzip.open(source / "gt" / f"{source_split}.jsonl.gz", "rt", encoding="utf-8") as f:
              rows = json.load(f)["annotations"]
          for row in TQDM(rows, desc=f"Converting HierText {source_split}"):
              image_id = row["image_id"]
              source_image = source / source_split / f"{image_id}.jpg"
              if not source_image.exists():
                  continue
              image = destination / split / "images" / f"{image_id}.jpg"
              link_image(source_image, image)
              im = cv2.imread(str(image))
              if im is None:
                  raise ValueError(f"Unreadable image: {source_image}")
              height, width = im.shape[:2]
              labels = []
              for paragraph in row["paragraphs"]:
                  for line in paragraph["lines"]:
                      for word in line["words"]:
                          if word["legible"] and (label := polygon_label(word["vertices"], width, height)):
                              labels.append(label)
              write_labels(destination / split / "labels", image_id, labels)

  final = Path(yaml["path"])
  parent = final.parent
  parent.mkdir(parents=True, exist_ok=True)
  with TemporaryDirectory(dir=parent, prefix=".scene-text-") as tmp:
      destination = Path(tmp)
      convert_coco_text(parent, destination / "coco-text")
      convert_hiertext(parent, destination / "hiertext")
      destination.rename(final)
Dimensioni del download e licenze

Le fonti richiedono circa 24 GB di download. Durante il download e l'estrazione iniziali, assicurati di avere almeno 50 GB di spazio libero, compresi gli archivi COCO temporanei. Se gli hard link non sono disponibili, le immagini copiate richiedono spazio aggiuntivo. Prima di usare o ridistribuire i dati convertiti, consulta i termini di licenza.

Utilizzo#

Addestra un modello YOLO26 OBB con immagini di dimensione 640 pixel usando i seguenti comandi. I file sorgente COCO e HierText già presenti in datasets_dir di Ultralytics vengono riutilizzati.

Esempio di addestramento
from ultralytics import YOLO

model = YOLO("yolo26n-obb.pt")
results = model.train(data="scene-text-obb.yaml", epochs=100, imgsz=640)

Applicazioni#

Usa questo dataset per addestrare rilevatori di testo a livello di parola destinati all'elaborazione di documenti, alla comprensione di ricevute, alla traduzione di cartelli, all'ispezione industriale e alle pipeline OCR. Il rilevamento è solo una fase dell'OCR: se ti serve la trascrizione, abbina il rilevatore a un riconoscitore di testo.

Licenze#

Il dataset combinato è soggetto a termini specifici per ciascuna fonte, non a un'unica licenza incondizionata:

  • Annotazioni COCO-Text: CC BY 4.0. Restano applicabili i termini relativi alle immagini COCO.
  • Annotazioni HierText: CC BY-SA 4.0. Le versioni adattate ridistribuite richiedono l'attribuzione, un avviso delle modifiche e una licenza uguale o compatibile.
  • Immagini HierText: provengono da Open Images. I termini di Open Images indicano che le immagini sono rilasciate con licenza CC BY 2.0 e invitano gli utenti a verificare le licenze delle singole immagini.

Queste licenze delle annotazioni consentono l'uso commerciale nel rispetto delle relative condizioni, ma il dataset non è di pubblico dominio. Mantieni l'attribuzione alle fonti e verifica i termini applicabili alle immagini quando ridistribuisci i dati.

Citazioni e ringraziamenti#

Se usi questo dataset nel tuo lavoro, cita entrambi i dataset di origine:

Citazione
@article{veit2016cocotext,
  title={COCO-Text: Dataset and Benchmark for Text Detection and Recognition in Natural Images},
  author={Veit, Andreas and Matera, Tomas and Neumann, Lukas and Matas, Jiri and Belongie, Serge},
  journal={arXiv preprint arXiv:1601.07140},
  year={2016}
}

@inproceedings{long2022towards,
  title={Towards End-to-End Unified Scene Text Detection and Layout Analysis},
  author={Long, Shangbang and Qin, Siyang and Panteleev, Dmitry and Bissacco, Alessandro and Fujii, Yasuhisa and Raptis, Michalis},
  booktitle={Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition},
  year={2022}
}

Ringraziamo i team di COCO-Text e HierText per aver creato e mantenuto questi dataset.

Domande frequenti#

  • No. La conversione genera poligoni di rilevamento delle parole a classe singola per l'addestramento OBB. Se la tua pipeline richiede anche le trascrizioni, usa le annotazioni originali di COCO-Text e HierText.

  • COCO-Text fornisce annotazioni di addestramento e convalida. Questa configurazione mantiene la suddivisione ufficiale di addestramento e divide in modo deterministico le immagini ufficiali di convalida in sottoinsiemi di convalida e test. HierText mantiene le sue suddivisioni ufficiali.

  • Sì. Inseriscilo in datasets_dir di Ultralytics, rispettando la struttura standard coco/ e includendo images/train2017, images/val2017 e i file di testo delle suddivisioni COCO. Lo script di download lo riutilizza senza scaricare nuovamente COCO.

Collaboratori

Commenti

Fai una domanda, condividi i tuoi risultati o aiuta qualcun altro.