Python实现可逆信息隐藏 简介 对如下参考文献进行代码实现,用于实现图片的可逆信息隐藏。
[1]赵彦涛, 李志全, and 董宇青. “基于排序和直方图修改的可逆信息隐藏方法.” 光电子.激光 21.1(2010):5.
算法介绍
将图像分为图像块,并且得出每个图像块的像素点。
将图像块序列从小到大进行排序,并且按照排序后的中间值灰度作为参考。
将排序后的其余像素与中间值灰度进行差值序列生成。
找到插值绝对值直方图的峰值最大点。
利用直方图修改的方法进行信息隐藏。
恢复出隐藏的信息和原始图片。
对该方法的抗攻击性进行验证。
代码实现 导入模块 按照如下要求导入相关的模块:
1 2 3 4 5 6 from PIL import Imageimport numpy as npimport matplotlib.pyplot as pltimport cv2import randomfrom PIL.ImageFilter import FIND_EDGES, EDGE_ENHANCE, EDGE_ENHANCE_MORE, SHARPEN
导入图片 导入图片,由于方法限制,仅限于导入正方形图片。
1 2 3 4 5 6 7 8 9 10 11 def importImg (imgLoc ): img = Image.open (imgLoc) if img.size[0 ] == img.size[1 ]: img = img.convert('L' ) imgLen = img.size[0 ] img = np.array(img) return img, imgLen else : print ("请输入正方形的图片" ) quit()
信息隐藏函数 根据如下代码进行二进制数据的信息隐藏。
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 def processBlock (blockX, blockY ): global curr_index left_top_point = (blockX * blockLen, blockY * blockLen) pixelList = [] x0 = left_top_point[0 ] y0 = left_top_point[1 ] for i in range (blockLen): for j in range (blockLen): x = x0 + i y = y0 + j value = img[x][y] pixelList.append((value, x, y)) pixelList.sort(key=getValue) middle_value = pixelList[pixelInBlock // 2 ][0 ] histogram = [0 for _ in range (260 )] for i in range (pixelInBlock): diff = abs (int (pixelList[i][0 ]) - int (middle_value)) histogram[diff] += 1 summit_diff = histogram.index(max (histogram)) summit[blockX][blockY] = summit_diff for i in range (pixelInBlock): if curr_index == len (data): return diff = int (pixelList[i][0 ]) - int (middle_value) x = pixelList[i][1 ] y = pixelList[i][2 ] if i < pixelInBlock // 2 : if diff < -summit_diff: img[x][y] -= 1 elif diff == -summit_diff: if data[curr_index] == '1' : img[x][y] -= 1 curr_index += 1 elif i > pixelInBlock // 2 : if diff > summit_diff: img[x][y] += 1 elif diff == summit_diff: if data[curr_index] == '1' : img[x][y] += 1 curr_index += 1
信息提取函数 根据如下代码进行二进制数据的信息可逆提取。
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 def recoverBlock (blockX, blockY, summitDiff ): leftTopPoint = (blockX * blockLen, blockY * blockLen) pixelList = [] x0 = leftTopPoint[0 ] y0 = leftTopPoint[1 ] for i in range (blockLen): for j in range (blockLen): x = x0 + i y = y0 + j value = imgWithData[x][y] pixelList.append((value, x, y)) pixelList.sort(key=getValue) middle_value = pixelList[pixelInBlock // 2 ][0 ] count = 0 for i in range (pixelInBlock): diff = int (pixelList[i][0 ]) - int (middle_value) x = pixelList[i][1 ] y = pixelList[i][2 ] if i < pixelInBlock // 2 : if diff == - summitDiff - 1 : pixelList[i] = (pixelList[i][0 ]+1 , x, y) count += 1 elif i > pixelInBlock // 2 : if diff == summitDiff + 1 : pixelList[i] = (pixelList[i][0 ]-1 , x, y) count += 1 pixelList.sort(key=getValue) for i in range (pixelInBlock): if len (data_extracted) == len (data): return x = pixelList[i][1 ] y = pixelList[i][2 ] diff = int (imgWithData[x][y]) - int (middle_value) if i < pixelInBlock // 2 : if diff < - summitDiff - 1 : imgWithData[x][y] += 1 elif diff == - summitDiff - 1 : imgWithData[x][y] += 1 data_extracted.append((x, y, '1' )) elif diff == - summitDiff: data_extracted.append((x, y, '0' )) elif i > pixelInBlock // 2 : if diff > summitDiff + 1 : imgWithData[x][y] -= 1 elif diff == summitDiff + 1 : imgWithData[x][y] -= 1 data_extracted.append((x, y, '1' )) elif diff == summitDiff: data_extracted.append((x, y, '0' ))
运行结果 二进制数据集为1101101101101110110110110110110110110110110 ,隐藏的图片为锤科的”OneStep一步“图标。
原始图片
隐藏后的图片
还原后的图片
恢复的数据集为:1101101101101110110110110110110110110110110 。成功提取出数据,并且PSNR为100,实现可逆信息隐藏。
鲁棒性测试 对于该方法进行鲁棒性测试,主要针对于:
高斯噪声
椒盐噪声
低通滤波
图片旋转
图片JPG压缩
图片锐化
测试结果为:
类型
无处理
高斯噪声
椒盐噪声
低通滤波
锐化
旋转
压缩
PSNR
100
26.122
21.312
27.17
13.71
12.64
59.87
误码率(%)
0
7
41
39
22
49
1
是否抵抗
NULL
否
否
否
否
否
是