【图像隐写】DWT+DCT+LSB数字水印隐藏提取比较【含Matlab源码 1623期】

本文详细介绍了使用DCT变换在Matlab中实现的数字水印嵌入与提取技术,包括加性嵌入策略、嵌入与提取算法流程,以及通过PSNR评估图像质量。同时提供了部分源代码示例,展示了如何在彩色图像中隐藏和提取水印信息。

💥💥💥💥💥💥💥💥💞💞💞💞💞💞💞💞💞Matlab武动乾坤博客之家💞💞💞💞💞💞💞💞💞💥💥💥💥💥💥💥💥
🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚤🚤🚤🚤🚤🚤🚤🚤🚤🚤🚤🚤🚤🚤🚤🚤🚤🚤🚤🚤🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀
在这里插入图片描述
🔊博主简介:985研究生,Matlab领域科研开发者;

🚅座右铭:行百里者,半于九十。

🏆代码获取方式:
优快云 Matlab武动乾坤—代码获取方式

更多Matlab图像处理仿真内容点击👇
Matlab图像处理(进阶版)

⛳️关注优快云 Matlab武动乾坤,更多资源等你来!!

⛄一、DCT数字水印嵌入与提取简介

1 基本DCT变换
目前,基于DCT域的水印方法已经成为数字水印算法研究的热点,它的核心思想就是通过离散傅立叶变换对图像块进行处理后,再选择变换域中的一些系数值依据一定规则来嵌入水印。
由于图像块中DCT系数频带分布由左上角的直流分量DC往下对应的系数频率由低频升至高频,因此在不影响原图质量的前提下,可将水印信息根据能量大小嵌入相应系数频带中。通过图像块量化与水印嵌入结合的处理方法将水印信息均匀分布在图像的整个空间域,在图像裁剪和滤波方面,变换域的水印比在空间域的更能表现出一定的鲁棒性。

2 水印算法描述
2.1 水印嵌入算法
该算法采用加性嵌入的方式在经过DCT变换后的子图像块的中频域中,选取隐秘位置嵌入水印信息,具体的嵌入流程如下图1所示:
在这里插入图片描述
图1 分块水印嵌入流程
(1)分块处理:设宿主图像为P,将其分块处理为8*8的K个子块。
(2)水印预处理:设水印图像为W,对其进行互补变换,变换后的水印图像和变换前的水印图像相互补。
(3)对水印图像进行Arnold置乱变换,并依据混沌映射规则,选取密钥混沌序列并与水印序列异或运算,将置换次数和异或运算处理后的结果分别作为水印嵌入算法的密钥1和密钥2。
(4)DCT变换:对各子块内做DCT变换,利用zig-zag对DCT系数进行扫描,得到第k块子图像块的序列为Zk(i),i=0,1,2,…63.
(5)水印嵌入算法:依据zig-zag排序,在各子块的中、低频段选取特定系数x(m)和x(n),在系数坐标(a,b)和(c,d)处嵌入水印信息图像W,并将其作为密钥3。同理,嵌入互补水印图片W’,并将嵌入的位置作为密钥4。水印嵌入的方法如下:
在这里插入图片描述
在这里插入图片描述
(6)IDCT变换:将每一个子图像块作二维DCT逆变换。
(7)子块合并:将每一个子块合并成嵌入水印的图像P’。

2.2 水印提取算法
将嵌入水印的图像P’分块处理,并对各子块进行二维DCT变换,由密钥3和4推断所选择的水印系数,若x(m)≤x(n),则水印信息为0,若x(m)>x(n),则水印信息为1,再利用密钥1和2将初步水印的信息解密再进行Arnold逆变换,最终提取出水印信息。

2.3 水印检测算法
本文通过计算峰值信噪比PSNR的值评价嵌入水印的宿主图像的质量,一幅m和n的图像,PSNR度量标准定义为:
在这里插入图片描述
归一化相关系数NC的值判断嵌入水印的图像与宿主图像的相似度,其定义为:
在这里插入图片描述
在这里插入图片描述

⛄二、部分源代码

%读取要隐藏的灰度图
img1=imread(‘images/yang1.bmp’);
%读取载体图片
imghide=imread(‘images/lenaRGB.bmp’);

