基于RGB图像LSB隐写的MATLAB代码求助(含编解码需求)
LSB图像隐写:编码/解码代码修复方案
嘿,你遇到的全黑图像问题我太熟了——大概率是编码时对像素值的处理逻辑出错了,比如不小心把整个像素值改成了0,或者用了JPEG这种有损格式保存,直接把隐写的位给冲没了。我给你整理了修复后的Python代码(用PIL库,兼容性拉满),还有对应的解码代码,顺便给你拆解关键细节:
修复后的编码代码
from PIL import Image def text_to_binary(text): # 把每个字符转成8位二进制,末尾加'\0'当结束标记(解码时知道什么时候停) binary_str = ''.join(format(ord(c), '08b') for c in text + '\0') return binary_str def lsb_encode(image_path, text_path, output_path): # 读取图像并强制转成RGB格式(避免灰度图坑) img = Image.open(image_path).convert('RGB') pixels = img.load() width, height = img.size # 读取要隐写的文本 with open(text_path, 'r', encoding='utf-8') as f: text = f.read() binary_data = text_to_binary(text) data_length = len(binary_data) # 先检查图像能不能装下数据:每个像素能存3位,总容量是宽×高×3 if data_length > width * height * 3: raise ValueError("图像太小啦,装不下这么多文本!") index = 0 # 遍历每个像素,依次往R、G、B通道的LSB写二进制位 for y in range(height): for x in range(width): if index >= data_length: break r, g, b = pixels[x, y] # 改R通道:先把最低位清零,再把当前二进制位写进去 r = (r & 0xFE) | int(binary_data[index]) index += 1 if index >= data_length: pixels[x, y] = (r, g, b) break # 改G通道 g = (g & 0xFE) | int(binary_data[index]) index += 1 if index >= data_length: pixels[x, y] = (r, g, b) break # 改B通道 b = (b & 0xFE) | int(binary_data[index]) index += 1 pixels[x, y] = (r, g, b) if index >= data_length: break # 必须存成PNG!JPEG的压缩会把LSB的信息搞丢 img.save(output_path, format='PNG') print(f"搞定!隐写后的图像已经存到 {output_path} 啦") # 测试用例:把Hello写到test.txt里,用input_image.png来隐写 lsb_encode('input_image.png', 'test.txt', 'stego_image.png')
编码时的关键注意点
- 只改最低位:用
& 0xFE把像素值的最后一位清零,再用|把二进制位加进去,这样像素值只会变0或1,肉眼完全看不出图像变化 - 结束标记:给文本末尾加
\0,解码时读到这个就停止,不会把多余的像素位当成文本 - 无损保存:PNG是无损格式,JPEG压缩会破坏LSB里的隐写数据,绝对不能用!
对应的解码代码
要把隐写的文本读出来,用下面的代码:
from PIL import Image def binary_to_text(binary_str): # 每8位转成一个字符,直到碰到结束标记'\0' text = [] for i in range(0, len(binary_str), 8): byte = binary_str[i:i+8] char = chr(int(byte, 2)) if char == '\0': break text.append(char) return ''.join(text) def lsb_decode(stego_image_path, output_text_path): img = Image.open(stego_image_path).convert('RGB') pixels = img.load() width, height = img.size binary_data = [] # 遍历每个像素,提取R、G、B通道的LSB for y in range(height): for x in range(width): r, g, b = pixels[x, y] binary_data.append(str(r & 1)) binary_data.append(str(g & 1)) binary_data.append(str(b & 1)) # 把提取到的二进制位转成文本 binary_str = ''.join(binary_data) text = binary_to_text(binary_str) with open(output_text_path, 'w', encoding='utf-8') as f: f.write(text) print(f"解码完成!文本已经存到 {output_text_path} 啦") # 测试解码 lsb_decode('stego_image.png', 'decoded_text.txt')
你之前得到全黑图像的常见原因
- 错误覆盖像素值:比如直接把像素值设成了二进制位(0或1),而不是只改最低位,导致所有像素都变成接近黑色的数值
- 用了JPEG保存:JPEG压缩会修改像素值,不仅丢隐写数据,还可能让图像变花甚至全黑
- 数据类型出错:比如处理像素时把uint8(0-255的整数)转成了浮点数,保存时没转回来,导致像素值被截断成0
- 没处理图像通道:比如用了灰度图却按RGB处理,通道数量不对,导致循环越界或者错误修改像素值
内容的提问来源于stack exchange,提问作者sumit kothia
相关产品推荐
相关产品推荐

