Spaces:
Sleeping
Sleeping
| import os | |
| import cv2 | |
| import numpy as np | |
| import gradio as gr | |
| from PIL import Image | |
| import pyheif | |
| import uuid | |
| from diffusers import StableDiffusionPipeline | |
| import torch | |
| # --- OUTPUT DIRECTORY --- | |
| OUTPUT_DIR = "outputs" | |
| os.makedirs(OUTPUT_DIR, exist_ok=True) | |
| # --- DEVICE SETUP --- | |
| device = "cpu" # Force CPU | |
| # --- LOAD STABLE DIFFUSION PIPELINE --- | |
| MODEL_NAME = "Lykon/anything-cartoon" # original model | |
| PUBLIC_MODEL = "runwayml/stable-diffusion-v1-5" # fallback | |
| HF_TOKEN = os.getenv("HF_TOKEN", None) # optional token for private repo | |
| try: | |
| pipe = StableDiffusionPipeline.from_pretrained( | |
| MODEL_NAME, | |
| torch_dtype=torch.float32, | |
| use_auth_token=HF_TOKEN | |
| ) | |
| except Exception as e: | |
| print(f"Failed to load '{MODEL_NAME}': {e}") | |
| print(f"Falling back to public model '{PUBLIC_MODEL}'") | |
| pipe = StableDiffusionPipeline.from_pretrained( | |
| PUBLIC_MODEL, | |
| torch_dtype=torch.float32 | |
| ) | |
| pipe.to(device) | |
| # --- HELPER FUNCTIONS --- | |
| def load_image(file): | |
| ext = os.path.splitext(file.name)[1].lower() if hasattr(file, "name") else os.path.splitext(file)[1].lower() | |
| if ext in [".heic", ".heif"]: | |
| if hasattr(file, "read"): | |
| heif_file = pyheif.read_heif(file.read()) | |
| else: | |
| with open(file, "rb") as f: | |
| heif_file = pyheif.read_heif(f.read()) | |
| image = Image.frombytes( | |
| heif_file.mode, | |
| heif_file.size, | |
| heif_file.data, | |
| "raw", | |
| heif_file.mode, | |
| heif_file.stride, | |
| ) | |
| return image | |
| else: | |
| if hasattr(file, "seek"): | |
| file.seek(0) | |
| return Image.open(file) | |
| else: | |
| return Image.open(file) | |
| def apply_filters(file, mode): | |
| image = load_image(file) | |
| img = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR) | |
| if mode == "Gray": | |
| gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) | |
| processed = cv2.cvtColor(gray, cv2.COLOR_GRAY2RGB) | |
| elif mode == "Scratch": | |
| gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) | |
| denoised = cv2.fastNlMeansDenoising(gray, h=10) | |
| processed = cv2.cvtColor(denoised, cv2.COLOR_GRAY2RGB) | |
| elif mode == "Pencil Sketch": | |
| gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) | |
| inv = 255 - gray | |
| blur = cv2.GaussianBlur(inv, (21, 21), 0) | |
| sketch = cv2.divide(gray, 255 - blur, scale=256.0) | |
| processed = cv2.cvtColor(sketch, cv2.COLOR_GRAY2RGB) | |
| elif mode == "Cartoon": | |
| num_down = 2 | |
| num_bilateral = 7 | |
| img_color = img.copy() | |
| for _ in range(num_down): | |
| img_color = cv2.pyrDown(img_color) | |
| for _ in range(num_bilateral): | |
| img_color = cv2.bilateralFilter(img_color, d=9, sigmaColor=75, sigmaSpace=75) | |
| for _ in range(num_down): | |
| img_color = cv2.pyrUp(img_color) | |
| if img_color.shape != img.shape: | |
| img_color = cv2.resize(img_color, (img.shape[1], img.shape[0])) | |
| img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) | |
| img_blur = cv2.medianBlur(img_gray, 7) | |
| edges = cv2.adaptiveThreshold(img_blur, 255, | |
| cv2.ADAPTIVE_THRESH_MEAN_C, | |
| cv2.THRESH_BINARY, 9, 2) | |
| edges = cv2.cvtColor(edges, cv2.COLOR_GRAY2BGR) | |
| cartoon = cv2.bitwise_and(img_color, edges) | |
| processed = cv2.cvtColor(cartoon, cv2.COLOR_BGR2RGB) | |
| elif mode == "AI Cartoon": | |
| pil_img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)) | |
| prompt = "cartoon, anime style, vibrant colors, detailed, smooth" | |
| # CPU only | |
| cartoon_img = pipe(prompt=prompt, image=pil_img, num_inference_steps=30).images[0] | |
| processed = np.array(cartoon_img) | |
| elif mode == "Sepia": | |
| sepia_filter = np.array([[0.272, 0.534, 0.131], | |
| [0.349, 0.686, 0.168], | |
| [0.393, 0.769, 0.189]]) | |
| sepia = cv2.transform(img, sepia_filter) | |
| sepia = np.clip(sepia, 0, 255).astype(np.uint8) | |
| processed = cv2.cvtColor(sepia, cv2.COLOR_BGR2RGB) | |
| elif mode == "Edge Detection": | |
| gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) | |
| edges = cv2.Canny(gray, 100, 200) | |
| processed = cv2.cvtColor(edges, cv2.COLOR_GRAY2RGB) | |
| elif mode == "HSV": | |
| hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) | |
| processed = cv2.cvtColor(hsv, cv2.COLOR_HSV2RGB) | |
| else: | |
| processed = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) | |
| output_filename = f"{uuid.uuid4().hex}_{mode.replace(' ', '_')}.png" | |
| output_path = os.path.join(OUTPUT_DIR, output_filename) | |
| Image.fromarray(processed).save(output_path) | |
| return processed, output_path | |
| # --- GRADIO INTERFACE --- | |
| demo = gr.Interface( | |
| fn=apply_filters, | |
| inputs=[ | |
| gr.File(label="Upload Image (PNG, JPG, HEIC)", type="filepath"), # FIXED | |
| gr.Radio( | |
| choices=["Gray", "Scratch", "Pencil Sketch", "Cartoon", "AI Cartoon", | |
| "Sepia", "Edge Detection", "RGB", "HSV"], | |
| value="Gray", | |
| label="Filter Mode" | |
| ), | |
| ], | |
| outputs=[ | |
| gr.Image(type="numpy", label="Filtered Image"), | |
| gr.File(label="⬇️ Download Image") | |
| ], | |
| title="🎨 Image Filter Lab", | |
| description="Apply filters including AI Cartoon. Supports iPhone HEIC images.", | |
| allow_flagging="never", | |
| theme="soft" | |
| ) | |
| if __name__ == "__main__": | |
| demo.launch() | |