Projet steganographie 1 : Tampon d'image

Objectif.

Le tampon d'image consiste à cacher une image dans une autre, l'idée est basée sur le fait que l'être humain (et les périphériques de l'ordinateur) a du mal à percevoir les petites nuances de couleurs.

Dans un premier temps nous allons construire une fonction qui va pour chaque pixel ôter n bits de poids faibles, et voir le peu d'influence si n est petit, puis nous allons faire une fonction qui mélangera deux images en ajoutant une pondération (cette fonction va faire le tampon) et enfin créer une fonction qui va récupérer l'image cachée.

Quelle image est cachée dans l'image ci dessous ?

Bits de poids faibles.

On rappelle que par exemple le nombre 137 est stocké en mémoire dans l'octet 10001001, ôter le bit de poids faible consiste à mettre le dernier bit à 0 (s'il est déjà il n'y a rien à faire), on obtient alors 10001000 = 136, de même si on veut ôter 2 bits de poids faibles on doit mettre les deux derniers bits à 0 comme le deuxiéme était déjà à 0, on ne le change pas et on obtient également 10001000 =136.

Mathématiquement ôter n bits de poids faibles s’interprète comme une soustraction du reste de la division entière par \(2^n\). Si a est un entier entre 0 et 255 alors a-a%(2**n) est l'entier qui correspond avec n bits de poids faible en moins. Un autre moyen d'oter n bits de poids faibles d'un nombre a est de faire a//2**n*2**n.

Exercices

Et pour ôter n bits de poids forts (i.e. les bits au début), il faut utiliser quelle opération ?

Exercices
  1. Faire une fonction poids_faibles_a_0(nb,n=1) où n représente le nombre de bits de poids faible à ôter au nombre nb et qui va retourner un nombre qui correspond à nb privé de n bits de poids faible. par exemple avec 139 = 100010112 :
    • poids_faibles_a_0(139,1) = 100010102 = 138.
    • poids_faibles_a_0(139,2) = 100010002 = 136.
    • poids_faibles_a_0(139,3) = 100010002 = 136.
    • poids_faibles_a_0(139,4) = 100000002 = 128.
  2. Faire une fonction image_moins_poids_faibles(nom_image,n=0), qui prend une EZ_image et qui retourne une EZ_image qui correspond à la transformation consistant à ôter n bits de poids faible à chaque couleur (pas à l'opacité par contre).
  3. Constater qu'oter un ou deux bits ne change pas grand chose.

Comme les bits de poids faibles n'ont pas une grosse influence sur nos yeux, on va les utiliser pour cacher une autre information. Les techniques sont nombreuses

Pour la suite essayer de prendre deux images de la même dimension, une image dite publique qui va contenir l'image que l'on va montrer et une image dite privée qui sera cachée dedans.

Exercices
  1. Faire une fonction prend_poids_forts(nb,n=1) qui a un nombre nb entre 0 et 255 va donner le nombre qui correspond à ses n bits de poids forts. Par exemple si nb = 200 = 110010002 alors :
    • prend_poids_forts(nb,n=1) = 12 = 1.
    • prend_poids_forts(200,n=2) = 112 = 3.
    • prend_poids_forts(200,n=3) = 1102 = 6.
    • prend_poids_forts(200,n=4) = 11002 = 12.
    • prend_poids_forts(200,n=5) = 110012 = 25.
    (indication penser en décimal comme récupérer les deux premiers chiffres de 12564269 avec une simple opération entière ?)
  2. Faire une fonction melange(publique,privée,nb_bits), qui va prendre deux images publique et privée et qui va retourner une image de même dimension que publique et qui va avoir pour chaque pixel les couleurs correspondantes de publique ôtées des nb_bits bits de poids faibles et ajoutée des nb_bits bits de poids forts de l'image privée.
  3. +=
  4. Faire une fonction prend_poids_faibles(nb,n=1) qui a un nombre nb entre 0 et 255 va donner le nombre qui correspond à ses n bits de poids faibles. Par exemple si nb = 200 = 110010002 alors :
    • prend_poids_faibles(nb,n=1) = 02 = 0.
    • prend_poids_faibles(200,n=2) = 002 = 0.
    • prend_poids_faibles(200,n=3) = 0002 = 0.
    • prend_poids_faibles(200,n=4) = 10002 = 8.
    • prend_poids_faibles(200,n=5) = 010002 = 8.
    (Penser au reste).
  5. Faire une fonction faible_en_fort(nb,n=1) qui va prendre un nombre n et retourner le nombre dont les n bits de poids forts sont égaux aux n bits de poids faibles du nombre d'origine (le reste des bits étant à 0). Par exemple avec 139 = 10001011 :
    • faible_en_fort(139,1) = 100000002 = 128.
    • faible_en_fort(139,2) = 110000002 = 192.
    • faible_en_fort(139,3) = 011000002 = 96.
    • faible_en_fort(139,4) = 101100002 = 176.
  6. Faire une fonction montre_cachee(image,nb_bits) qui va retourner l'image cachée contenu dans l'image.

L'image mélangée doit être sauvegardée en BMP car la compression est trop destructive, il existe cependant des techniques de tampon numérique qui résistent à la compression.

Exercices
  1. Que se passe t'il si on veut cacher une image en noir et blanc dans les 2 bits de poids faibles et que l'on décache l'image ? A t'on \(2^2×2^2×2^2 = 64\) couleurs ? Expliquer.
  2. On va faire mieux et stocker le niveau de gris de chaque pixel, pour cela on va utiliser les deux bits de poids faibles du rouge, et les trois du vert et du bleu, on aura donc 8 bits et l'image en noir et blanc sera cachée sans perte ! L'idée pour chaque pixel est la suivante : On prend le niveau de gris de l'image cachée (8bits) et on stocke les deux bits de poids fort dans le rouge, les trois bits suivants dans le vert et les derniers dans le bleu.

  3. Couleur image publique :

    Niveau gris :

    donne :
  4. Faire une fonction qui redonne l'image cachée par la méthode précédente et voir l'image cachée dans le ponton de la page.