JustPaste
HomeCategoriesAboutDonateContactTerms of UsePrivacy Policy
JustPaste

Free online notepad — write and share instantly

Navigate

  • Home
  • Timeline
  • Categories

Info

  • About
  • Donate
  • Contact

Legal

  • Terms of Use
  • Privacy Policy

© 2026 JustPaste.app. All rights reserved.

Made with ♥ by JustPaste

Untitled Page | JustPaste.app
about 2 months ago10 views
👨‍💻Programming
y este es el código comentado: import numpy as np
import cv2
import random

# ============================================================
# PRÁCTICA 1 - MEJORAMIENTO DE CONTRASTE CON ALGORITMO GENÉTICO
# Versión sencilla y comentada para explicación
# ============================================================

# ------------------------------------------------------------
# 1. CARGAR IMAGEN
# ------------------------------------------------------------
# Se elige la imagen a trabajar.
# Puedes cambiar entre imagen1, imagen2 o imagen3.
#imagen = "imagen1.png"
#imagen = "imagen2.jpeg"
imagen = "imagen3.png"

# cv2.imread(imagen, 0) carga la imagen en escala de grises.
# Después se divide entre 255.0 para normalizar los pixeles
# al rango [0,1], que es el rango que usaremos en la sigmoide.
img = cv2.imread(imagen, 0) / 255.0


# ------------------------------------------------------------
# 2. TRANSFORMACIÓN SIGMOIDE
# ------------------------------------------------------------
# Esta función aplica la transformación sigmoide a la imagen.
# alpha controla qué tan fuerte es el cambio de contraste.
# delta controla el punto donde ocurre el cambio principal.
#
# Fórmula:
# g(x) = 1 / (1 + e^(-alpha(x-delta)))
#
# Al final reescalamos la imagen nuevamente a [0,1].
def sigmoide(img, alpha, delta):
    g = 1 / (1 + np.exp(-alpha * (img - delta)))
    return (g - g.min()) / (g.max() - g.min())


# ------------------------------------------------------------
# 3. FUNCIONES OBJETIVO
# ------------------------------------------------------------
# El algoritmo genético necesita una forma de medir qué tan
# buena es una solución. Aquí usamos dos modelos:
#
# a) Entropía
# b) Desviación estándar


# Entropía:
# Mide la variabilidad o riqueza en la distribución de niveles
# de gris. Para calcularla:
# 1. Convertimos la imagen a 8 bits
# 2. Calculamos el histograma
# 3. Lo convertimos a probabilidades
# 4. Aplicamos la fórmula de entropía
def entropia(img):
    hist = cv2.calcHist([(img * 255).astype(np.uint8)], [0], None, [256], [0, 256])
    p = hist / hist.sum()
    p = p[p > 0]
    return -np.sum(p * np.log2(p))


# Desviación estándar:
# Mide qué tanto se dispersan los valores de intensidad de la
# imagen respecto a su media. Si hay más separación entre zonas
# claras y oscuras, normalmente aumenta.
def desviacion(img):
    return np.std(img)


# ------------------------------------------------------------
# 4. EVALUACIÓN DE UN INDIVIDUO
# ------------------------------------------------------------
# Un individuo representa una posible solución:
# individuo = [alpha, delta]
#
# Para evaluarlo:
# 1. Aplicamos la sigmoide con esos parámetros
# 2. Calculamos su fitness usando el modelo elegido
def evaluar(ind, modelo):
    alpha, delta = ind
    img2 = sigmoide(img, alpha, delta)

    if modelo == "entropia":
        return entropia(img2)
    else:
        return desviacion(img2)


# ------------------------------------------------------------
# 5. CREACIÓN DE UN INDIVIDUO
# ------------------------------------------------------------
# Genera aleatoriamente una solución inicial.
# alpha se genera entre 0 y 10
# delta se genera entre 0 y 1
def crear_ind():
    return [random.uniform(0, 10), random.uniform(0, 1)]


# ------------------------------------------------------------
# 6. SELECCIÓN POR TORNEO
# ------------------------------------------------------------
# Se eligen dos individuos al azar de la población.
# Luego se comparan sus fitness.
# Se selecciona el mejor para reproducirse.
#
# Esto corresponde a torneo binario.
def torneo(pob, fit):
    i, j = random.sample(range(len(pob)), 2)
    return pob[i] if fit[i] > fit[j] else pob[j]


