Skip to main content

Advanced Multi-Scale PatchMatch & AI-Powered Text Removal Engine for Manga

Project description

mangascourx

Version Python License Status PyPI

Advanced Multi-Scale PatchMatch & AI-Powered Text Removal Engine for Manga

إزالة النصوص من صور المانجا بدقة احترافية


ما هي mangascourx؟

mangascourx مكتبة Python متخصصة في إزالة النصوص والفقاعات من صور المانجا والكوميكس. تجمع بين خوارزميات كلاسيكية مُحسَّنة وتقنيات AI حديثة لتقديم نتائج احترافية جاهزة للطباعة أو إعادة الترجمة.

صورة مانجا أصلية  →  كشف النصوص والفقاعات  →  ترميم ذكي للمنطقة  →  صورة نظيفة

📋 المحتويات


✨ الميزات

🔍 كشف النصوص — طبقتان للدقة

الطريقة السرعة الدقة يحتاج AI
MSER — Maximally Stable Extremal Regions ⚡ سريع جداً متوسطة–عالية ❌ لا
CRAFT — Character Region Awareness For Text 🐢 أبطأ عالية جداً ✅ نعم

الاختيار تلقائي: إذا أعاد MSER نتائج قليلة، تنتقل المكتبة تلقائياً إلى CRAFT.

💬 كشف فقاعات الحوار

  • كشف مبني على الكنتور والمورفولوجيا
  • يتعامل مع الفقاعات الدائرية والبيضاوية والمخصصة
  • تنظيف الضوضاء تلقائياً قبل وبعد الكشف

🎨 ثلاث خوارزميات ترميم

الخوارزمية الجودة السرعة الاستخدام الأمثل
PatchMatch ⭐⭐⭐⭐⭐ ⚡⚡ متوسطة نصوص كبيرة، مناطق معقدة
Telea Fast Marching ⭐⭐⭐ ⚡⚡⚡⚡ سريع جداً نصوص صغيرة، معالجة سريعة
Coherence Transport ⭐⭐⭐⭐ ⚡⚡⚡ سريع الخطوط والعناصر الهندسية

⚡ الأداء

  • تسريع JIT عبر Numba (اختياري لكن موصى به)
  • معالجة متوازية prange للصور الكبيرة
  • هرم متعدد المستويات (Gaussian Pyramid) لدقة عالية
  • Fallback تلقائي إذا لم يكن Numba مثبتاً

📦 المتطلبات

Python >= 3.8

# أساسي
numpy >= 1.20.0
opencv-python-headless >= 4.5.0
scipy >= 1.7.0

# لتسريع الأداء (موصى به بشدة)
numba >= 0.53.0

# لكشف CRAFT (اختياري)
torch >= 1.9.0
torchvision >= 0.10.0

🚀 التثبيت

من PyPI

pip install mangascourx

إصدار محدد

pip install mangascourx==1.0.5

من GitHub

pip install git+https://github.com/zxui86/mangascourx.git

من المصدر

git clone https://github.com/zxui86/mangascourx.git
cd mangascourx
pip install -e .

التحقق من التثبيت

import mangascourx
print(mangascourx.__version__)  # 1.0.5

💡 الاستخدام

1. الحالة الأبسط — خط أنابيب كامل

import cv2
from mangascourx import TextRemovePipeline

image = cv2.imread("manga_page.jpg")

pipeline = TextRemovePipeline(
    inpainting_method="patchmatch",  # "patchmatch" | "telea"
    patch_size=7,
)

result = pipeline.run(image)

cv2.imwrite("cleaned.jpg", result["result"])
# result["result"]        — الصورة بعد الإزالة
# result["mask"]          — القناع الثنائي
# result["text_detected"] — True إذا وُجد نص

2. خط الأنابيب الكامل مع تبييض الخلفية

from mangascourx import MangaCleanPipeline

pipeline = MangaCleanPipeline(
    inpainting_method="patchmatch",
    patch_size=7,
    denoise_level=3,        # تقليل الضوضاء قبل المعالجة
    whiten_background=True  # تبييض ذكي للصفحات القديمة
)

output = pipeline.run(image)

cv2.imwrite("final.jpg", output["final_page"])
# output["final_page"]    — الصورة النهائية النظيفة
# output["mask"]          — القناع المستخدم
# output["text_removed"]  — True إذا أُزيل نص

3. التحكم الكامل في كل مرحلة

from mangascourx.detection import DetectionOrchestrator
from mangascourx.inpainting import PatchMatchInpainter

