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
textcon 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.
| Subset | Immagini / parole COCO-Text | Immagini / parole HierText | Immagini / parole combinate |
|---|---|---|---|
| Addestra | 43,686 / 65,919 | 8,281 / 862,577 | 51,967 / 928,496 |
| Convalida | 4,927 / 7,211 | 1,724 / 178,382 | 6,651 / 185,593 |
| Test | 5,073 / 7,714 | 1,634 / 167,188 | 6,707 / 174,902 |
| Totale | 53,686 / 80,844 | 11,639 / 1,208,147 | 65,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.
# 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)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.
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:
@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_dirdi Ultralytics, rispettando la struttura standardcoco/e includendoimages/train2017,images/val2017e i file di testo delle suddivisioni COCO. Lo script di download lo riutilizza senza scaricare nuovamente COCO.
Commenti
Fai una domanda, condividi i tuoi risultati o aiuta qualcun altro.