LSB(最低有效位隐写)方法以及python实现

来源为微信公众号 隐者联盟 的中的一篇极简综述01.

python实现为资源绑定!!!

JPEG早期的隐写基本来源为LSB(最低有效位)方法?

LSB方法

LSB算法分析与实现_煮酒笺华的博客-CSDN博客
简单说,就是改变颜色八位中的最后一位,来实现隐写,此为数字水印的其中一种:

(在最后一位存放信息。)
过程十分简单:把最后一位全部归零,然后依次在最后一位嵌入信息,最后再提取出来。
放置的链接中,大佬还放了代码。

PSNR指标(峰值信噪比):

PSNR全称为“Peak Signal-to-Noise Ratio”,中文意思即为峰值信噪比,是衡量图像质量的指标之一。PSNR是基于MSE(均方误差)定义,对给定一个大小为m*n的原始图像I和对其添加噪声后的噪声图像K,其MSE可定义为:
在像素上的差异。

diff = imag1 - imag2
mse = np.mean(np.square(diff))
psnr = 10 * np.log10(255 * 255 / mse)

则PSNR可定义为:
在这里插入图片描述

 其中MAXI为图像的最大像素值,PSNR的单位为dB。若每个像素由8位二进制表示,则其值为2^8-1=255。但注意这是针对灰度图像的计算方法,若是彩色图像,通常可以由以下方法进行计算:

方法一:计算RGB图像三个通道每个通道的MSE值再求平均值,进而求PSNR

方法二:直接使用matlab的内置函数psnr()(注意该函数将所有图像当成灰度图像处理)。

方法三:将图像转为YCbCr格式,只计算Y分量即亮度分量的PSNR。

     PSNR事实上只是将MSE换成了信号处理中常用的db(分贝)表达形式

知道信息熵的话,就会知道原理,其实就是log里面换成概率p,把MSE规范化为【0~1】之间的数值,如果把MSE作为分母,那么分子就设置为一个死数,这样公式中唯一的变量还是MSE。

所以PSNR与MSE没有什么本质上的不同,只是数字上看起来更加有区分度一些(从数学上讲这算不得什么根本性的东西,但从人的辨识度来讲,这个优势还是挺明显的)。由于PSNR公式将MSE放在了分母上,所以在进行图像质量评估时,PSNR数值越大表明待评估的图像质量越好,这一点与MSE相反。PSNR公式中的MAX是一个常数,它表示图像数据类型的最大动态范围。比如对于float型的图像数据,其取值范围是[0, 1],所以MAX=1​。对于uint8类型的图像数据,其取值范围是[0, 255],所以MAX=255​。一般情况下MAX就这两种情况。

MSE与PSNR的问题

MSE与PSNR的问题是,在计算每个位置上的像素差异时,其结果仅与当前位置的两个像素值有关,与其它任何位置上的像素无关。这也就是说,这种计算差异的方式仅仅将图像看成了一个个孤立的像素点,而忽略了图像内容所包含的一些视觉特征,特别是图像的局部结构信息(局部边缘和纹理的相似性,来模拟人眼的感知)。而图像质量的好坏极大程度上是一个主观感受,其中结构信息对人主观感受的影响非常之大。

因此,采用这种方式计算出来的差异有时不能很好地反映图像质量。这就是SSIM(Structural Similarity,结构相似性)所希望要解决的问题。

SSIM实现区域性计算

图像的差异构成:
亮度(luminance):像素值越大越亮,反之越暗。
对比度:像素值的分布,越广越有对比度,对应方差标准差。
结构:像素间相对位置以及比例关系,余弦相似度的概念,图像结构可以看做是图像在向量空间中的方向。
三个维度信息形成了一种互补的关系,在三者的共同约束下形成了对图像质量的描述。比如余弦相似度可以描述图像结构的差异程度,但是它却无法保证图像绝对数值的差异,比如向量(1, 2, 3),(2, 4, 6),(3, 6, 9)三者两两之间的余弦相似度均为1,但是它们的数值大小和方差却各不相同。反过来看,图像的均值和方差相同的情况下也无法保证图像的结构相同,因为即使我们将图像的像素位置完全打乱,其均值和方差也会保持完全不变,但是结构却发生了翻天覆地得变化。

一个局部区域(patch):给定来自一个图像的patch “x”和来自另一张图像的相应patch “y”

亮度相似性:0表示差异大,1表示无差异。
  
这个公式由来为(x-y)^2展开式,本式>=0,只有当x接近y的时候=0,转化之后,就是只有在x接近y的时候,相似度接近1。

