Rentrée 2016 - SEANCES n°1, 2 et 3


VOIR, C'EST CODER …


Remarque 1. Tous les paragraphes coloriés en orange correspondent à une action à accomplir.


  1. 1.Création et enregistrement d'une image sans compression
    Il existe différents formats d'images numériques et autant de formes différentes pour enregistrer les informations nécessaires à l'affichage d'une image.

    En utilisant un logiciel comme photofiltre 7, répertorier les principales extensions de fichier image:
    _______________________________________________


    Nous utiliserons pour ce travail les fichiers de type “bitmap” avec l'extension “.bmp”.

    Une image numérique est représentée par un tableau de points ou pixels.
    On parle également de matrice de points. Prenons un exemple:

    Créons une nouvelle image de 128 x 256 pixels soit 2
    7.28 = 215 = 32768 pixels.
    Chaque pixels peut afficher 16 millions de couleurs différentes !
    Voyons cela en détails. Les couleurs sont obtenues en mélengeant du Rouge, du Vert et du Bleu. Chacune de ces trois couleurs primaires peuvent être affichée avec 256 = 2
    8 intensités différentes. Récapitulons:  


                                                                                     


Chaque couleur nécessite donc 8 bits soit un octet(donc 1 octet –> 8 bits) et comme il y a 3 couleurs, il faut donc 3 octets pour coder la couleur d'un point.
On avait initialement 32768 pixels, donc 32768 x 3 = 98304 octets.


   
Sachant qu'unKilo-octets (Ko) correspond à 210 = 1024 octets le « poids » de notre image est donc de : _________ ko.


    Sachant qu'unMéga-octets (Mo) correspond à 210 = 1024 Kilo-octets le « poids » de notre image est donc de : _________ Mo.


Remarque: il existe d'autres systèmes pour coder les couleurs, par exemple en télévision le système Luminance et Chrominance.


  1. 2Affichage d'une image stockée dans un fichier bitmap


Pour cet exemple, nous allons utiliser une image utilisant 25 pixels en largeur et 25 pixels en hauteur avec 16 millions (224) de couleurs. Le fichier contenant l'image estnommé « ICN.bmp ». Pour voir son contenu, nous allons l'ouvrir avec un logiciel dit « éditeur hexadécimal ». Qu'est-ce que « l'Hexadécimal » et pourquoi le rencontre-t-on ici ?
Vous êtes habitués à compter en base 10. Cela signifie qu'après le nombre 9, il faut un deuxième chiffre pour écrire le nombre suivant qui est alors 1 suivi d'un 0, soit 10. De même après 19, on a 20 etc…
Mais en informatique les informations sont stockées sous forme de 0 et de 1 qu'on appelle « bits ». Un « bit » correspond à un transistor (sorte d'interrupteur éléectronique) qui peut donc prendre deux valeurs « 0 » ou « 1 ». Deux bits permettent donc d'afficher 4 valeurs différentes: « 00 », « 01 », « 10 » et « 11 ». Trois bits permettent d'afficher 8 valeurs différentes: « 000 », « 001 », « 010 », « 011 », « 100 », « 101 », « 110 » et « 111 ». A chaque bit ajouté, on multiplie par 2 le nombre de valeurs différentes. Le système qui compte en utilisant que les 0 et les 1 est dit « binaire » par opposition au système dit « décimal » qui utilise « 0,1,2,3,4,5,6,7,8 et 9 ».
Le système « hexadécimal » utilise 16 chiffres: « 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E et F ». Donc en hexadécimal, après le nombre 9, on trouve le nombre A. Puis, on a B, C,… et F. Et après F alors ? Et bien, comme dans les autres systèmes, on trouve « 10 » puis « 11 » , « 12 » , etc… Jusqu'à « 1F ». Et on recommence « 20 », « 21 », …, « 2F », « 30 », …
Vous avez compris ? Alors complétez:



