Skip to content Skip to sidebar Skip to footer

Using Python To Decode Steganography Images (example Images At Wikipedia)

At Wikipedia's Steganography Article there is an example image given with hidden image data. Original Image of trees found here Decrypted image data of a cat found here Wikipedia

Solution 1:

The subsequent normalization is linear interpolation of each color component.

Say, the the red color component of pixel 1,1 is 234.

The binary representation of 234 is

In [1]: bin(234)
Out[1]: '0b11101010'

We can remove everything but the two least significant bits with some bitwise operation:

In [2]: bin(234 & 0b11)
Out[2]: '0b10'

The range of a 8-bit image is 8-bits or 256 possible shades. But the range of our color value is just 2-bits or 4 possible shades.

The normalization part is doing linear interpolation to stretch the 2-bit value to fill 8-bit space:

In[3]: (234 & 0b11) * (256/4)
Out[2]: 128

Do this is done on each color component and the cat would appear.

Solution 2:

Normalization is the process of changing a range of values into another range of values.

You have the range [0,3] because of the binary values of 00, 01, 10 and 11. The reason why you want to normalize this to [0,255] is to cover the whole range of pixel intensities. If you were to just save an image from an array with values in the range [0,3], it would appear black because all of these values are very close to 0 and very far away from 255.

The wikipedia page on image normalization gives you the general formula for this. It also shows an example of converting the range [50,180] (call this range A) to [0,255] (range B).

First, we shift A so it starts from zero. Effectively, you subtract the lowest value (50) so that [50,180] becomes [0,130] (call this C). The maximum distance for C is 130-0 = 130 and for B it is 255-0 = 255. So you'll need to multiply all values of C by 255/130. Since the lowest value in C is 0, so it will be for C * 255/130. But if B doesn't start from 0, you simply add the necessary offset to account for this.

In case words are confusing, here's a visualisation of converting [2,5] to [-4,4].

Range normalization demonstration

In your cases, the normalization is from [0,3] to [0,255]. Since both ranges start from 0, you don't need any offsets, just a simple multiplication by 255/3. This result converts {0,1,2,3} to {0,85,170,255}.

A bit of caution here, 255/3 is conveniently an integer number. But if you were normalizing, say [0,7], the most accurate conversion would require the float scaling factor 255/7. Whether you keep that as a float or round it to an integer is outside the scope of this answer.

The simplest code to achieve this would be

import Image
import numpy as np

# The array will be of type `np.uint8`. For integer computations that exceed# this range, use `np.asarray(Image.open(...), dtype=int)`.
stego = np.asarray(Image.open('Steganography_original.png'))
extracted = stego & 0b00000011
extracted *= (255 / 3)

# Compare result with the one from wikipedia
wiki_extracted = np.asarray(Image.open('Steganography_recovered.png').convert('RGB'))
if np.all(wiki_extracted == extracted):
    print'All pixels match'

Post a Comment for "Using Python To Decode Steganography Images (example Images At Wikipedia)"