Revisión automática de la práctica 03-borrosa
Este es el resultado de una revisión automática de la prácica 03-borrosa, 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 solución
- Prueba automática del programa
- 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
- Archivos Python encontrados (excluyendo esos): difumina.py
Correcto, se elige difumina.py como entrega.
Comprobación con ficheros de solución
Los archivos son diferentes de los de la solución.
Prueba automática del programa
Pruebas realizadas por 03-borrosa/tests/test_difumina.py:
OK
Revisión automática de programa
Programa revisado:
import sys
import pixels
formato = "Se usa asi: difumina.py <imagen> <etapas>"
def lee_argumentos() -> tuple[str, int]:
if len(sys.argv) != 3:
print(formato)
exit()
imagen = sys.argv[1]
try:
etapas = int(sys.argv[2])
except ValueError:
print(f"Número de etapas debe ser un entero: {sys.argv[2]}")
print(formato)
exit()
return imagen, etapas
def emborrona() -> None:
for x in range(pixels.ancho):
for y in range(pixels.alto):
colores = []
vecinos = [
(x + 1, y),
(x - 1, y),
(x, y + 1),
(x, y - 1)
]
for vx, vy in vecinos:
try:
colores.append(pixels.lee(vx, vy))
except IndexError:
continue
if not colores:
continue
suma_r = sum(c[0] for c in colores)
suma_g = sum(c[1] for c in colores)
suma_b = sum(c[2] for c in colores)
media = (
suma_r // len(colores),
suma_g // len(colores),
suma_b // len(colores)
)
pixels.pinta(x, y, media)
def main() -> None:
imagen, etapas = lee_argumentos()
try:
pixels.prepara(imagen)
except FileNotFoundError:
print(f"Fichero de imagen no encontrado: {imagen}")
print(formato)
exit()
for etapa in range(etapas):
pixels.actualiza()
print(f"Etapa {etapa + 1}")
emborrona()
pixels.espera()
if __name__ == "__main__":
main()
Análisis
Cumple con el enunciado
El programa cumple con los requisitos básicos del enunciado:
- Valida correctamente los argumentos (número, existencia del archivo y formato del número de etapas).
- Sigue la estructura indicada en
main()conlee_argumentos()yemborrona(). - Maneja las excepciones
FileNotFoundErroryValueErrorcomo se especifica. - Itera el número correcto de etapas e imprime los mensajes "Etapa N".
Pero tiene un error crítico en el algoritmo: al modificar los píxeles mientras se recorre la imagen (sin usar una copia temporal), los cálculos de los píxeles vecinos usan valores ya modificados en la misma etapa. Esto distorsiona el resultado final, ya que el promedio debería calcularse siempre con los valores originales de la etapa actual, no con píxeles ya emborronados. Por ejemplo, al procesar el píxel (x,y), si el píxel (x-1,y) ya fue modificado en esta etapa, se usa su valor emborronado en lugar del original, lo que genera un efecto de difusión incorrecto.
Es fácil de leer y entender
El código es claro para un nivel principiante:
- Nombres de funciones y variables descriptivos (
emborrona,vecinos,colores). - Estructura lineal y lógica bien organizada.
- Comentarios implícitos en la lógica (ej.: manejo de bordes con
IndexError).
Mejorable: La función emborrona() podría dividirse en pasos más pequeños (ej.: calcular promedio en una función aparte) para facilitar su comprensión, pero no es crítico para este nivel.
Sigue buenas prácticas de programación
- PEP8: El formato es correcto (indentación, espacios, etc.).
- Manejo de errores: Captura excepciones específicas y muestra mensajes útiles.
-
Modularización: Separa lógica en funciones (
lee_argumentos,emborrona).
Falla grave: No usa una imagen temporal para calcular los nuevos píxeles. Esto viola un principio básico de procesamiento de imágenes: nunca modificar la fuente de datos mientras se está leyendo. El resultado es un algoritmo incorrecto, aunque el código "funcione" visualmente.
Recomendaciones de mejora
-
Usa una copia temporal en
emborrona():- Crea una lista o matriz temporal para almacenar los nuevos colores antes de actualizar la imagen.
- Ejemplo:
nueva_imagen = [] for x in ...: for y in ...: # Calcular promedio y guardarlo en nueva_imagen[x][y] for x in ...: for y in ...: pixels.pinta(x, y, nueva_imagen[x][y])
Esto asegura que todos los píxeles se calculen con los valores originales de la etapa.
-
Corrige el orden de operaciones en el bucle de etapas:
- Según el enunciado, el mensaje "Etapa N" debe mostrarse al iniciar la etapa, pero la imagen debe actualizarse después de procesarla. El código actual llama a
pixels.actualiza()antes deemborrona(), lo que muestra el estado anterior. Debería ser:print(f"Etapa {etapa + 1}") emborrona() pixels.actualiza() # Actualizar DESPUÉS de procesar
Esto garantiza que la imagen mostrada corresponda a la etapa completada.
- Según el enunciado, el mensaje "Etapa N" debe mostrarse al iniciar la etapa, pero la imagen debe actualizarse después de procesarla. El código actual llama a