OpenCV extracting image using LSB method

bit-manipulation, opencv, python, steganography

Solution

njuffa is correct. In the extraction, when you have embedded only 1 bit, you want to AND with 0b00000001 (1), for 2 bits with 0b00000011 (3), for 3 bits with 0b00000111 (7), etc. Generally, for `k` embedded bits, you want the mask `2**k - 1`.

Moreover, `cv2.imread()` will generate a numpy array of the pixels. Instead of looping through each pixel, you can vectorise your computations. All in all, this is what your code could look like.

import cv2

def embed(cover_file, secret_file, k):
    cover = cv2.imread(cover_file)
    secret = cv2.imread(secret_file)

    mask = 256 - 2**k
    stego = (cover & mask) | (secret >> (8 - k))
    cv2.imwrite('stego.png', stego)

def extract(stego_file, k):
    stego = cv2.imread(stego_file)

    mask = 2**k - 1
    output = (stego & mask) << (8 - k)
    cv2.imwrite('extracted.png', output)

Problem

Disclaimer: This was part of a homework assignment, however, it has been passed in already. I'm simply looking for the correct solution for future know-how. The goal with this program was to use the Python OpenCV library to implement image -> image steganography (Embedding/Extracting images inside other images). This is done with two images of equal size using the least significant bit(LSB) method. The program allows the user to choose the number of bits used for embedding, so with 1 bit used the embedded image is nearly undetectable to the human eye, and with 7 you can clearly make out the hidden image. I've correctly implemented the embedding just fine, by taking the most significant bits(MSB) of each RGB byte from the secret image, and setting them in the LSB places of the cover image. My problem is extracting the secret image after it has been embedded. After the code runs, the image that I'm left with seems to be only the blue representation of it. I'm not sure where I went wrong, but I have a feeling it has something to do with my bit manipulation techniques, or use of the OpenCV library. Any help is greatly appreciated, thanks in advance! Code for extracting: ``` import cv2 import numpy def extract(img1, bitsUsed): print "Extracting..." # Import image & get dimensions img = cv2.imread(img1) h = img.shape[0] w = img.shape[1] # Create new image to extract secret image # Same dimensions, and rgb channel secretImg = numpy.zeros((h,w,3), numpy.uint8) x, y = 0, 0 # Loop thru each pixel while x < w: while y < h: # Grab the LSB (based on bitsUsed from embedding) lsb_B = img.item(y,x,0) & bitsUsed lsb_G = img.item(y,x,1) & bitsUsed lsb_R = img.item(y,x,2) & bitsUsed # Place those bits into MSB positions on new img secretImg.itemset((y,x,0), lsb_B << (8 - bitsUsed)) secretImg.itemset((y,x,0), lsb_G << (8 - bitsUsed)) secretImg.itemset((y,x,0), lsb_R << (8 - bitsUsed)) y += 1 y = 0 x += 1 cv2.imwrite("extractedImg.png", secretImg) ```

Original source