📜  使用Python的基于图像的隐写术(1)

📅  最后修改于: 2023-12-03 15:06:53.896000             🧑  作者: Mango

使用Python的基于图像的隐写术

隐写术(Steganography)是指一种信息隐藏技术,通过在媒介载体中嵌入隐藏信息,以实现信息的隐蔽传输。图像隐写术是一种较为常见的隐写术方法,它隐藏的信息通常被嵌入到一张普通的图片文件中,不让人察觉。

在Python中,我们可以使用Pillow库(也被称为PIL,即Python Imaging Library)来处理图像,实现图像隐写术。

安装Pillow库
pip install pillow
图像的读取与显示

我们可以使用Pillow中的Image模块来读取和处理图像。下面是一个例子,我们读取一张本地的图片文件,并将图片显示在屏幕上。

from PIL import Image

# 打开图片
img = Image.open('test.png')

# 显示图片
img.show()
隐写信息的嵌入

嵌入隐秘信息到一张普通的图片文件中,是图像隐写术的核心技术。下面我们使用Python和Pillow库来实现基于图像的隐写术。

from PIL import Image

# 将信息嵌入图片
def encode(img_file, msg):
    # 打开图片
    img = Image.open(img_file)

    # 将字符串转换为二进制
    bin_msg = ''.join(format(i, '08b') for i in bytearray(msg, encoding ='utf-8'))

    # 获取图片的宽度和高度
    width, height = img.size

    # 计算需要嵌入信息的总像素数
    num_pixels = width * height

    # 隐写信息的长度不能超过像素数的1/4
    max_chars = int(num_pixels / 4)

    # 检查是否能嵌入信息
    if len(msg) > max_chars:
        raise ValueError("消息过长,无法嵌入。")

    # 计算每个像素RGB值的二进制
    pixels = img.load()
    pixel_index = 0

    # 隐写数据
    for bit in bin_msg:
        # 计算像素坐标
        x = pixel_index % width
        y = int(pixel_index / width)

        r, g, b = pixels[x, y]

        # 替换低位数据
        if bit == '1':
            # 对于奇数,将RGB值加上1(确保LSB位为1)
            if r % 2 == 0:
                r += 1
            if g % 2 == 0:
                g += 1
            if b % 2 == 0:
                b += 1
        else:
            # 对于偶数,将RGB值减去1(确保LSB位为0)
            if r % 2 == 1:
                r -= 1
            if g % 2 == 1:
                g -= 1
            if b % 2 == 1:
                b -= 1

        # 写入隐写数据
        pixels[x, y] = (r, g, b)

        # 更新像素索引
        pixel_index += 1

        # 完成嵌入信息
        if pixel_index == max_chars * 4:
            break

    # 保存更改后的图片
    img.save(img_file)
隐写信息的提取

隐写信息的提取通常也是一种比较容易实现的方法。我们可以按照之前嵌入隐秘信息的方法,逆向提取隐秘信息。

from PIL import Image

# 从图片中提取信息
def decode(img_file):
    # 打开图片
    img = Image.open(img_file)

    # 获取图片的宽度和高度
    width, height = img.size

    # 计算需要提取信息的总像素数
    num_pixels = width * height

    # 检查是否有嵌入数据(至少需要4个像素,每个像素至少需要取出一个LSB数据)
    pixels = img.load()
    pixel_index = 0
    bin_str = ''
    for i in range(num_pixels):
        x = pixel_index % width
        y = int(pixel_index / width)

        r, g, b = pixels[x, y]

        # 提取LSB数据
        bin_str += str(r % 2)
        bin_str += str(g % 2)
        bin_str += str(b % 2)

        # 更新像素索引
        pixel_index += 1

        if pixel_index >= 4 and pixel_index % 4 == 0:
            # 检测是否为ASCII码
            if bin_str[-8:] == '00000000':
                break

    # 转换二进制字符串为ASCII编码
    decoded_msg = ''.join(chr(int(bin_str[i:i+8], 2)) for i in range(0, len(bin_str), 8))

    return decoded_msg
测试

为了测试我们的图像隐写术程序,我们需要准备一张图片和一条隐秘信息,并将隐秘信息嵌入到图片中。然后,我们将提取隐秘信息并检查是否和预期的内容相同。

# 测试图像隐写术
if __name__ == '__main__':
    # 图片文件
    img_file = 'test.png'

    # 隐秘信息
    secret_msg = 'Hello, World!'

    # 将隐秘信息嵌入到图片中
    encode(img_file, secret_msg)

    # 提取嵌入的隐秘信息
    decoded_msg = decode(img_file)

    # 输出结果
    print(decoded_msg)  # Hello, World!

验证结果是正确的,我们成功地使用Python实现了一种基于图像的隐写术程序。