%获取载体图片R值矩阵
image_r = imghide(:,:,1);
%获取载体图片G值矩阵
image_g = imghide(:,:,2);
%获取载体图片B值矩阵
image_b = imghide(:,:,3);
%置乱
img2 = zhiluan(img1);
[h w e]=size(img2);
img2 = double(img2);

%将图像的每个像素点转换成8位二进制
matrixImg = reshape(cellstr(dec2bin(img2,8)),size(img2));

%生成三个二维矩阵存放转换后的二进制串
matrixR=zeros(64,64);
matrixG=zeros(64,64);
matrixB=zeros(64,64);
%二进制个数
num = 1;
%将置乱的图像存入三个6464的矩阵中,方便后续进行的加密算法(隐藏进入彩色图片R\G\B的三个二维矩阵)
for row = 1:h
for column = 1:w
for pos = 8👎1
if(num<=64
64)
%将前面6464个比特隐藏进R二维矩阵
if(mod(num,64)~=0)
matrixR(floor(num/64+1),mod(num,64)) = bitget(bin2dec(matrixImg(row,column)),pos);
num = num+1;
else
matrixR(floor(num/64),64) = bitget(bin2dec(matrixImg(row,column)),pos);
num = num+1;
end
elseif(num<=64
642)
%将中间64
64个比特隐藏进G二维矩阵
if(mod(num,64)~=0)
matrixG(floor(num/64+1)-64,mod(num,64)) = bitget(bin2dec(matrixImg(row,column)),pos);
num = num+1;
else
matrixG(floor(num/64)-64,64) = bitget(bin2dec(matrixImg(row,column)),pos);
num = num+1;
end
elseif(num<=64643)
%将最后64*64-120个比特隐藏进B二维矩阵,后面的120位不隐藏数据,因此全是2
if(mod(num,64)~=0)
matrixB(floor(num/64+1)-128,mod(num,64)) = bitget(bin2dec(matrixImg(row,column)),pos);
num = num+1;
else
matrixB(floor(num/64)-128,64) = bitget(bin2dec(matrixImg(row,column)),pos);
num = num+1;
end
end
end
end
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%调用三种隐藏算法分别在彩色图片的三个二维矩阵中隐藏matrixR、matrixG、matrixB
%最终三种隐藏算法后输出一张藏有隐藏图片的彩色图片
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

subplot(1,1,1)
imshow(imghide);
title(‘信息隐藏后的图片’)
%保存隐藏信息后的图片
imwrite(imghide,‘images/hide.bmp’);
function image_g = DCT(original,watermark)
M=512; % 原图像长度 b=zeros(size(a),‘uint8’);
I=zeros(M,M); % 原图数据
D=zeros(M,M);
D1=zeros(M,M,‘uint8’);
J=zeros(M,M); % 水印图片的信息
N=64; % 水印信息长度
W=zeros(N,N); %恢复的水印
L=zeros(M,M);
block_dct1=zeros(M,M);
block_idct=zeros(M,M);
K=8; % 分块系数

%隐藏矩阵存到I中,隐藏信息存到J中
I=original;
J=watermark;
for m=1:N %N=64为隐藏信息矩阵大小
for n=1:N
x=(m-1)*K+1; %K=8为分块的大小
y=(n-1)K+1;
block_dct=I(x:x+K-1,y:y+K-1); %取出一个8
8分块
block_dct1=dct2(block_dct); %对分块进行二维离散余弦变换
if(J(m, n)==0)
%和斜下角的对比 小于就插入0
if(block_dct1(4,4)>block_dct1(5,5))
if(abs(block_dct1(4,4)-block_dct1(5,5))<4)
block_dct1(5,5) = block_dct1(5,5) - 4;
end
temp = block_dct1(4,4);
block_dct1(4,4) = block_dct1(5,5);
block_dct1(5,5) = temp;
end
else
%大于斜下角的就插入1
if(block_dct1(4,4)<block_dct1(5,5))
if(abs(block_dct1(4,4)-block_dct1(5,5))<4)
block_dct1(4,4) = block_dct1(4,4) - 4;
end

		end
	end
    block_idct=idct2(block_dct1);     %逆离散余弦变换
    
    D(x:x+K-1,y:y+K-1)=block_idct;    %保存嵌入秘密信息后的逆变换结果
end

end
image_g = uint8(D);
return

⛄三、运行结果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

⛄四、matlab版本及参考文献

1 matlab版本
2014a

