Spaces:
Running
Running
import numpy as np | |
import cv2 | |
import gradio as gr | |
PCA_MODEL_PATH = "pca_texture_model.npy" | |
COMPONENT_NAMES_PATH = "component_names.txt" | |
# Load PCA model | |
pca = np.load(PCA_MODEL_PATH, allow_pickle=True).item() | |
mean_texture = pca.mean_ | |
components = pca.components_ | |
explained_variance = pca.explained_variance_ | |
n_components = components.shape[0] | |
TEXTURE_SIZE = int(np.sqrt(mean_texture.shape[0] // 3)) | |
# Calculate slider ranges | |
slider_ranges = [3 * np.sqrt(var) for var in explained_variance] | |
# Load component names if available | |
try: | |
with open(COMPONENT_NAMES_PATH, "r") as f: | |
component_names = [f"Component {i+1} ({line.strip()})" if line.strip() else f"Component {i+1}" for i, line in enumerate(f.readlines())] | |
if len(component_names) < n_components: | |
component_names += [f"Component {i+1}" for i in range(len(component_names), n_components)] | |
except FileNotFoundError: | |
component_names = [f"Component {i+1}" for i in range(n_components)] | |
def generate_texture(*component_values): | |
component_values = np.array(component_values) | |
new_texture = mean_texture + np.dot(component_values, components) | |
new_texture = np.clip(new_texture, 0, 255).astype(np.uint8) | |
new_texture = new_texture.reshape((TEXTURE_SIZE, TEXTURE_SIZE, 3)) | |
new_texture = cv2.cvtColor(new_texture, cv2.COLOR_BGR2RGB) | |
return new_texture | |
def randomize_texture(): | |
sampled_coefficients = np.random.normal(0, np.sqrt(explained_variance), size=n_components) | |
return sampled_coefficients.tolist() | |
def update_texture(*component_values): | |
texture = generate_texture(*component_values) | |
return texture | |
def on_random_click(): | |
random_values = randomize_texture() | |
texture = generate_texture(*random_values) | |
# Prepare updates for sliders and the image | |
updates = [gr.update(value=value) for value in random_values] | |
updates.append(texture) | |
return updates | |
def on_image_upload(image): | |
# Process the uploaded image and get PCA coefficients | |
coefficients = process_uploaded_image(image) | |
texture = generate_texture(*coefficients) | |
# Update sliders and image | |
updates = [gr.update(value=value) for value in coefficients] | |
updates.append(texture) | |
return updates | |
# Create Gradio interface | |
with gr.Blocks() as demo: | |
with gr.Row(): | |
with gr.Column(): | |
sliders = [] | |
for i in range(n_components): | |
range_limit = slider_ranges[i] | |
slider = gr.Slider( | |
minimum=-range_limit, | |
maximum=range_limit, | |
step=10, | |
value=0, | |
label=component_names[i] | |
) | |
sliders.append(slider) | |
with gr.Column(): | |
output_image = gr.Image( | |
label="Generated Texture" | |
) | |
random_button = gr.Button("Randomize Texture") | |
upload_image = gr.Image( | |
label="Upload Image", | |
sources=['upload', 'clipboard'], | |
type="numpy" | |
) | |
# Update texture when any slider changes | |
for slider in sliders: | |
slider.change( | |
fn=update_texture, | |
inputs=sliders, | |
outputs=output_image | |
) | |
# Randomize texture and update sliders and image | |
random_button.click( | |
fn=on_random_click, | |
inputs=None, | |
outputs=[*sliders, output_image] | |
) | |
# Update sliders and image based on uploaded image | |
upload_image.change( | |
fn=on_image_upload, | |
inputs=upload_image, | |
outputs=[*sliders, output_image] | |
) | |
demo.launch() | |