Repository: mindee/doctr

Issue:
[visualization] Some unsupported characters make page synthesis crash
## 🐛 Page synthesis doesn't support all characters

After some investigation on why the page synthesis feature was crashing (cf. https://twitter.com/nudelbrot/status/1442737151700082691), it turns out that default text drawing with Pillow doesn't support all characters.

## To Reproduce

```python
from PIL import Image, ImageDraw
img = Image.new('RGB', (100, 100), color=(255, 255, 255))
d = ImageDraw.Draw(img)
d.text((0, 0), '€', fill=(0, 0, 0))
```

yields:
```
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
~/miniconda3/lib/python3.8/site-packages/PIL/ImageDraw.py in draw_text(ink, stroke_width, stroke_offset)
    407             try:
--> 408                 mask, offset = font.getmask2(
    409                     text,

AttributeError: 'ImageFont' object has no attribute 'getmask2'

During handling of the above exception, another exception occurred:

UnicodeEncodeError                        Traceback (most recent call last)
<ipython-input-5-ec97abdf1c71> in <module>
----> 1 d.text((0, 0), '€', fill=(0, 0, 0))

~/miniconda3/lib/python3.8/site-packages/PIL/ImageDraw.py in text(self, xy, text, fill, font, anchor, spacing, align, direction, features, language, stroke_width, stroke_fill, embedded_color, *args, **kwargs)
    461             else:
    462                 # Only draw normal text
--> 463                 draw_text(ink)
    464 
    465     def multiline_text(

~/miniconda3/lib/python3.8/site-packages/PIL/ImageDraw.py in draw_text(ink, stroke_width, stroke_offset)
    421             except AttributeError:
    422                 try:
--> 423                     mask = font.getmask(
    424                         text,
    425                         mode,

~/miniconda3/lib/python3.8/site-packages/PIL/ImageFont.py in getmask(self, text, mode, *args, **kwargs)
    147                  :py:mod:`PIL.Image.core` interface module.
    148         """
--> 149         return self.font.getmask(text, mode)
    150 
    151 

UnicodeEncodeError: 'latin-1' codec can't encode character '\u20ac' in position 0: ordinal not in range(256)
```

## Expected behavior

Page synthesis should be working with any character

## Environment

 - DocTR Version: 0.3.1
 - TensorFlow Version: 2.5.0
 - PyTorch & torchvision versions: 1.9.0 & 0.10.0
 - OpenCV Version: 4.5.1
 - OS: Ubuntu 20.04.3 LTS
 - How you installed DocTR: source
 - Python version: 3.8
 - CUDA/cuDNN version: 11.4.100
 - GPU models and configuration: Could not collect




Discussion:

Resolving patch:
diff --git a/doctr/utils/visualization.py b/doctr/utils/visualization.py
--- a/doctr/utils/visualization.py
+++ b/doctr/utils/visualization.py
@@ -11,6 +11,7 @@
 from copy import deepcopy
 import numpy as np
 import cv2
+from unidecode import unidecode
 from typing import Tuple, List, Dict, Any, Union, Optional
 
 from .common_types import BoundingBox, RotatedBbox
@@ -279,7 +280,11 @@ def synthesize_page(
                 img = Image.new('RGB', (xmax - xmin, ymax - ymin), color=(255, 255, 255))
                 d = ImageDraw.Draw(img)
                 # Draw in black the value of the word
-                d.text((0, 0), word["value"], font=font, fill=(0, 0, 0))
+                try:
+                    d.text((0, 0), word["value"], font=font, fill=(0, 0, 0))
+                except UnicodeEncodeError:
+                    # When character cannot be encoded, use its unidecode version
+                    d.text((0, 0), unidecode(word["value"]), font=font, fill=(0, 0, 0))
 
                 # Colorize if draw_proba
                 if draw_proba:


Test patch: