leonett commited on
Commit
10c4b17
·
verified ·
1 Parent(s): 2c37b05

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +40 -29
app.py CHANGED
@@ -8,11 +8,10 @@ from facenet_pytorch import MTCNN
8
  from io import BytesIO
9
  import logging
10
 
11
- logging.basicConfig(level=logging.DEBUG)
12
-
13
  # Configuración
 
14
  device = torch.device("cpu")
15
- CANVAS_SIZE = (256, 256) # Reduced size for free plan
16
 
17
  # Modelo de envejecimiento
18
  class AgingModel(torch.nn.Module):
@@ -32,42 +31,49 @@ class AgingModel(torch.nn.Module):
32
  x = x * (1 + age_factor / 100.0)
33
  return torch.clamp(x, 0, 1)
34
 
 
35
  model = AgingModel().to(device)
36
  model.eval()
37
- mtcnn = MTCNN(image_size=64, margin=0, min_face_size=10, device=device)
38
 
39
  def resize_to_canvas(image, canvas_size=CANVAS_SIZE):
 
40
  img = image.convert("RGB")
41
- img = img.resize(canvas_size, Image.LANCZOS) # Force exact size
42
- return img
 
 
 
43
 
44
  def align_and_preprocess(image):
 
45
  logging.debug("Starting face detection")
46
  if isinstance(image, np.ndarray):
47
  img = Image.fromarray(image).convert("RGB")
48
  elif isinstance(image, Image.Image):
49
  img = image.convert("RGB")
50
  else:
51
- return None, f"Invalid image type: {type(image)}"
52
 
53
  detected_face, _ = mtcnn.detect(img)
54
- logging.debug(f"Detected faces: {detected_face}")
55
  if detected_face is None:
56
- return None, "No face detected. Please upload a clear face image."
57
 
58
  box = detected_face[0].astype(int)
59
  face_img = img.crop((box[0], box[1], box[2], box[3]))
60
 
61
  transform = transforms.Compose([
62
- transforms.Resize((64, 64)),
63
  transforms.ToTensor()
64
  ])
65
  return transform(face_img).unsqueeze(0).to(device), None
66
 
67
  def generate_aged_image(input_image, target_age):
68
- logging.debug("Starting image generation")
 
69
  if input_image is None:
70
- return None, "Please upload a valid image."
71
 
72
  input_image = resize_to_canvas(input_image)
73
  input_tensor, error = align_and_preprocess(input_image)
@@ -76,46 +82,50 @@ def generate_aged_image(input_image, target_age):
76
 
77
  with torch.no_grad():
78
  output = model(input_tensor, target_age)
79
- logging.debug(f"Output tensor min: {output.min()}, max: {output.max()}")
80
 
81
  output_image = output.squeeze().permute(1, 2, 0).cpu().numpy()
82
  output_image = np.clip(output_image * 255, 0, 255).astype(np.uint8)
83
 
84
  output_image = cv2.cvtColor(output_image, cv2.COLOR_RGB2BGR)
85
  gray = cv2.cvtColor(output_image, cv2.COLOR_BGR2GRAY)
86
- edges = cv2.Canny(gray, 100, 200)
87
  edges = cv2.dilate(edges, None, iterations=1)
88
- output_image[edges > 0] = output_image[edges > 0] * 0.6 # Stronger wrinkles
89
  output_image = cv2.cvtColor(output_image, cv2.COLOR_BGR2RGB)
90
 
91
  output_image = output_image.astype(np.float32)
92
- output_image = output_image * (1 - target_age / 300.0) # Stronger tone adjustment
93
- output_image[:, :, 0] = np.clip(output_image[:, :, 0] * 0.95, 0, 255) # Skin yellowing
94
- output_image[:, :, 1] = np.clip(output_image[:, :, 1] * 1.05, 0, 255)
95
- output_image[:, :, 2] = np.clip(output_image[:, :, 2] * 1.1, 0, 255)
96
- output_image = np.clip(output_image, 0, 255).astype(np.uint8)
97
 
98
  result = Image.fromarray(output_image)
99
- result = resize_to_canvas(result)
100
 
101
- # Convert to JPEG
102
  buffer = BytesIO()
103
  result.save(buffer, format="JPEG", quality=95)
104
  jpeg_image = Image.open(buffer)
105
 
106
- logging.debug("Image generation completed")
107
  return jpeg_image, None
108
 
 
109
  def create_interface():
110
- with gr.Blocks() as interface:
111
- gr.Markdown("# Sistema de Envejecimiento Facial")
 
 
 
 
 
 
 
112
  with gr.Row():
113
- with gr.Column():
114
- input_image = gr.Image(label="Imagen de entrada", type="pil", image_mode="RGB", height=256, width=256)
115
  age_slider = gr.Slider(0, 100, value=30, step=1, label="Edad objetivo")
116
  submit_button = gr.Button("Generar imagen envejecida")
117
- with gr.Column():
118
- output_image = gr.Image(label="Resultado envejecido", type="pil", image_mode="RGB", format="jpeg", height=256, width=256)
 
119
  error_message = gr.Textbox(label="Mensajes", interactive=False)
120
 
121
  submit_button.click(
@@ -123,6 +133,7 @@ def create_interface():
123
  inputs=[input_image, age_slider],
124
  outputs=[output_image, error_message]
125
  )
 
126
  return interface
127
 
128
  if __name__ == "__main__":
 
8
  from io import BytesIO
9
  import logging
10
 
 
 
11
  # Configuración
12
+ logging.basicConfig(level=logging.DEBUG)
13
  device = torch.device("cpu")