# ─── كاشف مخصص ───────────────────────────────────
detector = DetectionOrchestrator(
    mser_params={
        "delta": 5,
        "min_area": 60,
        "max_area": 14400,
    },
    bubble_params={
        "block_size": 31,
        "morph_open": 3,
        "morph_close": 5,
    },
    merge_priority=["text", "bubbles"],
    final_cleanup=True,
    fallback_min_boxes=3,
)

# ─── كشف النصوص والفقاعات ─────────────────────────
detection = detector.run(image, enable_text=True, enable_bubbles=True)

mask         = detection["mask"]          # القناع الموحد
text_boxes   = detection["text_boxes"]    # [(x, y, w, h), ...]
bubble_boxes = detection["bubble_boxes"]  # [(x, y, w, h), ...]

# ─── ترميم مخصص ──────────────────────────────────
inpainter = PatchMatchInpainter(
    patch_size=9,
    iterations=5,
    knn=3,
    use_rotation=True,
    use_scale=True,
    use_coherence=True,
    verbose=True,
)

result = inpainter.run(image, mask)

4. معاينة النتائج المرحلية

import cv2
import numpy as np

detection = detector.run(image)

stages = {
    "original":    image,
    "unified_mask": detection["mask"],
    "text_mask":   detection.get("text_mask", np.zeros(image.shape[:2], np.uint8)),
    "bubble_mask": detection.get("bubble_mask", np.zeros(image.shape[:2], np.uint8)),
}

for name, img in stages.items():
    cv2.imwrite(f"debug_{name}.jpg", img)

5. معالجة دفعة من الصور

import os, cv2
from mangascourx import TextRemovePipeline

pipeline = TextRemovePipeline(inpainting_method="telea")  # telea أسرع للدفعات

for filename in os.listdir("input/"):
    if filename.lower().endswith((".jpg", ".png", ".webp")):
        img = cv2.imread(f"input/{filename}")
        out = pipeline.run(img)
        cv2.imwrite(f"output/{filename}", out["result"])
        print(f"✓ {filename}")

📚 الواجهة البرمجية

TextRemovePipeline

from mangascourx import TextRemovePipeline

pipeline = TextRemovePipeline(
    merge_priority=["text", "bubbles"],  # أولوية دمج القنوات
    patch_size=7,                        # حجم رقعة PatchMatch
    inpainting_method="patchmatch",      # "patchmatch" | "telea"
)

output = pipeline.run(image)
# output["result"]        → NDArray[uint8]
# output["mask"]          → NDArray[uint8]
# output["text_detected"] → bool
# output["meta"]          → dict  (إذا وُجد نص)

MangaCleanPipeline

from mangascourx import MangaCleanPipeline

pipeline = MangaCleanPipeline(
    inpainting_method="patchmatch",
    patch_size=7,
    denoise_level=0,        # 0 = بدون denoising، 1–10 = شدة التنظيف
    whiten_background=True, # تبييض تكيفي للخلفية
)

output = pipeline.run(image)
# output["final_page"]  → NDArray[uint8]
# output["mask"]        → NDArray[uint8]
# output["text_removed"] → bool

DetectionOrchestrator

from mangascourx.detection import DetectionOrchestrator

detector = DetectionOrchestrator(
    craft_model_path=None,              # مسار نموذج CRAFT (.pth) أو None
    device="cpu",                       # "cpu" | "cuda" | "cuda:0"
    mser_params=None,                   # dict لتخصيص MSER
    craft_params=None,                  # dict لتخصيص CRAFT
    bubble_params=None,                 # dict لتخصيص كشف الفقاعات
    merge_priority=["text", "bubbles"], # ترتيب الأولوية عند التداخل
    final_cleanup=True,                 # تنظيف مورفولوجي نهائي
    fallback_min_boxes=3,               # حد الانتقال من MSER إلى CRAFT
)

# الاستدعاء الرئيسي
result = detector.run(image, enable_text=True, enable_bubbles=True)
# أو بالاسم البديل:
result = detector.detect(image, enable_text=True, enable_bubbles=True)

# المخرجات:
# result["mask"]         → NDArray[uint8]  — القناع الموحد
# result["text_mask"]    → NDArray[uint8]  — قناع النصوص فقط
# result["bubble_mask"]  → NDArray[uint8]  — قناع الفقاعات فقط
# result["text_boxes"]   → list[(x,y,w,h)] — مربعات النصوص
# result["bubble_boxes"] → list[(x,y,w,h)] — مربعات الفقاعات
# result["priority"]     → list[str]

