diffsketchedit / handler_fresh_1748635858.py
jree423's picture
Backup handler with timestamp 1748635858
70410f6 verified
raw
history blame
12.2 kB
from PIL import Image, ImageDraw, ImageFilter
import math
import random
import io
import base64
class EndpointHandler:
def __init__(self, path=""):
"""Initialize DiffSketchEdit handler for Hugging Face Inference API"""
pass
def __call__(self, data):
"""Edit sketch based on text prompt"""
# Extract prompt
inputs = data.get("inputs", "")
if isinstance(inputs, dict):
prompt = inputs.get("prompt", inputs.get("text", ""))
input_image_data = inputs.get("input_image", None)
edit_type = inputs.get("edit_type", "refine")
else:
prompt = str(inputs)
input_image_data = data.get("input_image", None)
edit_type = data.get("edit_type", "refine")
if not prompt:
prompt = "edit sketch"
# Handle input image if provided
input_image = None
if input_image_data:
try:
if isinstance(input_image_data, str):
# Base64 encoded image
img_data = base64.b64decode(input_image_data)
input_image = Image.open(io.BytesIO(img_data)).convert('RGB')
input_image = input_image.resize((224, 224))
except Exception:
input_image = None
# Generate/edit sketch
image = self.edit_sketch(prompt, input_image, edit_type)
# Return PIL Image directly for HF Inference API
return image
def edit_sketch(self, prompt, input_image=None, edit_type="refine"):
"""Edit or create a sketch based on the prompt"""
if input_image is None:
# Create initial sketch
img = self._create_initial_sketch(prompt)
else:
img = input_image.copy()
# Apply editing based on type
if edit_type == "refine":
img = self._refine_sketch(img, prompt)
elif edit_type == "style_transfer":
img = self._apply_style_transfer(img, prompt)
elif edit_type == "add_details":
img = self._add_details(img, prompt)
elif edit_type == "color":
img = self._apply_coloring(img, prompt)
else:
# Default refinement
img = self._refine_sketch(img, prompt)
return img
def _create_initial_sketch(self, prompt):
"""Create initial sketch based on prompt"""
img = Image.new('RGB', (224, 224), 'white')
draw = ImageDraw.Draw(img)
prompt_lower = prompt.lower()
if any(word in prompt_lower for word in ['house', 'building', 'home']):
self._draw_house_sketch(draw)
elif any(word in prompt_lower for word in ['tree', 'plant', 'nature']):
self._draw_tree_sketch(draw)
elif any(word in prompt_lower for word in ['face', 'portrait', 'person']):
self._draw_face_sketch(draw)
elif any(word in prompt_lower for word in ['car', 'vehicle']):
self._draw_car_sketch(draw)
elif any(word in prompt_lower for word in ['flower', 'bloom']):
self._draw_flower_sketch(draw)
else:
self._draw_abstract_sketch(draw, prompt)
return img
def _draw_house_sketch(self, draw):
"""Draw basic house sketch"""
# Base
draw.rectangle([50, 120, 174, 180], outline='black', width=2)
# Roof
draw.polygon([(50, 120), (112, 80), (174, 120)], outline='black', width=2)
# Door
draw.rectangle([100, 150, 124, 180], outline='black', width=2)
# Windows
draw.rectangle([70, 140, 90, 160], outline='black', width=2)
draw.rectangle([134, 140, 154, 160], outline='black', width=2)
def _draw_tree_sketch(self, draw):
"""Draw basic tree sketch"""
# Trunk
draw.rectangle([105, 140, 119, 200], fill='brown', outline='black', width=2)
# Crown
draw.ellipse([70, 80, 154, 150], outline='green', width=3)
# Branches
for angle in range(0, 360, 60):
x = 112 + 25 * math.cos(math.radians(angle))
y = 115 + 25 * math.sin(math.radians(angle))
draw.line([112, 115, x, y], fill='brown', width=2)
def _draw_face_sketch(self, draw):
"""Draw basic face sketch"""
center = (112, 112)
# Head outline
draw.ellipse([center[0]-40, center[1]-50, center[0]+40, center[1]+30],
outline='black', width=2)
# Eyes
draw.ellipse([center[0]-20, center[1]-20, center[0]-10, center[1]-10],
outline='black', width=2)
draw.ellipse([center[0]+10, center[1]-20, center[0]+20, center[1]-10],
outline='black', width=2)
# Nose
draw.line([center[0], center[1]-5, center[0]-3, center[1]+5], fill='black', width=2)
# Mouth
draw.arc([center[0]-15, center[1]+5, center[0]+15, center[1]+20], 0, 180, fill='black', width=2)
def _draw_car_sketch(self, draw):
"""Draw basic car sketch"""
# Body
draw.rectangle([50, 120, 174, 160], outline='black', width=2)
# Roof
draw.rectangle([70, 100, 154, 120], outline='black', width=2)
# Wheels
draw.ellipse([60, 150, 80, 170], outline='black', width=2)
draw.ellipse([144, 150, 164, 170], outline='black', width=2)
# Windows
draw.rectangle([75, 105, 100, 115], outline='black', width=1)
draw.rectangle([124, 105, 149, 115], outline='black', width=1)
def _draw_flower_sketch(self, draw):
"""Draw basic flower sketch"""
center = (112, 112)
# Stem
draw.line([center[0], center[1]+20, center[0], 200], fill='green', width=4)
# Petals
for angle in range(0, 360, 45):
x = center[0] + 25 * math.cos(math.radians(angle))
y = center[1] + 25 * math.sin(math.radians(angle))
draw.ellipse([x-8, y-15, x+8, y+5], outline='black', width=2)
# Center
draw.ellipse([center[0]-8, center[1]-8, center[0]+8, center[1]+8],
outline='black', width=2)
def _draw_abstract_sketch(self, draw, prompt):
"""Draw abstract sketch"""
prompt_hash = hash(prompt) % 100
for i in range(5):
x1 = (i * 40 + prompt_hash) % 180 + 22
y1 = (i * 30 + prompt_hash) % 160 + 32
x2 = x1 + 40 + (i * 10) % 30
y2 = y1 + 60 + (i * 15) % 40
draw.ellipse([x1, y1, x2, y2], outline='black', width=2)
def _refine_sketch(self, img, prompt):
"""Refine the sketch with enhanced details"""
# Apply sharpening
img = img.filter(ImageFilter.SHARPEN)
draw = ImageDraw.Draw(img)
# Add refinement details based on prompt
prompt_lower = prompt.lower()
if "house" in prompt_lower:
# Add roof tiles
for y in range(80, 120, 5):
for x in range(50 + (y-80)//2, 174 - (y-80)//2, 10):
draw.line([x, y, x+5, y], fill='gray', width=1)
# Add door handle
draw.ellipse([120, 164, 122, 166], fill='black')
elif "tree" in prompt_lower:
# Add leaf details
for i in range(10):
x = 70 + random.randint(0, 84)
y = 80 + random.randint(0, 70)
draw.ellipse([x-2, y-2, x+2, y+2], fill='green')
elif "face" in prompt_lower:
# Add facial details
center = (112, 112)
# Eyebrows
draw.arc([center[0]-25, center[1]-35, center[0]-5, center[1]-25], 0, 180, fill='black', width=2)
draw.arc([center[0]+5, center[1]-35, center[0]+25, center[1]-25], 0, 180, fill='black', width=2)
# Pupils
draw.ellipse([center[0]-17, center[1]-17, center[0]-13, center[1]-13], fill='black')
draw.ellipse([center[0]+13, center[1]-17, center[0]+17, center[1]-13], fill='black')
return img
def _apply_style_transfer(self, img, prompt):
"""Apply style transfer effects"""
prompt_lower = prompt.lower()
if "cartoon" in prompt_lower:
# Cartoon style - enhance colors and add outlines
img = img.filter(ImageFilter.EDGE_ENHANCE_MORE)
# Increase saturation
from PIL import ImageEnhance
enhancer = ImageEnhance.Color(img)
img = enhancer.enhance(1.5)
elif "realistic" in prompt_lower:
# Realistic style - add shading and texture
img = img.filter(ImageFilter.GaussianBlur(radius=0.5))
# Add subtle noise for texture
import numpy as np
pixels = np.array(img)
noise = np.random.normal(0, 3, pixels.shape)
pixels = np.clip(pixels + noise, 0, 255).astype(np.uint8)
img = Image.fromarray(pixels)
elif "watercolor" in prompt_lower:
# Watercolor style - soft edges and bleeding
img = img.filter(ImageFilter.GaussianBlur(radius=1.0))
from PIL import ImageEnhance
enhancer = ImageEnhance.Color(img)
img = enhancer.enhance(0.8)
return img
def _add_details(self, img, prompt):
"""Add contextual details to the sketch"""
draw = ImageDraw.Draw(img)
prompt_lower = prompt.lower()
if "landscape" in prompt_lower:
# Add clouds
for i in range(3):
x = 40 + i * 60
y = 30 + i * 10
draw.ellipse([x, y, x+30, y+15], fill='lightgray', outline='gray')
# Add birds
for i in range(2):
x = 60 + i * 80
y = 50 + i * 5
draw.arc([x, y, x+10, y+5], 0, 180, fill='black', width=1)
elif "portrait" in prompt_lower:
# Add hair details
center = (112, 112)
for i in range(15):
x = center[0] + random.randint(-50, 50)
y = center[1] - 60 + random.randint(0, 30)
draw.line([x, y, x + random.randint(-5, 5), y + random.randint(10, 30)],
fill='brown', width=1)
elif "building" in prompt_lower:
# Add architectural details
# Window frames
draw.rectangle([69, 139, 91, 161], outline='black', width=1)
draw.rectangle([133, 139, 155, 161], outline='black', width=1)
# Chimney
draw.rectangle([140, 70, 150, 90], outline='black', width=2)
return img
def _apply_coloring(self, img, prompt):
"""Apply coloring to the sketch"""
# Convert to RGBA for transparency effects
img = img.convert('RGBA')
# Create color overlay
color_overlay = Image.new('RGBA', img.size, (0, 0, 0, 0))
draw = ImageDraw.Draw(color_overlay)
prompt_lower = prompt.lower()
if "sunset" in prompt_lower:
# Sunset colors
draw.rectangle([0, 0, 224, 112], fill=(255, 200, 100, 50))
draw.rectangle([0, 112, 224, 224], fill=(255, 150, 50, 30))
elif "nature" in prompt_lower:
# Nature colors
draw.rectangle([0, 140, 224, 224], fill=(100, 200, 100, 40)) # Green ground
draw.rectangle([0, 0, 224, 140], fill=(150, 200, 255, 30)) # Blue sky
elif "warm" in prompt_lower:
# Warm color palette
draw.rectangle([0, 0, 224, 224], fill=(255, 200, 150, 25))
elif "cool" in prompt_lower:
# Cool color palette
draw.rectangle([0, 0, 224, 224], fill=(150, 200, 255, 25))
# Blend with original
img = Image.alpha_composite(img, color_overlay)
img = img.convert('RGB')
return img