File size: 4,340 Bytes
ac73e0b
 
 
 
 
0f44356
8741690
 
ac73e0b
5b17844
 
 
ac73e0b
 
c1bccc1
ac73e0b
8741690
c1bccc1
ac73e0b
9d6728f
 
 
0d21fa6
9d6728f
0d21fa6
9d6728f
0d21fa6
9d6728f
0d21fa6
c1bccc1
ac73e0b
8741690
 
 
c1bccc1
ac73e0b
c1bccc1
 
 
 
0d21fa6
 
 
ac73e0b
0d21fa6
c1bccc1
0d21fa6
 
 
 
ac73e0b
3b2ba80
 
 
 
 
 
 
 
 
 
5c0bb25
 
 
 
 
56e1cfe
 
 
 
c1bccc1
 
 
 
 
 
 
 
 
 
 
 
0d21fa6
c1bccc1
 
 
 
0d21fa6
c1bccc1
5c0bb25
 
cc976c1
5c0bb25
 
f2c754e
 
 
0d21fa6
56e1cfe
 
 
 
 
 
c1bccc1
0d21fa6
c1bccc1
 
0d21fa6
c1bccc1
 
ac73e0b
56e1cfe
 
5c0bb25
 
56e1cfe
 
 
 
 
 
 
 
5c0bb25
 
56e1cfe
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
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)
    updates = [gr.update(value=value) for value in random_values]
    updates.append(texture)
    return updates

def process_uploaded_image(uploaded_image):
    resized_image = cv2.resize(uploaded_image, (TEXTURE_SIZE, TEXTURE_SIZE))
    resized_image = cv2.cvtColor(resized_image, cv2.COLOR_RGB2BGR)
    flattened_image = resized_image.flatten()

    centered_image = flattened_image - mean_texture
    coefficients = np.dot(centered_image, components.T)
    clipped_coefficients = [np.clip(coeff, -slider_ranges[i], slider_ranges[i]) for i, coeff in enumerate(coefficients)]
    return clipped_coefficients

def on_image_upload(image):
    coefficients = process_uploaded_image(image)
    updates = [gr.update(value=value) for value in coefficients]
    return updates

def on_update_click(*component_values):
    texture = generate_texture(*component_values)
    return texture

# 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"
            )
            upload_image = gr.Image(
                label="Upload Image",
                sources=['upload', 'clipboard'],
                type="numpy"
            )
            update_texture_button = gr.Button("Update Texture")
            random_button = gr.Button("Randomize Texture")
            get_components_button = gr.Button("Get Components from Image")
    
    # Update texture when clicking the "Update Texture" button
    update_texture_button.click(
        fn=on_update_click,
        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 based on the uploaded image when clicking "Get Components from Image"
    get_components_button.click(
        fn=on_image_upload,
        inputs=upload_image,
        outputs=sliders
    )

    # Keep the uploaded image for reference (no update on texture yet)
    upload_image.change(
        fn=None,
        inputs=None,
        outputs=[]
    )

demo.launch()