| --- |
| language: |
| - ar |
| pipeline_tag: image-to-image |
| tags: |
| - arabic |
| - manuscripts |
| - historical-documents |
| - document-restoration |
| - image-restoration |
| - unet |
| - pytorch |
| datasets: |
| - Archatext/AraMS-28k-HTR |
| - Archatext/AraMS-Restore |
| --- |
| |
| # AraMS-Restore β restoration generators |
|
|
| Two U-Net generators that take a **degraded Arabic manuscript line** and return a |
| readable one. Same architecture, same data, same schedule β they differ only in |
| what they optimize: |
|
|
| | | `unimodal` (Level 1) | `recaware` (Level 2) | |
| |---|---|---| |
| | Loss | L1 + ResNet50 perceptual | the same **+ a frozen HATFormer OCR critic** | |
| | Optimizes for | visual fidelity | **legibility** | |
| | Text | not used | used as a loss target, never as an input | |
|
|
| The Level-2 critic reads the restored image and is scored against the true |
| transcription, so gradients flow into the pixels that matter for reading. Code: |
| [github.com/ArchaText/AraMS-Restore](https://github.com/ArchaText/AraMS-Restore). |
|
|
| ## Results |
|
|
| On **real** damaged lines from a held-out manuscript β the honest test β the |
| image-only model does not help, while the recognition-aware one does: |
|
|
| | Input to the reader | CER % | WER % | |
| |---|---|---| |
| | Degraded (untouched) | 29.81 | 59.98 | |
| | Level 1 restored | 30.15 | 59.98 | |
| | **Level 2 restored** | **28.15** | **58.44** | |
|
|
| The ranking *inverts* between the two ways of measuring β Level 1 wins every pixel |
| metric it is optimized for, and loses on reading: |
|
|
| | | PSNR β | SSIM β | CER β | |
| |---|---|---|---| |
| | Degraded | 22.76 | 0.9498 | 35.11 | |
| | Level 1 | **34.66** | **0.9886** | 28.12 | |
| | Level 2 | 30.66 | 0.9781 | **27.13** | |
|
|
| *(Synthetic test set. CER read by the frozen HATFormer reader.)* |
|
|
| ## Files |
|
|
| ``` |
| unimodal/best.pt 124 MB Level 1 generator (plain state_dict) |
| recaware/best.pt 124 MB Level 2 generator (plain state_dict) |
| ``` |
|
|
| Each is a `state_dict` for the generator built by |
| `restoration.models.unet_pix2pix.build_generator`: 31.04 M parameters, float32, |
| RGB in/out, `base=64`, `depth=4`, no discriminator (pix2pix off). |
|
|
| ## Usage |
|
|
| ```bash |
| hf download Archatext/Restoration --local-dir checkpoints/restore |
| ``` |
|
|
| That is exactly the layout the configs resolve, so the repo's scripts work |
| unchanged: |
|
|
| ```bash |
| python scripts/restore_real.py --score # CER before vs. after, both models |
| python app/server.py # drag-and-drop web demo |
| ``` |
|
|
| Or load one directly: |
|
|
| ```python |
| import torch, yaml |
| from restoration.models.unet_pix2pix import build_generator |
| |
| cfg = yaml.safe_load(open("configs/restore_recaware.yaml")) |
| gen = build_generator(cfg["model"]) |
| gen.load_state_dict(torch.load("checkpoints/restore/recaware/best.pt", map_location="cpu")) |
| gen.eval() |
| ``` |
|
|
| ### Input representation |
|
|
| A line is resized to height 64 keeping aspect and right-padded to width 1152 |
| (`build_strip`), RGB in [0, 1], padding pure black and excluded by a mask. 1152 = |
| 3 Γ 384 tiles cleanly into the HATFormer 384 Γ 384 RTL-flipped canvas, which is |
| what makes the Level-2 recognition loss exact. Feeding a differently-shaped or |
| grayscale image will degrade output quality. |
|
|
| ## Training |
|
|
| Both models: 20 epochs, AdamW `lr=2e-4` (Ξ²=0.5, 0.999), batch 8, seed 1337, and 4 |
| distinct degraded variants per clean line per epoch. Damage is synthesized **on the |
| fly** from clean `train`-split lines only β never val/test β by the localized |
| degradation engine (erasure, tears, worm holes, bleed-through, ink blots, ink |
| feathering), calibrated against real manuscript decay. |
|
|
| | | weights | |
| |---|---| |
| | `unimodal` | L1 1.0, perceptual 0.02 | |
| | `recaware` | image 1.0 (L1 1.0 + perceptual 0.02), recognition 0.5 | |
|
|
| Level 2's critic is [`Archatext/hatformer-arams28k`](https://huggingface.co/Archatext/hatformer-arams28k), |
| frozen throughout. |
|
|
| Training data: [AraMS-28k-HTR](https://huggingface.co/datasets/Archatext/AraMS-28k-HTR), |
| `train` split β 20,103 lines from 9 manuscripts. |
|
|
| ## Leakage |
|
|
| Splits are manuscript-level disjoint: the evaluation manuscripts (book_03, 05, 09) |
| are held out of restoration training entirely, **and** the OCR critic that scores |
| the output never trained on them either. Both conditions are needed β a critic that |
| had seen the test books would contaminate the training signal and the metric at |
| once. |
| |
| ## Limitations |
| |
| - Trained on **synthetic** degradation; real decay is a different distribution, and |
| the gap shows β the CER gain on real damage (1.7 points) is smaller than on the |
| synthetic test set. |
| - Single script tradition and a single corpus of 14 manuscripts; no claim of |
| generalization to other hands, papers or languages. |
| - Level 1 makes real damage marginally *harder* to read (30.15 vs 29.81 CER) while |
| scoring far better on PSNR/SSIM β do not select a restoration model on pixel |
| metrics alone. |
| - Line-level only. Page segmentation is upstream and not part of this release. |
| |
| ## Citation |
| |
| <!-- TODO: thesis / paper reference --> |
| |
| |