数据库实验4-图片数据隐藏和提取

文章发布时间:

最后更新时间:

数据库实验-图片数据隐藏和提取

前言

LSB全称leastsignificant bit,是一种基于图片最低有效位修改储存信息的隐写方法。

准备工作

首先打开画图,创建一个纯红色的,100*100的图片**(请自行修改图片……)**:

img

使用QQ的截图工具获取到对应的RGB**(无意义,只是方便叙述)**。

另存为该文件为1.png,放到D盘目录。

之后创建第二个文件为信息文件,大小为100*100,文件内容使用黑色字体书写一部分内容**(建议使用黑色字体,其他字体可能会显示不正常)**:

img

保存为2.png

进行代码编写及原理剖析

本思路的LSB算法的核心为:首先,对原始图像的最后1bit(也就是最低位)置零,并不会改变图像的视觉效果;然后,将用1bit表示的版权信息,赋值给原始图像的最后1bit,实现版权信息写入,写入以后依旧不会改变原始图像,观察者也根本看不见版权信息的存在;最后,如果需要解码,只需要将图像的前7bits(高7位)置零,仅留下最后1bit(最低位),这最后1bit就是版权信息。由于只有1bit只能表示黑/白,所以要对第二张图进行二值化(颜色小于xxx的为黑,否则为白)

于是进行代码编写:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
import PIL
import cv2
from matplotlib import pyplot as plt
import numpy as np
from PIL import Image


# 输入水印图片和原图
def lsb_encoder(copyright_image, original_image):
# 读取
original_image = original_image.astype(np.uint8)
copyright_image = copyright_image.astype(np.uint8)
# 2: 对original图像和copyright图像备份,不能在原图上更改
watermark = original_image.copy()
copyright = copyright_image.copy()
# 3:将copyright二值化,使其仅含0和1,用1bit表示
copyright[copyright < 200] = 1
copyright[copyright >= 200] = 0
# 3:将watermark的最后1bit的R、G、B全部置零
for i in range(0, watermark.shape[0]):
for j in range(0, watermark.shape[1]):
watermark[i, j, :] = (watermark[i, j, :] // 2) * 2
for i in range(0, copyright.shape[0]):
for j in range(0, copyright.shape[1]):
# 5:将用1bit表示的二值化的水印信息
# 添加到watermark最后1bit上
watermark[i, j, 0] = watermark[i, j, 0] + copyright[i, j, 0]
return watermark


def remove_transparency(img_pil, bg_colour=(255, 255, 255)):
# Only process if image has transparency
if img_pil.mode in ('RGBA', 'LA') or \
(img_pil.mode == 'P' and 'transparency' in img_pil.info):
# Need to convert to RGBA if LA format due to a bug in PIL (http://stackoverflow.com/a/1963146)
alpha = img_pil.convert('RGBA').split()[-1]

# Create a new background image of our matt color.
# Must be RGBA because paste requires both images have the same format
# (http://stackoverflow.com/a/8720632 and http://stackoverflow.com/a/9459208)
bg = Image.new("RGBA", img_pil.size, bg_colour + (255,))
bg.paste(img_pil, mask=alpha)
return bg
else:
return img_pil


def lsb_decoder(watermark_image):
watermark_image = watermark_image.astype(np.uint8)
# 获取watermark图像的备份,不在原图上更改
watermark = watermark_image.copy()
watermark_copyright = (watermark % 2) * 255
return watermark_copyright


if __name__ == '__main__':
img1 = Image.open('D:\\1.png') # 读取数据
# 输入原图
img11 = np.array(img1)
img2 = Image.open('D:\\2.png')
# 输入要加密进入的图片
img22 = np.array(img2)
plt.imshow(img11)
plt.show()
plt.imshow(img2)
plt.show()
# 进行加密操作
img3 = lsb_encoder(img22, img11)
# 显示加密完成的图片
plt.imshow(img3)
plt.show()
# 进行解密,直接进行取余之后会让第一个数字为255,但是这样操作会导致透明度变成0,所以我们要转换成RGB丢弃掉通道
# 如果不使用255的话,,可以让显示文字颜色变成其他颜色。
secret = lsb_decoder(img3)
# 将解密的图片从数组转换为普通图片对象再变成RGB
withalpha = PIL.Image.fromarray(secret).convert('RGB')
# 显示这个没有alpha通道的图
plt.imshow(withalpha)
plt.show()

运行代码查看情况:

img

第一次读取的图片为纯红色图片。

img

要写入的图片展示

img

写入完毕的图片展示,右下角的RGBA值明显发生了变动,但人眼无法读取

img

使用RGB方式显示,可以看到加密进入的图片信息。