Spaces:
Runtime error
Runtime error
import skia | |
import numpy as np | |
import gradio as gr | |
def load_image(path): | |
"""Load an image from the given path using Skia.""" | |
return skia.Image.open(path) | |
def save_image(image, path): | |
"""Save the given image to the specified path.""" | |
image.save(path) | |
def image_to_array(image): | |
"""Convert a Skia image to a numpy array.""" | |
return np.array(image) | |
def array_to_image(array): | |
"""Convert a numpy array to a Skia image.""" | |
return skia.Image.fromarray(np.uint8(array)) | |
def texture_image_with_normal(A, A_normal, B): | |
"""Texture image B onto image A based on the normal map A_normal.""" | |
# Load images | |
A_img = load_image(A) | |
A_normal_img = load_image(A_normal) | |
B_img = load_image(B) | |
# Convert images to numpy arrays | |
A_array = image_to_array(A_img) | |
A_normal_array = image_to_array(A_normal_img) | |
B_array = image_to_array(B_img) | |
# Ensure all images have the same dimensions | |
assert A_array.shape == A_normal_array.shape == B_array.shape, "All images must have the same dimensions." | |
# Normalize the normal map (values should be between 0 and 1) | |
A_normal_array = A_normal_array / 255.0 | |
# Create an empty array for the textured image | |
textured_array = np.zeros_like(A_array, dtype=np.float32) | |
# Texture the image B onto A based on the normal map | |
for y in range(A_array.shape[0]): | |
for x in range(A_array.shape[1]): | |
# Get the normal vector at this pixel | |
normal = A_normal_array[y, x] | |
# Calculate the offset based on the normal vector | |
offset_x = int(normal[0] * B_array.shape[1]) | |
offset_y = int(normal[1] * B_array.shape[0]) | |
# Calculate the new coordinates in B | |
new_x = (x + offset_x) % B_array.shape[1] | |
new_y = (y + offset_y) % B_array.shape[0] | |
# Apply the texture from B to A | |
textured_array[y, x] = B_array[new_y, new_x] | |
# Convert the textured array back to an image | |
textured_image = array_to_image(textured_array) | |
return textured_image | |
def gradio_interface(A, A_normal, B): | |
"""Gradio interface function to texture images.""" | |
textured_image = texture_image_with_normal(A, A_normal, B) | |
return np.array(textured_image) | |
# Define example inputs | |
examples = [ | |
["examples/image_A_1.png", "examples/image_A_normal_1.png", "examples/image_B_1.png"], | |
["examples/image_A_2.png", "examples/image_A_normal_2.png", "examples/image_B_2.png"], | |
["examples/image_A_3.png", "examples/image_A_normal_3.png", "examples/image_B_3.png"] | |
] | |
# Create Gradio interface | |
iface = gr.Interface( | |
fn=gradio_interface, | |
inputs=[ | |
gr.Image(type="filepath", label="Image A"), | |
gr.Image(type="filepath", label="Normal Map A_normal"), | |
gr.Image(type="filepath", label="Image B") | |
], | |
outputs=gr.Image(type="numpy", label="Textured Image"), | |
title="Image Texturing with Normal Map", | |
description="Upload Image A, its Normal Map A_normal, and Image B to texture B onto A based on A_normal.", | |
examples=examples | |
) | |
# Launch the interface | |
iface.launch() |