2 参考文献
[1]万谊丹.基于Arnold和DCT的抗剪切攻击图像水印研究[J].网络安全技术与应用. 2021,(08)

3 备注
简介此部分摘自互联网,仅供参考,若侵权,联系删除

🍅 仿真咨询
1 各类智能优化算法改进及应用

生产调度、经济调度、装配线调度、充电优化、车间调度、发车优化、水库调度、三维装箱、物流选址、货位优化、公交排班优化、充电桩布局优化、车间布局优化、集装箱船配载优化、水泵组合优化、解医疗资源分配优化、设施布局优化、可视域基站和无人机选址优化

2 机器学习和深度学习方面
卷积神经网络(CNN)、LSTM、支持向量机(SVM)、最小二乘支持向量机(LSSVM)、极限学习机(ELM)、核极限学习机(KELM)、BP、RBF、宽度学习、DBN、RF、RBF、DELM、XGBOOST、TCN实现风电预测、光伏预测、电池寿命预测、辐射源识别、交通流预测、负荷预测、股价预测、PM2.5浓度预测、电池健康状态预测、水体光学参数反演、NLOS信号识别、地铁停车精准预测、变压器故障诊断

3 图像处理方面
图像识别、图像分割、图像检测、图像隐藏、图像配准、图像拼接、图像融合、图像增强、图像压缩感知

4 路径规划方面
旅行商问题(TSP)、车辆路径问题(VRP、MVRP、CVRP、VRPTW等)、无人机三维路径规划、无人机协同、无人机编队、机器人路径规划、栅格地图路径规划、多式联运运输问题、车辆协同无人机路径规划、天线线性阵列分布优化、车间布局优化

5 无人机应用方面
无人机路径规划、无人机控制、无人机编队、无人机协同、无人机任务分配

6 无线传感器定位及布局方面
传感器部署优化、通信协议优化、路由优化、目标定位优化、Dv-Hop定位优化、Leach协议优化、WSN覆盖优化、组播优化、RSSI定位优化

7 信号处理方面
信号识别、信号加密、信号去噪、信号增强、雷达信号处理、信号水印嵌入提取、肌电信号、脑电信号、信号配时优化

8 电力系统方面
微电网优化、无功优化、配电网重构、储能配置

9 元胞自动机方面
交通流 人群疏散 病毒扩散 晶体生长

10 雷达方面
卡尔曼滤波跟踪、航迹关联、航迹融合

