No post anterior implementamos o framework basico que nos permiteaplicar o algoritmo a qualquer problema. O desafio agora e encontrar uma maneirade 'traduzir' um vetor de poligonos (nossa aproximacao da imagem) em um cromossomo, e implementar ummetodo getFitness que nos diga a qualidade de nossa aproximacao. Antes disso vamos definir algumas classes utilitarias para nos auxiliar com as imagens e com a configuracao de parametros.Classe ImageUtilsEssa classe nos ajuda a converter objetos Image em BufferedImage, assim como salvar essasimagens em formato .jpg. Segue a classe ImageUtils:import javax.swing.*;import java.io.*;import java.util.*;import java.awt.*;import java.awt.image.*;import com.sun.image.codec.jpeg.*;public class ImageUtils{ public static BufferedImage imageToBufferedImage(Image img) { BufferedImage bi = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_RGB); Graphics2D g2 = bi.createGraphics(); g2.drawImage(img, null, null); return bi; } public static void saveJPG(Image img, String filename) { BufferedImage bi = imageToBufferedImage(img); FileOutputStream out = null; try { out = new FileOutputStream(filename); } catch (java.io.FileNotFoundException io) { System.out.println("File Not Found"); } JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out); JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(bi); param.setQuality(1.0f, false); //ou 0.8f encoder.setJPEGEncodeParam(param); try { encoder.encode(bi); out.close(); } catch (java.io.IOException io) { System.out.println("IOException"); } } public static Image loadJPG(String filename) { FileInputStream in = null; try { in = new FileInputStream(filename); } catch (java.io.FileNotFoundException io) { System.out.println("File Not Found"); } JPEGImageDecoder decoder = JPEGCodec.createJPEGDecoder(in); BufferedImage bi = null; try { bi = decoder.decodeAsBufferedImage(); in.close(); } catch (java.io.IOException io) { System.out.println("IOException"); } return bi; } }Classe Params Essa classe nos permite usar um arquivo externo para configurar alguns parametros do programa, como o numero de poligonos, o nome da imagem, etc. A estrutura do arquivo Params.ini e mostrada apos a classe:import java.io.*;import java.util.HashMap;import java.util.Scanner;public class Params { static int VERTICES = 0; static int N_POLY = 0; static float MUTATION_RATE = 0.0f; static int PHOTO_INTERVAL_SEC = 0; static String TARGET_FILE; static boolean RANDOMIZE_START = false; static int MIN_ALPHA = 0; static int MAX_ALPHA = 0; public Params() { Scanner scanner = new Scanner(this.getClass().getResourceAsStream("params.ini")); HashMap<String, String> map = new HashMap<String, String>(); while (scanner.hasNext()) { map.put(scanner.next(), scanner.next()); } TARGET_FILE = map.get("target_file"); VERTICES = Integer.parseInt(map.get("vertices")); N_POLY = Integer.parseInt(map.get("n_poly")); MUTATION_RATE = Float.parseFloat(map.get("mutation_rate")); PHOTO_INTERVAL_SEC = Integer.parseInt(map.get("photo_interval_sec")); RANDOMIZE_START = Boolean.parseBoolean(map.get("randomize_start")); MIN_ALPHA = Integer.parseInt(map.get("min_alpha")); MAX_ALPHA = Integer.parseInt(map.get("max_alpha")); } } //fim da classeArquivo params.iniSalve esse arquivo como 'params.ini', pois a classe Params ira procurar por esse nomeao tentar carrega-lo:vertices 3n_poly 80mutation_rate 0.001fphoto_interval_sec 30target_file apple.jpgrandomize_start truemin_alpha 10max_alpha 120Classe PolygonColor O objetivo agora e transformar um vetor de poligonos em um BinaryIntChromosome e encontrar uma maneira de comparar nossa aproximacao com a imagem alvo. Para comecar, vamos definir a classe PolygonColor, que representa um Poligono e sua cor RGBA. A classe e bem simples:import java.awt.*;public class PolygonColor{ protected Color color; protected Polygon polygon; public PolygonColor(){} public PolygonColor(Color color, Polygon polygon) { this.color = color; this.polygon = polygon; }}Classe PolygonDecoderEssa classe nos ajuda a decodificar um cromossomo em um vetor de poligonos, alem dedefinir os valores minimos e maximos que cada gene pode assumir. Esses calculos dependembasicamente do numero de poligonos utilizados e do numero de vertices de cada poligono. O metodo chromosomeToPolygons recebe o fenotipo de um cromossomo e a configuracao dos poligonos, retornando um vetor de objetos PolygonColor. O metodo getChromosomeBounds recebe as dimensoes