m0_70035249 2023-09-02 23:05 采纳率: 57.1%
浏览 27
已结题

LSB隐写图像后提取数据时出现乱码

代码如下

import random
import string
import numpy as np
#5000bits的数据所占字节
bytes = 5000//8
#生成每次都不同的随机数据
def generate_random_letters(length):
    letters = string.ascii_letters  # 包含所有英文字母的字符串
    random_letters = ''.join(random.choice(letters) for _ in range(length))
    return random_letters

random_data = generate_random_letters(bytes)

end_str = "00000000"
#chr()函数将一个整数参数转换为对应的ASCII字符
end = chr(int(end_str,2))#\x00

with open('input_secret_text.txt','w') as f_raw:
    #写入字符串
    f_raw.write(random_data)
    f_raw.close()
    
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np

input_secret_text_path = "input_secret_text.txt"
output_secret_text_path = "output_secret_text.txt"
Lena_path = "C:/Users/86138/Desktop/Lena.bmp"
L_mod_path = "C:/Users/86138/Desktop/Lena_mod.bmp"
Airplane_path = "C:/Users/86138/Desktop/Airplane.bmp"
A_mod_path = "C:/Users/86138/Desktop/Airplane_mod.bmp"
Baboon_path = "C:/Users/86138/Desktop/Baboon.bmp"
B_mod_path = "C:/Users/86138/Desktop/Baboon_mod.bmp"
com_img_path = "D:/PyCharm/programm/usst/compare.png"

def read_image():
    L_raw_image = Image.open(Lena_path)
    return L_raw_image
def read_text():
    f = open(input_secret_text_path,'r',encoding="utf-8")
    text = f.read()
    f.close()
    return text
def insertText(secret_text,raw_image):
    mod_image = raw_image.copy()
    width = mod_image.size[0]#512
    height = mod_image.size[1]#5
    #将625个数据化为二进制数据
    #从文档中读出加密信息并转换为二进制字符串
    binstr = text_to_binary(secret_text)
    #拼贴结束字段
    #binstr为二进制字符串
    binstr += end_str
    #print(binstr)
    i = 0
    #遍历图像的每个像素
    for w in range(width):
        for h in range(height):
            if i == len(binstr):
                break
            #获取当前像素值   灰度值:范围从0到255 使用一个字节存储灰度值,可以表示256个不同的灰度级别
            pixel = mod_image.getpixel((w,h))
            #print(value)
            bit = int(binstr[i])
            #lsb低位替换
            modified_pixel = lsb_gray_pixel(pixel, bit)
            mod_image.putpixel((w, h), modified_pixel)
            
            i += 1

    return mod_image

def lsb_gray_pixel(pixel, bit):
    mask = 0xFE  # 掩码,将最低有效位清零
    #0xFE:11111110
    #通过 pixel & mask 对 pixel 和 mask 进行按位与操作,将 pixel 的最低位清零。这样可以确保最低位保持为零。
    pixel = (pixel & mask) | bit  # 替换最低有效位
    #|(按位或)操作符将清零后的 pixel 和给定的 bit 进行按位或运算。这样可以将 bit 的值替换为清零后的 pixel 的最低位。
    return pixel
def text_to_binary(text):
        binary_str = ''.join(format(ord(char), '08b') for char in text)
        return binary_str
def getText(mod_img):
    width = mod_img.size[0]#图像宽度 512
    height = mod_img.size[1]#图像高度 512
    get_text = ""
    text = ""
    countEND = 0
    #遍历每个像素点
    for w in range(width):
        for h in range(height):
            pixel = mod_img.getpixel((w,h))
            get_text += get_lsb(pixel)
            if len(get_text) == 8 :
                # 转换成ASCII码
                # 例:"0110 0001" -> 97 -> 'a'
                ch = chr(int(get_text, 2))
                if ch == end :
                    countEND = countEND + 1
                if countEND == 2 :
                    break
                text += ch
                get_text = ""
    return text
def get_lsb(value):
     return format(value, '08b')[-1]
def write_text_to_file(text, output_secret_text_path):
    with open(output_secret_text_path, 'w', encoding='utf-8') as f:
        f.write(text)
        f.close()

def main():
    text = read_text()
    raw_img = read_image()
    mod_img = insertText(text,raw_img)
    mod_img.save(L_mod_path)
    secret = getText(mod_img)
    #print(secret)
    #print(text)
    write_text_to_file(secret,output_secret_text_path)
  
    #构造对比图
    plt.rcParams['font.sans-serif']=['SimHei']  # 中文字体设置
    plt.rcParams['axes.unicode_minus'] = False
    plt.subplot(131)
    plt.title("嵌有秘密信息的载体图像")
    plt.imshow(mod_img,cmap='gray')
    plt.subplot(132)
    plt.title("原始载体图像")
    plt.imshow(raw_img,cmap='gray')
  
    # 保存对比图
    plt.savefig(com_img_path)
    # 显示对比图
    plt.show()
    
    print(len(secret))
    main()

当输入数据量为5000bits时提取出的数据存在乱码,随数据量的增大乱码减少至消失
请问产生原因及解决方法

img

img

  • 写回答

8条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2023-09-02 23:27
    关注

    引用 皆我百晓生 小程序回复内容作答:

    产生乱码的原因是LSB隐写算法在提取数据时需要按照一定规则进行拆分和转换才能正确还原数据。在你的代码中,当输入数据量为5000bits时,由于每个字符的ASCII码所占用的二进制位数不足8位,导致在拆分和转换过程中可能出现错误,从而导致乱码的产生。

    解决方法是在提取数据时,根据LSB隐写算法的规则,逐步拼接和转换二进制位,直到得到完整的文本信息。具体修改代码如下:

    def getText(mod_img):
        width = mod_img.size[0]  # 图像宽度 512
        height = mod_img.size[1]  # 图像高度 512
        get_text = ""
        text = ""
        countEND = 0
        # 遍历每个像素点
        for w in range(width):
            for h in range(height):
                pixel = mod_img.getpixel((w, h))
                get_text += get_lsb(pixel)
                if get_text.endswith(end_str):
                    text += get_text[:-len(end_str)]
                    return text
                if len(get_text) >= 8:
                    # 转换成ASCII码
                    # 例:"0110 0001" -> 97 -> 'a'
                    ch = chr(int(get_text[:8], 2))
                    if ch == end:
                        countEND += 1
                    if countEND == 2:
                        break
                    text += ch
                    get_text = get_text[8:]
        return text
    

    这样修改后,即可正确提取到数据,并避免乱码的产生。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(7条)

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 9月3日
  • 已采纳回答 9月3日
  • 创建了问题 9月2日

悬赏问题

  • ¥15 ansys electronics 2021 R1安装报错,错误代码2,如图
  • ¥30 搭建面包板由NE555N和SN74LS90N组成的计时电路时出了问题
  • ¥15 无源定位系统的时差估计误差标准差
  • ¥15 请问这个代码哪里有问题啊
  • ¥20 python--version在命令端输入结果Python is not defined怎么办?还有pip不是exe格式是不是没安装成功?
  • ¥15 通过GaussianView进行结构微调消除虚频
  • ¥15 调用transformers库
  • ¥15 由于导出的数据名字中带有/,导致Matlab打不开,怎么办?
  • ¥15 新硬盘安装的程序总是崩溃,提示遇到错误
  • ¥15 openpcdet自制数据集评估bev精度和3d精度相同