Python+OpenCV 实现图像位平面分层进行图像信息隐藏

引言

闲言:这篇博客回归了传统图像处理领域,主要是在研究生的数字图像处理课程上接触到了新的知识--图像位平面,觉得还挺有意思的,可以用来做信息隐藏,索性记录一下。因为拖延的缘故,到学期末才赶出来一篇,后续可能还会有一篇消除图像摩尔纹的trick介绍(如果效果好的话)。  本文的主题是介绍图像位平面相关知识,并依据不同位平面包含信息量的多寡设计了一种图像信息隐藏的算法,实际就是位平面的叠加,可以适用于图片加水印等场景。

图像位平面

首先对图像的位平面进行介绍,众所周知,图像在计算机中存储方式为二维矩阵,矩阵的每一个元素都代表对应位置处像素点的亮度值,通常用uint8来表示,取值范围为0~255。换而言之,每个像素点都是一个8位二进制数,那么如果我们将每个像素点的一位抽取出来就可构造一个对应原图大小的为片面,其元素取值变为了0~1。举例而言,假设有一2*2的图像,其灰度值为: <math xmlns="http://www.w3.org/1998/Math/MathML"> [ [ 1 , 2 ] , [ 3 , 4 ] ] [[1,2],[3,4]] </math>[[1,2],[3,4]] 那么其最低位位平面就为: <math xmlns="http://www.w3.org/1998/Math/MathML"> [ [ 1 , 0 ] , [ 1 , 0 ] ] [[1,0],[1,0]] </math>[[1,0],[1,0]]

值得注意的是,不同位片面的取值范围虽然相同,但其所包含的信息量是不同的(或者说权重),这是因为在构成图像时,它们要乘以对应二进制位数的权重,而位数越高从0变换至1或者从1变化至0给图像带来的影响越剧烈,位数越高保留的图像信息越整体,反之则越细节。对比如下:

那么利用这一性质,我们就可以把用隐藏图片的最高位平面替换载体图片的最低位片面来达到隐藏信息,或者给图片加水印的目的。

代码

代码上实现还是比较简单的,通过与运算提取出待隐藏图片的最高位平面,将其信息移动到要插入的位平面;然后去除载体图片对应的位平面,并进行替换即完成了隐藏部分。复原部分就只是前一阶段的逆过程,整体如下所示

python 复制代码
import cv2
import warnings
import numpy as np
import matplotlib.pyplot as plt

def InfoHidden(carry_img,info_img,bit_plane):
    """
    carry_img: 作为载体的图片
    info_img: 作为隐藏信息的图片
    bit_plane: 要进行信息替换的平面
    """
    assert bit_plane in range(0,8),"Invaied BitPlane"
    if carry_img.shape!=info_img.shape:
        warnings.warn("shape of the two images don't match")
        carry_img=cv2.resize(carry_img,(info_img.shape[1],info_img.shape[0]))
    # 抽取info_img信息量最大平面
    info_img=np.bitwise_and(info_img,np.left_shift(1,7))
    # 转为二进制
    info_img_bit=np.right_shift(info_img,(7-bit_plane))
    # 构造carry_img的蒙版
    mask=np.bitwise_not(np.left_shift(1,bit_plane))
    hidden_img=info_img_bit+np.bitwise_and(carry_img,mask)
    return  hidden_img

def InfoExtrac(hidden_img,bit_plane):
    # 提取位平面
    recoverd_img = np.bitwise_and(hidden_img, np.left_shift(1,bit_plane))
    # 提升到最高位恢复信息
    recoverd_img=np.left_shift(recoverd_img,(7-bit_plane))
    return recoverd_img
img_path1=r"D:\temp\pic1.jpg"
img_path2=r"D:\temp\pic2.jpg"
carry_img=plt.imread(img_path1)
info_img=plt.imread(img_path2)
hidden_img=InfoHidden(carry_img,info_img,1)
plt.imshow(hidden_img)
plt.show(block=True)
recovered_img=InfoExtrac(hidden_img,1)
plt.axis('off')
plt.title('recovered image')
plt.imshow(recovered_img)
plt.show(block=True)

结果展示

待隐藏图片:

载体图片:

隐藏后图片:

复原图片:

可以看到隐藏效果还是很不错的,只是因为用的图都是彩色图样,所以存在着差异,如果是灰度图,恢复效果会十分优秀。

相关推荐
倔强青铜三17 分钟前
苦练Python第23天:元组秘籍与妙用
人工智能·python·面试
Norvyn_740 分钟前
LeetCode|Day18|20. 有效的括号|Python刷题笔记
笔记·python·leetcode
chao_7891 小时前
更灵活方便的初始化、清除方法——fixture【pytest】
服务器·自动化测试·python·pytest
心情好的小球藻1 小时前
Python应用进阶DAY9--类型注解Type Hinting
开发语言·python
都叫我大帅哥1 小时前
LangChain加载HTML内容全攻略:从入门到精通
python·langchain
惜.己2 小时前
使用python读取json数据,简单的处理成元组数组
开发语言·python·测试工具·json
都叫我大帅哥3 小时前
Python的Optional:让你的代码优雅处理“空值”危机
python
曾几何时`5 小时前
基于python和neo4j构建知识图谱医药问答系统
python·知识图谱·neo4j
写写闲篇儿7 小时前
Python+MongoDB高效开发组合
linux·python·mongodb
杭州杭州杭州8 小时前
Python笔记
开发语言·笔记·python