Fairface / main.py
dfernandezl12's picture
Upload main.py
872de02 verified
Raw
History Blame Contribute Delete
4.76 kB
import os
import numpy as np
import tensorflow as tf
from tensorflow.keras import layers, models
from flask import Flask, request, jsonify, render_template
from PIL import Image
import io
from datasets import load_dataset
# ------------------------------
# Configuración
# ------------------------------
MODEL_PATH = "modelo_sexo.keras" # Cambiado para evitar conflictos con el viejo
IMG_SIZE = (64, 64)
def build_model():
model = models.Sequential([
layers.Conv2D(32, (3, 3), activation='relu', input_shape=(64, 64, 3)),
layers.MaxPooling2D((2, 2)),
layers.Conv2D(64, (3, 3), activation='relu'),
layers.Flatten(),
layers.Dense(64, activation='relu'),
layers.Dense(1, activation='sigmoid') # 1 = mujer, 0 = hombre
])
model.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy'])
return model
def train_and_save_model():
print("Cargando dataset FairFace...")
ds = load_dataset("HuggingFaceM4/FairFace", "0.25")
# Usamos todo el dataset de entrenamiento disponible
ds_train = ds['train']
images = []
labels = []
print("Procesando imágenes para clasificación de género...")
for item in ds_train:
img = item['image'].convert('RGB').resize(IMG_SIZE)
images.append(np.array(img) / 255.0)
# En FairFace: 0 corresponde a 'Male' (Hombre) y 1 a 'Female' (Mujer)
labels.append(1.0 if item['gender'] == 1 else 0.0)
X = np.array(images)
y = np.array(labels)
print(f"Datos cargados: {len(X)} imágenes (mujeres: {sum(y)}, hombres: {len(y)-sum(y)})")
# Entrenar modelo
model = build_model()
print("Entrenando clasificador de género...")
model.fit(X, y, epochs=7, batch_size=64, validation_split=0.2, verbose=1)
# Guardar el nuevo modelo
model.save(MODEL_PATH)
print(f"Modelo guardado como {MODEL_PATH}")
return model
# Cargar modelo o entrenar si no existe
def load_or_train_model():
if os.path.exists(MODEL_PATH):
try:
model = tf.keras.models.load_model(MODEL_PATH)
print("✅ Modelo de género cargado desde disco correctamente")
return model
except Exception as e:
print(f"⚠️ Error al cargar el modelo: {e}")
print("Entrenando uno nuevo...")
return train_and_save_model()
else:
print("Modelo no encontrado. Entrenando desde cero...")
return train_and_save_model()
# Inicializar el modelo global
model = load_or_train_model()
# ------------------------------
# Aplicación Flask
# ------------------------------
app = Flask(__name__)
def predecir_sexo(imagen_bytes):
img = Image.open(io.BytesIO(imagen_bytes)).convert('RGB')
img = img.resize(IMG_SIZE)
img_array = np.array(img) / 255.0
img_array = np.expand_dims(img_array, axis=0)
prediccion = model.predict(img_array, verbose=0)[0][0]
return "mujer" if prediccion >= 0.5 else "hombre"
@app.route('/')
def index():
return render_template('index.html')
@app.route('/predict', methods=['POST'])
def predict():
if 'image' not in request.files:
return jsonify({'error': 'No se encontró ninguna imagen'}), 400
file = request.files['image']
if file.filename == '':
return jsonify({'error': 'Nombre de archivo vacío'}), 400
try:
imagen_bytes = file.read()
# 1. Obtenemos el valor numérico puro de la predicción
img = Image.open(io.BytesIO(imagen_bytes)).convert('RGB')
img = img.resize(IMG_SIZE)
img_array = np.array(img) / 255.0
img_array = np.expand_dims(img_array, axis=0)
# Guardamos la predicción como un float para poder operar con ella
prediccion_raw = float(model.predict(img_array, verbose=0)[0][0])
# 2. Calculamos la clase y el porcentaje de confianza
if prediccion_raw >= 0.5:
genero = "mujer"
# Si es mujer, la confianza es directamente el valor predicho (ej: 0.90 -> 90%)
confianza = prediccion_raw * 100
else:
genero = "hombre"
# Si es hombre, la confianza es lo que le falta para 1 (ej: 0.10 predicho -> 90% seguro de que es hombre)
confianza = (1.0 - prediccion_raw) * 100
# 3. Devolvemos el JSON con ambos datos, formateando la confianza a 2 decimales
return jsonify({
'genero': genero,
'confianza': f"{confianza:.2f}%"
})
except Exception as e:
return jsonify({'error': str(e)}), 500
if __name__ == '__main__':
port = int(os.environ.get("PORT", 7860))
app.run(host='0.0.0.0', port=port)