خوارزميات الترميم

PatchMatchInpainter — الأعلى جودةً

from mangascourx.inpainting import PatchMatchInpainter

inpainter = PatchMatchInpainter(
    patch_size=7,           # حجم الرقعة (7–15 مناسب للمانجا)
    pyramid_levels=5,       # عدد مستويات هرم الصورة
    iterations=6,           # عدد التكرارات لكل مستوى
    knn=3,                  # عدد أقرب الجيران
    random_decay=0.5,       # معدل تقليص نطاق البحث العشوائي
    use_rotation=True,      # السماح بالتطابق بعد الدوران
    use_scale=True,         # السماح بالتطابق بعد تغيير الحجم
    use_coherence=True,     # بحث الاتساق بين البكسلات المجاورة
    use_bidirectional=True, # تحسين بالاتجاهين
    use_features=False,     # استخدم التدرجات كميزات إضافية
    seed=None,              # بذرة للنتائج القابلة للتكرار
    verbose=False,
)

result = inpainter.run(image, mask)  # → NDArray[uint8]

TeleaInpainter — الأسرع

from mangascourx.inpainting import TeleaInpainter

inpainter = TeleaInpainter(radius=5)
result = inpainter.run(image, mask)  # → NDArray[uint8]

CoherenceTransport — للخطوط الهندسية

from mangascourx.inpainting import CoherenceTransport

inpainter = CoherenceTransport(iterations=3, step_size=0.25)
result = inpainter.run(image, mask)  # → NDArray[uint8]

أدوات المورفولوجيا والكنتور

from mangascourx.detection.bubbles.morphology import (
    clean_noise, dilate, erode, open_mask, close_mask, improve_mask
)
from mangascourx.detection.bubbles.contours import (
    detect_bubbles, find_contours, filter_contours_by_area,
    draw_contours, draw_bounding_rects
)
from mangascourx.detection.text.mser import detect_text_regions
from mangascourx.detection.mask import process_masks, merge_labeled, cleanup_mask

⚡ msx_all — الاختصار الشامل

في v1.0.5 أضفنا msx_all، ملف واحد يستورد كل دوال وكلاسات المكتبة دفعة واحدة:

import mangascourx.msx_all as msx

# بدلاً من استيرادات متعددة من مسارات مختلفة:
msx.TextRemovePipeline()
msx.MangaCleanPipeline()
msx.DetectionOrchestrator()
msx.PatchMatchInpainter()
msx.TeleaInpainter()
msx.CoherenceTransport()

# كشف النصوص
msx.detect_text_regions(image)
msx.create_mser(delta=5, min_area=60)
msx.non_max_suppression(boxes, overlap_threshold=0.5)
msx.CRAFTDetector("weights.pth", device="cpu")

# كشف الفقاعات
msx.detect_bubbles(binary_mask)
msx.find_contours(mask)
msx.filter_contours_by_area(contours, min_area=100)
msx.draw_contours(image, contours)
msx.draw_bounding_rects(image, rects)

# مورفولوجيا
msx.clean_noise(mask, open_kernel_size=3, close_kernel_size=5)
msx.dilate(mask, kernel_size=3)
msx.erode(mask, kernel_size=3)
msx.open_mask(mask, kernel_size=3)
msx.close_mask(mask, kernel_size=3)
msx.improve_mask(mask, blur_ksize=3)

# دمج الأقنعة
msx.process_masks({"text": t_mask, "bubbles": b_mask}, priority=["text", "bubbles"])
msx.merge_labeled(masks_dict, priority=["text", "bubbles"])
msx.cleanup_mask(mask)

# أدوات SWT
msx.stroke_width_transform(gray_image)
msx.swt_to_mask(swt_map)
msx.detect_text_swt(image)

# رياضيات الأساس
msx.PriorityQueue(capacity=10000)
msx.euclidean_distance_transform(mask)
msx.connected_components(binary_mask)
msx.structure_tensor(gray)
msx.perona_malik_diffusion(image)
msx.curvature_diffusion(image)

# إصدار
print(msx.__version__)  # 1.0.5

ملاحظة: msx_all مفيد للتجربة السريعة والاستكشاف. في الإنتاج يُفضَّل الاستيراد المباشر من المسار الكامل لوضوح الكود.


🏗️ البنية المعمارية