# ------------------------------------------------------------
# 7. CRUZA
# ------------------------------------------------------------
# Esta versión usa una cruza sencilla por promedio.
# A partir de dos padres:
# p1 = [alpha1, delta1]
# p2 = [alpha2, delta2]
#
# Los hijos quedan en el punto medio entre ambos.
#
# Nota:
# En clase se mostró SBX, pero aquí usamos una cruza más simple
# para que el código sea más claro y fácil de explicar.
def cruza(p1, p2):
    hijo1 = [(p1[0] + p2[0]) / 2, (p1[1] + p2[1]) / 2]
    hijo2 = [(p1[0] + p2[0]) / 2, (p1[1] + p2[1]) / 2]
    return hijo1, hijo2


# ------------------------------------------------------------
# 8. MUTACIÓN
# ------------------------------------------------------------
# Con cierta probabilidad, alteramos ligeramente alpha o delta.
#
# alpha puede cambiar entre -1 y 1
# delta puede cambiar entre -0.1 y 0.1
#
# Al final se limita el individuo para que:
# alpha siga en [0,10]
# delta siga en [0,1]
def mutar(ind):
    if random.random() < 0.2:
        ind[0] += random.uniform(-1, 1)

    if random.random() < 0.2:
        ind[1] += random.uniform(-0.1, 0.1)

    ind[0] = min(max(ind[0], 0), 10)
    ind[1] = min(max(ind[1], 0), 1)

    return ind


# ------------------------------------------------------------
# 9. ALGORITMO GENÉTICO
# ------------------------------------------------------------
# Este bloque reúne todo el proceso evolutivo.
#
# Pasos:
# 1. Crear población inicial
# 2. Evaluar población
# 3. Mientras no se llegue al máximo de evaluaciones:
#    - Seleccionar padres
#    - Cruzarlos
#    - Mutar hijos
#    - Formar nueva población
#    - Evaluar nueva población
# 4. Regresar el mejor individuo encontrado
def AG(modelo):
    POP = 10

    # Crear población inicial
    poblacion = [crear_ind() for _ in range(POP)]

    # Evaluar población inicial
    fitness = [evaluar(ind, modelo) for ind in poblacion]

    # Ya evaluamos 10 individuos
    evaluaciones = POP

    # La práctica pide 40 evaluaciones
    while evaluaciones < 40:
        nueva = []

        # Crear una nueva población de tamaño 10
        while len(nueva) < POP:
            # Selección de padres
            p1 = torneo(poblacion, fitness)
            p2 = torneo(poblacion, fitness)

            # Cruza
            h1, h2 = cruza(p1, p2)

            # Mutación
            nueva.append(mutar(h1))
            nueva.append(mutar(h2))

        # Reemplazo total de población
        poblacion = nueva[:POP]

        # Evaluación de la nueva población
        fitness = [evaluar(ind, modelo) for ind in poblacion]

        # Sumamos 10 evaluaciones más
        evaluaciones += POP

    # Elegimos el mejor individuo final
    mejor = poblacion[np.argmax(fitness)]
    return mejor


# ------------------------------------------------------------
# 10. EJECUCIÓN DE LOS DOS MODELOS
# ------------------------------------------------------------
# Se corre el algoritmo dos veces:
# 1. Maximizando entropía
# 2. Maximizando desviación estándar
#
# Para cada caso:
# - Se obtiene el mejor individuo
# - Se genera la imagen mejorada
# - Se guarda en disco
# - Se imprimen los parámetros encontrados
for modelo in ["entropia", "desviacion"]:
    mejor = AG(modelo)

    # Aplicar la sigmoide con la mejor solución encontrada
    img_final = sigmoide(img, mejor[0], mejor[1])

    # Guardar imagen resultante
    cv2.imwrite(f"{modelo}_{imagen}", (img_final * 255).astype(np.uint8))

    # Mostrar en consola los parámetros óptimos encontrados
    print(modelo, "->", mejor)
← Back to timeline