我试图通过创建一个程序,用python模块将图像转换为二进制文件,从而在python中创建一个stegnography技术的示例。一旦转换,它将从每个像素值中删除最不重要的比特,并将其更改为编码跨越一定数量字节的消息;它将这样做,同时(理论上)保持文件的大致大小并保持图像的大部分外观。
然而,我遇到了一个问题,在这个问题上,我无法用剩下的数据重建图像或任何图像。
#secret message to be injected into the final bits.
injection = '0111001101100101011000110111001001100101011101000010000001101101011001010111001101110011011000010110011101100101001000000110100101101110011010100110010101100011011101000110100101101111011011100010000001101101011011110110110101100101011011100111010000100000011010000110010101101000011001010110100001100101011010000110010101101000011001010110100001100101'
injection_array=[]
count = 0
#loop to create an array of characters for the injection
for char in injection:
injection_array.append(injection[count])
count += 1
injectioncount = 0
count = 0
#loop to replace each bit with the desired injection
for element in pixel_bin:
cached_element = pixel_bin[count]
lsb_strip = cached_element[:-1]
lsb_replace = lsb_strip + injection_array[injectioncount]
pixel_bin[count] = lsb_replace
count += 1
injectioncount += 1
if injectioncount == len(injection):
break
#dumps outputted value for comparison with a control file of original pixel values
with open("comparison.json","w") as f:
json.dump(pixel_bin,f, indent=2)这就是我所能得到的。它的输出是一个列表,其中包含了变化的二进制序列,最后的位被改变了。
首先,我是这样获得像素数据的:
def bincon(image):
from PIL import Image
count = 0
pixel_binaries = []
im = Image.open(image, 'r')
pix_val = list(im.getdata()) #outputs rgb tuples for every pixel
pix_val_flat = [x for sets in pix_val for x in sets] #flattens the list so that each list item is just one rgb value
for elements in pix_val_flat: #converts each rgb value into binary
pixel_binaries.append(bin(pix_val_flat[count]))
count += 1
return pixel_binaries我将如何将收集到的数据重构成类似于程序输入的图像?
编辑-尝试im_out = Image.fromarray(array_data_is_stored_in)方法确实返回一个图像文件,该文件打开,但不包含数据,当然不是原始图像。
发布于 2022-09-30 08:21:07
您发布的代码不是一个最小的可重复的示例,因此很难诊断问题是什么。
但是,基本方法是将图像读取到Numpy数组中。该数组为x,y (2d)数组,用于每个层/颜色。
Numpy在数组上有一个flatten()和reshape()方法。这意味着,在迭代数组以更改每个像素之前,可以将其扁平化。然后在修改后再重新塑造它。
这可能是什么样子的一个例子:
from pathlib import Path
from typing import List
import imageio.v3 as iio
import numpy as np
secret_bit = 0
def max_msg_len(data: np.ndarray) -> int:
row_size, column_size, layers = data.shape
return (row_size * column_size * layers) // 8
def text_to_bits(txt: str) -> List[bool]:
data = txt.encode()
bin_str = "".join([f"{x:08b}" for x in data])
bits = [x == "1" for x in bin_str]
return bits
def bits_to_text(bits: List[bool]) -> bytes:
data = bytearray()
for x in range(0, (len(bits) // 8 * 8), 8):
char = int("".join(["1" if i else "0" for i in bits[x: x + 8]]), 2)
data.append(char)
return_str = "".join([x for x in data.decode() if x.isprintable()])
return return_str
def read_file(filename: Path) -> np.ndarray:
return iio.imread(filename)
def write_file(filename: Path, data: bytes) -> None:
iio.imwrite(filename, data)
def extract_message(data: np.ndarray) -> List[bool]:
flat_data = data.flatten()
extracted_bits = []
for pixel in range(len(flat_data)):
value = flat_data[pixel]
found_bit = get_bit(value, secret_bit)
extracted_bits.append(found_bit)
return extracted_bits
def embed_message(data: np.ndarray, bits: List[bool]) -> bytes:
orig_shape = data.shape
flat_data = data.flatten()
idx = 0
bit_len = len(bits)
for pixel in range(len(flat_data)):
value = flat_data[pixel]
if pixel < bit_len:
flat_data[pixel] = set_bit(value, secret_bit, bits[pixel])
else:
flat_data[pixel] = set_bit(value, secret_bit, False)
idx += 1
return flat_data.reshape(orig_shape)
def set_bit(octet: int, bit: int, value: bool) -> int:
mask = 1 << bit
octet &= ~mask
if value:
octet |= mask
return octet
def get_bit(octet: int, bit: int) -> bool:
value = octet >> bit
value &= 1
return bool(value)
def main(img_in: Path, img_out: Path, msg: str) -> None:
print("Message to hide:", msg)
msg_bits = text_to_bits(msg)
# Read img file
img_content = read_file(img_in)
# Check message will fit in image file
# print(max_msg_len(img_content), len(msg), msg_bits)
if len(msg) > max_msg_len(img_content):
print(
f"Message too long for image file. "
f"Can only have {max_msg_len(img_content)} characters"
)
exit()
# Modify data
new_data = embed_message(img_content, msg_bits)
# Check message can be extracted
extracted_bits = extract_message(new_data)
print("Message in new image:", bits_to_text(extracted_bits))
# Save to file
write_file(img_out, new_data)
# Read from secret file
img_content = read_file(img_out)
read_bits = extract_message(img_content)
print(f"From {img_out.name} read: {bits_to_text(read_bits)}")
if __name__ == "__main__":
# Files
data_dir = Path(__file__).parent.joinpath("data")
original_png = data_dir.joinpath("gnome-xterm.png")
secret_png = data_dir.joinpath("secret.png")
# Message
txt_to_hide = "secret message to hide hehehe"
main(original_png, secret_png, txt_to_hide)这在终端中提供了以下输出:
Message to hide: secret message to hide hehehe
Message in new image: secret message to hide hehehe
From secret.png read: secret message to hide hehehe前、后图像如下:

https://stackoverflow.com/questions/73896442
复制相似问题