práctica 5 Búsqueda con retroceso estructuras de datos y algoritmos facultad de informática curso 2009-2010 Objetivo Escribir un algoritmo que transforme los colores de las componentes conexas de una imagen en cuatro colores. 1. Algoritmo de recoloreado El algoritmo tomará como entrada un fichero (en formato ppm) y escribirá en otro fichero (en formato ppm) el resultado de recolorerar en 4 colores las componentes conexas de la imagen del fichero de entrada. Usage: ppm4colors inputimage.ppm outputimage.ppm Estrategia: 1. Determinar las componentes conexas (CC) 4-conectadas de la imagen de entrada. Una componente conexa de una imagen es un subconjunto de pı́xeles de la imagen de un mismo color que se están tocando entre sı́. Se dice que una componente conexa es 4-conectada si se puede ir de cualquier pı́xel del subconjunto a cualquier otro moviéndose sólo en cuatro direcciones: norte, sur, este y oeste. 2. Representar las CC en forma de grafo. Los vértices del grafo son las CC y las aristas representan relaciones entre las CC. Dadas dos componentes conexas c1, c2, existirá una arista (c1, c2) en el grafo, si se cumple que dos pı́xeles p1 ∈ c1 y p2 ∈ c2 están 4-conectados. 3. Aplicar el algoritmo de Vuelta atrás o Backtracking sobre el grafo para encontrar una solución que permita colorear las componentes conexas en 4 colores. Se tendrá que satisfacer la restricción que una CC tiene que tener un color diferente a las que están relacionadas con ellas en el grafo. 4. Generar la imagen de salida recoloreando los pı́xeles de las componentes conexas siguiendo la solución encontrada. 2. Determinar las componentes conexas El cálculo de las componentes conexas de una imagen fue el objetivo de la práctica 3. Para esta práctica se proporciona la clase MFSet (mfset.h, mfset.cc) y el algoritmo que dada una imagen devuelve el MFSet con las componentes conexas de la imagen (connected_components.cc). Para mayor información sobre el cálculo de componentes conexas de una imagen consultar el boletı́n de la práctica 3. 3. Representar las CC en forma de grafo Para representar las CC en forma de grafo es necesario seguir los siguientes pasos: Crear un grafo con un número de vértices igual al número de subconjuntos del MFSet (número de CC de la imagen). Como en el grafo los vértices se identifican por un número entero u ∈ [0, nV ert − 1], es necesario relacionar el ı́ndice del vértice con el representante (número entero) de la CC a la que representa. Para este fin se utilizará el diccionario estándar STL map. La clase map es un contenedor asociativo que pemirte asignar a una clave un valor único identificativo. En este caso las claves serán los ı́ndices de los representantes y el valor único asociado será el ı́ndice del vértice que lo representa en el grafo. Para utilizar el diccionario map será necesario: 1. Incluir el uso de la clase map: include <map> 2. Declarar la variable contenedor: map <key_type, value_type> var_map_name 3. Asignar a cada clave (representante) un vértice: 1 for(int i=0; i < NumRep; i++) var_map_name[clave_rep] = i; Crear las aristas del grafo que relacionen las componentes conexas entre sı́ tal como se ha explicado al exponer la estrategia del algoritmo. En la clase Graph se proporciona un método addEdge para añadir una arista al grafo. Para añadir las aristas al grafo, bastará con recorrer los pı́xeles de la imagen y, para cada pı́xel, si el pı́xel de la derecha o el pı́xel de abajo pertenecen a componentes conexas distintas se creará una nueva arista entre los vértices que representan en el grafo a cada componente conexa. 4. Algoritmo Backtracking Utilizando la estrategia de Vuelta Atrás o Backtracking se buscará una solución al problema de asignar un color (de entre 4 posibles) a cada CC cumpliendo la restricción de que una CC no puede tener el mismo color que las que están relacionadas con ella en el grafo. Para tal fin, se ha declarado un vector color en la clase graph de tamaño igual al número de CC. El resultado de la solución será almacenar en este vector para cada vértice del grafo (CC) el ı́ndice del color asignado. Este ı́ndice será un valor entero entre 0 y 3. En el programa principal ppm4colors.cc se ha creado un vector colors (de tamaño 4) donde se han generado aleatoriamente 4 colores. De esta forma el color 0 se corresponderá con el color de la posición 0 del vector colors y ası́ sucesivamente. 5. Recoloreado de la imagen Utilizando los colores de la solución, se recolorearán todos los pı́xeles de la imagen. Para ello, será necesario obtener de cada pı́xel, a qué CC pertenece (representante) y asignarle el color que la solución ha encontrado para esta CC. 6. Actividades en el laboratorio 1. Completa el nuevo método de la clase Graph::colorVertices(int numColors) que siguiendo la estrategia de Backtracking asigna a cada vértice del grafo uno de los numColors colores satisfaciendo la restricción explicada. 2. Completa el código del programa principal ppm4colors siguiendo las directrices indicadas.