如何使用 LSB 替换将一幅图像隐藏到另一幅图像中?
How to hide one image into another one using LSB substitutuion?
我正在尝试实现一种基本的速记技术,其中我用消息图像的 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 个通道。我想要的是通过保留相应位置的值将一个特定的通道拆分为 Red 进一步分成 8 个 Variations。
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
适用于整个数组的任何内容都可以矢量化。如果只想对数组的一部分应用操作,请将其切片。
我提供了完整的代码,因此不会对 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 位置,没有条件。
我正在尝试实现一种基本的速记技术,其中我用消息图像的 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 个通道。我想要的是通过保留相应位置的值将一个特定的通道拆分为 Red 进一步分成 8 个 Variations。
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
适用于整个数组的任何内容都可以矢量化。如果只想对数组的一部分应用操作,请将其切片。
我提供了完整的代码,因此不会对 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 位置,没有条件。