对比度相似性:比较纹理的数量,纹理数量相似为1,不相似(一个平坦,一个纹理多),相似度为0.
(原理同上,但是从数值变成了分布,也就是从亮度变为对比度(纹理),平均值和标准差正好是分布定义的两个指标)

结构相似度:当两个patch包含具有相同位置和方向的边缘时,得分很高,但如果patch在边缘的位置上存在分歧,则得分很低。(此为相关性系数,弥补了协方差不能再两个不同量纲下计算的不足)


其中,协方差可以用来看相关性,大于0为正相关,小于0为负相关。
如果均值把这些(x,y)分为四个区域,然后做距离,分布在12区域多的话,就为负,为负相关;反之,为正相关。
然而,方差和标准差都是协方差的一种,就是xy为一个变量。

 上述S函数为C3=C2/2的简化形式。

这里我通常发出疑问,为什么不是直接相加,而是通过相乘,并且加常数避免分母为0呢?

我的解答为:这三个条件是同时满足,而不是满足一个就好,同时满足,而且范围都在【01】之间,那么安装概率统计规律,必然相乘。

图像质量评估指标:MSE,PSNR,SSIM-蒲公英云 这一篇推导很不错,但是格式有问题。

Skimage.measure 的compare_psnr和compare_ssim的改动_哈土奇的博客-CSDN博客

信息隐藏基础算法——LSB算法(python实现)_ma_ling_shu的博客-CSDN博客

上传的代码里面没有实现PRSN以及SSIM的计算。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当然可以!下面是一个使用PythonLSB加解密脚本示例: ```python import cv2 import numpy as np def hide_data_in_video(video_path, data): # 读取视频 cap = cv2.VideoCapture(video_path) fps = cap.get(cv2.CAP_PROP_FPS) frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) # 将数据转换为二进制 binary_data = ''.join(format(ord(char), '08b') for char in data) # 隐藏数据 frame_index = 0 bit_index = 0 while cap.isOpened() and frame_index < frame_count and bit_index < len(binary_data): ret, frame = cap.read() if not ret: break # 获取当前像素的RGB值 r, g, b = frame[:,:,0], frame[:,:,1], frame[:,:,2] # 将数据嵌入到最低有效位中 r = np.bitwise_and(r, 0xFE) | int(binary_data[bit_index]) bit_index += 1 if bit_index < len(binary_data): g = np.bitwise_and(g, 0xFE) | int(binary_data[bit_index]) bit_index += 1 if bit_index < len(binary_data): b = np.bitwise_and(b, 0xFE) | int(binary_data[bit_index]) bit_index += 1 # 更新帧的RGB值 frame[:,:,0], frame[:,:,1], frame[:,:,2] = r, g, b # 显示帧 cv2.imshow('Steganography', frame) if cv2.waitKey(int(1000/fps)) & 0xFF == ord('q'): break frame_index += 1 cap.release() cv2.destroyAllWindows() def extract_data_from_video(video_path, data_length): # 读取视频 cap = cv2.VideoCapture(video_path) frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) # 提取数据 frame_index = 0 bit_index = 0 extracted_data = '' while cap.isOpened() and frame_index < frame_count and bit_index < data_length: ret, frame = cap.read() if not ret: break # 获取当前像素的RGB值 r, g, b = frame[:,:,0], frame[:,:,1], frame[:,:,2] # 提取最低有效位中的数据 extracted_data += str(r & 1) bit_index += 1 if bit_index < data_length: extracted_data += str(g & 1) bit_index += 1 if bit_index < data_length: extracted_data += str(b & 1) bit_index += 1 frame_index += 1 cap.release() return ''.join(chr(int(extracted_data[i:i+8], 2)) for i in range(0, len(extracted_data), 8)) # 测试代码 video_path = 'input.mp4' data = 'Hello, World!' # 要隐藏的数据 # 隐藏数据 hide_data_in_video(video_path, data) # 提取数据 extracted_data = extract_data_from_video(video_path, len(data) * 8) print('Extracted Data:', extracted_data) ``` 上述脚本中,`hide_data_in_video`函数用于向视频中隐藏数据,`extract_data_from_video`函数用于从视频中提取隐藏的数据。隐藏数据时,我们将数据转换为二进制表示,并将其嵌入到每个像素的RGB通道的最低有效位中。提取数据时,我们逆向操作,提取每个像素的RGB通道的最低有效位并恢复为二进制数据,然后将其转换回原始数据。 请注意,该示例仅提供了基本的LSB加解密功能,并可能不适用于所有视频格式和编解码器。在实际应用中,还需要考虑视频质量、压缩等因素,并根据需求进行适当的修改和扩展。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值