Revisión automática de la práctica 03-imagen
Este es el resultado de una revisión automática de la prácica 03-imagen, tal y como la hemos recogido de este repositorio de entrega. Por favor, ten en cuenta que al ser una revisión automática, realizada en parte con la ayuda de un asistente de inteligencia artificial generativa, puede incluir errores, y ser incorrecta. Pero leela con atención, porque creemos que puede tener información útil. Si tienes cualquier duda, o crees que la revisión es errónea, por favor, consulta con los profesores de la asignatura.
- Comprobación de archivos con extension '.py'
- Comprobación con ficheros de plantilla
- Comprobación con ficheros de solución
- Revisión automática de programa
- Análisis
- Recomendaciones de mejora
Comprobación de archivos con extension '.py'
- Archivos Python excluidos de la búsqueda: pixels.py, invert.py
- Archivos Python encontrados (excluyendo esos): process.py
Correcto, se elige process.py como entrega.
Comprobación con ficheros de plantilla
Los archivos son diferentes de los de la plantilla.
Comprobación con ficheros de solución
Los archivos son diferentes de los de la solución.
Revisión automática de programa
Programa revisado:
#!/usr/bin/env python3
import sys
import pixels
def lee_argumentos() -> tuple[str, float, int]:
"""Lee los argumentos de la línea de comandos y devuelve el nombre del fichero, el factor de brillo y el desplazamiento."""
if len(sys.argv) != 4:
print("Uso: python3 process.py <fichero_imagen.gif> <factor_brillo (float)> <desplazamiento (int)>")
sys.exit(1)
imagen = sys.argv[1]
try:
brillo = float(sys.argv[2])
except ValueError:
print(f"Error: El factor de brillo debe ser un número real (float). Valor proporcionado: {sys.argv[2]}")
sys.exit(1)
try:
desplazamiento = int(sys.argv[3])
except ValueError:
print(f"Error: El desplazamiento debe ser un número entero (int). Valor proporcionado: {sys.argv[3]}")
sys.exit(1)
return imagen, brillo, desplazamiento
# --------------------------------------------------
def _ajusta_componente(valor: float) -> int:
"""Función auxiliar para asegurar que el valor del componente RGB esté entre 0 y 255."""
if valor > 255:
return 255
elif valor < 0:
return 0
return int(round(valor))
def cambia_brillo(brillo: float):
"""Aplica el factor de brillo a cada pixel de la imagen."""
ancho, alto = pixels.tam_lienzo()
for x in range(ancho):
for y in range(alto):
(r, g, b) = pixels.lee(x, y)
r_nuevo = r * brillo
g_nuevo = g * brillo
b_nuevo = b * brillo
r_final = _ajusta_componente(r_nuevo)
g_final = _ajusta_componente(g_nuevo)
b_final = _ajusta_componente(b_nuevo)
pixels.pinta(x, y, (r_final, g_final, b_final))
# --------------------------------------------------
def cambia_desplazamiento(desplazamiento: int):
"""Aplica la variación de desplazamiento de los colores a cada pixel de la imagen."""
ancho, alto = pixels.tam_lienzo()
for x in range(ancho):
for y in range(alto):
(r, g, b) = pixels.lee(x, y)
r_nuevo = r + desplazamiento
g_nuevo = g + desplazamiento
b_nuevo = b + desplazamiento
r_final = _ajusta_componente(r_nuevo)
g_final = _ajusta_componente(g_nuevo)
b_final = _ajusta_componente(b_nuevo)
pixels.pinta(x, y, (r_final, g_final, b_final))
# --------------------------------------------------
def main():
imagen, brillo, desplazamiento = lee_argumentos()
pixels.prepara(imagen)
cambia_brillo(brillo)
cambia_desplazamiento(desplazamiento)
pixels.espera()
# --------------------------------------------------
if __name__ == "__main__":
main()
Análisis
Cumple con el enunciado
El programa cumple con los requisitos técnicos del enunciado:
- Lee correctamente los argumentos de la línea de comandos con
lee_argumentos(), validando tipos y mostrando mensajes de error. - Aplica el cambio de brillo multiplicando cada componente RGB por el factor y ajustando valores fuera de rango con
_ajusta_componente. - Aplica el desplazamiento sumando el mismo valor entero a los tres componentes RGB, también ajustando valores fuera de rango.
- Sigue el orden de operaciones especificado: primero brillo, luego desplazamiento.
- Incluye la estructura
main()y el bloqueif __name__ == "__main__".
Sin embargo, no sigue PEP8 en la separación de funciones: las líneas #-------------------------------------------------- son innecesarias y no cumplen con la recomendación de dejar dos líneas en blanco entre funciones de nivel superior.
Es fácil de leer y entender
El código es bastante claro para un principiante:
- Usa nombres descriptivos en español (
cambia_brillo,cambia_desplazamiento). - Incluye docstrings explicativos en cada función.
- La lógica de procesamiento de píxeles está bien estructurada con bucles anidados.
- La función auxiliar
_ajusta_componenteencapsula la lógica de ajuste de valores, evitando repetición de código.
Pero podría mejorar en:
- Comentarios breves dentro de las funciones para explicar pasos clave (ej: "Aplicar factor de brillo a cada componente").
- Explicar por qué se usa
round()al convertir el brillo (aunque es correcto, no está explícito en la documentación).
Sigue buenas prácticas de programación
El programa aplica buenas prácticas:
- Separa responsabilidades en funciones independientes.
- Reutiliza la lógica de ajuste de valores con
_ajusta_componente. - Valida tipos de datos y maneja errores de entrada.
- Evita código duplicado en el procesamiento de píxeles.
Pero hay espacios de mejora:
- La función
_ajusta_componentepodría simplificarse usandomin(max(valor, 0), 255)en lugar deif-elif-else. - No se validan explícitamente que los valores de brillo y desplazamiento sean positivos o negativos (aunque el enunciado lo permite).
Recomendaciones de mejora
-
Eliminar las líneas de separación con
#--------------------------------------------------y reemplazarlas por dos líneas en blanco entre funciones, como recomienda PEP8. -
Simplificar
_ajusta_componenteusandomin(max(valor, 0), 255)para evitar condicionales múltiples. -
Agregar comentarios breves en las funciones
cambia_brilloycambia_desplazamientoexplicando que el orden de aplicación (brillo primero, desplazamiento después) afecta el resultado final. -
Documentar el comportamiento de
_ajusta_componenteen su docstring, aclarando que acepta valores flotantes (por el brillo) y enteros (por el desplazamiento), ya que ambos fluyen a través de esta función. - Validar que el factor de brillo sea positivo (aunque el enunciado no lo exige, un brillo negativo no tendría sentido lógico y podría causar errores en el procesamiento).