Metadata-Version: 2.4
Name: mangascourx
Version: 1.0.5.1
Summary: Advanced Multi-Scale PatchMatch & AI-Powered Text Removal Engine for Manga
Home-page: https://github.com/zxui86/mangascourx
Author: Zizo
Author-email: zly30257@gmail.com
License: MIT
Keywords: manga,comic,inpainting,text-removal,patchmatch
Classifier: Development Status :: 4 - Beta
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Scientific/Engineering :: Image Processing
Requires-Python: >=3.8
Description-Content-Type: text/markdown
Requires-Dist: numpy>=1.20.0
Requires-Dist: opencv-python-headless>=4.5.0
Requires-Dist: numba>=0.53.0
Requires-Dist: scipy>=1.7.0
Requires-Dist: torch>=1.9.0
Requires-Dist: torchvision>=0.10.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0.0; extra == "dev"
Requires-Dist: twine>=4.0.0; extra == "dev"
Requires-Dist: build>=0.8.0; extra == "dev"
Dynamic: author
Dynamic: author-email
Dynamic: classifier
Dynamic: description
Dynamic: description-content-type
Dynamic: home-page
Dynamic: keywords
Dynamic: license
Dynamic: provides-extra
Dynamic: requires-dist
Dynamic: requires-python
Dynamic: summary

# mangascourx

<div align="center">

![Version](https://img.shields.io/badge/version-1.0.5-brightblue.svg?style=for-the-badge)
![Python](https://img.shields.io/badge/python-3.8%2B-3776ab.svg?style=for-the-badge&logo=python&logoColor=white)
![License](https://img.shields.io/badge/license-MIT-22c55e.svg?style=for-the-badge)
![Status](https://img.shields.io/badge/status-Stable-22c55e.svg?style=for-the-badge)
![PyPI](https://img.shields.io/badge/PyPI-mangascourx-f97316.svg?style=for-the-badge&logo=pypi&logoColor=white)

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

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

</div>

---

## ما هي mangascourx؟

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

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

---

## 📋 المحتويات

- [✨ الميزات](#-الميزات)
- [📦 المتطلبات](#-المتطلبات)
- [🚀 التثبيت](#-التثبيت)
- [💡 الاستخدام](#-الاستخدام)
- [📚 الواجهة البرمجية](#-الواجهة-البرمجية)
- [⚡ msx_all — الاختصار الشامل](#-msx_all--الاختصار-الشامل)
- [🏗️ البنية المعمارية](#️-البنية-المعمارية)
- [📝 سجل الإصدارات](#-سجل-الإصدارات)
- [🤝 المساهمة](#-المساهمة)

---

## ✨ الميزات

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

| الطريقة | السرعة | الدقة | يحتاج 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
```bash
pip install mangascourx
```

### إصدار محدد
```bash
pip install mangascourx==1.0.5
```

### من GitHub
```bash
pip install git+https://github.com/zxui86/mangascourx.git
```

### من المصدر
```bash
git clone https://github.com/zxui86/mangascourx.git
cd mangascourx
pip install -e .
```

### التحقق من التثبيت
```python
import mangascourx
print(mangascourx.__version__)  # 1.0.5
```

---

## 💡 الاستخدام

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

```python
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. خط الأنابيب الكامل مع تبييض الخلفية

```python
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. التحكم الكامل في كل مرحلة

```python
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. معاينة النتائج المرحلية

```python
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. معالجة دفعة من الصور

```python
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`

```python
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`

```python
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`

```python
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` — الأعلى جودةً

```python
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` — الأسرع

```python
from mangascourx.inpainting import TeleaInpainter

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

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

```python
from mangascourx.inpainting import CoherenceTransport

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

---

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

```python
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`، ملف واحد يستورد **كل** دوال وكلاسات المكتبة دفعة واحدة:

```python
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'`

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

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

### `ImportError` بعد التثبيت

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

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

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

### `CRAFT` لا يعمل

```python
# 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**

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

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

---

## 📄 الترخيص

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

---

## 👤 المؤلف

- GitHub: [@zxui86](https://github.com/zxui86)
- Email: zly30257@gmail.com
- Issues: [github.com/zxui86/mangascourx/issues](https://github.com/zxui86/mangascourx/issues)

---

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

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

---

<div align="center">

**mangascourx v1.0.5** — مستقر ✅

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

</div>
ديث: يونيو 2025*

</div>
