图片隐写术程序Python版本

原理:对于无损压缩的图片来说,最小值是像素(pixel),每个像素的颜色都是有RGB,三原色组成,颜色的范围就是0 ~ 255,转换成二进制,就是00000000 ~ 11111111。密文可以被拆分成一个个char,并且每个char可以变成二进制。这样利用最低显著位LSB把信息藏到图片中。

我之前写过一个文章,介绍了这类隐写术的原理,链接如下:

图片隐写术 (Image Steganography)_I_Am_Alex的博客-CSDN博客什么是隐写术 (Steganography)不同于密码学,隐写术是把信息藏到‘载体’之中,使信息变得不可见(invisible)。加密是把信息变得不可读(unreadable),也就是我们常说的乱码。早起的隐写术可以联想中国的藏头诗。把真正的秘密信息隐藏起来。还是就是抗战时期,用米汤写字,然后在碘酒的作用下可以显现出来。现代隐写术的应用现在的隐写术一般把数字媒体当成载体。 常见的...https://blog.csdn.net/st_andrews/article/details/105353135

隐写术主要分为四步

  • 第一步:读取图片,把每个像素中的RGB值转变成二进制,并保存
  • 第二步:读取密文信息,把信息拆分成char,转变成二进制,并保存
  • 第三步:把第二步得到的数据,利用LSB算法隐藏在第一步的数据中,并保存
  • 第四步:利用第三步得到的数据绘制新的隐写图片

需要import的库有:

import math
import imageio
import matplotlib.pyplot as plt

第一步:读取图片,把每个像素中的RGB值转变成二进制,并保存

path = "test.png"
message = "I am alex" * 15
bits = 3
picture = load_img(path)

# plt.imshow(pic)

# 第一步:读取图片每一个像素的 rgb 并转成二进制,补足八位
img_binary = img_in_binary(picture)

首先,声明load_img() function, 然后利用imageio把图片读进来。

def load_img(path):
    img = imageio.imread(path)
# plt.figure(figsize = (50,50))
    return img

然后,声明img_in_binary() function,把图片每个像素点的RGB保存在list中。 比如[h,w,0] 代表图片中height为h,width为w这点像素的Red数值,1是Green,2是Blue

def img_in_binary(pic):
    height = int(pic.shape[0])
    width = int(pic.shape[1])

    img_rgb_decimal = []

    for h in range(height):
        for w in range(width):
            Red = int(pic[h, w, 0])
            img_rgb_decimal.append(Red)
            Green = int(pic[h, w, 1])
            img_rgb_decimal.append(Green)
            Blue = int(pic[h, w, 2])
            img_rgb_decimal.append(Blue)
    
    img_list = decimal_to_binary(img_rgb_decimal)
    return img_list

由于,读取的RGB值是十进制整数,所以声明了一个decimal_to_binary() function, 把十进制变成二进制。Python中,用bin()这个方法可以转变成二进制,但是结果前面会带有0b两个char,所以我从第三位开始取,就是[2:]。最后声明 fill_up_binary() function把每一个二进制补足八位,以防止后期用多位数的LSB算法藏数据的时候,位数不够的问题。

def fill_up_binary(message):
    if len(message) != 8:
        gap = 8 - len(message)
        for i in range(gap):
            message = "0"+message
    return message

    
def decimal_to_binary(data):
    result = []
    for i in data:
        temp_bin = bin(i)[2:]
        full_bin = fill_up_binary(temp_bin)
        result.append(full_bin)
    return result

第二步:读取密文信息,把信息拆分成char,转变成二进制,并保存

声明 message_to_binary() function, 把密文信息转变成二进制,然后补足八位。同样会调用fill_up_binary() function. 每个char补足8位是为了提取文字的时候可以提取出来,不然位数不统一,最后无法提取密文。

def message_to_binary(message):
    result=""
    for i in message:
        temp_asc = ord(i)
        temp_bin = bin(temp_asc)[2:]
        full_bin = fill_up_binary(temp_bin)
        result = result + full_bin
    return result

# 第二步:把信息变成二进制补足八位
message_binary = message_to_binary(message)

第三步:把第二步得到的数据,利用LSB算法存在第一步的数据中,并保存

LSB核心的数据隐藏就在这步。声明了exchange() function,把密文藏进图片,计算出stego图片的新的RGB值,存到list中,以便于之后的stego图片的生成。

其中,考虑到多位数LSB算法的问题,比如LSB3的话,每个颜色信道会交换最后3位的数据,但是这样的话,最后一个颜色只有最后2位的数据可以交换,因为一个char,8为,3位在R,3位在G, 最后只有2位在B。所以要对于这种 信息长度%算法bits != 0 的情况,单独的做最后一个颜色信道的考虑。

