LSB图像隐写实验
1嵌入
首先将图片和水印进行转化为灰度图并且将水印二值化,然后将两张图片的尺寸保持一致相当于8层选一层去嵌入水印,也就是把那一层的矩阵变成水印的二值化这样就可以将其嵌入好了
2提取信息
提取信息便是将嵌入水印与原图相减去再除以2**层数,把他写进矩阵最后转化成图片
3代码
附上代码(先写了一遍最后在gpt帮助下模块化了)
import numpy as np from PIL import Image # 定义一个函数,用来打开图片并转换成灰度图 def open_and_convert(path): try: img = Image.open(path) img = img.convert('L') return img except FileNotFoundError: print(f"图片{path}不存在,请检查路径是否正确。") return None # 定义一个函数,用来把图片二值化 def binarize(img, threshold=200): table = [] for i in range(256): if i < threshold: table.append(0) else: table.append(1) img = img.point(table, '1') return img # 定义一个函数,用来嵌入水印 def embed_watermark(carrier_path, watermark_path, layer): # 打开载体图片和水印图片,并转换成灰度图 carrier = open_and_convert(carrier_path) watermark = open_and_convert(watermark_path) # 如果有一张图片不存在,就返回None if carrier is None or watermark is None: return None # 把载体图片和水印图片都调整成1000*1000的大小 carrier = carrier.resize((1000, 1000)) watermark = watermark.resize((1000, 1000)) # 把载体图片和水印图片都转换成numpy数组 carrier_array = np.array(carrier) watermark_array = np.array(watermark) # 判断层数是否在合理的范围内(0-7) if layer < 0 or layer > 7: print(f"层数{layer}不合理,请输入0-7之间的整数。") return None # 计算载体图片每个像素除以2的layer次方的余数 remainder = carrier_array % (2 ** layer) # 计算水印图片每个像素乘以2的layer次方的值 value = watermark_array * (2 ** layer) # 计算嵌入水印后的图片数组,即载体图片数组减去余数再加上值 embedded_array = carrier_array - remainder + value # 把嵌入水印后的图片数组转换成PIL图像对象,并返回 embedded_img = Image.fromarray(embedded_array) return embedded_img # 定义一个函数,用来提取水印 def extract_watermark(embedded_path, original_path, layer): # 打开嵌入水印后的图片和原始图片,并转换成灰度图 embedded = open_and_convert(embedded_path) original = open_and_convert(original_path) # 如果有一张图片不存在,就返回None if embedded is None or original is None: return None # 把嵌入水印后的图片和原始图片都调整成1000*1000的大小 embedded = embedded.resize((1000, 1000)) original = original.resize((1000, 1000)) # 把嵌入水印后的图片 embedded_array = np.array(embedded) original_array = np.array(original) # 判断层数是否在合理的范围内(0-7) if layer < 0 or layer > 7: print(f"层数{layer}不合理,请输入0-7之间的整数。") return None # 计算提取水印后的图片数组,即嵌入水印后的图片数组减去原始图片数组再除以2的layer次方 extracted_array = (embedded_array - original_array) // (2 ** layer) # 把提取水印后的图片数组转换成PIL图像对象,并返回 extracted_img = Image.fromarray(extracted_array) return extracted_img # 调用嵌入水印的函数,传入载体图片路径,水印图片路径和层数 embedded_img = embed_watermark("C:/Users/冯博宇/Desktop/dlt.png", "C:/Users/冯博宇/Desktop/hhh.png", 0) # 如果返回的不是None,就保存嵌入水印后的图片 if embedded_img is not None: embedded_img.save("C:/Users/冯博宇/Desktop/embedded.png") # 调用提取水印的函数,传入嵌入水印后的图片路径,原始图片路径和层数 extracted_img = extract_watermark("C:/Users/冯博宇/Desktop/embedded.png", "C:/Users/冯博宇/Desktop/dlt.png", 0) # 如果返回的不是None,就保存提取水印后的图片,并把它二值化 if extracted_img is not None: extracted_img.save("C:/Users/冯博宇/Desktop/extracted.png") extracted_img = binarize(extracted_img) extracted_img.save("C:/Users/冯博宇/Desktop/extracted_bin.png")
4效果
水印和原图
最后生成的一些图片这里取得0层