14
+ CANVAS_SIZE = (512, 512) # Tamaño original del lienzo
15
 
16
  # Modelo de envejecimiento
17
  class AgingModel(torch.nn.Module):
 
31
  x = x * (1 + age_factor / 100.0)
32
  return torch.clamp(x, 0, 1)
33
 
34
+ # Inicializar modelo y MTCNN
35
  model = AgingModel().to(device)
36
  model.eval()
37
+ mtcnn = MTCNN(image_size=128, margin=0, min_face_size=10, device=device) # Más sensible
38
 
39
  def resize_to_canvas(image, canvas_size=CANVAS_SIZE):
40
+ """Redimensionar imagen para ajustarse al lienzo manteniendo proporciones."""
41
  img = image.convert("RGB")
42
+ img.thumbnail(canvas_size, Image.LANCZOS)
43
+ canvas = Image.new("RGB", canvas_size, (255, 255, 255)) # Fondo blanco
44
+ offset = ((canvas_size[0] - img.size[0]) // 2, (canvas_size[1] - img.size[1]) // 2)
45
+ canvas.paste(img, offset)
46
+ return canvas
47
 
48
  def align_and_preprocess(image):
49
+ """Alinear y preprocesar la imagen para el modelo."""
50
  logging.debug("Starting face detection")
51
  if isinstance(image, np.ndarray):
52
  img = Image.fromarray(image).convert("RGB")
53
  elif isinstance(image, Image.Image):
54
  img = image.convert("RGB")
55
  else:
56
+ return None, f"Tipo de imagen no válido: {type(image)}"
57
 
58
  detected_face, _ = mtcnn.detect(img)
59
+ logging.debug(f"Caras detectadas: {detected_face}")
60
  if detected_face is None:
61
+ return None, "No se detectó una cara. Por favor, sube una imagen con un rostro claro."
62
 
63
  box = detected_face[0].astype(int)
64
  face_img = img.crop((box[0], box[1], box[2], box[3]))
65
 
66
  transform = transforms.Compose([
67
+ transforms.Resize((128, 128)),
68
  transforms.ToTensor()
69
  ])
70
  return transform(face_img).unsqueeze(0).to(device), None
71
 
72
  def generate_aged_image(input_image, target_age):
73
+ """Generar imagen envejecida."""
74
+ logging.debug("Iniciando generación de imagen")
75
  if input_image is None:
76
+ return None, "Por favor, sube una imagen válida."
77
 
78
  input_image = resize_to_canvas(input_image)
79
  input_tensor, error = align_and_preprocess(input_image)
 
82
 
83
  with torch.no_grad():
84
  output = model(input_tensor, target_age)
85
+ logging.debug(f"Tensor de salida min: {output.min()}, max: {output.max()}")
86
 
87
  output_image = output.squeeze().permute(1, 2, 0).cpu().numpy()
88
  output_image = np.clip(output_image * 255, 0, 255).astype(np.uint8)
89
 
90
  output_image = cv2.cvtColor(output_image, cv2.COLOR_RGB2BGR)
91
  gray = cv2.cvtColor(output_image, cv2.COLOR_BGR2GRAY)
92
+ edges = cv2.Canny(gray, 50, 150) # Umbrales ajustados para mejor detección
93
  edges = cv2.dilate(edges, None, iterations=1)
94
+ output_image[edges > 0] = output_image[edges > 0] * 0.6 # Arrugas más marcadas
95
  output_image = cv2.cvtColor(output_image, cv2.COLOR_BGR2RGB)
96
 
97
  output_image = output_image.astype(np.float32)
98
+ output_image = np.clip(output_image * (1 - target_age / 300.0), 0, 255).astype(np.uint8)
 
 
 
 
99
 
100
  result = Image.fromarray(output_image)
101
+ result = resize_to_canvas(result) # Ajustar al lienzo final
102
 
 
103
  buffer = BytesIO()
104
  result.save(buffer, format="JPEG", quality=95)
105
  jpeg_image = Image.open(buffer)
106
 
107
+ logging.debug("Generación de imagen completada")
108
  return jpeg_image, None
109
 
110
+ # Interfaz de Gradio
111
  def create_interface():
112
+ with gr.Blocks(css=".container {max-width: 1200px; margin: auto; padding: 20px; background-color: #f5f5f5;} .canvas {width: 512px !important; height: 512px !important; object-fit: contain;}") as interface:
113
+ gr.Markdown(
114
+ """
115
+ # Sistema de Envejecimiento Facial para Personas Desaparecidas
116
+ Sube una imagen y selecciona la edad objetivo para generar una versión envejecida.
117
+ Este sistema está diseñado para apoyar a unidades policiales en la búsqueda de personas desaparecidas.
118
+ """
119
+ )
120
+
121
  with gr.Row():
122
+ with gr.Column(scale=1):
123
+ input_image = gr.Image(label="Imagen de entrada", type="pil", image_mode="RGB", height=512, width=512, elem_classes=["container", "canvas"])
124
  age_slider = gr.Slider(0, 100, value=30, step=1, label="Edad objetivo")
125
  submit_button = gr.Button("Generar imagen envejecida")
126
+
127
+ with gr.Column(scale=1):
128
+ output_image = gr.Image(label="Resultado envejecido", type="pil", image_mode="RGB", format="jpeg", height=512, width=512, elem_classes=["container", "canvas"])
129
  error_message = gr.Textbox(label="Mensajes", interactive=False)
130
 
131
  submit_button.click(
 
133
  inputs=[input_image, age_slider],
134
  outputs=[output_image, error_message]
135
  )
136
+
137
  return interface
138
 
139
  if __name__ == "__main__":