File size: 4,489 Bytes
f725299
 
 
340c680
f725299
 
 
 
 
340c680
f725299
 
 
 
 
 
340c680
 
 
f725299
 
 
 
 
 
 
340c680
f725299
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
340c680
f725299
340c680
f725299
 
 
 
 
340c680
f725299
 
 
 
 
 
340c680
f725299
340c680
f725299
340c680
 
 
f725299
340c680
f725299
 
340c680
 
 
f725299
340c680
 
 
f725299
340c680
 
 
 
 
 
 
f725299
340c680
 
f725299
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
340c680
 
 
 
 
 
 
 
 
 
 
 
 
f725299
 
 
 
 
 
 
 
8e67fbc
f725299
8e67fbc
 
f725299
 
 
 
 
 
 
 
 
 
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
"""
This script creates a Gradio GUI for detecting and classifying signature blocks in document images
using the SignatureBlockModel. It loads example images from the /assets directory, displays
bounding boxes in the result image, and shows signature crops with labels in a gallery.
"""

import gradio as gr
import numpy as np
from PIL import Image
from typing import Tuple, List
import os
from scripts.signature_blocks import SignatureBlockModel

ASSETS_DIR = os.path.join(os.path.dirname(__file__), "assets")


def process_image(
    image: np.ndarray,
) -> Tuple[np.ndarray, str, List[Tuple[np.ndarray, str]]]:
    """
    Process an input image using the SignatureBlockModel.

    Args:
        image (np.ndarray): Input image as a numpy array.

    Returns:
        Tuple[np.ndarray, str, List[Tuple[np.ndarray, str]]]: Processed image, status, and list of crops with labels.
    """
    # Convert numpy array to PIL Image
    pil_image = Image.fromarray(image)

    # Initialize the model
    model = SignatureBlockModel(pil_image)

    # Get processed image with boxes
    image_with_boxes = model.draw_boxes()

    # Get signature crops
    signature_crops = create_signature_crops(model)

    # Determine status
    labels = model.get_labels()
    if not labels.any():
        status = "Unsigned"
    elif all(label == 1 for label in labels):
        status = "Fully Executed"
    elif all(label == 2 for label in labels):
        status = "Unsigned"
    else:
        status = "Partially Executed"

    return np.array(image_with_boxes), status, signature_crops


def create_signature_crops(model: SignatureBlockModel) -> List[Tuple[np.ndarray, str]]:
    """
    Create individual images for each signature crop with label and score information.

    Args:
        model (SignatureBlockModel): The initialized SignatureBlockModel.

    Returns:
        List[Tuple[np.ndarray, str]]: List of tuples containing crop images and labels.
    """
    boxes = model.get_boxes()
    scores = model.get_scores()
    labels = model.get_labels()
    classes = model.classes

    crop_data = []

    for box, label, score in zip(boxes, labels, scores):
        crop = model.extract_box(box)
        # resized_crop = resize_crop(crop)
        label_text = f"{classes[label]}, Score: {score:.2f}"
        crop_data.append((crop, label_text))

    return crop_data


def resize_crop(crop: np.ndarray, max_height: int = 200) -> np.ndarray:
    """
    Resize a crop to a maximum height while maintaining aspect ratio.

    Args:
        crop (np.ndarray): Input crop as a numpy array.
        max_height (int): Maximum height for the crop.

    Returns:
        np.ndarray: Resized crop.
    """
    crop_image = Image.fromarray(crop)
    aspect_ratio = crop_image.width / crop_image.height
    new_height = min(crop_image.height, max_height)
    new_width = int(new_height * aspect_ratio)

    resized_crop = crop_image.resize((new_width, new_height), Image.LANCZOS)
    return np.array(resized_crop)


def load_examples():
    """
    Load example images from the /assets directory.

    Returns:
        List[List[str]]: List of example image paths.
    """
    examples = []
    for filename in os.listdir(ASSETS_DIR):
        if filename.lower().endswith((".png", ".jpg", ".jpeg")):
            examples.append([os.path.join(ASSETS_DIR, filename)])
    return examples


with gr.Blocks() as demo:
    gr.Markdown("# Signature Block Detection")
    gr.Markdown("Upload a document image to detect and classify signature blocks.")

    with gr.Row():
        input_image = gr.Image(label="Upload Document Image", type="numpy", height=500)
        output_image = gr.Image(label="Processed Image", type="numpy", height=500)

    signature_crops = gr.Gallery(
        label="Signature Crops",
        show_label=True,
        elem_id="gallery",
        columns=[6],
        rows=[1],
        allow_preview=True,
        object_fit="contain",
        height=250,
    )

    with gr.Row():
        status_box = gr.Textbox(label="Document Status")

    process_btn = gr.Button("Process Image")

    examples = gr.Examples(
        examples=load_examples(),
        fn=process_image,
        inputs=input_image,
        outputs=[output_image, status_box, signature_crops],
        cache_examples=True,
    )

    process_btn.click(
        fn=process_image,
        inputs=input_image,
        outputs=[output_image, status_box, signature_crops],
    )

if __name__ == "__main__":
    demo.launch()