Spaces:
Running
Running
"updated crops layout"
Browse files
app.py
CHANGED
@@ -1,23 +1,22 @@
|
|
1 |
"""
|
2 |
This script creates a Gradio GUI for detecting and classifying signature blocks in document images
|
3 |
using the SignatureBlockModel. It loads example images from the /assets directory, displays
|
4 |
-
bounding boxes in the result image, and shows
|
5 |
"""
|
6 |
|
7 |
import gradio as gr
|
8 |
import numpy as np
|
9 |
from PIL import Image
|
10 |
-
import
|
11 |
-
import io
|
12 |
-
from typing import Tuple
|
13 |
import os
|
14 |
-
|
15 |
from scripts.signature_blocks import SignatureBlockModel
|
16 |
|
17 |
ASSETS_DIR = os.path.join(os.path.dirname(__file__), "assets")
|
18 |
|
19 |
|
20 |
-
def process_image(
|
|
|
|
|
21 |
"""
|
22 |
Process an input image using the SignatureBlockModel.
|
23 |
|
@@ -25,7 +24,7 @@ def process_image(image: np.ndarray) -> Tuple[np.ndarray, str, np.ndarray]:
|
|
25 |
image (np.ndarray): Input image as a numpy array.
|
26 |
|
27 |
Returns:
|
28 |
-
Tuple[np.ndarray, str, np.ndarray]: Processed image, status, and
|
29 |
"""
|
30 |
# Convert numpy array to PIL Image
|
31 |
pil_image = Image.fromarray(image)
|
@@ -53,83 +52,50 @@ def process_image(image: np.ndarray) -> Tuple[np.ndarray, str, np.ndarray]:
|
|
53 |
return np.array(image_with_boxes), status, signature_crops
|
54 |
|
55 |
|
56 |
-
def
|
57 |
"""
|
58 |
-
|
59 |
-
|
60 |
-
Args:
|
61 |
-
crop (np.ndarray): Input crop as a numpy array.
|
62 |
-
target_size (Tuple[int, int]): Target size for the crop.
|
63 |
-
|
64 |
-
Returns:
|
65 |
-
np.ndarray: Resized crop.
|
66 |
-
"""
|
67 |
-
crop_image = Image.fromarray(crop).convert("RGB")
|
68 |
-
crop_size = crop_image.size
|
69 |
-
target_size = tuple(int(dim * factor) for dim in crop_size)
|
70 |
-
print(f"Target Size: {target_size}")
|
71 |
-
crop_image = crop_image.resize(target_size)
|
72 |
-
return np.array(crop_image)
|
73 |
-
|
74 |
-
|
75 |
-
def create_signature_crops(model: SignatureBlockModel) -> np.ndarray:
|
76 |
-
"""
|
77 |
-
Create an image with stacked signature crops and labels.
|
78 |
|
79 |
Args:
|
80 |
model (SignatureBlockModel): The initialized SignatureBlockModel.
|
81 |
|
82 |
Returns:
|
83 |
-
np.ndarray:
|
84 |
"""
|
85 |
boxes = model.get_boxes()
|
86 |
scores = model.get_scores()
|
87 |
labels = model.get_labels()
|
88 |
classes = model.classes
|
89 |
|
90 |
-
|
91 |
-
fig, axes = plt.subplots(len(boxes), 2, figsize=(10, 3 * len(boxes)))
|
92 |
-
# plt.subplots_adjust(hspace=0.5, wspace=0.1) # Add space between subplots
|
93 |
-
|
94 |
-
# Ensure axes is always a 2D array, even with only one box
|
95 |
-
if len(boxes) == 1:
|
96 |
-
axes = axes.reshape(1, -1)
|
97 |
|
98 |
-
for
|
99 |
crop = model.extract_box(box)
|
100 |
-
|
|
|
|
|
101 |
|
102 |
-
|
103 |
-
ax_label.set_facecolor("black")
|
104 |
-
ax_image.set_facecolor("black")
|
105 |
|
106 |
-
# Add label text
|
107 |
-
label_text = f"Label: {classes[label]}\nScore: {score:.2f}"
|
108 |
-
ax_label.text(
|
109 |
-
0.05,
|
110 |
-
0.5,
|
111 |
-
label_text,
|
112 |
-
color="white",
|
113 |
-
fontsize=12,
|
114 |
-
verticalalignment="center",
|
115 |
-
horizontalalignment="left",
|
116 |
-
)
|
117 |
-
ax_label.axis("off")
|
118 |
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
|
123 |
-
|
|
|
|
|
124 |
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
|
|
131 |
|
132 |
-
|
|
|
133 |
|
134 |
|
135 |
def load_examples():
|
@@ -151,12 +117,22 @@ with gr.Blocks() as demo:
|
|
151 |
gr.Markdown("Upload a document image to detect and classify signature blocks.")
|
152 |
|
153 |
with gr.Row():
|
154 |
-
input_image = gr.Image(label="Upload Document Image")
|
155 |
-
output_image = gr.Image(label="Processed Image")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
156 |
|
157 |
with gr.Row():
|
158 |
status_box = gr.Textbox(label="Document Status")
|
159 |
-
signature_crops = gr.Image(label="Signature Crops")
|
160 |
|
161 |
process_btn = gr.Button("Process Image")
|
162 |
|
|
|
1 |
"""
|
2 |
This script creates a Gradio GUI for detecting and classifying signature blocks in document images
|
3 |
using the SignatureBlockModel. It loads example images from the /assets directory, displays
|
4 |
+
bounding boxes in the result image, and shows signature crops with labels in a gallery.
|
5 |
"""
|
6 |
|
7 |
import gradio as gr
|
8 |
import numpy as np
|
9 |
from PIL import Image
|
10 |
+
from typing import Tuple, List
|
|
|
|
|
11 |
import os
|
|
|
12 |
from scripts.signature_blocks import SignatureBlockModel
|
13 |
|
14 |
ASSETS_DIR = os.path.join(os.path.dirname(__file__), "assets")
|
15 |
|
16 |
|
17 |
+
def process_image(
|
18 |
+
image: np.ndarray,
|
19 |
+
) -> Tuple[np.ndarray, str, List[Tuple[np.ndarray, str]]]:
|
20 |
"""
|
21 |
Process an input image using the SignatureBlockModel.
|
22 |
|
|
|
24 |
image (np.ndarray): Input image as a numpy array.
|
25 |
|
26 |
Returns:
|
27 |
+
Tuple[np.ndarray, str, List[Tuple[np.ndarray, str]]]: Processed image, status, and list of crops with labels.
|
28 |
"""
|
29 |
# Convert numpy array to PIL Image
|
30 |
pil_image = Image.fromarray(image)
|
|
|
52 |
return np.array(image_with_boxes), status, signature_crops
|
53 |
|
54 |
|
55 |
+
def create_signature_crops(model: SignatureBlockModel) -> List[Tuple[np.ndarray, str]]:
|
56 |
"""
|
57 |
+
Create individual images for each signature crop with label and score information.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
58 |
|
59 |
Args:
|
60 |
model (SignatureBlockModel): The initialized SignatureBlockModel.
|
61 |
|
62 |
Returns:
|
63 |
+
List[Tuple[np.ndarray, str]]: List of tuples containing crop images and labels.
|
64 |
"""
|
65 |
boxes = model.get_boxes()
|
66 |
scores = model.get_scores()
|
67 |
labels = model.get_labels()
|
68 |
classes = model.classes
|
69 |
|
70 |
+
crop_data = []
|
|
|
|
|
|
|
|
|
|
|
|
|
71 |
|
72 |
+
for box, label, score in zip(boxes, labels, scores):
|
73 |
crop = model.extract_box(box)
|
74 |
+
# resized_crop = resize_crop(crop)
|
75 |
+
label_text = f"{classes[label]}, Score: {score:.2f}"
|
76 |
+
crop_data.append((crop, label_text))
|
77 |
|
78 |
+
return crop_data
|
|
|
|
|
79 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
80 |
|
81 |
+
def resize_crop(crop: np.ndarray, max_height: int = 200) -> np.ndarray:
|
82 |
+
"""
|
83 |
+
Resize a crop to a maximum height while maintaining aspect ratio.
|
84 |
|
85 |
+
Args:
|
86 |
+
crop (np.ndarray): Input crop as a numpy array.
|
87 |
+
max_height (int): Maximum height for the crop.
|
88 |
|
89 |
+
Returns:
|
90 |
+
np.ndarray: Resized crop.
|
91 |
+
"""
|
92 |
+
crop_image = Image.fromarray(crop)
|
93 |
+
aspect_ratio = crop_image.width / crop_image.height
|
94 |
+
new_height = min(crop_image.height, max_height)
|
95 |
+
new_width = int(new_height * aspect_ratio)
|
96 |
|
97 |
+
resized_crop = crop_image.resize((new_width, new_height), Image.LANCZOS)
|
98 |
+
return np.array(resized_crop)
|
99 |
|
100 |
|
101 |
def load_examples():
|
|
|
117 |
gr.Markdown("Upload a document image to detect and classify signature blocks.")
|
118 |
|
119 |
with gr.Row():
|
120 |
+
input_image = gr.Image(label="Upload Document Image", type="numpy", height=500)
|
121 |
+
output_image = gr.Image(label="Processed Image", type="numpy", height=500)
|
122 |
+
|
123 |
+
signature_crops = gr.Gallery(
|
124 |
+
label="Signature Crops",
|
125 |
+
show_label=True,
|
126 |
+
elem_id="gallery",
|
127 |
+
columns=[6],
|
128 |
+
rows=[1],
|
129 |
+
allow_preview=True,
|
130 |
+
object_fit="contain",
|
131 |
+
height=250,
|
132 |
+
)
|
133 |
|
134 |
with gr.Row():
|
135 |
status_box = gr.Textbox(label="Document Status")
|
|
|
136 |
|
137 |
process_btn = gr.Button("Process Image")
|
138 |
|