We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[docs] Add a visualization of the example script in the README
While the readme specifies how you can use the example script, it does not show any visualization examples. We could easily add one to help users.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `doctr/utils/visualization.py`
Content:
```
1 # Copyright (C) 2021, Mindee.
2 
3 # This program is licensed under the Apache License version 2.
4 # See LICENSE or go to <https://www.apache.org/licenses/LICENSE-2.0.txt> for full license details.
5 
6 import matplotlib.pyplot as plt
7 import matplotlib.patches as patches
8 import mplcursors
9 import numpy as np
10 from typing import Tuple, List, Dict, Any
11 
12 from .common_types import BoundingBox
13 
14 __all__ = ['visualize_page']
15 
16 
17 def create_patch(
18     geometry: BoundingBox,
19     label: str,
20     page_dimensions: Tuple[int, int],
21     color: Tuple[int, int, int],
22     alpha: float = 0.3,
23     linewidth: int = 2,
24 ) -> patches.Patch:
25     """Create a matplotlib patch (rectangle) bounding the element
26 
27     Args:
28         geometry: bounding box of the element
29         label: label to display when hovered
30         page_dimensions: dimensions of the Page
31         color: color to draw box
32         alpha: opacity parameter to fill the boxes, 0 = transparent
33         linewidth: line width
34 
35     Returns:
36         a rectangular Patch
37     """
38     h, w = page_dimensions
39     (xmin, ymin), (xmax, ymax) = geometry
40     xmin, xmax = xmin * w, xmax * w
41     ymin, ymax = ymin * h, ymax * h
42     rect = patches.Rectangle(
43         (xmin, ymin),
44         xmax - xmin,
45         ymax - ymin,
46         fill=True,
47         linewidth=linewidth,
48         edgecolor=(*color, alpha),
49         facecolor=(*color, alpha),
50         label=label
51     )
52     return rect
53 
54 
55 def visualize_page(
56     page: Dict[str, Any],
57     image: np.ndarray,
58     words_only: bool = True,
59 ) -> None:
60     """Visualize a full page with predicted blocks, lines and words
61 
62     Example::
63         >>> import numpy as np
64         >>> import matplotlib.pyplot as plt
65         >>> from doctr.utils.visualization import visualize_page
66         >>> from doctr.models import ocr_db_crnn
67         >>> model = ocr_db_crnn(pretrained=True)
68         >>> input_page = (255 * np.random.rand(600, 800, 3)).astype(np.uint8)
69         >>> out = model([[input_page]])
70         >>> visualize_page(out[0].pages[0].export(), input_page)
71         >>> plt.show()
72 
73     Args:
74         page: the exported Page of a Document
75         image: np array of the page, needs to have the same shape than page['dimensions']
76         words_only: whether only words should be displayed
77     """
78     # Display the image
79     _, ax = plt.subplots()
80     ax.imshow(image)
81     # hide both axis
82     ax.axis('off')
83 
84     artists: List[patches.Patch] = []  # instantiate an empty list of patches (to be drawn on the page)
85 
86     for block in page['blocks']:
87         if not words_only:
88             rect = create_patch(block['geometry'], 'block', page['dimensions'], (0, 1, 0), linewidth=1)
89             # add patch on figure
90             ax.add_patch(rect)
91             # add patch to cursor's artists
92             artists.append(rect)
93 
94         for line in block['lines']:
95             if not words_only:
96                 rect = create_patch(line['geometry'], 'line', page['dimensions'], (1, 0, 0), linewidth=1)
97                 ax.add_patch(rect)
98                 artists.append(rect)
99 
100             for word in line['words']:
101                 rect = create_patch(word['geometry'], f"{word['value']} (confidence: {word['confidence']:.2%})",
102                                     page['dimensions'], (0, 0, 1))
103                 ax.add_patch(rect)
104                 artists.append(rect)
105 
106         if not words_only:
107             for artefact in block['artefacts']:
108                 rect = create_patch(artefact['geometry'], 'artefact', page['dimensions'], (0.5, 0.5, 0.5), linewidth=1)
109                 ax.add_patch(rect)
110                 artists.append(rect)
111 
112     # Create mlp Cursor to hover patches in artists
113     mplcursors.Cursor(artists, hover=2).connect("add", lambda sel: sel.annotation.set_text(sel.artist.get_label()))
114
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/doctr/utils/visualization.py b/doctr/utils/visualization.py
--- a/doctr/utils/visualization.py
+++ b/doctr/utils/visualization.py
@@ -56,6 +56,7 @@
     page: Dict[str, Any],
     image: np.ndarray,
     words_only: bool = True,
+    scale: float = 10,
 ) -> None:
     """Visualize a full page with predicted blocks, lines and words
 
@@ -74,9 +75,13 @@
         page: the exported Page of a Document
         image: np array of the page, needs to have the same shape than page['dimensions']
         words_only: whether only words should be displayed
+        scale: figsize of the largest windows side
     """
+    # Get proper scale and aspect ratio
+    h, w = image.shape[:2]
+    size = (scale * w / h, scale) if h > w else (scale, h / w * scale)
+    fig, ax = plt.subplots(figsize=size)
     # Display the image
-    _, ax = plt.subplots()
     ax.imshow(image)
     # hide both axis
     ax.axis('off')
@@ -111,3 +116,4 @@
 
     # Create mlp Cursor to hover patches in artists
     mplcursors.Cursor(artists, hover=2).connect("add", lambda sel: sel.annotation.set_text(sel.artist.get_label()))
+    fig.tight_layout()

{"golden_diff": "diff --git a/doctr/utils/visualization.py b/doctr/utils/visualization.py\n--- a/doctr/utils/visualization.py\n+++ b/doctr/utils/visualization.py\n@@ -56,6 +56,7 @@\n     page: Dict[str, Any],\n     image: np.ndarray,\n     words_only: bool = True,\n+    scale: float = 10,\n ) -> None:\n     \"\"\"Visualize a full page with predicted blocks, lines and words\n \n@@ -74,9 +75,13 @@\n         page: the exported Page of a Document\n         image: np array of the page, needs to have the same shape than page['dimensions']\n         words_only: whether only words should be displayed\n+        scale: figsize of the largest windows side\n     \"\"\"\n+    # Get proper scale and aspect ratio\n+    h, w = image.shape[:2]\n+    size = (scale * w / h, scale) if h > w else (scale, h / w * scale)\n+    fig, ax = plt.subplots(figsize=size)\n     # Display the image\n-    _, ax = plt.subplots()\n     ax.imshow(image)\n     # hide both axis\n     ax.axis('off')\n@@ -111,3 +116,4 @@\n \n     # Create mlp Cursor to hover patches in artists\n     mplcursors.Cursor(artists, hover=2).connect(\"add\", lambda sel: sel.annotation.set_text(sel.artist.get_label()))\n+    fig.tight_layout()\n", "issue": "[docs] Add a visualization of the example script in the README\nWhile the readme specifies how you can use the example script, it does not show any visualization examples. We could easily add one to help users.\n", "before_files": [{"content": "# Copyright (C) 2021, Mindee.\n\n# This program is licensed under the Apache License version 2.\n# See LICENSE or go to <https://www.apache.org/licenses/LICENSE-2.0.txt> for full license details.\n\nimport matplotlib.pyplot as plt\nimport matplotlib.patches as patches\nimport mplcursors\nimport numpy as np\nfrom typing import Tuple, List, Dict, Any\n\nfrom .common_types import BoundingBox\n\n__all__ = ['visualize_page']\n\n\ndef create_patch(\n    geometry: BoundingBox,\n    label: str,\n    page_dimensions: Tuple[int, int],\n    color: Tuple[int, int, int],\n    alpha: float = 0.3,\n    linewidth: int = 2,\n) -> patches.Patch:\n    \"\"\"Create a matplotlib patch (rectangle) bounding the element\n\n    Args:\n        geometry: bounding box of the element\n        label: label to display when hovered\n        page_dimensions: dimensions of the Page\n        color: color to draw box\n        alpha: opacity parameter to fill the boxes, 0 = transparent\n        linewidth: line width\n\n    Returns:\n        a rectangular Patch\n    \"\"\"\n    h, w = page_dimensions\n    (xmin, ymin), (xmax, ymax) = geometry\n    xmin, xmax = xmin * w, xmax * w\n    ymin, ymax = ymin * h, ymax * h\n    rect = patches.Rectangle(\n        (xmin, ymin),\n        xmax - xmin,\n        ymax - ymin,\n        fill=True,\n        linewidth=linewidth,\n        edgecolor=(*color, alpha),\n        facecolor=(*color, alpha),\n        label=label\n    )\n    return rect\n\n\ndef visualize_page(\n    page: Dict[str, Any],\n    image: np.ndarray,\n    words_only: bool = True,\n) -> None:\n    \"\"\"Visualize a full page with predicted blocks, lines and words\n\n    Example::\n        >>> import numpy as np\n        >>> import matplotlib.pyplot as plt\n        >>> from doctr.utils.visualization import visualize_page\n        >>> from doctr.models import ocr_db_crnn\n        >>> model = ocr_db_crnn(pretrained=True)\n        >>> input_page = (255 * np.random.rand(600, 800, 3)).astype(np.uint8)\n        >>> out = model([[input_page]])\n        >>> visualize_page(out[0].pages[0].export(), input_page)\n        >>> plt.show()\n\n    Args:\n        page: the exported Page of a Document\n        image: np array of the page, needs to have the same shape than page['dimensions']\n        words_only: whether only words should be displayed\n    \"\"\"\n    # Display the image\n    _, ax = plt.subplots()\n    ax.imshow(image)\n    # hide both axis\n    ax.axis('off')\n\n    artists: List[patches.Patch] = []  # instantiate an empty list of patches (to be drawn on the page)\n\n    for block in page['blocks']:\n        if not words_only:\n            rect = create_patch(block['geometry'], 'block', page['dimensions'], (0, 1, 0), linewidth=1)\n            # add patch on figure\n            ax.add_patch(rect)\n            # add patch to cursor's artists\n            artists.append(rect)\n\n        for line in block['lines']:\n            if not words_only:\n                rect = create_patch(line['geometry'], 'line', page['dimensions'], (1, 0, 0), linewidth=1)\n                ax.add_patch(rect)\n                artists.append(rect)\n\n            for word in line['words']:\n                rect = create_patch(word['geometry'], f\"{word['value']} (confidence: {word['confidence']:.2%})\",\n                                    page['dimensions'], (0, 0, 1))\n                ax.add_patch(rect)\n                artists.append(rect)\n\n        if not words_only:\n            for artefact in block['artefacts']:\n                rect = create_patch(artefact['geometry'], 'artefact', page['dimensions'], (0.5, 0.5, 0.5), linewidth=1)\n                ax.add_patch(rect)\n                artists.append(rect)\n\n    # Create mlp Cursor to hover patches in artists\n    mplcursors.Cursor(artists, hover=2).connect(\"add\", lambda sel: sel.annotation.set_text(sel.artist.get_label()))\n", "path": "doctr/utils/visualization.py"}], "after_files": [{"content": "# Copyright (C) 2021, Mindee.\n\n# This program is licensed under the Apache License version 2.\n# See LICENSE or go to <https://www.apache.org/licenses/LICENSE-2.0.txt> for full license details.\n\nimport matplotlib.pyplot as plt\nimport matplotlib.patches as patches\nimport mplcursors\nimport numpy as np\nfrom typing import Tuple, List, Dict, Any\n\nfrom .common_types import BoundingBox\n\n__all__ = ['visualize_page']\n\n\ndef create_patch(\n    geometry: BoundingBox,\n    label: str,\n    page_dimensions: Tuple[int, int],\n    color: Tuple[int, int, int],\n    alpha: float = 0.3,\n    linewidth: int = 2,\n) -> patches.Patch:\n    \"\"\"Create a matplotlib patch (rectangle) bounding the element\n\n    Args:\n        geometry: bounding box of the element\n        label: label to display when hovered\n        page_dimensions: dimensions of the Page\n        color: color to draw box\n        alpha: opacity parameter to fill the boxes, 0 = transparent\n        linewidth: line width\n\n    Returns:\n        a rectangular Patch\n    \"\"\"\n    h, w = page_dimensions\n    (xmin, ymin), (xmax, ymax) = geometry\n    xmin, xmax = xmin * w, xmax * w\n    ymin, ymax = ymin * h, ymax * h\n    rect = patches.Rectangle(\n        (xmin, ymin),\n        xmax - xmin,\n        ymax - ymin,\n        fill=True,\n        linewidth=linewidth,\n        edgecolor=(*color, alpha),\n        facecolor=(*color, alpha),\n        label=label\n    )\n    return rect\n\n\ndef visualize_page(\n    page: Dict[str, Any],\n    image: np.ndarray,\n    words_only: bool = True,\n    scale: float = 10,\n) -> None:\n    \"\"\"Visualize a full page with predicted blocks, lines and words\n\n    Example::\n        >>> import numpy as np\n        >>> import matplotlib.pyplot as plt\n        >>> from doctr.utils.visualization import visualize_page\n        >>> from doctr.models import ocr_db_crnn\n        >>> model = ocr_db_crnn(pretrained=True)\n        >>> input_page = (255 * np.random.rand(600, 800, 3)).astype(np.uint8)\n        >>> out = model([[input_page]])\n        >>> visualize_page(out[0].pages[0].export(), input_page)\n        >>> plt.show()\n\n    Args:\n        page: the exported Page of a Document\n        image: np array of the page, needs to have the same shape than page['dimensions']\n        words_only: whether only words should be displayed\n        scale: figsize of the largest windows side\n    \"\"\"\n    # Get proper scale and aspect ratio\n    h, w = image.shape[:2]\n    size = (scale * w / h, scale) if h > w else (scale, h / w * scale)\n    fig, ax = plt.subplots(figsize=size)\n    # Display the image\n    ax.imshow(image)\n    # hide both axis\n    ax.axis('off')\n\n    artists: List[patches.Patch] = []  # instantiate an empty list of patches (to be drawn on the page)\n\n    for block in page['blocks']:\n        if not words_only:\n            rect = create_patch(block['geometry'], 'block', page['dimensions'], (0, 1, 0), linewidth=1)\n            # add patch on figure\n            ax.add_patch(rect)\n            # add patch to cursor's artists\n            artists.append(rect)\n\n        for line in block['lines']:\n            if not words_only:\n                rect = create_patch(line['geometry'], 'line', page['dimensions'], (1, 0, 0), linewidth=1)\n                ax.add_patch(rect)\n                artists.append(rect)\n\n            for word in line['words']:\n                rect = create_patch(word['geometry'], f\"{word['value']} (confidence: {word['confidence']:.2%})\",\n                                    page['dimensions'], (0, 0, 1))\n                ax.add_patch(rect)\n                artists.append(rect)\n\n        if not words_only:\n            for artefact in block['artefacts']:\n                rect = create_patch(artefact['geometry'], 'artefact', page['dimensions'], (0.5, 0.5, 0.5), linewidth=1)\n                ax.add_patch(rect)\n                artists.append(rect)\n\n    # Create mlp Cursor to hover patches in artists\n    mplcursors.Cursor(artists, hover=2).connect(\"add\", lambda sel: sel.annotation.set_text(sel.artist.get_label()))\n    fig.tight_layout()\n", "path": "doctr/utils/visualization.py"}]}