IUP Miage Master MIAGE, spécialité SIMI Module T1/D226 Activité n 1 2012-1 NB : Le travail demandé est un travail personnel. L'étudiant s'engage donc, par le rendu de ce travail, à garantir sur son honneur le caractère personnel celui-ci. Exercice I Une image binaire, en noir et blanc, a les dimensions 16x16 pixels. Elle est représentée ci-dessous : a) Combien faut-il de bits pour coder cette image binaire au format matriciel? Chaque pixel est codé sur 1 bit (0 ou 1) donc 16*16 = 256 bits b) On la code suivant la méthode des arbres quaternaires (on ne code que les points noirs). Donner le codage avec la méthode des arbres quaternaires (exercice 9 du chapitre Introduction). La convention de codage est NO = 0, NE = 1, SE = 2, SO = 3. Codage non compacté : 0200 0201 0210 0213 0220 0221 0222 0223 0232 0233 0311 0322 1230 1233 1312 1320 1321 1322 1323 1330 1331 1332 1333 2000 2001 2002 2003 2010 2011 2012 2013 2020 2021 2100 2103 3011 3012 3100 3101 3102 3103 3110 3111 3112 3113 3130 3131 Codage compacté : 0200 0201 0210 0213 022X 0232 0233 0311 0322 1230 1233 1312 132X 133X 200X 201X 2020 2021 2100 2103 3011 3012 310X 311X 3130 3131 c) Combien faudrait-il de bits pour coder une représentation de cet arbre quaternaire? Pour le codage compacté, si on utilise 2 bits pour coder chaque symbole (4 symboles différents), il faut 4*47*2=376 bits Pour le codage non compacté, si on utilise 3 bits pour coder chaque symbole (5 symboles différents), il faut 4*26*3=312 bits
Exercice II Voici un programme Java permettant de dessiner et manipuler l image ci dessus. Compléter le programme pour qu il donne le codage par la méthode des arbres quaternaires de l image. Proposition de solution : la méthode récursive «codes» renvoie la liste des codes non compactés correspondant au codage par les arbres quaternaires : public List<String> codes(int x, int y, int pas, String prefix) { List<String> result = new ArrayList<String>(); if (pas == 1) { if (Color.NOIR == getbinarycolor(x, y)) result.add(prefix); else { result.addall(codes(x, y, pas / 2, prefix + "0"));// NO result.addall(codes(x + pas / 2, y, pas / 2, prefix + "1"));// NE result.addall(codes(x + pas / 2, y + pas / 2, pas / 2, prefix + "2"));// SE result.addall(codes(x, y + pas / 2, pas / 2, prefix + "3"));// SO return result; public static void main(string argv[]) { List<String> codes = petittrain.codes(0, 0, 16, ""); for (String code : codes) { System.out.print(code + " "); System.out.println(); Ajouter une méthode pour permettre une rotation d angle θ (passé en paramètre) de l image. Proposition de solution : la méthode «rotate» renvoie une nouvelle image correspondant à la rotation d angle theta (en degres) de l image : public ImageBinaire rotate(int theta) { ImageBinaire resultat = new ImageBinaire(image.getWidth(),image.getHeight()); double angleradian = (double) theta * 2 * Math.PI / 360; System.out.println("angle en radian: " + angleradian); int centrex = image.getwidth() / 2; int centrey = image.getheight() / 2; for (int x = 0; x < image.getwidth(); x++) for (int y = 0; y < image.getheight(); y++) if (Color.NOIR == getbinarycolor(x, y)) { // translation (-centrex,-centrey) double ix1 = x - centrex; double iy1 = y - centrey; // rotation d'angle theta double ix2 = (Math.cos(angleRadian) * ix1 - Math.sin(angleRadian) * iy1); double iy2 = (Math.sin(angleRadian) * ix1 + Math.cos(angleRadian) * iy1); // translation (+centrex,+centrey) double ix3 = ix2 + centrex; double iy3 = iy2 + centrey; // arrondi et conversion en entier int ix = (int) Math.round(ix3); int iy = (int) Math.round(iy3); resultat.setbinarycolor(ix, iy, Color.NOIR); return resultat; public static void main(string argv[]) { ImageBinaire imgbinaire = petittrain.rotate(90); imgbinaire.affiche();
Exercice III Sur une image 16x16, on souhaite tracer le segment de droite entre le point de coordonnées (0,0) et le point (15,7). 1. En utilisant l algorithme de Bresenham, dessiner ce segment de droite 2. Ecrire un programme implémentant cet algorithme (on donnera en paramètre les 2 points du segment de droite) public static void bresenham(imagebinaire img, int x1, int ny1, int x2,int ny2){ int y1 = img.image.getheight()-ny1-1; int y2 = img.image.getheight()-ny2-1; double m = ((double) (y2 - y1)) / (double) (x2 - x1); img.setbinarycolor(x1, y1, ImageBinaire.Color.NOIR); double epsilon = 0.0; if (x1 < x2 && 0 <= m && m <= 1) {// octant 1 for (int x = x1 + 1; x <= x2; x++) { if (epsilon + m > 0.5) { y = y + 1; epsilon = (epsilon + m) - 1; else { epsilon = epsilon + m; if (x1 < x2 && 1 < m) {// octant 2 for (int y = y1 + 1; y <= y2; y++) { if (epsilon + 1 / m > 0.5) { x = x + 1; epsilon = (epsilon + 1 / m) - 1; else { epsilon = epsilon + 1 / m; if (y1 < y2 && m < -1) {// octant 3 for (int y = y1 + 1; y <= y2; y++) { if (epsilon - 1 / m > 0.5) { x = x - 1; epsilon = epsilon - 1 / m - 1; else epsilon = epsilon - 1 / m;
if (x2 < x1 && -1 <= m && m <= 0) {// octant 4 for (int x = x1-1; x >= x2; x--) { if (epsilon - m > 0.5) { y = y + 1; epsilon = epsilon - m - 1; else epsilon = epsilon - m; if (x2 < x1 && 0 < m && m <= 1) {// octant 5 for (int x = x1-1; x >= x2; x--) { if (epsilon + m > 0.5) { y = y - 1; epsilon = epsilon + m - 1; else epsilon = epsilon + m; if (y2 < y1 && 1 < m) {// octant 6 for (int y = y1-1; y >= y2; y--) { if (epsilon + 1 / m > 0.5) { x = x - 1; epsilon = epsilon + 1 / m - 1; else epsilon = epsilon + 1 / m; if (y2 < y1 && m < -1) {// octant 7 for (int y = y1-1; y >= y2; y--) { if (epsilon - 1 / m > 0.5) { x = x + 1; epsilon = epsilon - 1 / m - 1; else epsilon = epsilon - 1 / m; if (x1 < x2 && -1 <= m) {// octant 8 for (int x = x1 + 1; x <= x2; x++) { if (epsilon - m > 0.5) { y = y - 1; epsilon = epsilon - m - 1; else epsilon = epsilon - m;
Exercice IV Transformation Niveaux de Gris -> Image Binaire 1. Décrire un algorithme permettant de transformer une image en Niveaux de Gris en un image binaire en utilisant les matrices de seuil (implémentation facultative) Le but est d associer chaque niveau de gris à un bloc binaire défini par les matrices de seuil.. Il faut définir les intervalles de niveaux de gris associés à chaque bloc. Si on prend des blocs 2x2, avec 5 niveaux, par exemple : si on a 256 niveaux de gris pixel de niveau 0 à 51 -> bloc de niveau 4 pixel de niveau 52 à 103 -> bloc de niveau 3 pixel de niveau 104 à 155 -> bloc de niveau 2 pixel de niveau 156 à 202 -> bloc de niveau 1 pixel de niveau 203 à 255 -> bloc de niveau 0 L image binaire finale sera donc 2 fois plus large et 2 fois plus haute. Il suffit de parcourir chacun des pixels de l image, determiner a quel bloc il correspond et mettre en noir les pixels dans l image finale qui sont dans le bloc correspondant. Exemple d implémentation : public ImageBinaire matriceseuil_2x2() { int w = img.getwidth(); int h = img.getheight(); ImageBinaire imgbinaire = new ImageBinaire(w * 2, h * 2); for (int x = 0; x < w; x++) for (int y = 0; y < h; y++) { int niveau = getniveau(x, y); if (niveau <= 51) imgbinaire.setbinarycolor(2 * x, 2 * y, ImageBinaire.Color.NOIR); if (niveau <= 103) imgbinaire.setbinarycolor(2 * x + 1, 2*y+1,ImageBinaire.Color.NOIR); if (niveau <= 155) imgbinaire.setbinarycolor(2 * x + 1,2*y,ImageBinaire.Color.NOIR); if (niveau <= 202) imgbinaire.setbinarycolor(2 * x, 2 * y + 1,ImageBinaire.Color.NOIR); return imgbinaire; Il serait plus «joli» d utiliser une matrice plus grande pour avoir un bloc par niveau. Exemple avec matrice 2x2 :