Spaces:
Running
Running
support heic and heif
Browse filesadd pip freeze and environ printing at the beginning of the demo
add image_utils patch that intercepts large heic images and forces their downsampling
- app.py +7 -0
- gradio_dualvision/app_template.py +9 -1
- gradio_dualvision/gradio_patches/image_utils.py +92 -0
- requirements.txt +1 -0
app.py
CHANGED
|
@@ -63,12 +63,19 @@ class ImageFiltersApp(DualVisionApp):
|
|
| 63 |
Process an input image into multiple modalities using the provided arguments or default settings.
|
| 64 |
Returns two dictionaries: one containing the modalities and another with the actual settings.
|
| 65 |
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 66 |
filter_size = kwargs.get("filter_size", self.DEFAULT_FILTER_SIZE)
|
| 67 |
|
|
|
|
| 68 |
image_out_gray = image_in.convert("L")
|
| 69 |
image_out_gaussian = image_in.filter(ImageFilter.GaussianBlur(filter_size // 2))
|
| 70 |
image_out_median = image_in.filter(ImageFilter.MedianFilter(filter_size))
|
| 71 |
|
|
|
|
| 72 |
out_modalities = {
|
| 73 |
"Gray": image_out_gray,
|
| 74 |
"Gaussian": image_out_gaussian,
|
|
|
|
| 63 |
Process an input image into multiple modalities using the provided arguments or default settings.
|
| 64 |
Returns two dictionaries: one containing the modalities and another with the actual settings.
|
| 65 |
"""
|
| 66 |
+
# Downscale the image to 1024px on the longer side
|
| 67 |
+
scale = min(1.0, 1024 / max(image_in.width, image_in.height))
|
| 68 |
+
image_in = image_in.resize((round(image_in.width * scale), round(image_in.height * scale)), Image.LANCZOS)
|
| 69 |
+
|
| 70 |
+
# Read settings from kwargs or use default
|
| 71 |
filter_size = kwargs.get("filter_size", self.DEFAULT_FILTER_SIZE)
|
| 72 |
|
| 73 |
+
# Process the input image in a variety of ways
|
| 74 |
image_out_gray = image_in.convert("L")
|
| 75 |
image_out_gaussian = image_in.filter(ImageFilter.GaussianBlur(filter_size // 2))
|
| 76 |
image_out_median = image_in.filter(ImageFilter.MedianFilter(filter_size))
|
| 77 |
|
| 78 |
+
# Return the results and current settings to update the UI
|
| 79 |
out_modalities = {
|
| 80 |
"Gray": image_out_gray,
|
| 81 |
"Gaussian": image_out_gaussian,
|
gradio_dualvision/app_template.py
CHANGED
|
@@ -21,11 +21,18 @@
|
|
| 21 |
# https://github.com/prs-eth/Marigold-DC#-citation
|
| 22 |
# https://github.com/prs-eth/rollingdepth#-citation
|
| 23 |
# --------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
import glob
|
| 25 |
import json
|
| 26 |
-
import os
|
| 27 |
import re
|
| 28 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 29 |
import gradio as gr
|
| 30 |
from .version import __version__
|
| 31 |
|
|
@@ -39,6 +46,7 @@ import spaces
|
|
| 39 |
from PIL import Image as PILImage
|
| 40 |
from gradio import Component, ImageSlider
|
| 41 |
|
|
|
|
| 42 |
from .gradio_patches.examples import Examples
|
| 43 |
from .gradio_patches.gallery import Gallery
|
| 44 |
from .gradio_patches.image import Image
|
|
|
|
| 21 |
# https://github.com/prs-eth/Marigold-DC#-citation
|
| 22 |
# https://github.com/prs-eth/rollingdepth#-citation
|
| 23 |
# --------------------------------------------------------------------------
|
| 24 |
+
import os
|
| 25 |
+
print("\n".join(f"{k}={v}" for k, v in os.environ.items()))
|
| 26 |
+
os.system("pip freeze")
|
| 27 |
+
|
| 28 |
import glob
|
| 29 |
import json
|
|
|
|
| 30 |
import re
|
| 31 |
|
| 32 |
+
from pi_heif import register_heif_opener
|
| 33 |
+
register_heif_opener()
|
| 34 |
+
|
| 35 |
+
|
| 36 |
import gradio as gr
|
| 37 |
from .version import __version__
|
| 38 |
|
|
|
|
| 46 |
from PIL import Image as PILImage
|
| 47 |
from gradio import Component, ImageSlider
|
| 48 |
|
| 49 |
+
from .gradio_patches import image_utils
|
| 50 |
from .gradio_patches.examples import Examples
|
| 51 |
from .gradio_patches.gallery import Gallery
|
| 52 |
from .gradio_patches.image import Image
|
gradio_dualvision/gradio_patches/image_utils.py
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import annotations
|
| 2 |
+
|
| 3 |
+
import warnings
|
| 4 |
+
from pathlib import Path
|
| 5 |
+
from typing import Literal, cast
|
| 6 |
+
|
| 7 |
+
import gradio
|
| 8 |
+
from gradio.image_utils import decode_base64_to_file, decode_base64_to_image, decode_base64_to_image_array, format_image
|
| 9 |
+
import numpy as np
|
| 10 |
+
import PIL.Image
|
| 11 |
+
from PIL import ImageOps
|
| 12 |
+
|
| 13 |
+
from gradio import processing_utils
|
| 14 |
+
from gradio.data_classes import ImageData
|
| 15 |
+
from gradio.exceptions import Error
|
| 16 |
+
|
| 17 |
+
PIL.Image.init() # fixes https://github.com/gradio-app/gradio/issues/2843 (remove when requiring Pillow 9.4+)
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
def patched_preprocess_image(
|
| 21 |
+
payload: ImageData | None,
|
| 22 |
+
cache_dir: str,
|
| 23 |
+
format: str,
|
| 24 |
+
image_mode: Literal[
|
| 25 |
+
"1", "L", "P", "RGB", "RGBA", "CMYK", "YCbCr", "LAB", "HSV", "I", "F"
|
| 26 |
+
]
|
| 27 |
+
| None,
|
| 28 |
+
type: Literal["numpy", "pil", "filepath"],
|
| 29 |
+
) -> np.ndarray | PIL.Image.Image | str | None:
|
| 30 |
+
if payload is None:
|
| 31 |
+
return payload
|
| 32 |
+
if payload.url and payload.url.startswith("data:"):
|
| 33 |
+
if type == "pil":
|
| 34 |
+
print("Preprocessing payload as PIL image")
|
| 35 |
+
return decode_base64_to_image(payload.url)
|
| 36 |
+
elif type == "numpy":
|
| 37 |
+
print("Preprocessing payload as numpy array")
|
| 38 |
+
return decode_base64_to_image_array(payload.url)
|
| 39 |
+
elif type == "filepath":
|
| 40 |
+
print("Preprocessing payload as file path")
|
| 41 |
+
return decode_base64_to_file(payload.url, cache_dir, format)
|
| 42 |
+
if payload.path is None:
|
| 43 |
+
raise ValueError("Image path is None.")
|
| 44 |
+
file_path = Path(payload.path)
|
| 45 |
+
if payload.orig_name:
|
| 46 |
+
p = Path(payload.orig_name)
|
| 47 |
+
name = p.stem
|
| 48 |
+
suffix = p.suffix.replace(".", "")
|
| 49 |
+
if suffix in ["jpg", "jpeg"]:
|
| 50 |
+
suffix = "jpeg"
|
| 51 |
+
else:
|
| 52 |
+
name = "image"
|
| 53 |
+
suffix = "webp"
|
| 54 |
+
|
| 55 |
+
if suffix.lower() == "svg":
|
| 56 |
+
if type == "filepath":
|
| 57 |
+
return str(file_path)
|
| 58 |
+
raise Error("SVG files are not supported as input images for this app.")
|
| 59 |
+
|
| 60 |
+
# Check for heif or heic suffix, treat it as a special case and drop resolution immediately
|
| 61 |
+
if suffix.lower() in ["heif", "heic"] and type == "filepath":
|
| 62 |
+
im = PIL.Image.open(file_path).convert("RGB")
|
| 63 |
+
scale = min(1.0, 1024 / max(im.width, im.height))
|
| 64 |
+
im = im.resize((round(im.width * scale), round(im.height * scale)), PIL.Image.BILINEAR)
|
| 65 |
+
file_path = processing_utils.save_pil_to_cache(im, cache_dir=cache_dir)
|
| 66 |
+
|
| 67 |
+
im = PIL.Image.open(file_path)
|
| 68 |
+
if type == "filepath" and (image_mode in [None, im.mode]):
|
| 69 |
+
return str(file_path)
|
| 70 |
+
|
| 71 |
+
exif = im.getexif()
|
| 72 |
+
# 274 is the code for image rotation and 1 means "correct orientation"
|
| 73 |
+
if exif.get(274, 1) != 1 and hasattr(ImageOps, "exif_transpose"):
|
| 74 |
+
try:
|
| 75 |
+
im = ImageOps.exif_transpose(im)
|
| 76 |
+
except Exception:
|
| 77 |
+
warnings.warn(f"Failed to transpose image {file_path} based on EXIF data.")
|
| 78 |
+
if suffix.lower() != "gif" and im is not None:
|
| 79 |
+
with warnings.catch_warnings():
|
| 80 |
+
warnings.simplefilter("ignore")
|
| 81 |
+
if image_mode is not None:
|
| 82 |
+
im = im.convert(image_mode)
|
| 83 |
+
return format_image(
|
| 84 |
+
im,
|
| 85 |
+
type=cast(Literal["numpy", "pil", "filepath"], type),
|
| 86 |
+
cache_dir=cache_dir,
|
| 87 |
+
name=name,
|
| 88 |
+
format=suffix,
|
| 89 |
+
)
|
| 90 |
+
|
| 91 |
+
|
| 92 |
+
gradio.image_utils.preprocess_image = patched_preprocess_image
|
requirements.txt
CHANGED
|
@@ -1,3 +1,4 @@
|
|
| 1 |
gradio==5.29.0
|
| 2 |
gradio_client==1.10.0
|
|
|
|
| 3 |
spaces==0.36.0
|
|
|
|
| 1 |
gradio==5.29.0
|
| 2 |
gradio_client==1.10.0
|
| 3 |
+
pi_heif==1.1.1
|
| 4 |
spaces==0.36.0
|