小力士丸 2024-10-20 16:53 采纳率: 50%
浏览 14

lsb图片信息隐写为什么提取时乱码


import tkinter as tk
from tkinter import filedialog
import numpy as np
from PIL import Image
import os

# 全局变量,用于存储选择的图片路径
image_path = ""

def select_image():
    """打开文件对话框,让用户选择图片,并更新全局变量 image_path"""
    global image_path
    image_path = filedialog.askopenfilename(filetypes=[("Image files", "*.png;*.jpg;*.jpeg;*.bmp;*.gif")])
    if image_path:
        image_label.config(text=f"已选择图片: {os.path.basename(image_path)}")

def lsb_embed(pic_src, secrets):
    """将秘密信息嵌入到图片中"""
    original_picture = Image.open(pic_src)
    original_format = original_picture.format
    pic_data = np.array(original_picture)

    im_data = np.array(original_picture.copy()).ravel().tolist()

    def cover_lsb(bin_index, data):
        res = []
        for i in range(8):
            data_i_bin = bin(data[i])[2:].zfill(8)
            if bin_index[i] == '0':
                data_i_bin = data_i_bin[0:7] + '0'
            elif bin_index[i] == '1':
                data_i_bin = data_i_bin[0:7] + '1'
            res.append(int(data_i_bin, 2))
        return res

    pic_idx = 0
    res_data = []
    for char in secrets:
        index = ord(char)
        bin_index = bin(index)[2:].zfill(8)
        res = cover_lsb(bin_index, im_data[pic_idx * 8: (pic_idx + 1) * 8])
        pic_idx += 1
        res_data += res
    res_data += im_data[pic_idx * 8:]

    new_im_data = np.array(res_data).astype(np.uint8).reshape((pic_data.shape))
    res_im = Image.fromarray(new_im_data)
    res_im = res_im.convert(original_picture.mode)

    pic_folder_path = './pic'
    if not os.path.exists(pic_folder_path):
        os.makedirs(pic_folder_path)

    res_im.save(f'./pic/res_encode.{original_format.lower()}')
    print(f"在 pic 中已生成 res_encode.{original_format.lower()}")

def lsb_extract(pic_src):
    """从图片中提取秘密信息"""
    picture = Image.open(pic_src)
    pic_datas = np.array(picture).ravel().tolist()

    def lsb_decode(data):
        str_bin = ''
        for i in range(len(data)):
            data_i_bin = bin(data[i])[2:][-1]
            str_bin += data_i_bin
        return chr(int(str_bin, 2))

    str_data = ''
    pic_idx = 0
    while True:
        data = pic_datas[pic_idx * 8: (pic_idx + 1) * 8]
        char = lsb_decode(data)
        if char == '\x00':
            # 增加一个判断,如果下一个字符也为 '\x00',则停止提取
            if pic_idx * 8 + 8 < len(pic_datas) and lsb_decode(pic_datas[pic_idx * 8 + 8: (pic_idx + 1) * 8 + 8]) == '\x00':
                break
        # 判断是否为可打印字符,如果不是则停止提取
        if not char.isprintable():
            break
        str_data += char
        pic_idx += 1

    return str_data

def embed_message():
    """处理隐藏信息按钮的点击事件"""
    secrets = input_text.get("1.0", tk.END).strip()
    if not secrets:
        result_label.config(text="请输入要隐藏的信息!", fg="red")
        return
    if not image_path:
        result_label.config(text="请选择图片!", fg="red")
        return
    lsb_embed(image_path, secrets)
    result_label.config(text="隐写成功!", fg="green")

def extract_message():
    """处理提取信息按钮的点击事件"""
    if not image_path:
        result_label.config(text="请选择图片!", fg="red")
        return
    extracted_data = lsb_extract(image_path)
    extracted_text.config(text=extracted_data)
    result_label.config(text=f"提取成功!提取的信息如上")

# 创建 Tkinter 窗口
root = tk.Tk()
root.title("QのLSB 隐写和提取工具!")
root.title_label = tk.Label(root, text=root.title(), fg="green")
root.title_label.pack()

# 创建并放置选择图片标签和按钮
image_label = tk.Label(root, text="请选择图片以继续...")
image_label.pack(pady=10)
select_image_button = tk.Button(root, text="选择图片", command=select_image)
select_image_button.pack(pady=5)

# 创建信息输入和输出框架
info_frame = tk.Frame(root)
info_frame.pack(pady=10)

# 创建输入部分
input_label = tk.Label(info_frame, text="输入要隐藏的信息:")
input_label.pack(pady=5, anchor='w')
input_text = tk.Text(info_frame, height=5, width=40, bg='white')
input_text.pack(pady=5)

# 创建提取部分
extracted_label = tk.Label(info_frame, text="提取的信息:")
extracted_label.pack(pady=5, anchor='w')
extracted_text = tk.Label(info_frame, text="", wraplength=300, bg='white')
extracted_text.config(height=4, width=40)
extracted_text.pack(pady=5)

# 创建按钮框架
button_frame = tk.Frame(root)
button_frame.pack(pady=10)

# 创建并放置隐藏信息和提取信息的按钮
embed_button = tk.Button(button_frame, text="隐藏信息", command=embed_message)
embed_button.pack(side=tk.LEFT, padx=20)
extract_button = tk.Button(button_frame, text="提取信息", command=extract_message)
extract_button.pack(side=tk.RIGHT, padx=20)

# 创建并放置结果标签
result_label = tk.Label(root, text="", wraplength=300)
result_label.pack(pady=10)

# 进入 Tkinter 主事件循环
root.mainloop()

为什么提取的时候出现乱码

img

  • 写回答

1条回答 默认 最新

  • 无疆76 2024-10-20 16:54
    关注

    以下回复参考:皆我百晓生券券喵儿等免费微信小程序作答:

    你的Python代码在LSB隐写提取时遇到乱码问题,可能是因为提取过程不正确或解码部分存在问题。这个问题可能是由于几个原因导致的:

    1. 二进制解析错误:在lsb_decode函数中,你试图从每个像素值的二进制表示中提取最低位(LSB)来构建消息。但是,你似乎只提取了每个像素的最后一个比特位,而没有正确处理所有比特位。此外,当你合并所有的比特位时,可能没有正确地将其转换回字符串或字符。
    2. 信息编码方式问题:在嵌入信息时,你可能使用了某种特定的编码方式(如UTF-8),但在提取时可能没有正确地解码。确保在嵌入和提取时使用相同的编码方式。
    3. 终止条件问题:在lsb_extract函数的while循环中,你使用了一个基于字符的终止条件。如果嵌入的信息不包含足够的可打印字符来正确终止循环,可能会导致乱码或无限循环。确保嵌入的信息具有适当的终止条件。
    4. 可能的损坏图片问题:如果原始图片被修改或损坏,或者嵌入信息时的操作不正确,可能导致提取信息时出现乱码。

    针对这些问题,你需要检查和修改你的代码以确保正确处理LSB隐写过程。特别是在解析LSB和解码过程中需要更多的细致工作来确保信息被正确地提取和转换。另外,检查并确保在嵌入信息时使用了正确的编码方式,并在提取时使用相同的解码方式。最后,确保嵌入的信息具有明确的终止条件,以便正确结束提取过程。

    评论

报告相同问题?

问题事件

  • 创建了问题 10月20日