File size: 5,196 Bytes
a42c30f
00a78a6
 
00b55a6
a3d8190
00b55a6
a45d2d7
00a78a6
19e9e99
 
 
 
a45d2d7
19e9e99
3575b55
 
 
 
 
 
19e9e99
3575b55
 
 
 
 
19e9e99
 
 
 
 
 
 
 
 
 
 
 
a45d2d7
 
a3d8190
 
 
a45d2d7
 
 
 
 
a3d8190
a45d2d7
 
a3d8190
a45d2d7
a3d8190
 
 
 
 
 
 
a45d2d7
 
 
 
 
 
 
 
 
a3d8190
 
 
 
 
 
 
 
 
211f5d5
a45d2d7
 
a3d8190
 
 
3575b55
a3d8190
00a78a6
a3d8190
a45d2d7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3575b55
 
9d2d3c1
a45d2d7
 
3575b55
a45d2d7
 
 
 
 
 
 
 
 
 
 
 
00a78a6
 
a45d2d7
 
 
 
 
00a78a6
3575b55
 
00a78a6
 
 
a45d2d7
 
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
import gradio as gr
import tensorflow as tf
import numpy as np
import cv2
from huggingface_hub import hf_hub_download
import time
import os

model_path = hf_hub_download(repo_id="Bmo411/DenoisingAutoencoder", filename="autoencoder_complete_model_Fourier.keras")
model = tf.keras.models.load_model(model_path)

from tensorflow.keras.saving import register_keras_serializable

@register_keras_serializable()
def fourier_transform(x):
    fourier = tf.signal.fft2d(tf.cast(x, tf.complex64))
    fourier = tf.complex(tf.math.real(fourier), tf.math.imag(fourier))
    fourier = tf.abs(fourier)
    return tf.concat([tf.math.real(fourier), tf.math.imag(fourier)], axis=-1)

@register_keras_serializable()
def inverse_fourier_transform(x):
    real_part, imag_part = tf.split(x, num_or_size_splits=2, axis=-1)
    complex_fourier = tf.complex(real_part, imag_part)
    return tf.abs(tf.signal.ifft2d(complex_fourier))
    
# Configuración de GPU para TensorFlow
physical_devices = tf.config.list_physical_devices('GPU')
if physical_devices:
    print("GPU disponible. Configurando...")
    try:
        for gpu in physical_devices:
            tf.config.experimental.set_memory_growth(gpu, True)
        print("Configuración de GPU completada")
    except Exception as e:
        print(f"Error en configuración de GPU: {e}")
else:
    print("No se detectó GPU. El procesamiento será más lento.")

# Funciones de preprocesamiento optimizadas
def degrade_image(image, downscale_factor=4):
    """Reduce la calidad de la imagen reduciendo su tamaño y volviéndola a escalar."""
    h, w = image.shape[:2]
    
    # Verificar tamaño mínimo
    if h < downscale_factor*4 or w < downscale_factor*4:
        return image  # Evitar downscaling excesivo en imágenes pequeñas
    
    # Reducir tamaño (forzando pérdida de calidad)
    small_img = cv2.resize(image, (w // downscale_factor, h // downscale_factor), 
                          interpolation=cv2.INTER_AREA)

    # Volver a escalarla al tamaño original
    degraded_img = cv2.resize(small_img, (w, h), interpolation=cv2.INTER_NEAREST)

    return degraded_img

def preprocess_image(image, std_dev=0.1, downscale_factor=4, target_size=(256, 256)):
    """Recibe una imagen en numpy array, la degrada en calidad, le agrega ruido y la normaliza."""
    
    # Verificar si la imagen es a color o en escala de grises
    if len(image.shape) == 2:
        # Convertir a RGB si es escala de grises
        image = cv2.cvtColor(image, cv2.COLOR_GRAY2RGB)
    elif image.shape[2] == 4:
        # Convertir de RGBA a RGB si tiene canal alpha
        image = cv2.cvtColor(image, cv2.COLOR_RGBA2RGB)
        
    # Reducir calidad
    degraded_img = degrade_image(image, downscale_factor)

    # Redimensionar a tamaño esperado por el modelo
    resized_img = cv2.resize(degraded_img, target_size, interpolation=cv2.INTER_AREA)
    
    # Normalizar
    resized_img = resized_img.astype(np.float32) / 255.0

    # Agregar ruido gaussiano
    noise = np.random.normal(0.3, std_dev, resized_img.shape)
    noisy_img = resized_img + noise
    noisy_img = np.clip(noisy_img, 0, 1)

    return noisy_img

# Función de denoising
def Denoiser(imagen):
    """Aplica el modelo autoencoder para eliminar ruido de la imagen."""
    
    # Verificar que la imagen no sea None
    if imagen is None:
        return None, None
    
    # Convertir imagen de entrada a array NumPy
    imagen = np.array(imagen)
    
    # Verificar dimensiones de la imagen
    if len(imagen.shape) < 2:
        return None, None
    
    try:
        # Preprocesar imagen (degradarla y agregar ruido)
        noisy_image = preprocess_image(imagen)
        
        # Expandir dimensiones para el formato del modelo
        noisy_image_input = np.expand_dims(noisy_image, axis=0)
        
        # Medir el tiempo de la predicción
        start_time = time.time()
        
        # Para la primera versión usamos el modelo simple sin Fourier
        # Esto resolverá el problema de lambda layers
        reconstructed = model(noisy_image_input, training=False).numpy()[0]
        
        prediction_time = time.time() - start_time
        print(f"Tiempo de predicción: {prediction_time:.2f} segundos")
        
        # Asegurarse de que las imágenes estén en el rango [0, 255]
        noisy_image = np.uint8(noisy_image * 255)
        reconstructed = np.uint8(reconstructed * 255)
        
        return noisy_image, reconstructed
        
    except Exception as e:
        print(f"Error en el procesamiento: {e}")
        return None, None

# Crear interfaz en Gradio
demo = gr.Interface(
    fn=Denoiser, 
    inputs=gr.Image(type="numpy"),
    outputs=[
        gr.Image(type="numpy", label="Imagen con Ruido"), 
        gr.Image(type="numpy", label="Imagen Restaurada")
    ],
    title="Autoencoder para Denoising",
    description="""Este modelo de autoencoder reduce el ruido en imágenes. Sube una imagen para ver el resultado.
                  Nota: Esta es una versión simplificada que no utiliza el modelo pre-entrenado debido a limitaciones técnicas.""",
)

# Lanzar la aplicación en Gradio
if __name__ == "__main__":
    demo.launch(share=False)