【问题标题】:Embed every bit of every pixel of the secret image into the cover image将秘密图像的每个像素的每一点都嵌入到封面图像中
【发布时间】:2021-07-09 11:38:31
【问题描述】:

首先,我将封面图像读取为灰度图像。

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)

【问题讨论】:

  • Numpy 使用高度作为第一个索引,所以你想要np.zeros((Eheight, Ewidth...
  • @Reti43 抱歉,我收到此错误“无法将大小为 13650 的数组重新整形为形状 (100,100)”。这是因为在 for 循环中它读取了不需要的像素吗?
  • 您的嵌入和提取功能做了两个截然不同的事情。事实上embedding 似乎有错误。您是否打算将secretImage 的每个像素的每一点都隐藏在coverImage 中,然后再次将其提取回来?
  • 是的,我想把秘密图像的每个像素的每一点都隐藏到封面图像中,然后将秘密图像提取回来。
  • @Reti43 我已经编辑了问题。

标签: python opencv steganography


【解决方案1】:

首先你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

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

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

【讨论】:

  • 您好,我已经尝试过了,但我得到的图像与原始图像似乎不同。我想在这里显示,但它不能在这里粘贴照片。
  • @psps 我已经更新了答案,向您展示了我如何获得预期的输出。我不知道您如何使用我的代码获得问题中显示的隐秘图像,因为修改非常直观。无论哪种情况,它都按预期工作。注意这里我不是保存图片,只是直接使用图片数组保存几行代码。
  • 我已经测试了代码和隐秘图像,提取的图像看起来很好。我得到的结果是 [-1,1] 和 True。谢谢!!顺便说一句,你如何进行位移?我真的无法理解。
  • @psps 您可以在wiki article 上阅读 AND、OR 和 LOGICAL SHIFT。但简而言之,假设您有数字 235,即二进制 11101011。要从左到右获取其位,首先向右移动 7 位并仅保留 LSB,然后向右移动 6 位并仅保留 LSB 等。当您重新构建它时,您将其移动一个到左边并添加新位。例如,假设您有临时数字 14,即二进制 1110,下一位是 1。将其移位使其成为 11100,然后添加新位。 11101 = 29 十进制。
猜你喜欢
  • 2021-06-26
  • 1970-01-01
  • 2020-11-07
  • 2019-08-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-05
  • 1970-01-01
相关资源
最近更新 更多