Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -2,8 +2,6 @@ import gradio as gr
|
|
| 2 |
import logging
|
| 3 |
from roboflow import Roboflow
|
| 4 |
from PIL import Image, ImageDraw, ImageFont, ImageFilter
|
| 5 |
-
import cv2
|
| 6 |
-
import numpy as np
|
| 7 |
import os
|
| 8 |
|
| 9 |
# Configure logging
|
|
@@ -22,7 +20,7 @@ PROJECT_NAME = "model_verification_project"
|
|
| 22 |
VERSION_NUMBER = 2
|
| 23 |
FONT_PATH = "./STEVEHANDWRITING-REGULAR.TTF"
|
| 24 |
|
| 25 |
-
# Function to process image and overlay text
|
| 26 |
def process_image(image, text):
|
| 27 |
try:
|
| 28 |
# Initialize Roboflow
|
|
@@ -39,92 +37,73 @@ def process_image(image, text):
|
|
| 39 |
prediction = model.predict(input_image_path, confidence=70, overlap=50).json()
|
| 40 |
logging.debug(f"Inference result: {prediction}")
|
| 41 |
|
| 42 |
-
#
|
| 43 |
-
|
| 44 |
|
|
|
|
| 45 |
for obj in prediction['predictions']:
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
]
|
| 57 |
-
|
| 58 |
-
# Approximate a perspective transformation matrix
|
| 59 |
-
dst_corners = [
|
| 60 |
-
[0, 0], # Top-left in the new perspective
|
| 61 |
-
[width, 0], # Top-right
|
| 62 |
-
[width, height], # Bottom-right
|
| 63 |
-
[0, height], # Bottom-left
|
| 64 |
-
]
|
| 65 |
-
matrix = cv2.getPerspectiveTransform(np.float32(corners), np.float32(dst_corners))
|
| 66 |
-
|
| 67 |
-
# Warp the detected region
|
| 68 |
-
warped = cv2.warpPerspective(image_cv, matrix, (width, height))
|
| 69 |
-
|
| 70 |
-
# Draw text on the warped region
|
| 71 |
-
pil_warped = Image.fromarray(cv2.cvtColor(warped, cv2.COLOR_BGRA2RGBA))
|
| 72 |
-
draw = ImageDraw.Draw(pil_warped)
|
| 73 |
-
|
| 74 |
-
# Calculate dynamic font size and adjust for multi-line text
|
| 75 |
-
font_size = max(10, int(height * 0.2)) # Adjust size relative to height
|
| 76 |
try:
|
| 77 |
-
font = ImageFont.truetype(FONT_PATH, size=
|
| 78 |
-
logging.debug(f"Font loaded successfully: {FONT_PATH} with size {font_size}")
|
| 79 |
except Exception as e:
|
| 80 |
logging.warning(f"Error loading font. Using default. {e}")
|
| 81 |
font = ImageFont.load_default()
|
| 82 |
|
| 83 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 84 |
words = text.split()
|
| 85 |
lines = []
|
| 86 |
current_line = ""
|
|
|
|
| 87 |
for word in words:
|
| 88 |
test_line = f"{current_line} {word}".strip()
|
| 89 |
-
bbox =
|
| 90 |
-
if bbox[2] - bbox[0] <=
|
| 91 |
current_line = test_line
|
| 92 |
else:
|
| 93 |
lines.append(current_line)
|
| 94 |
current_line = word
|
|
|
|
| 95 |
if current_line:
|
| 96 |
lines.append(current_line)
|
| 97 |
|
| 98 |
# Draw each line of text within the bounding box
|
| 99 |
-
line_height =
|
| 100 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 101 |
for i, line in enumerate(lines):
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
text_y =
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
|
| 113 |
-
warped_with_text, matrix_back,
|
| 114 |
-
(image_cv.shape[1], image_cv.shape[0]),
|
| 115 |
-
flags=cv2.WARP_INVERSE_MAP,
|
| 116 |
-
)
|
| 117 |
-
|
| 118 |
-
# Overlay the transformed text onto the original image
|
| 119 |
-
mask = transformed_back[:, :, 3] > 0 # Alpha channel as mask
|
| 120 |
-
logging.debug(f"Alpha mask shape: {mask.shape}, Non-zero values: {np.count_nonzero(mask)}")
|
| 121 |
-
|
| 122 |
-
image_cv[mask] = transformed_back[mask]
|
| 123 |
-
|
| 124 |
-
# Convert back to PIL format and save
|
| 125 |
-
output_image = Image.fromarray(cv2.cvtColor(image_cv, cv2.COLOR_BGRA2RGBA))
|
| 126 |
output_image_path = "/tmp/output_image.png"
|
| 127 |
-
|
| 128 |
return output_image_path
|
| 129 |
|
| 130 |
except Exception as e:
|
|
|
|
| 2 |
import logging
|
| 3 |
from roboflow import Roboflow
|
| 4 |
from PIL import Image, ImageDraw, ImageFont, ImageFilter
|
|
|
|
|
|
|
| 5 |
import os
|
| 6 |
|
| 7 |
# Configure logging
|
|
|
|
| 20 |
VERSION_NUMBER = 2
|
| 21 |
FONT_PATH = "./STEVEHANDWRITING-REGULAR.TTF"
|
| 22 |
|
| 23 |
+
# Function to process image and overlay text
|
| 24 |
def process_image(image, text):
|
| 25 |
try:
|
| 26 |
# Initialize Roboflow
|
|
|
|
| 37 |
prediction = model.predict(input_image_path, confidence=70, overlap=50).json()
|
| 38 |
logging.debug(f"Inference result: {prediction}")
|
| 39 |
|
| 40 |
+
# Open the image for processing
|
| 41 |
+
pil_image = image.convert("RGBA")
|
| 42 |
|
| 43 |
+
# Iterate over detected objects
|
| 44 |
for obj in prediction['predictions']:
|
| 45 |
+
x1 = int(obj['x'] - obj['width'] / 2)
|
| 46 |
+
y1 = int(obj['y'] - obj['height'] / 2)
|
| 47 |
+
x2 = int(obj['x'] + obj['width'] / 2)
|
| 48 |
+
y2 = int(obj['y'] + obj['height'] / 2)
|
| 49 |
+
|
| 50 |
+
# Calculate bounding box dimensions
|
| 51 |
+
box_width = x2 - x1
|
| 52 |
+
box_height = y2 - y1
|
| 53 |
+
|
| 54 |
+
# Load font
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 55 |
try:
|
| 56 |
+
font = ImageFont.truetype(FONT_PATH, size=20) # Set a base font size
|
|
|
|
| 57 |
except Exception as e:
|
| 58 |
logging.warning(f"Error loading font. Using default. {e}")
|
| 59 |
font = ImageFont.load_default()
|
| 60 |
|
| 61 |
+
# Ensure pil_image is in RGBA mode
|
| 62 |
+
if pil_image.mode != "RGBA":
|
| 63 |
+
pil_image = pil_image.convert("RGBA")
|
| 64 |
+
|
| 65 |
+
# Create a transparent text layer
|
| 66 |
+
text_layer = Image.new("RGBA", pil_image.size, (255, 255, 255, 0))
|
| 67 |
+
text_draw = ImageDraw.Draw(text_layer)
|
| 68 |
+
|
| 69 |
+
# Split text into lines to fit within the bounding box
|
| 70 |
words = text.split()
|
| 71 |
lines = []
|
| 72 |
current_line = ""
|
| 73 |
+
|
| 74 |
for word in words:
|
| 75 |
test_line = f"{current_line} {word}".strip()
|
| 76 |
+
bbox = text_draw.textbbox((0, 0), test_line, font=font)
|
| 77 |
+
if bbox[2] - bbox[0] <= box_width: # Check if text fits
|
| 78 |
current_line = test_line
|
| 79 |
else:
|
| 80 |
lines.append(current_line)
|
| 81 |
current_line = word
|
| 82 |
+
|
| 83 |
if current_line:
|
| 84 |
lines.append(current_line)
|
| 85 |
|
| 86 |
# Draw each line of text within the bounding box
|
| 87 |
+
line_height = font.getsize("Hg")[1]
|
| 88 |
+
total_text_height = len(lines) * line_height
|
| 89 |
+
|
| 90 |
+
if total_text_height > box_height:
|
| 91 |
+
logging.warning("Text exceeds bounding box height and may be clipped.")
|
| 92 |
+
|
| 93 |
for i, line in enumerate(lines):
|
| 94 |
+
text_x = x1 + (box_width - text_draw.textbbox((0, 0), line, font=font)[2]) // 2
|
| 95 |
+
text_y = y1 + (i * line_height)
|
| 96 |
+
text_draw.text((text_x, text_y), line, fill=(0, 0, 0, 180), font=font)
|
| 97 |
+
|
| 98 |
+
# Apply slight blur to the text layer
|
| 99 |
+
blurred_text_layer = text_layer.filter(ImageFilter.GaussianBlur(radius=1.0))
|
| 100 |
+
|
| 101 |
+
# Composite the blurred text onto the original image
|
| 102 |
+
pil_image = Image.alpha_composite(pil_image, blurred_text_layer)
|
| 103 |
+
|
| 104 |
+
# Save and return output image path
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 105 |
output_image_path = "/tmp/output_image.png"
|
| 106 |
+
pil_image.convert("RGB").save(output_image_path)
|
| 107 |
return output_image_path
|
| 108 |
|
| 109 |
except Exception as e:
|