File size: 4,044 Bytes
d00dcd7
97ba84c
 
d00dcd7
97ba84c
 
 
 
d00dcd7
97ba84c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d00dcd7
 
5015c53
d00dcd7
97ba84c
 
 
 
5015c53
d00dcd7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97ba84c
 
 
5015c53
97ba84c
 
 
 
d00dcd7
97ba84c
 
 
 
 
d00dcd7
 
97ba84c
 
 
 
 
 
 
 
 
5015c53
97ba84c
 
 
d00dcd7
 
 
 
 
5015c53
97ba84c
 
 
 
 
 
 
d00dcd7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
import os
import gradio as gr
from jinja2 import Environment, FileSystemLoader
from typing_extensions import TypeAlias

_ENV = Environment(loader=FileSystemLoader("app/assets/jinja-templates"))
_IMAGE_TEMPLATE = _ENV.get_template("image.j2")

from typing import NamedTuple, TypeAlias
from dawsonia.typing import BBoxTuple


class TableCell(NamedTuple):
    polygon: tuple[tuple[int, int], ...]
    text_x: int
    text_y: int
    text: str


class Page(NamedTuple):
    width: int
    height: int
    cells: list[TableCell]
    path: str


Collection: TypeAlias = list[Page]


def render_image(collection: Collection, current_page_index: int) -> str:
    return _IMAGE_TEMPLATE.render(
        page=collection[current_page_index],
    )


def toggle_navigation_button(collection: Collection):
    visible = len(collection) > 1
    return gr.update(visible=visible)


def activate_left_button(current_page_index):
    interactive = current_page_index > 0
    return gr.update(interactive=interactive)


def activate_right_button(collection: Collection, current_page_index):
    interactive = current_page_index + 1 < len(collection)
    return gr.update(interactive=interactive)


def right_button_click(collection: Collection, current_page_index):
    max_index = len(collection) - 1
    return min(max_index, current_page_index + 1)


def left_button_click(current_page_index):
    return max(0, current_page_index - 1)


def update_image_caption(collection: Collection, current_page_index):
    n_pages = len(collection)
    label = os.path.split(collection[current_page_index].path)[-1]
    return f"image {current_page_index + 1} of {n_pages}: `{label}`"


with gr.Blocks() as visualizer:
    gr.Markdown(
        "πŸ›ˆ The image to the below shows where Dawsonia found text in the image."
    )

    with gr.Row():
        # Annotated image panel
        with gr.Column(scale=1):
            image = gr.HTML(
                label="Annotated image",
                padding=False,
                elem_classes="svg-image",
                container=True,
                min_height="40vh",
                max_height="50vh",
                show_label=True,
            )

            image_caption = gr.Markdown(elem_classes="button-group-viz")
            with gr.Row(elem_classes="button-group-viz"):
                left = gr.Button(
                    "← Previous", visible=False, interactive=False, scale=0
                )
                right = gr.Button("Next β†’", visible=False, scale=0)

    collection = gr.State()
    current_page_index = gr.State(0)

    # Wiring of navigation buttons
    left.click(left_button_click, current_page_index, current_page_index)
    right.click(
        right_button_click, [collection, current_page_index], current_page_index
    )

    # Updates on collection change:
    # - update the view
    # - reset the page index (always start on page 0)
    # - toggle visibility of navigation buttons (don't show them for single pages)
    # - update the image caption
    collection.change(
        render_image, inputs=[collection, current_page_index], outputs=image
    )
    collection.change(lambda _: 0, current_page_index, current_page_index)
    collection.change(toggle_navigation_button, collection, left)
    collection.change(toggle_navigation_button, collection, right)
    collection.change(
        update_image_caption,
        inputs=[collection, current_page_index],
        outputs=image_caption,
    )

    # Updates on page change:
    # - update the view
    # - activate/deactivate buttons
    # - update the image caption
    current_page_index.change(
        render_image, inputs=[collection, current_page_index], outputs=image
    )
    current_page_index.change(activate_left_button, current_page_index, left)
    current_page_index.change(
        activate_right_button, [collection, current_page_index], right
    )
    current_page_index.change(
        update_image_caption,
        inputs=[collection, current_page_index],
        outputs=image_caption,
    )