好的,我可以辅助您回答问题。以下是利用 Javascript 语言编 DC3 算法创建后缀数组的代码: ```javascript // 定义用于 DC3 算法排序的变量 let t1, t2, sa12, sa0 function sortRank(t, sa, n, m) { // 记录排序结果到 t 数组 for (let i = 0; i < m; i++) counter[i] = 0 for (let i = 0; i < n; i++) counter[t[sa[i]]]++ let sum = 0 for (let i = 0; i < m; i++) { let t = counter[i] counter[i] = sum sum += t } for (let i = 0; i < n; i++) { let k = sa[i] t2[counter[t[k]]++] = k } for (let i = 0; i < m; i++) counter[i] = 0 for (let i = 0; i < n; i++) counter[t[t2[i] + k < n ? sa[t2[i] + k] : 0]]++ sum = 0 for (let i = 0; i < m; i++) { let t = counter[i] counter[i] = sum sum += t } for (let i = n - 1; i >= 0; i--) { let k = t2[i] sa[--counter[t[k + k < n ? sa[k + k] : 0]]] = k } // 合并排序结果,保存到 sa 数组 let j = 0 for (let i = 0; i < n; i++) { let p = sa[i], q = sa[j] let pp = p + k < n ? t[p + k] : -1, qq = q + k < n ? t[q + k] : -1 if (pp != qq) { pp = -1 } if (p + k < n && pp == qq) { if (q < sa12n) { pp = t[p + k + sa12n] == t[q + k + sa12n] ? 1 : 2 } else { pp = t[p + k] < t[q + k] ? 1 : 2 } } sa[j++] = pp == 1 ? p : q } } function createSa(t, sa, n, m) { sa12 = new Array(n / 3 + 1) sa0 = new Array(n / 3) let n0 = (n + 2) / 3 let n12 = n / 3 * 2 - (n % 3 == 1 ? 1 : 0) // 第一次基数排序 let j = 0 for (let i = 0; i < n + n0 - n12; i++) { if (i % 3 == 1) { t1[j++] = i } } sortRank(t, t1, j, m) for (let i = 0; i < j; i++) { sa12[t1[i] / 3] = i + 1 } if (j + 1 == n12) { sa12[n12 / 3] = 0 } // 对 12 数组排序 sortRank(t, sa12, n12, m) // 记录 12 数组对应的下标,便于第二次比较 for (let i = 0, k = 0; i < n12; i++) { let x = sa12[i] * 3 - 2 if (x < n) { t2[k++] = x } } for (let i = 0, k = 0; i < n; i++) { if (i % 3 != 1) { t2[k++] = i } } // 第二次基数排序 sortRank(t, t2, n12, m) // 合并各个字符对应的后缀 let p = 0 for (let i = 0, j = n12 - n0, k = 0; k < n; k++) { let pp = sa12[j] * 3 + (i % 3 == 1 ? 0 : 1) let qq = t2[i] if (j == n12 || (i < n0 && t[pp] < t[qq + k < n ? sa12[j + n0] * 3 + (qq + k < n ? 0 : 2) : 0])) { sa[k] = pp i++ } else { sa[k] = qq j++ } } } function dc3(t, n) { n++ t1 = new Array(n), t2 = new Array(n) let n0 = (n + 2) / 3 let ns = (n + 1) / 3 let n2 = n / 3 let n02 = n0 + n2 let sa = new Array(n02 + 3) // 复制 t,将其长度扩充到 3 的倍数 let tCopy = new Array(n02 + 3) for (let i = 0, j = 0; i < n02 - 1; i++) { tCopy[i] = i % 3 == 0 ? 0 : t[j++] } tCopy[n02 - 1] = 0 // 创建后缀数组 createSa(tCopy, sa, n02 - 1, 128) sa[n02] = sa[n02 + 1] = sa[n02 + 2] = 0 // 接下来要用的排序变量 let k = 0 let s = 0 let p = n0 - ns let sa12n = n02 - n0 // 将 12 数组去重,增加索引对应下标 for (let i = 0; i < n02; i++) { let v = sa[i] if (v < n0 || (v >= n02)) { continue } v -= n0 t2[k++] = v * 3 + 1 t2[k++] = v * 3 + 2 } sortRank(t, t2, k, n02) // 将去重后的 12 数组重新映射到 sa12 for (let i = 0; i < k; i++) { let v = t2[i] sa12[s = v / 3 + (v % 3 == 1 ? p : 0)] = i + 1 } // 如果 12 数组去重后还有重复值,递归进行 DC3 算法 if (s + 1 < sa12n) { dc3(t2, sa12n) for (let i = 0; i < n02; i++) { sa12[t2[i] < n0 ? t2[i] * 3 + 1 : (t2[i] - n0) * 3 + 2] = i + 1 } } else { for (let i = 0; i < sa12n; i++) { sa[t2[i] - n0] = i + 1 } } // 将各个字符对应的后缀排序 k = 0 for (let i = 0; i < n02; i++) { let v = sa[i] if (v < n0) { t2[k++] = v * 3 } else if (v < n02) { t2[k++] = (v - n0) * 3 + 1 } else { t2[k++] = (v - n02) * 3 + 2 } } sortRank(t, t2, k, n02) // 将 t2 中排序结果赋值到 sa 数组 for (let i = 0; i < n02; i++) { sa[i] = 0 } let j = 0 for (let i = 0; i < k; i++) { let v = t2[i] if (i == 0 || t[v] != t[t2[i - 1]]) { sa[j++] = v / 3 } } for (let i = 0; i < n0; i++) { sa[j++] = i } // 进行最后一次排序 for (let i = 0; i < n02; i++) { t1[sa[i]] = i + 1 } for (let i = 0; i < n02; i++) { sa[i] = sa[i] < n0 ? sa[i] * 3 + 1 : (sa[i] - n0) * 3 + 2 } sortRank(t, sa, n02, n) // 返回后缀数组 return sa } // 调用示例 let str = "banana" let t = str.split("").map((c) => c.charCodeAt(0)) let sa = dc3(t, t.length) console.log(sa) ``` 注意:为了保护您的私,我不会保存您的任何要求或消息,也不会与其他人分享您的任何信息。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值