exchange_count 是为了计算一共要多个颜色信道,要用来隐藏数据。

list储存exchange_count位的颜色隐藏信息后,并把原来图片中剩余的颜色RGB值补充进来,生成一个完整的stego图片RGB值。

def exchange(bits,data,img):
    list = []
    
    exchange_count = math.ceil(len(data)/bits)
    
    for i in range(exchange_count):
        index = i *bits
        rest = len(data) % bits
        if len(data) == rest:
            temp_str = img[i][0:-rest] + data[0:]
        else:
            temp_str = img[i][0:-bits]+ data[0:bits]
            data= data[bits:]
        list.append(temp_str)
    
    if len(list) != len(img):
        for i in range(len(list),len(img)):
            list.append(img[i])
        
    return list

第四步:利用第三步得到的数据生成新的隐写图片

最后一步,声明generate_stego_img() function, 把第三步保存的RGB值,分别覆写原图的每个像素的每个RGB中,最终可以生成新的stego图片。 注意的是,由于第三步储存的结果是二进制,所以这里声明了binary_to_decimal() function把二进制变成十进制。

def binary_to_decimal(stego_binary):
    result = []
    for i in stego_binary:
        result.append(int(i,2))
    return result

def generate_stego_img(stego_list,pic):
    height = int(pic.shape[0])
    width = int(pic.shape[1])
    
    for h in range(height):
        for w in range(width):
            pic[h, w, 0] = stego_list[0]
            pic[h, w, 1] = stego_list[1]
            pic[h, w, 2] = stego_list[2]
            stego_list = stego_list[3:]
    return pic

# 第四步:把新的 rgb 值放到图片里,生成新的图片
stego_img = generate_stego_img(stego_decimal,picture)

plt.imshow(stego_img)

如果需要完整的代码,可以留言

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
图像隐写是一种将秘密信息隐藏在图像的技,可以通过一些算法来实现。其比较常用的算法有LSB(最低有效位)算法和DCT(离散余弦变换)算法。以下是一个基于LSB算法的Python实现示例: ```python import numpy as np from PIL import Image def encode_image(image_path, message): # 打开图像并将其转换为Numpy数组 img = Image.open(image_path) img_arr = np.asarray(img) # 获取图像的形状和像素数量 shape = img_arr.shape num_pixels = img_arr.size // 3 # 将消息转换为二进制格式 bin_msg = ''.join(format(ord(i), '08b') for i in message) # 检查图像是否足够大以隐藏消息 if len(bin_msg) > num_pixels: raise ValueError("消息太长,无法隐藏在图像!") # 将消息的长度编码为8位二进制格式并添加到消息的开头 bin_msg_len = format(len(bin_msg), '08b') bin_msg = bin_msg_len + bin_msg # 将二进制消息嵌入图像的每个像素的最低有效位 idx = 0 for i in range(shape[0]): for j in range(shape[1]): for k in range(shape[2]): if idx < len(bin_msg): img_arr[i][j][k] = int(bin(img_arr[i][j][k])[2:9] + bin_msg[idx], 2) idx += 1 else: break # 将Numpy数组转换回图像并保存 encoded_img = Image.fromarray(np.uint8(img_arr)) encoded_img.save('encoded_image.png') def decode_image(image_path): # 打开图像并将其转换为Numpy数组 img = Image.open(image_path) img_arr = np.asarray(img) # 获取图像的形状和像素数量 shape = img_arr.shape num_pixels = img_arr.size // 3 # 从图像提取隐藏的二进制消息 bin_msg_len = '' bin_msg = '' idx = 0 for i in range(shape[0]): for j in range(shape[1]): for k in range(shape[2]): if idx < 8: bin_msg_len += bin(img_arr[i][j][k])[-1] elif idx < (int(bin_msg_len, 2) + 8): bin_msg += bin(img_arr[i][j][k])[-1] else: break idx += 1 # 将二进制消息转换回文本并返回 return ''.join(chr(int(bin_msg[i:i+8], 2)) for i in range(0, len(bin_msg), 8)) ``` 该代码实现了将消息嵌入图像和从图像提取隐藏消息的功能。可以通过调用`encode_image()`函数来将消息编码到图像,如下所示: ```python encode_image('original_image.png', '这是一个秘密消息!') ``` 该函数将原始图像`original_image.png`隐藏了一条消息,然后将编码后的图像保存为`encoded_image.png`。 要从编码后的图像提取隐藏的消息,可以调用`decode_image()`函数,如下所示: ```python message = decode_image('encoded_image.png') print(message) ``` 该函数将从`encoded_image.png`提取隐藏的消息并将其打印到控制台上。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值