将秘密图像的每个像素的每一位嵌入到封面图像中

Embed every bit of every pixel of the secret image into the cover image

首先,我把封面图片看成了灰度图。

coverImage = cv2.imread(coverImagePath, 0)

然后我将封面图像传递给另一个函数以创建另一个较小的图像,而那个较小的图像就是我的秘密图像。

def makeSecretImage(coverImage):
    copyImage = coverImage.copy()
    secretImage = cv2.resize(copyImage, (100,100))
    return secretImage

之后,我将这两张图片传递给我的嵌入函数,将秘密图片嵌入到封面图片中。我的意图是将秘密图像的每个像素的每一位嵌入到封面图像的 LSB 中,封面图像的 LSB 是随机选择的。此函数的最终输出是一个隐写图像,它看起来与封面图像完全相同,因为它只改变像素的 LSB。

def embedding(coverImage,secretImage, password):
    indices = permute_indices(coverImage.shape, password)
    for i in range (secretImage.shape[0]):
        for j in range(secretImage.shape[1]):
            x,y = next(indices)
            #convert pixel to binary 
            pixels_cover = format(coverImage[x][y], '08b')
            pixels_hide = format(secretImage[i][j], '08b')
            binary = list(pixels_hide)
            #error : keep overwriting the last bit
            for dataIndex in range(0,8):
                stegoImage = pixels_cover[:7] + binary[dataIndex]
                dataIndex += 1
        coverImage[x][y] = int(stegoImage, 2)
    cv2.imwrite('StegoImage.png', coverImage)

然后读取隐写图像并将其传递给提取函数。在这里,我正在获取所选像素的最后一位并返回像素。然后将那些像素值放回黑色图像。但是我在这里遇到错误,因为它从隐写图像中读取了额外的像素。

def extracting(stgimg,secretImage, password):
    Swidth, Sheight = stgimg.shape
    Ewidth, Eheight = secretImage.shape
    newPixel = []
    pixelList = []
    # create 2 blank images 
    OriImg = np.zeros((Swidth, Sheight, 1), np.uint8) 
    ExtractedImg = np.zeros((Ewidth, Eheight, 1), np.uint8)
    indices = permute_indices(stgimg.shape, password)
    for x in range(Swidth):
        for y in range(Sheight):
            a, b = next(indices)
            stegopixel = format(stgimg[a][b], '08b')
            bitValue = stegopixel[-1]
            newPixel.append(bitValue)
    for i in range(0, len(newPixel),8):
        pixelBit = ''.join(newPixel[i:i+8])
        pixelByte = int(pixelBit, 2)
        pixelList.append(pixelByte)
    img = np.array(pixelList, dtype=np.uint8).reshape(secretImage.shape)
    cv2.imwrite('ExtractedImage.png', ExtractedImg)

首先,你有一个错误embedding

for dataIndex in range(0,8):
    stegoImage = pixels_cover[:7] + binary[dataIndex]
    dataIndex += 1

您在同一像素的 LSB 中隐藏了 8 位,有效地覆盖了它们并仅保留最后一位。您应该将每一位隐藏在不同的像素中,因此 您的封面图像中的像素至少需要比您的秘密所具有的像素多 8 倍。考虑到这一点

def embedding(coverImage, secretImage, password):
    stegoImage = coverImage.copy()
    indices = permute_indices(coverImage.shape, password)
    for pixel in secretImage.flatten():
        # no need for string "bit manipulation", straight up bitwise operations
        for shift in range(7, -1, -1):
            x, y = next(indices)
            bit = (pixel >> shift) & 0x01
            stegoImage[x,y] = (coverImage[x,y] & 0xfe) | bit
    return stegoImage

然后

def extracting(stegoImage, password):
    indices = permute_indices(stegoImage.shape, password)
    pixels = []
    for _ in range(secretImage.size):
        pixel = 0
        for _ in range(8):
            x, y = next(indices)
            bit = stegoImage[x,y] & 0x01
            pixel = (pixel << 1) | bit
        pixels.append(pixel)
    pixels = np.array(pixels, dtype=np.uint8).reshape(secretImage.shape)
    return pixels

编辑:我已经将上述函数修改为return图像数组而不是保存它们,所以我可以直接用原始输入进行测试。这也假设 permute_indices 仍然与定义的 .

相同
password = 'password'
coverImage = cv2.imread('original.png', 0)
secretImage = makeSecretImage(coverImage)
stegoImage = embedding(coverImage, secretImage, password)
extractedImage = extracting(stegoImage, password)

diff = coverImage.astype(int) - stegoImage
print(diff.min(), diff.max())                 # Differences should be in the [-1, 1] range
print(np.all(secretImage == extractedImage))  # True