Ultralytics YOLO27: انضم إلى قائمة الانتظار.
ابدأ

مجموعة بيانات OBB لنصوص المشاهد

تجمع مجموعة بيانات OBB لنصوص المشاهد بين COCO-Text وHierText في مجموعة بيانات أحادية الفئة لاكتشاف الكلمات، مخصصة لتدريب الصناديق المحيطة الموجّهة (OBB). وتضم صورًا للمشاهد الطبيعية والمستندات، تحتوي على نصوص مدوّرة ومنحنية ومتراصة بكثافة ومكتوبة بخط اليد ومطبوعة.

الميزات الرئيسية#

  • 65,325 صورة و1,288,991 تعليقًا توضيحيًا لكلمات مقروءة بعد التحويل.
  • فئة واحدة text مع تسميات مضلعات مطبّعة، متوافقة مع نماذج Ultralytics YOLO OBB.
  • تُسهم COCO-Text بمشاهد طبيعية متنوعة، بينما تُسهم HierText بنصوص كثيفة من مشاهد طبيعية ومستندات.
  • تنزيل تلقائي للمصادر، وتحويل التعليقات التوضيحية، وربط الصور عبر الأنظمة الأساسية من خلال ملف YAML لمجموعة البيانات.
  • تُحفَظ مضلعات المصدر التي يزيد عدد نقاطها على أربع، ويحوّلها مسار بيانات OBB إلى مستطيلات ذات الحد الأدنى للمساحة.

بنية مجموعة البيانات#

تتضمن مجموعة البيانات المحوّلة التقسيمات التالية. تشمل الأعداد الكلمات المقروءة ذات مساحة محيطية لا تقل عن بكسل واحد فقط؛ وتُستبعد الصور التي لا تتوفر ملفات المصدر الخاصة بها.

المجموعة الفرعيةصور COCO-Text / الكلماتصور HierText / الكلماتالصور المجمعة / الكلمات
التدريب43,686 / 65,9198,281 / 862,57751,967 / 928,496
التحقق4,927 / 7,2111,724 / 178,3826,651 / 185,593
الاختبار5,073 / 7,7141,634 / 167,1886,707 / 174,902
الإجمالي53,686 / 80,84411,639 / 1,208,14765,325 / 1,288,991

تستخدم COCO-Text مجموعة التدريب الرسمية. وتُقسّم صور التحقق الرسمية فيها حتميًا إلى مجموعتين فرعيتين متوازنتين تقريبًا للتحقق والاختبار، بالاستناد إلى معرّف الصورة. وتحتفظ HierText بتقسيمات التدريب والتحقق والاختبار الرسمية، مع تغيير اسم validation إلى val.

تبقى الصور التي لا تحتوي على كلمات محتفظ بها ضمن مجموعة البيانات، مع ملفات تسميات فارغة، وتُستخدم كصور خلفية. وتتبع المجلدات المحوّلة هذا الهيكل:

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

يحتوي كل صف تسمية على الفئة 0 متبوعة بإحداثيات مضلع مطبّعة. وتُنشأ روابط صلبة للصور إذا كان نظام الملفات يدعمها، وإلا فتُنسخ الصور.

ملف YAML لمجموعة البيانات#

يشير الإعداد scene-text-obb.yaml إلى مجموعتي البيانات المحوّلتين. عند الاستخدام لأول مرة، ينزّل صور COCO 2017 وتعليقات COCO-Text التوضيحية وتعليقات HierText التوضيحية وصور HierText، ثم يحوّلها.

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)
حجم التنزيل والترخيص

تتطلب المصادر تنزيل نحو 24 GB. خصّص مساحة تخزين حرة لا تقل عن 50 GB أثناء التنزيل والاستخراج الأوليين، بما في ذلك أرشيفات COCO المؤقتة. إذا لم تتوفر الروابط الصلبة، فستحتاج الصور المنسوخة إلى مساحة تخزين إضافية. راجع شروط الترخيص قبل استخدام البيانات المحوّلة أو إعادة توزيعها.

الاستخدام#

درّب نموذج YOLO26 OBB بحجم صورة يبلغ 640 بكسل باستخدام الأوامر التالية. ستُعاد الاستفادة من ملفات المصدر الحالية لـ COCO وHierText الموجودة ضمن datasets_dir في Ultralytics.

مثال على التدريب
from ultralytics import YOLO

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

التطبيقات#

استخدم مجموعة البيانات هذه لتدريب كواشف نصوص على مستوى الكلمات لمعالجة المستندات، وفهم الإيصالات، وترجمة اللافتات، والفحص الصناعي، ومسارات عمل OCR. لا يمثل الكشف سوى مرحلة واحدة من OCR؛ لذا أقرن الكاشف بمتعرّف نصوص عند الحاجة إلى تحويل النصوص إلى كتابة.

الترخيص#

تخضع مجموعة البيانات المجمعة لشروط خاصة بكل مصدر، لا لترخيص واحد غير مشروط:

  • تعليقات COCO-Text التوضيحية: CC BY 4.0. وتظل شروط صور COCO الأساسية سارية.
  • تعليقات HierText التوضيحية: CC BY-SA 4.0. وتتطلب التعديلات المُعاد توزيعها ذكر المصدر، والإشارة إلى التغييرات، والترخيص بموجب الترخيص نفسه أو ترخيص متوافق معه.
  • صور HierText: مصدرها Open Images. وتدرج شروط Open Images الصور بموجب CC BY 2.0، وتطلب من المستخدمين التحقق من تراخيص الصور كلٌّ على حدة.

تتيح تراخيص التعليقات التوضيحية هذه الاستخدام التجاري وفقًا لشروطها، لكن مجموعة البيانات ليست ملكية عامة. احفظ بيانات الإسناد إلى المصادر، وراجع الشروط المنطبقة على الصور عند إعادة توزيع البيانات.

الاستشهادات والشكر والتقدير#

إذا استخدمت مجموعة البيانات هذه في عملك، فاستشهد بمجموعتي البيانات المصدر:

الاستشهاد
@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}
}

نتوجه بالشكر إلى فريقي COCO-Text وHierText لإنشاء مجموعتي البيانات هاتين وصيانتهما.

الأسئلة الشائعة#

  • لا. ينتج عن التحويل مضلعات أحادية الفئة لاكتشاف الكلمات، مخصصة لتدريب OBB. استخدم التعليقات التوضيحية الأصلية لـ COCO-Text وHierText إذا كان مسار عملك يتطلب أيضًا النصوص المكتوبة.

  • توفر COCO-Text تعليقات توضيحية للتدريب والتحقق. يحتفظ هذا الإعداد بتقسيم التدريب الرسمي، ويقسّم صور التحقق الرسمية حتميًا إلى مجموعتين فرعيتين للتحقق والاختبار. وتحتفظ HierText بتقسيماتها الرسمية.

  • نعم. ضعه ضمن datasets_dir في Ultralytics، مع اتباع بنية coco/ القياسية، بما في ذلك images/train2017 وimages/val2017 وملفات النص الخاصة بتقسيمات COCO. سيعيد نص التنزيل استخدامه بدلًا من تنزيل COCO مرة أخرى.

المساهمون

التعليقات

اطرح سؤالًا، وشارك نتائجك، أو ساعد شخصًا آخر.