空域信息隐藏算法(完成基于LSB的图像信息隐藏)
最近在上信息隐藏,做一个记录
一,实验要求
(1)了解信息隐藏算法的分类方式和分类依据
(2)理解空域信息隐藏算法的基本思想
(3)掌握最低有效位算法原理
(4)完成基于LSB的图像信息隐藏
二、实验内容
载体图像为24位真彩色bmp图像Lena.bmp,嵌入的秘密图像为黑白的bmp图像LSB.bmp,要求采用空域信息隐藏算法,将LSB.bmp嵌入到Lena.bmp的最低有效位中,同屏显示原载体图像、需要嵌入的秘密图像、嵌入了秘密图像的伪装载体、提取的秘密图像。
以下为实验材料:lena.bmp 和 LSB.bmp
隐体:
三、实验步骤和设计思想
1,使用pyhton库,skimage来完成相关的土图像处理
2,通过skimage库打开隐体,发现只有两个值【255,和 0】所以,其实隐藏时,只要用一位就可以隐藏隐体,将255使用1代替,0不变,将其藏在载体的最后一位即可。
3,因为隐体为RGB三通道图像,为了隐藏的更好,使用随机数将0和1,随机选定一个图层进行隐藏,当然为了能够还原原图像,使用一个seed作为key,这样产生的随机数就可以顺序提取。
4,隐藏和提取时,使用位运算可轻松的实现数字的高低位的存取。
5,将变换后的图片进行保存,再使用相同的key和隐藏信息后的载体,进行提取。
6,为了方便使用,将隐藏的方法和过程使用,面向对象的思想,封装为类。
四,### 代码
from skimage import io
import numpy
class IMG_LSB:
def __init__(self, key):
self.key = key
def show(self, img):
"""
显示图片
:param img: 显示的图片矩阵
:return: none
"""
io.imshow(img)
io.show()
def create_cover(self, img_cover_name, img_info_name, save_img_name):
"""
使用LSB算法对图像进行隐藏,隐藏到使用key作为种子生成的随机数指定的RGB通道中
:param img_cover_name: 载体图片名
:param img_info_name: 隐体图片名
:param save_img_name: LSB生成后的图片保存位置以及名字
:return: LSB生成后的图片矩阵
"""
img_info = io.imread(img_info_name)
img_cover = io.imread(img_cover_name)
self.show(img_info)
self.show(img_cover)
self.ls_info = img_info.shape[0] # 得到隐体图片的长和宽
self.ls_cover = img_cover.shape[0] # 得到载体的长和宽
if self.ls_info > self.ls_cover:
print("载体太小")
# 开始隐藏
numpy.random.seed(self.key)
for i in range(0, self.ls_info):
for j in range(0, self.ls_info):
if img_info[i][j] == 255 : # 如果隐体为255则藏在R层最低为置为1
img_cover[i, j, numpy.random.randint(0, 3)] |= 1 # 随机选定一个通道进行隐藏
else:
img_cover[i, j, numpy.random.randint(0, 3)] &= 254 # 如果隐体为0则藏在R层最低为置为0
self.show(img_cover)
io.imsave(save_img_name, img_cover)
return img_cover
def extract_img(self, blmb_name, save_img_name):
"""
对隐体进行提取并显示
:param blmb_name: LSB生成的含有隐体的载体名
:param save_img_name: 提取后的隐体存储的位置
:return: 提取后的隐体的矩阵
"""
blmb = io.imread(blmb_name)
matrix = [[255 for i in range(self.ls_info)] for i in range(self.ls_info)] # 生成与隐体相同大小的矩阵,并赋值为255
re_info_img = numpy.array(matrix, dtype=numpy.uint8) # 将生成的矩阵转化为可存储图像的8位格式
self.show(re_info_img)
# 开始提取
numpy.random.seed(self.key)
for i in range(0, self.ls_info):
for j in range(0, self.ls_info):
randint_value = numpy.random.randint(0, 3) # 使用seed控制随机数的生成保证与之前隐藏时,生成的随机数一致
blmb[i, j, randint_value] &= 1 # 取出最后一位
if blmb[i, j, randint_value] == 0:
re_info_img[i][j] &= 0 # 如果最后一位为0则隐体原处为0,为1则为255
else:
re_info_img[i][j] |= 255
io.imsave("img/re_img.bmp", re_info_img)
self.show(re_info_img)
return re_info_img
# 测试
if __name__ == '__main__':
img = IMG_LSB(123) # key为123
img.create_cover("img/Lena.bmp", "img/LSB.bmp", "img/blmb2.bmp")
img.extract_img("img/blmb2.bmp", "img/re_img.bmp")
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构