You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

LSB图像隐写术编码后像素值异常变更问题求助

LSB图像隐写中像素值莫名变更的问题解决办法

你遇到的这个像素值诡异变更的问题,核心原因其实很直白:你用错了图像格式。JPEG是有损压缩格式,它天生和LSB隐写的需求冲突——LSB隐写依赖精确保留像素的最低位修改,但JPEG在保存时会自动丢弃视觉上“不重要”的信息,直接篡改你辛苦修改的像素数据,导致解码时看到的图像和你内存中修改后的完全不一样。

具体问题拆解

  1. JPEG压缩的致命影响:你在encode函数里修改完像素后,保存为temp2.JPG时,JPEG的压缩算法会重新编码图像,不仅会改变你修改的LSB位,甚至会调整整个像素值,这就是为什么你在decode里打开图像后,像素值完全变了样。
  2. 额外的冗余压缩操作:你的encode里有一行多余的enc_img.save("OUT.JPG"),这会在你还没修改像素时就先做一次有损压缩,进一步干扰后续的隐写操作。
  3. 像素坐标的逻辑错误:PIL的Image.size返回的是(width, height),但你写了height, width = enc_img.size,把宽高搞反了,导致你遍历像素的顺序完全错误,这也会让隐写的数据乱掉。

解决方案

1. 改用无损图像格式

把所有涉及的图像文件换成PNG格式(比如temp.png),保存时明确指定PNG格式,确保像素数据被精确保存:

# 打开图像时用PNG
img = Image.open("temp.png")
# 保存时明确指定PNG格式,避免默认压缩
enc_img.save('temp2.png', format='PNG')

2. 修正encode函数的核心逻辑

删掉冗余的保存操作,修正宽高顺序,同时简化LSB修改的逻辑(原来的条件判断太绕,容易出错):

def encode():
    data = "This is a data"
    img = Image.open("temp.png")
    data = preprocess_data(data)
    data.append(list('11111111'))
    print(data)
    
    i = 0
    j = 0
    enc_img = img.copy()
    width, height = enc_img.size  # 修正:size返回(width, height)
    pixels = enc_img.load()
    finished = False
    
    for h in range(height):
        for w in range(width):
            pixel = list(enc_img.getpixel((w, h)))  # 坐标修正为(w, h)
            newpixel = []
            
            for k in range(3):
                # 简化LSB修改逻辑:清除原LSB,再设置目标位
                target_bit = int(data[i][j])
                # 先把原像素的LSB置0,再按目标位设置
                modified_pixel = (pixel[k] & ~1) | target_bit
                newpixel.append(modified_pixel)
                
                # 更新数据指针
                j = (j + 1) % 8
                if j == 0:
                    i += 1
                    # 检查是否写完所有数据(包括终止符)
                    if i == len(data):
                        enc_img.save('temp2.png', format='PNG')
                        print("Saved")
                        finished = True
                        break
            if finished:
                break
            pixels[w, h] = tuple(newpixel)  # 坐标修正
        if finished:
            break
    print("Encoding done!!")

3. 修正decode函数的逻辑

同样修正坐标问题,优化数据收集的逻辑:

def decode():
    img = Image.open("temp2.png")
    width, height = img.size
    data = ""
    current_byte = ""
    bit_count = 0
    pixels = img.load()
    
    for h in range(height):
        for w in range(width):
            pixel = pixels[w, h]
            for k in range(3):
                current_byte += str(pixel[k] & 1)
                bit_count += 1
                
                if bit_count == 8:
                    if current_byte == "11111111":
                        return data
                    # 转成ASCII字符
                    data += chr(int(current_byte, 2))
                    current_byte = ""
                    bit_count = 0
                    break
    return data

总结

  • 永远记住:LSB隐写只能用无损压缩格式(PNG、BMP等),JPEG这类有损格式会直接破坏隐写数据。
  • 仔细核对PIL的坐标和尺寸逻辑,避免因宽高搞反导致的遍历错误。
  • 简化LSB修改的逻辑,用位运算直接操作比复杂的条件判断更可靠。

内容的提问来源于stack exchange,提问作者Dharmender Lodhi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 09:15:13