mangascourx/                           ← حزمة Python الرئيسية
│
├── __init__.py                        ← TextRemovePipeline, MangaCleanPipeline
├── _version.py                        ← "1.0.5"
├── manga_clean.py                     ← MangaCleanPipeline + تبييض تكيفي
├── text_remove.py                     ← TextRemovePipeline (خط الأنابيب)
├── msx_all.py                    ⭐NEW ← كل الدوال في ملف واحد
│
├── detection/
│   ├── detection.py                   ← DetectionOrchestrator (المنسق)
│   ├── mask.py                        ← merge_labeled, process_masks
│   ├── base.py                        ← BaseDetector (واجهة كاشفات)
│   │
│   ├── bubbles/
│   │   ├── contours.py                ← detect_bubbles, find_contours
│   │   └── morphology.py              ← clean_noise, dilate, erode
│   │
│   └── text/
│       ├── mser.py                    ← detect_text_regions (MSER)
│       ├── craft_adapter.py           ← CRAFTDetector (AI)
│       └── swt.py                     ← stroke_width_transform
│
├── inpainting/
│   ├── base.py                        ← Inpainter + _find_boundary + _propagate
│   ├── telea.py                       ← TeleaInpainter (Fast Marching)
│   ├── coherence.py                   ← CoherenceTransport
│   └── patchmatch/
│       ├── core.py                    ← NNF, patch ops, transforms (Numba JIT)
│       ├── engine.py                  ← PatchMatchInpainter (المحرك)
│       └── propagation.py             ← initialize_nnf, propagate, random_search
│
└── core/
    ├── distance.py                    ← euclidean_distance_transform
    ├── components.py                  ← connected_components, UnionFind
    ├── tensor.py                      ← structure_tensor
    ├── diffusion.py                   ← perona_malik, curvature_diffusion
    ├── priority_queue.py              ← PriorityQueue (min-heap)
    └── etf.py                         ← Edge Tangent Flow (مستقبلي)

📊 مسار البيانات

cv2.imread()  →  uint8 BGR Array
       │
       ├──► DetectionOrchestrator.run()
       │         │
       │         ├──► MSER / CRAFT  →  text_mask   (binary 0/255)
       │         ├──► Bubble Seg    →  bubble_mask (binary 0/255)
       │         └──► process_masks →  final_mask  (binary 0/255)
       │
       └──► Inpainter.run(image, final_mask)
                 │
                 ├──► PatchMatch   →  multi-level NNF search → reconstruct
                 ├──► Telea        →  Fast Marching → propagate
                 └──► Coherence    →  structure tensor → transport
                 │
                 └──► uint8 result

📝 سجل الإصدارات


🆕 v1.0.5 — "Package Architecture Edition"

تاريخ الإصدار: يونيو 2025 الأهمية: إصلاح بنيوي شامل — هذا الإصدار هو أول نسخة تعمل فعلياً بعد التثبيت

المشكلة الجذرية

كانت جميع ملفات المشروع مبعثرة في جذر الريبو مباشرة بدلاً من أن تكون داخل مجلد mangascourx/:

# الوضع الخاطئ (v1.0.4 وما قبله):
repo/
├── core/          ← في الجذر مباشرة!
├── detection/     ← في الجذر مباشرة!
├── inpainting/    ← في الجذر مباشرة!
└── setup.py

# الوضع الصحيح (v1.0.5):
repo/
├── setup.py
└── mangascourx/   ← الحزمة الفعلية
    ├── core/
    ├── detection/
    └── inpainting/

هذا جعل pip install mangascourx ينصّب حزمة فارغة، وأي import mangascourx يفشل فوراً.

الإصلاحات الكاملة

# الملف المشكلة الإصلاح
1 البنية كلها الملفات في جذر الريبو لا داخل mangascourx/ إعادة هيكلة كاملة
2 detection/detection.py from .masks import — الملف اسمه mask.py from .mask import
3 detection/detection.py الكلاس Detector لكن text_remove.py يستورد DetectionOrchestrator إعادة تسمية + alias للتوافق
4 detection/detection.py بدون .run() — وtext_remove.py يستدعي .run() أضفنا run() يستدعي detect()
5 detection/detection.py detect_text_regions(image, **self.mser_params) خاطئ detect_text_regions(image, mser_params=self.mser_params)
6 inpainting/base.py غير موجودtelea.py وcoherence.py يستوردانه إنشاء من صفر
7 inpainting/base.py _find_boundary() و_propagate() غير معرَّفتان نقلهما إلى Inpainter base
8 inpainting/patchmatch/engine.py @njit داخل method بدون استيراد أضفنا import مع fallback
9 inpainting/patchmatch/propagation.py from numba import بدون try/except أضفنا الـ fallback
10 setup.py مسار _version.py نسبي يعتمد على CWD os.path.abspath()

