Spaces:
Sleeping
Sleeping
import base64 | |
import io | |
import gradio as gr | |
from ultralytics import YOLO | |
import numpy as np | |
import cv2 | |
from PIL import Image | |
import traceback | |
import json | |
import os | |
from huggingface_hub import hf_hub_download | |
from huggingface_hub import login | |
login(token = os.environ["HUGGINGFACE_TOKEN"],add_to_git_credential=True) | |
# In a Hugging Face Space, authentication is handled by the environment | |
# No need to explicitly set a token in the Space environment | |
try: | |
# Try to download the model from Hugging Face Hub | |
print("Downloading model from Hugging Face Hub...") | |
try: | |
# First try with force_download | |
model_path = hf_hub_download(repo_id="tech4humans/yolov8s-signature-detector", | |
filename="yolov8s.pt", | |
force_download=True) # Force download for Space environment | |
except Exception as force_error: | |
print(f"Force download failed: {str(force_error)}") | |
# Try again without force_download | |
model_path = hf_hub_download(repo_id="tech4humans/yolov8s-signature-detector", | |
filename="yolov8s.pt", | |
force_download=False) | |
# Load the model from the downloaded path | |
model = YOLO(model_path) | |
print(f"Signature detector model loaded successfully from: {model_path}") | |
except Exception as e: | |
print(f"Error downloading/loading model: {str(e)}") | |
print("Falling back to default YOLOv8 model...") | |
try: | |
# Fallback to standard model | |
model = YOLO("yolov8s.pt") | |
print("Standard YOLOv8 model loaded successfully as fallback!") | |
except Exception as fallback_error: | |
print(f"Error loading fallback model: {str(fallback_error)}") | |
traceback.print_exc() | |
raise | |
def preprocess_image(image): | |
"""Convert image to correct format for YOLO.""" | |
if image is None: | |
# Return a blank image if None is provided | |
blank_image = np.zeros((100, 100, 3), dtype=np.uint8) | |
return blank_image | |
elif isinstance(image, str): | |
# If image is a file path | |
return cv2.imread(image) | |
elif isinstance(image, np.ndarray): | |
# If image is already a numpy array | |
if len(image.shape) == 2: # Grayscale | |
return cv2.cvtColor(image, cv2.COLOR_GRAY2RGB) | |
elif image.shape[2] == 4: # RGBA | |
return cv2.cvtColor(image, cv2.COLOR_RGBA2RGB) | |
return image | |
elif isinstance(image, Image.Image): | |
# If image is a PIL Image | |
return np.array(image) | |
# Added support for base64 encoded images | |
elif isinstance(image, str) and image.startswith('data:image'): | |
try: | |
# Extract base64 part | |
encoded_data = image.split(',')[1] | |
binary_data = base64.b64decode(encoded_data) | |
image = Image.open(io.BytesIO(binary_data)) | |
return np.array(image) | |
except Exception as e: | |
print(f"Error decoding base64 image: {str(e)}") | |
raise | |
else: | |
raise ValueError(f"Unsupported image type: {type(image)}") | |
def detect_signature(image): | |
try: | |
if image is None: | |
# Return empty results for None input | |
blank_image = np.zeros((100, 100, 3), dtype=np.uint8) | |
return blank_image, [] | |
# Handle both regular images and base64 encoded ones | |
processed_image = preprocess_image(image) | |
# Save the processed image to a temporary file if it's not already a file path | |
image_path = None | |
if not isinstance(image, str) or not image.startswith('http'): | |
temp_img = Image.fromarray(processed_image) | |
image_path = 'temp_image.jpg' | |
temp_img.save(image_path) | |
else: | |
image_path = image | |
# Run prediction using the direct approach | |
results = model.predict(source=image_path, save=False, verbose=False) | |
if not results or len(results) == 0: | |
return processed_image, [] | |
# Process results | |
result = results[0] | |
output = [] | |
if hasattr(result, 'boxes'): | |
for box in result.boxes: | |
try: | |
conf = float(box.conf[0]) | |
cls = int(box.cls[0]) | |
class_name = model.names[cls] | |
if conf > 0.3: # Confidence threshold | |
output.append({ | |
"confidence": round(conf, 3), | |
"label": class_name | |
}) | |
except Exception as e: | |
print(f"Error processing box: {str(e)}") | |
traceback.print_exc() | |
continue | |
# Use the plotted image with annotations | |
annotated_image = result.plot() | |
return annotated_image, output | |
except Exception as e: | |
print(f"Error in detect_signature: {str(e)}") | |
traceback.print_exc() | |
# Return original image and empty results in case of error | |
if image is None: | |
return np.zeros((100, 100, 3), dtype=np.uint8), [] | |
return image, [] | |
# Add a direct API endpoint for our Node.js server | |
def api_detect_signature(image_data): | |
"""API endpoint for direct signature detection without UI""" | |
try: | |
# Handle None input | |
if image_data is None: | |
return {"success": False, "error": "No image data provided"} | |
# If data is base64 encoded | |
if isinstance(image_data, str) and image_data.startswith('data:image'): | |
# Use the existing function | |
result_img, detections = detect_signature(image_data) | |
# Convert result image to base64 for API response | |
buffered = io.BytesIO() | |
Image.fromarray(result_img).save(buffered, format="JPEG") | |
img_str = base64.b64encode(buffered.getvalue()).decode() | |
return { | |
"success": True, | |
"detections": detections, | |
"annotated_image": f"data:image/jpeg;base64,{img_str}" | |
} | |
else: | |
return {"success": False, "error": "Invalid image format. Send base64 encoded image."} | |
except Exception as e: | |
print(f"Error in api_detect_signature: {str(e)}") | |
traceback.print_exc() | |
return {"success": False, "error": str(e)} | |
# Create Gradio interface | |
interface = gr.Interface( | |
fn=detect_signature, | |
inputs=gr.Image(type="filepath", label="Upload an image"), | |
outputs=[ | |
gr.Image(label="Detected Signatures"), | |
gr.JSON(label="Detection Results") | |
], | |
title="Signature Detector", | |
description="Upload an image to detect signatures", | |
examples=[ | |
["temp_image.jpg"] if os.path.exists("temp_image.jpg") else None | |
], | |
flagging_mode="never", | |
cache_examples=True | |
) | |
# Create a dedicated API endpoint for direct access | |
api_interface = gr.Interface( | |
fn=api_detect_signature, | |
inputs=gr.Textbox(label="Base64 Image", placeholder="data:image/jpeg;base64,..."), | |
outputs=gr.JSON(label="API Response"), | |
title="Signature Detection API", | |
description="For programmatic access", | |
flagging_mode="never", | |
examples=[ | |
["data:image/jpeg;base64,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"] if os.path.exists("temp_image.jpg") else None | |
] | |
) | |
# Create a Gradio Blocks app that includes both interfaces | |
with gr.Blocks() as app: | |
gr.Markdown("# Signature Detection Demo") | |
with gr.Tab("Interactive Demo"): | |
interface.render() | |
with gr.Tab("API Access"): | |
api_interface.render() | |
gr.Markdown(""" | |
## API Usage Instructions | |
You can use this API endpoint from your applications by sending a POST request: | |
### Method 1 (Latest Gradio API, recommended): | |
``` | |
POST /predict | |
{ | |
"data": ["data:image/jpeg;base64,your_base64_encoded_image"] | |
} | |
``` | |
### Method 2 (Standard API): | |
``` | |
POST /api/predict | |
{ | |
"data": ["data:image/jpeg;base64,your_base64_encoded_image"] | |
} | |
``` | |
### Method 3 (Legacy format): | |
``` | |
POST /run/predict | |
{ | |
"fn_index": 0, | |
"data": ["data:image/jpeg;base64,your_base64_encoded_image"] | |
} | |
``` | |
The response will contain detection results and an annotated image. | |
See README-API.md for more details. | |
""") | |
# Launch with specific configs for API access | |
# In Hugging Face Spaces, use Gradio's default launcher settings | |
app.launch( | |
server_name="0.0.0.0", # Bind to all network interfaces | |
show_api=True, # Enable API endpoints | |
allowed_paths=["*.jpg", "*.png", "*.jpeg"] # Allow access to image files | |
) | |