如何使用LSB替代将一个图像隐藏到另一个图像中?

时间:2017-02-10 09:59:27

标签: python opencv numpy steganography

我正在尝试实现一种基本的速记技术,其中我用载体图像的MSB替换载体图像的LSB。 LSB可以属于任何RGB通道。

我的方法非常幼稚,因为我正在循环message_matrix并将其特定RGB通道的MSB存储在carrier_matrix的相应LSB中。由于图像大小不超过1024 * 1024,执行此操作的时间复杂度为O(n ^ 2),但由于我使用python,因此与Java相比,所花费的时间非常长。

可以以更优化的方式执行相同的操作吗?

def hide_using_bpcs(self, carrier_path, message_path, index, color_index):
            carrier_matrix = self.image_to_matrix(carrier_path)     
            message_matrix = self.image_to_matrix(message_path)              #use np.zeros

            for row_index, row in enumerate(message_matrix):
                for pixel_index, pixel in enumerate(row):
                    color = message_matrix[row_index][pixel_index][color_index]
                    msb = (color & 0xff) >> 7
                    carrier_pixel = carrier_matrix[
                        row_index][pixel_index][color_index]
                    carrier_matrix[row_index][pixel_index][
                        color_index] = self.set_bit(carrier_pixel, index, msb)

            stegano_image = self.matrix_to_image(carrier_matrix)
            return stegano_image

现在,为了显示一个特定的位平面,让我们说(红色0),我将绿色和蓝色平面的所有值设置为0,并仅保留红色的LSB(或0位)的值。图片。我已经完成了一些使用openCV完成的实现,如[b,g,r = cv2.split(img)],但这只是将图像分成3个通道。我想要的是通过保留相应位置的值来分割特定的通道,然后将红色进一步分为8个变化。

    def display_bit_plane(self, path, color_index, color_bit):
            matrix = self.image_to_matrix(path)
            matrix = matrix.astype(int)
            result_matrix = self.image_to_matrix(path)
            mask = 1 << color_bit

            for row_index, row in enumerate(matrix):
                for pixel_index, pixel in enumerate(row):
                    for iterator in range(0, 3):
                        result_matrix[row_index][pixel_index][iterator] = 0 
                    color = matrix[row_index][pixel_index][color_index]
                    result_matrix[row_index][pixel_index][color_index] = self.set_bit(0, 7, ((color & mask) != 0))

            stegano_image = self.matrix_to_image(result_matrix)
            return stegano_image

我正在使用NumPy数组执行所有计算。然而,以通常的方式迭代它是非常昂贵的。请在上述两个功能中进行一些优化,以便在不到1秒的时间内完成这些操作。

编辑1:

我已经优化了检索位平面的第二个功能。如果可以进一步简化,请告诉我们。 Color_index分别代表R,G,B为0,1,2,color_bit是0-7的位位置。

def display_bit_plane_optimised(self, path, color_index, color_bit): 
        message_matrix = self.image_to_matrix(path)
        change_index = [0, 1, 2]
        change_index.remove(color_index)
        message_matrix[:, :, change_index] = 0
        mask = 1 << color_bit
        message_matrix = message_matrix & mask
        message_matrix[message_matrix == 1] = 1 << 7
        stegano_image = self.matrix_to_image(message_matrix)
        return stegano_image

1 个答案:

答案 0 :(得分:1)

任何适用于整个阵列的东西都可以进行矢量化。如果要仅对阵列的一部分应用操作,请将其切片。

我提供了完整的代码,因此不要对image_to_matrix()matrix_to_image()方法做出假设。从那里拿走它。

我保持你的逻辑原封不动,但是如果你只打算在LSB中嵌入秘密,你可以抛弃pixel_bit,将其值设置为零并简化任何常数结果出来的。例如,在embed()中,您只需获得mask = 0xfe,而任何位移0都无关紧要。

import numpy as np
from PIL import Image

class Steganography:
    def embed(self, cover_file, secret_file, color_plane, pixel_bit):
        cover_array = self.image_to_matrix(cover_file)
        secret_array = self.image_to_matrix(secret_file)
        # every bit except the one at `pixel_bit` position is 1
        mask = 0xff ^ (1 << pixel_bit)
        # shift the MSB of the secret to the `pixel_bit` position
        secret_bits = ((secret_array[...,color_plane] >> 7) << pixel_bit)
        height, width, _ = secret_array.shape
        cover_plane = (cover_array[:height,:width,color_plane] & mask) + secret_bits
        cover_array[:height,:width,color_plane] = cover_plane
        stego_image = self.matrix_to_image(cover_array)
        return stego_image

    def extract(self, stego_file, color_plane, pixel_bit):
        stego_array = self.image_to_matrix(stego_file)
        change_index = [0, 1, 2]
        change_index.remove(color_plane)
        stego_array[...,change_index] = 0
        stego_array = ((stego_array >> pixel_bit) & 0x01) << 7
        exposed_secret = self.matrix_to_image(stego_array)
        return exposed_secret

    def image_to_matrix(self, file_path):
        return np.array(Image.open(file_path))

    def matrix_to_image(self, array):
        return Image.fromarray(array)

当我运行它时,它会在一秒钟内完成。

plane = 0
bit = 1

cover_file = "cover.jpg"
secret_file = "secret.jpg"

stego_file = "stego.png"
extracted_file = "extracted.png"

S = Steganography()
S.embed(cover_file, secret_file, plane, bit).save(stego_file)
S.extract(stego_file, plane, bit).save(extracted_file)

备注

您的display_bit_plane_optimised()已合理优化,但如果color_bit除了0之外它有一个错误。该行

message_matrix = message_matrix & mask

每隔一位零,但除非color_bit为0,否则这些值将是2的其他幂。所以当你来

message_matrix[message_matrix == 1] = 1 << 7

没有像素被修改。如果你想保持自己的方式,你必须将最后一行改为

message_matrix[message_matrix != 0] = 1 << 7

我的方法是简单地将嵌入位置于LSB位置,每隔一位将其置零,然后将其移至MSB位置而没有条件。