ملفات __init__.py المفقودة (5 ملفات)

mangascourx/__init__.py                    ← أُنشئ
mangascourx/detection/__init__.py          ← أُنشئ
mangascourx/detection/text/__init__.py     ← أُنشئ
mangascourx/inpainting/__init__.py         ← أُنشئ
mangascourx/inpainting/patchmatch/__init__.py ← أُنشئ

الإضافة الجديدة

  • mangascourx/msx_all.py — ملف اختصار يستورد كل دوال وكلاسات المكتبة

v1.0.4

  • تحسينات في أداء PatchMatch
  • إصلاحات بسيطة في MSER

v1.0.3

  • إضافة CoherenceTransport
  • تحسين واجهة MangaCleanPipeline

v1.0.2

  • إضافة CRAFT adapter
  • تحسين عملية دمج الأقنعة

v1.0.1

  • PatchMatch multi-scale pyramid
  • إضافة Telea inpainter

v1.0.0

  • الإطلاق الأول
  • MSER + PatchMatch الأساسي

🔧 استكشاف الأخطاء

ModuleNotFoundError: No module named 'mangascourx'

# تأكد من التثبيت الصحيح
pip install --force-reinstall mangascourx==1.0.5

# أو من المصدر
pip install -e .

ImportError بعد التثبيت

# امسح الكاش
find . -name "__pycache__" -type d -exec rm -r {} +
pip cache purge
pip install --no-cache-dir mangascourx

numba بطيء أول استدعاء

هذا طبيعي — Numba يقوم بتجميع الكود في أول تشغيل (JIT compilation). من المرة الثانية سيكون سريعاً.

CRAFT لا يعمل

# CRAFT يحتاج torch وملف الأوزان
detector = DetectionOrchestrator(
    craft_model_path="path/to/craft_mlt_25k.pth",
    device="cpu",  # أو "cuda"
)
# إذا لم يكن CRAFT متاحاً، سيستخدم MSER تلقائياً

🤝 المساهمة

  1. Fork المستودع
  2. git checkout -b feature/your-feature
  3. git commit -m "Add: your feature"
  4. git push origin feature/your-feature
  5. افتح Pull Request

أدوات التطوير

pip install -e ".[dev]"
pytest tests/
flake8 mangascourx/
black mangascourx/

📄 الترخيص

هذا المشروع مرخص تحت MIT License.


👤 المؤلف


🗺️ الخارطة المستقبلية

  • نموذج AI خاص للمانجا (Manga-specific text detector)
  • دعم الفيديو وملفات CBZ/CBR
  • واجهة سطر أوامر mangascourx clean input.jpg
  • معالجة GPU كاملة (CUDA-native PatchMatch)
  • توثيق تفاعلي مع أمثلة مرئية

mangascourx v1.0.5 — مستقر ✅

آخر تحديث: يونيو 2025

ديث: يونيو 2025*

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mangascourx-1.0.5.2.tar.gz (49.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mangascourx-1.0.5.2-py3-none-any.whl (52.4 kB view details)

Uploaded Python 3

File details

Details for the file mangascourx-1.0.5.2.tar.gz.

File metadata

  • Download URL: mangascourx-1.0.5.2.tar.gz
  • Upload date:
  • Size: 49.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.20

File hashes

Hashes for mangascourx-1.0.5.2.tar.gz
Algorithm Hash digest
SHA256 87e0c3b862f73f0fc932e6145ce4ef4f32812f2b8125e0fbaaf0891dc4bcc346
MD5 31e209d71caee817f574226e70edd25b
BLAKE2b-256 65d83e91862f603576f3342145891ccfc85e9bc26b6ecf76eb9cdadcb6f9c902

See more details on using hashes here.

File details

Details for the file mangascourx-1.0.5.2-py3-none-any.whl.

File metadata

  • Download URL: mangascourx-1.0.5.2-py3-none-any.whl
  • Upload date:
  • Size: 52.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.20

File hashes

Hashes for mangascourx-1.0.5.2-py3-none-any.whl
Algorithm Hash digest
SHA256 650a0a5d4817fe37beac79d05e6aabf3904d7a54c58346d1f432d3a511b2882a
MD5 f3e46c489781c3b67128885fbf2e5113
BLAKE2b-256 892a120da254d66f50edef65a9e9efdf37a7d28c7c269fa3e8c7082c852c7c64

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page