Pixel Value Differencing (PVD) – Explications
Présentation de la méthode de Pixel Value Differencing (PVD), explications en Français.
Cette méthode est généralement associée à de la stéganographie. En effet, elle permet de cacher séquentiellement de la data dans une image.
Son principe est relativement simple. Du moins, la méthode originale.
Voici son schéma de principe, résumant aussi bien l’extraction que la méthode pour cacher les données:
- Résumons la méthode pour cacher les données:
On part d’une image en noir et blanc, c’est à dire que ses pixels sont constitués d’une seule valeur, une graduation de noir sur un octet. On a également un “secret byte stream” qui est le message à cacher, en binaire. On le nommera ” b “.
Etape 1 : Pour effectuer les calculs, nous devons utiliser deux pixels nommés Pi et P(i+1), et la différence d=|P(i+1)-Pi|. Attention, la valeur absolue de la différence est très importante. En temps normal, la lecture des pixels se fait en “ZigZag”, c’est à dire que la première ligne de pixels se lit de gauche à droite, la deuxième de droite à gauche, la troisième de gauche à droite etc.
Etape 2 : Ensuite, il faut définir un tableau de ranges. Ce tableau va servir à déterminer la quantité de bits pouvant être cachés dans la différence des deux pixels. (voir l’exemple à la fin).
Etape 3 : Grâce à cette range, on va pouvoir déterminer R[Lo,Hi] qui détermine la valeur minimum de notre range (Lo) et la valeur maximum de notre range (Hi).
Pour résumer, le tableau est constitué des sections:
0 à 7 -> R[0,7]
8 à 15 -> R[8,15]
16-31 -> R[16,31]
32-63 -> R[32,63]
64-127 -> R[64,127]
128-255-> R[128,255]
Nous avons donc à notre disposition les éléments suivants:
- Pi, P(i+1) -> les deux pixels originaux
- b -> le byte stream à cacher
- d -> la différence des deux pixels
- R[Lo,Hi] -> La valeur minimum et maximum du palier auquel ” d ” appartient
Etape 4 : Le calcul du nombre de bits a cacher dans la différence se fait grâce à la formule suivante: NbBits = log2(R[Hi]-R[Lo]+1)
Etape 5 : On peut calculer ” d’ “, la nouvelle différence des pixels avec le calcul suivant: d’ = R[Lo] + decimal(b)
Etape 6 : Et on peut calculer ” m ” qui est la valeur absolue de la différence… des différences : m = |d’ – d|
Etape 7 : Enfin, les deux “nouveaux” pixels, Pi’ et P(i+1)’ sont calculés avec la méthode suivante: Pi’ = Pi – ValeurSupérieure(m/2) et P(i+1)’ = P(i+1) – ValeurInférieure(m/2)
Et hop ! on peut reconstituer une image !
Exemple d’application sur deux pixels consécutifs: byte stream à cacher = 10111101101110001010
Pi = 102 et P(i+1) = 120 on a donc la différence d = | 120 – 102 | = 18
Pour situer “d” dans notre range: 16<d<31 donc on a R[16,31] et 4 bits peuvent être cachés (car log2(31-16+1) = 4). La conversion des 4 premiers bits “1011” en décimal donne 11.
La nouvelle différence ” d’ ” est égale à (16 + b), soit 16+11 = 27.
On calcule : m = |27 – 18| = 9
On trouve donc les nouvelles valeurs suivantes: Pi’ = 102 – ValeurSuperieure(9/2) = 102 – 5 = 97 et P(i+1)’ = 120 – ValeurInferieure(9/2) = 120+4 = 124.
Etc pour toute l’image !
2. Extraction des données:
La méthode d’extraction est très similaire à la méthode pour cacher les données.
Je vais donc vous laisser appliquer les étapes de 1 à 4.
On dispose alors de:
- Pi, P(i+1) -> les deux pixels à étudier
- d’ -> la différence des deux pixels
- R[Lo,Hi] -> Les valeurs minimum et maximum du palier auquel ” d ” appartient
- NbBits -> Le nombre de bits à récupérer dans la différence
Il ne nous reste plus qu’à effectuer un petit calcul pour retrouver le byteStream caché: b’ = d’ – R[lo]
Pour l’exemple on va appliquer la procédure inverse à notre exemple précédent:
On a deux pixels Pi = 97 et P(i+1) = 124 avec la différence d’ = |124 – 97| = 27
16<27<31 donc on a R[16,31] et log2(31-16+1) = 4, il faut donc récupérer 4 bits.
b’ = 27-16 = 11 soit 1011 en binaire, voilà la partie de notre message que nous avons cachés précédemment.
/!\ Attention:
Plusieurs éléments sont à prendre en compte.
- Le padding est très important:
Prenons un Exemple: vous devez récupérer 7 bits car vous avez d’ = 129 et vous obtenez b’ = 129-128 = 1
en binaire dec(1) = bin(1), mais vous devez récupérer 7 bits! Alors il est nécessaire de concaténer un nombre de “0”, avant b’ pour réguler le padding.
Pour notre exemple, b’ = 0000001.
- La “direction” que la personne a pris pour cacher les données l’est tout autant.
Si il a décidé de cacher les données dans la différence de deux pixels consécutifs verticalement, ou en diagonale, il faudra adapter la lecture des pixels. La méthode régulière du PVD fait intervenir une lecture en “zigzag” des pixels: première ligne de gauche à droite, la ligne suivante de droite à gauche etc.
Pour un exemple d’application concrète, cherchez sur google 😀 . En suivant la méthode précédemment expliquée, vous devriez y arriver sans trop de problèmes.
La bise.
Commentaires
Propre !
in the implementation what if the
the remaining bits are 2 bits for example ( we got only “01” left )
1st pixel = 254
2nd pixel = 254
difference = 0
n of bits that can be hidden = 3
chosen bits : 01
decimal representation=1
new difference = 0
m = 1
new p1=253
new_p2=254
in the extraction this will be padded to 001 instead of 01
which is kinda inconvenient when concatenating bits to form a text in ASCII
I think you’ve found the limitations of this technique !