« 256 » est le nombre de nuances de chacune des trois couleurs de chaque point. Donc chaque couleur sera représentée dans notre fichier par un nombre héxadécimal allant de « 00 » à « FF ».

    Il est temps d'ouvrir ce fameux fichier « ICN.bmp » avec notre éditeur hexadécimal. Voilà ce que vous devez obtenir:




    Bon: cela à l'air compliqué, mais rassurez-vous, nous allons vite décoder ce qui nous est utile.     Tout ce qui est en bleu décrit l'image elle-même (les pixels). Dans la première partie (les 14 premiers octets), on peut lire:


    1. le type de fichier: 42 4D (bitmap)

    2. la taille du fichier: A2 07 00 00 (soit 25*25*3+25+14+40=1954 octets ou encore&07A2 –> 7*28 + 10*24+2=1954)

      1. 25*25*3 nombre d'octets pour les données de l'image.

      2. 25 marqueurs de fin de ligne.

      3. 14 octets pour les informations sur le fichier.

      4. 40 octets pour les informations sur l'image.

    3. 36 représente, en hexadécimal, le nombre d'octets avant les données de l'image, soit 54 octets.

  1.     La seconde partie (les 40 octets suivants de 15 à 54) contiennent des informations sur les         dimensions et le format couleur de l'image.

    1. 28 00 00 00 : taille de la structure

    2. 19 00 00 00 : largeur de l'image en pixels

    3. 19 00 00 00 : hauteur de l'image en pixels

    4. 01 00 : nombre de plans pour le rendu

    5. 18 00 : nombre de bits par pixels(&18=24bits/pixel)

    6. 00 00 00 00 : type de compression

    7. 6C 07 00 00 : nombre d'octets dans l'image(25*25*3+25)

    8. E8 03 00 00 : résolution horizontale(03E8=1000 pixels/mètre soit 10 pixels/cm)

    9. E8 03 00 00 :résolution verticale

    10. 00 00 00 00 : nombre de couleurs utilisées(0 indique que toutes sont utilisées)

    11. 00 00 00 00 : nombre de couleurs importantes

  2.         Vérifions la taille du fichier par un clic droit puis propriétés du fichier:


       


    La troisième partie est celle qui nous interesse le plus ici. Elle contient les informations de tous les pixels. Chaque groupe de 3 octets contient la valeur (le poids) de chaque couleur pour un pixel donné dans l'ordre Bleu, Vert, Rouge. Par exemple, ici: 00 00 FF signifie

    1. Bleu: &00 –> 0/256

    2. Vert: &00 –> 0/256

    3. Rouge: &FF –> 256/256

  1.     Le but de ce chapitre est maintenant de modifier les couleurs d'une image.


  1. 3Modification d'une image stockée dans un fichier bitmap
    Pour modifier les pixels d'une image, il suffit donc de modifier les valeurs précédentes.


    Tout d'abord, afficher le fichier ICN.bmp: On doit obtenir un carré rouge.
    A l'aide de l'éditeur hexadécimal, recherchez toutes les séquences « 00 00 FF » et remplacez-les par « 00 FF 00 ». Enregistrez le fichier et ouvrez-le à nouveau normalement. Quelle est la couleur du carré obtenu ? Pourquoi ?
    A l'aide de l'éditeur hexadécimal, recherchez toutes les séquences « 00 FF 00 » et remplacez-les par « FF 00 00 ». Enregistrez le fichier et ouvrez-le à nouveau normalement. Quelle est la couleur du carré obtenu ? Pourquoi ?
    A l'aide de l'éditeur hexadécimal, recherchez toutes les séquences « FF 00 00 » et remplacez-les par « 62 00 F4 ». Enregistrez le fichier et ouvrez-le à nouveau normalement. Quelle est la couleur du carré obtenu ? Pourquoi ?

    On remarque ici qu'il est facile de modifier l'image parce qu'on donne à tous les pixels la même valeur. S'il fallait procéder de la sorte pour modifier des pixels tous différents, il faudrait beaucoup de temps ! D'où la nécessité d'utiliser un « programme » pour automatiser ces modifications. Un programme est décrit par un « algorithme » qui est une suite logique d'actions permettant d'arriver au résultat souhaité. Dans ce chapître, nous allons maintenant utiliser un programme écrit en langage python dont nous expliquerons uniquement la partie qui nous concerne pour modifier les couleurs des pixels. Nous étudierons ce langage par le suite.
    Voici le code de ce programme:


    # Créé par thierrykrebs, le 30/06/2016 en Python 3.2
    from struct import pack
    image=input("entrez le nom de l'image bmp à modifier avec son .bmp")
    print("limage modifiée sera dans le fichier image2.bmp")
    fich=open(image,"rb")
    fichbis=open("image2.bmp","wb")

    fich.seek(10)
    #on lit les 4 octets correspondants à l'offset qui sont situés après le 10éme octet
    m=fich.read(4)


    def num(m):
    """retourne le nombre correspondant à 4 octets lus en little indian"""

    return m[0]+m[1]*16*16+m[2]*16**4+m[3]*16**6
    offset=num(m) #cela donne le décalage netre le début du fichier et le début de l'image
    print("l'offset est : ",offset) #pour vérification
    #on se remet au début du fichier
    fich.seek(0)
    #on lit l'entête et on la recopie dans le nouveau fichier
    deb=fich.read(offset)
    fichbis.write(deb)
    #on cherche la largeur et la hauteur dans l'entête
    #largeur 4 octets en commençant parès le 18éme
    fich.seek(18)
    m=fich.read(4)

    largeur=num(m)
    print("la largeur de l'image est : ",largeur)

    #la hauteur les 4 octets suivants
    m=fich.read(4)
    hauteur=num(m)
    print("la hauteur de l'image est : ",hauteur)
    #on se place au début de l'image
    fich.seek(offset)

    #on lit les différentes lignes

    for j in range(hauteur):
    for i in range(largeur):
    #on lit 3 octets pour les trois couleurs
    m=fich.read(3)

    #on fait des modifications sur chaque couleur(ici juste pour essai)
    #on pourra ensuite faire d'autres modifications…
    #attention de rester entre 0 et 255 !

    r=abs(m[0]-20)
    g=abs(m[1]-20)
    b=abs(m[2]-20)

    #pack du module struct transforme en bytes : le premier argument est le format
    #ici B signifie un entier non signé….
    l=pack('BBB',r,g,b)

    fichbis.write(l)

    #attention les fichiers bmp doivent avoir un nombre d'octets qui est multiple de 4
    #dans chaque ligne…sinon on complète par des zéros
    #ici on recopie simplement ces zéros de fich dans fichbis.
    #dans chaque ligne il y a 3*largeur octets
    decal=(largeur*3)%4 #reste dans la dicvision par 4
    if decal!=0:
    for i in range(4-decal): #4-decal est le nombre de zéros
    m=fich.read(1)
    fichbis.write(m)

    fich.close()
    fichbis.close()

    Seules les trois lignes en rouges nous concernent pour le moment. Nous allons d'abord utiliser le programme tel qu'il est, puis nous l'améliorerons pour obtenir des résultats plus « originaux ».


    1. Assombrissement - éclaircissement d'une image

      Lancez Edupython puis ouvrez le fichier contenant le programme python « bmp.py ». Démarrez le programme python en cliquant sur le triangle vert. Entrez le nom du fichier de l'image que l'on veut modifier « lenna.bmp » dans la boîte de dialogue. Attendre la fin du traitement puis ouvrir normalement le fichier généré « image2.bmp ».
      Que constatez-vous ?
      Ouvrez image2.bmp avec l'éditeur hexadécimal et vérifiez sur quelques exemples de pixels l'action du programme.

      Que faudrait-il faire pour éclaircir l'image ? Modifiez l'image en conséquence et vérifiez l'effet de votre travail.
      Nous voudrions maintenant appliquer des modifications plus complexes comme le réglage du contraste ou afficher une image en négatif. Observons d'abord l'action du logiciel en ligne sur notre serveur à l'adresse:
      http://www.thierrykrebs.eu/traitementimage/traitement.php
      Essayez différents traitements de l'image.
      Essayons d'obtenir des effets similaires avec notre programme python.

      for j in range(hauteur):
      for i in range(largeur):
      #on lit 3 octets pour les trois couleurs
      m=fich.read(3)

      #on fait des modifications sur chaque couleur(ici juste pour essai)
      #on pourra ensuite faire d'autres modifications…
      #attention de rester entre 0 et 255 !

      r=(m[0]*2)%256
      g=(m[1]*
      2)%256
      b=(m[2]*
      2)%256
      #pack du module struct transforme en bytes : le premier argument est le format
      #ici B signifie un entier non signé….
      l=pack('BBB',r,g,b)

      fichbis.write(l)

      Modifiez le programme en changeant les valeurs. Que remarquez-vous ?

    2. Négatif d'une image
      Le négatif d'une image est obtenu en remplaçant la couleur de chaque pixel par sa couleur complémentaire. Par exemple, si un pixel est défini par R= 67, V=189, B=240, le pixel « négatif » correspond à R=255-67=188, V=255-189=66, B=255-240=15.

      Modifiez le programme précédent pour obtenir le résultat voulu et vérifier expérimentalement.

    3. Changement du contraste d'une image
      Cette fois-ci, nous allons tenter de comprendre comment fonctionne le programme qui change le contraste d'une image:


      moy=0
      k=0
      for j in range(hauteur):
      for i in range(largeur):
      #on lit 3 octets pour les trois couleurs
      m=fich.read(3)

      #on fait des modifications sur chaque couleur(ici juste pour essai)
      #on pourra ensuite faire d'autres modifications…
      #attention de rester entre 0 et 255 !
      moy=moy+m[0]+m[1]+m[2]
      k=k+3
      moy=moy//k
      print(moy)

      fich.seek(offset)
      #on lit les différentes lignes
      contraste=int(input('Valeur du contraste ?(10)'))
      for j in range(hauteur):
      for i in range(largeur):
      #on lit 3 octets pour les trois couleurs
      m=fich.read(3)

      #on fait des modifications sur chaque couleur(ici juste pour essai)
      #on pourra ensuite faire d'autres modifications…
      #attention de rester entre 0 et 255 !


      if (m[0]+m[1]+m[2])/3<moy:
      if (m[0]-contraste)>0:
      r=(m[0]-contraste)
      else:
      r=0
      if (m[1]-contraste)>0:
      g=(m[1]-contraste)
      else:
      g=0
      if (m[2]-contraste)>0:
      b=(m[2]-contraste)
      else:
      b=0




      else:
      if (m[0]+contraste)<256:
      r=(m[0]+contraste)
      else:
      r=255
      if (m[1]+contraste)<256:
      g=(m[1]+contraste)
      else:
      g=255
      if (m[2]+contraste)<256:
      b=(m[2]+contraste)
      else:
      b=255

      #pack du module struct transforme en bytes : le premier argument est le format
      #ici B signifie un entier non signé….
      l=pack('BBB',r,g,b)

      Expliquez le calcul effectué dans la partie rouge du programme.
      Quelle est la différence de traitement entre les parties verte et bleue du programme ? Comment fonctionne le programme ?
      Testez le programme.
      Ouvrez le fichier obtenu avec l'éditeur hexadécimal et vérifiez les réponses précédantes sur quelques pixels.

  1. 4Cas des fichiers de grandes dimensions
    Les appareils photos actuels génèrent des images de grandes tailles (environ 4000 par 3000 pixels). Les fichiers, s'ils n'étaient pas compressés, auraient des tailles très importantes (4000x3000x3=36 000 000 octets soit 34,3 Mo). Le stockage et la gestion de fichiers d'une telle taille nécessiterait des ordinateurs très puissants et coûteux. La compression des images résoud en partie le problème.
    On constante également que le programme ne traite pas instantanément les images. Notre fichier « lenna.bmp » estde taille réduite (1,9 Ko seulement soit 18 000 fois plus petit !). Imaginez le temps de traitement d'un fichier de 34,3 Mo !

        A votre avis, comment peut-on procéder pour accélérer le travail du logiciel et approcher un travail « en temps réel » ? Donnez toutes les pistes que vous pourriez explorer.