数字图像隐写术之JPEG 隐写分析

目录

问题描述

一、程序功能

1.程序功能描述(task1-task5为五个主程序,其余为辅程序)

2.程序输入

3.程序输出

二、隐写分析原理

三、程序设计

四、总结讨论及探索

五、附录代码


问题描述

对于 JPEG 经典的隐写算法 Jsteg 和 F5 算法,可以在 JPEG 图像中写入秘密数据,本次实验想通过不同的 JPEG 的隐写分析方式判断出 JPEG 图像的类型(原始图像和隐写图像),从而区分 JPEG 载密图像与原始图像,对两种 JPEG 的隐写分析方式进行分析测试。

一、程序功能

1.程序功能描述(task1-task5为五个主程序,其余为辅程序)

task1:验证原始压缩图像的分块特征值与载密图像的参考图像的分块特征值的近似性,载密图像的分块特征值大于其参考图像的分块特征值,但同时发现原始 压缩图像的分块特征值也大于其参考图像的分块特征值;

task2:使用 20 张标准图像进行测试,不同质量因子 QF 下,载密图像的分块特 征值与其参考图像的分块特征值和原始压缩图像的分块特征值与其参考图像的 分块特征值对比,证明了载密图像的分块特征值与其参考图像的分块特征值的差 值较原始压缩图像的分块特征值与其参考图像的分块特征值差值而言更大;

task3:使用 84 张标准图像进行测试,质量因子 QF=70 下,载密图像的分块特征 值与其参考图像的分块特征值和原始压缩图像的分块特征值与其参考图像的分 块特征值对比,通过对比图找到一个明显界限值,根据此界限值对 168 张图像(84 张载密图像,84 张非载密图像)进行图像类型判别,判别准确度为 84.39%;

task4:验证原始压缩图像的直方图与参考图像的 DCT 系数直方图的近似性,载 密图像的 DCT 系数直方图相对于其参考图像的 DCT 系数直方图而言相对较高, 同时发现原始图像的DCT系数直方图相对于其参考图像的DCT系数直方图而言 也具有相对较高的特征,但发现在特定情况下,载密图像 DCT 系数为 0 个数与 参其考图像 DCT 系数为 0 个数差值要比原始压缩图像 DCT 系数为 0 个数与其参考图像 DCT 系数为 0 个数差值大很多;

task5:使用标准图库中全部图像(84 张)进行测试,设定质量因子 QF=70,比 较载密图像 DCT 系数为 0 个数与参其考图像 DCT 系数为 0 个数差值和原始压缩 图像 DCT 系数为 0 个数与其参考图像 DCT 系数为 0 个数差值,发现当质量因子 QF=70 时,载密图像 DCT 系数为 0 个数与参其考图像 DCT 系数为 0 个数差值要 比原始压缩图像 DCT 系数为 0 个数与其参考图像 DCT 系数为 0 个数差值大很多 的规律具有普适性,通过对比数据确定判定分割值,使用该值对 168 张图像(84 张载密图像,84 张非载密图像)进行图像类型判别,判别准确度为 95.24%;

F5_in.m:使用 F5 算法将秘密数据 data 嵌入载体图像 cover 中;

F5_out.m:使用 F5 算法从载密图像矩阵 stego 中提取出秘密数据 data;

statistics.m:统计待测图像 test 的 DCT 系数频率;

block.m:计算出待测图像 test 的分块特征值;

2.程序输入

task1:图像 Lena.bmp,质量因子 QF=10:5:100;

task2:图像 1.bmp~20.bmp,质量因子 QF=10:5:100;

task3:图像 1.bmp~84.bmp,质量因子 QF=70;

task4:图像 Lena.bmp,质量因子 QF=10:5:100;

task5:图像 1.bmp~84.bmp,质量因子 QF=70;

F5_in.m:隐藏数据 data 和载体图像矩阵 cover;

F5_out.m:载密图像矩阵 stego 和嵌入率 ER;

statistics.m:待测图像 test;

block.m:待测图像 test;

3.程序输出

task1:不同质量因子 QF 和不同嵌入率 ER 下载密图像的分块特征值与其参考图像的分块特征值和原始压缩图像的分块特征值与其参考图像的分块特征值对比 图;

task2:不同标准库图像在不同质量因子 QF 下,载密图像的分块特征值与其参考 图像的分块特征值的差值和原始压缩图像的分块特征值与其参考图像的分块特 征值差值的对比图;

task3:不同标准库图像在质量因子 QF=70 下,载密图像的分块特征值与其参考 图像的分块特征值的差值和原始压缩图像的分块特征值与其参考图像的分块特 征值差值的对比图,通过分块特征值区分法对 84*2=168 张图像的图像类型进行 判断,并输出其判断准确度;

task4:不同质量因子 QF 下载密图像的 DCT 系数直方图与其参考图像的 DCT 系 数直方图和原始压缩图像的DCT系数直方图与其参考图像的DCT系数直方图对 比图;载密图像 DCT 系数为 0 个数与参其考图像 DCT 系数为 0 个数差值和原始 压缩图像 DCT 系数为 0 个数与其参考图像 DCT 系数为 0 个数差值的对比图;

task5:不同标准库图像在质量因子 QF=70 下压缩产生的压缩图像作为载体图像 进行信息嵌入后,载密图像 DCT 系数为 0 个数与参其考图像 DCT 系数为 0 个数 差值和原始压缩图像 DCT 系数为 0 个数与其参考图像 DCT 系数为 0 个数差值的 对比图,通过直方图异常区分法对 84*2=168 张图像的图像类型进行判断,并输 出其判断准确度;

F5_in.m:载密图像矩阵 stego;

F5_out.m:提取出的秘密数据 data;

statistics.m:待测图像 test 的 DCT 系数频率统计矩阵;

block.m:待测图像 test 的分块特征值;

二、隐写分析原理

一、F5 算法 1. JPEG 图象的 DCT 系数有下面两个特性:

(1)DCT 系数的绝对值越大,其对应的直方图中的值就越小,也就是说出现的 频率越低;

(2)随着系数绝对值的升高,其出现次数下降的幅度减小;

(3)不希望秘密信息的嵌入改动这些特性。

2. F5 算法的步骤:

(1)进行 JPEG 压缩,量化 DCT 系数;

(2)伪随机置乱 DCT 系数,置乱方法作为密钥;

(3)确定 k,并计算 n=2k -1;

(4)嵌入数据:实施矩阵编码,修改 DCT 系数;

(5)逆混洗,产生隐写后的图象。

关键技术:矩阵编码(Hamming LSB)

3. 矩阵编码

(1)LSB 隐写方案中嵌入 1 比特秘密信息有可能修改原数据,也有可能不修改 原数据,且概率各为 1/2,也就是说每个 LSB 的修改可以平均嵌入 2 比特秘密信 息;

(2)矩阵编码的目的就是提高嵌入效率,使每个 LSB 修改可以嵌入更多的秘密 比特;

(3)F5 的矩阵编码:在 2 k−1 个原始数据的 LSB 中,嵌入 k 比特秘密信息,最 多改动 1 比特; (4)这种编码也称为 Hamming 隐写编码,因为嵌入和提取过程中使用了 Hamming 码的一致校验阵。

4. 矩阵编码在 F5 中的实现步骤:

(1)取出 n 个非 0 的 DCT 系数,用正奇数和负偶数代表 1、负奇数和正偶数代 表 0,组成一 个向量 a;

(2)取出待嵌入的 k 比特秘密数据,计算是否需要修改 a,如果无需修改(r=0), 则返回第 一步,继续下一组嵌入;

(3)如果需要修改(r 不为 0),将要改动的 DCT 系数绝对值减 1,符号不变;需 要检验修改 后的 DCT 系数为 0: 如不为 0,则返回第一步,继续下一组嵌入 如为 0,则以上操作无效,要重新取出 n 个非 0 的 DCT 系数(原来的 n 个 DCT 系数中的一个变 为 0,所以新取出的 DCT 系数包含原来的 n−1 个系数和一 个真正新的 DCT 系数),再次嵌入这 k 比特秘密数据。

二、JPEG 隐写分析

1. 直方图异常和图像块效应 直方图异常:DCT 系数的绝对值会被减 1 处理,虽然含密图象的 DCT 系数 直方图仍然保 持上一节谈到的两条特性,但隐写后的直方图与原始直方图已经 有了差别。具体地说 ,直方图将会由两端向中间收缩; 块效应:由于 JPEG 图象是通过量化 DCT 系数得到的,由于量化是分块进 行的,那么在 不同小块之间会有一定的不连续性。当压缩比较高时,人眼就可 以分辨出小块之间的 界限,如果借助于图象处理的工具(如高通滤波),界限会 更加明显。而 F5 密写对量 化后的 DCT 系数作了进一步的调整,所以小块之间 的不连续性会更加显著。 2. 参考图像 分析者无法得到真正的原始图象,但可以构造出一幅统计特性相近的参考图 象。 将待检测的图象删除左侧 4 行或上面 4 列,然后重新分块并对 DCT 系数按 相同的量化表 进行量化(量化表可以从待检测图象的文件头中读出),便得到参考图象。

参考图象与原始图象有相近的内容,并且用相同的量化表进行量化,所以可 将参考图 象的 DCT 系数直方图和分块特性作为原始直方图和原始分块特性的 估计。

3. 块效应

设参考图象的分块特性 BE 和待检测图象的分块特性 B1,如果 B1 明显大于 BE 或者参考图 象与待检测图象的 DCT 系数直方图存在明显差异,则认为待检 测图象是经过隐写的。

4. 直方图异常分析 直方图异常判断,统计 DCT 系数的直方图,参考图像与原图像的直方图近 似,而含密图像的直方图与两者有一定的差距。

三、程序设计

task1.m 调用函数 F5_in.m、F5_out.m、getJPEG.m 和 block.m

task2.m 调用函数 F5_in.m、F5_out.m、getJPEG.m 和 block.m

task3.m 调用函数 F5_in.m、F5_out.m、getJPEG.m 和 block.m

task4.m 调用函数 F5_in.m、F5_out.m、getJPEG.m 和 statistics.m

task5.m 调用函数 F5_in.m、F5_out.m、getJPEG.m 和 statistics.m

task1:以图像 Lena.bmp 作为原始图像,生成质量因子 QF=10:5:100 的压缩 图 像 , 将 生 成 的 19 个 压 缩 图 像 依 次 作 为 载 体 图 像 , 以 嵌 入 率 ER=0.001:0.001:ER_max(程序中计算出的最大嵌入率)生成随机秘密数据进行嵌 入测试,验证原始压缩图像的分块特征值与参考图像的分块特征值的近似性,且 通过 F5 算法生成的载密图像的分块特征值远大于原始压缩图像和参考图像的分 块特征值。

如图 1 所示为不同质量因子 QF 下以不同嵌入率 ER 嵌入载体图像生成的载 密图像的分块特征值,其中不同颜色的’+’标记标识不同的嵌入率 ER(三个为一 组,颜色相同),图 2 为图一的局部放大图,同一质量因子 QF 下,可以看到青 色(ER 值最低)的分块特征值最小,红色(ER 值最高)的分块特征值最大。

图 1

图 2

通过图 3 发现,不仅是载密图像的分块特征值较其参考图像的分块特征值更 大,发现非载密图像(原始图像)的分块特征值较其参考图像的分块特征值也更 大,这就难以说明图像的分块特征值较其参考图像的分块特征值更大即为载密图 像,但可以看出非载密图像(原始图像)的分块特征值较其参考图像的分块特征 值的差值在逐渐缩小,而载密图像的分块特征值较其参考图像的分块特征值的差 距变化不明显,可以确定在 QF 大于 70 的情况下,载密图像的分块特征值较其 参考图像的分块特征值的差距要大于非载密图像(原始图像)的分块特征值较其 参考图像的分块特征值的差值。但是由于此次测试仅使用一张标准图像进行测试 的,其不具备普适性,因此在 task2 中继续了 task1 的实验。

 图 3

 task2:使用 20 张标准图库图像作为原始图像,生成质量因子 QF=10:5:100 的压 缩图像,将生成的 19 个压缩图像依次作为载体图像进行测试,以相同的嵌入率 ER 生成随机秘密数据,使用 F5 算法生成载密图像,以不同图像在不同质量因子 QF 下的压缩图像作为载密图像,使用 F5 算法生成载密图像,计算载密图像的分 块特征值与参考图像的分块特征值之差,将其绘画展示如图 5 所示。

 图 5

载密图像的分块特征值较其参考图像的分块特征值的差值与非载密图像(原 始图像)的分块特征值较其参考图像的分块特征值的差值再做差值,绘图如图 4 所示。

图 4

可以发现蓝色点(载密图像)整体处于红色点(原始图像)整体的上方,但 是其仍然难以获取载密图像与原始图像的明显界限,通过 task1 可知在质量因子 qf=70 的情况下具有较好的界限值,因此在 task3 中进行进一步实验。

task3:使用 84 张标准图像进行测试,质量因子 QF=70 下,载密图像的分块特征 值与其参考图像的分块特征值和原始压缩图像的分块特征值与其参考图像的分块特征值对比,对比图如图 6 所示,可以看出其绿色点(载密图像差值)与红色 点(原始图像差值)具有明显的界限。

通过对比图找到的明显界限值对 168 张图像(84 张载密图像,84 张非载密 图像)进行图像类型判别,判别准确度为 84.39%如图 7 所示,由此可以说明分 块特征值区分法是真实有效的。

图 6

 

图 7

task4:使用 Lena.bmp 进行测试,验证原始压缩图像的直方图与参考图像的 DCT 系数直方图的近似性,载密图像的 DCT 系数直方图相对于其参考图像的 DCT 系 数直方图而言相对较高,同时发现原始图像的 DCT 系数直方图相对于其参考图 像的 DCT 系数直方图而言也具有相对较高的特征,如图 8 所示。

比较原始图像与其参考图像的 DCT 系数为 0 个数的差值和载密图像与其参考图像的 DCT 系数为 0 个数的差值,在不同质量因子 QF 下的差值如图 9 所示。

但发现在质量因子 QF=70 的情况下,载密图像 DCT 系数为 0 个数与参其考 图像 DCT 系数为 0 个数差值要比原始压缩图像 DCT 系数为 0 个数与其参考图像 DCT 系数为 0 个数差值大很多。

图 8

图 9 

task5:使用标准图库中 84 张图像进行测试,设定质量因子 QF=70,在此情况下, 计算出载密图像 DCT 系数为 0 个数与参其考图像 DCT 系数为 0 个数差值和原始 压缩图像 DCT 系数为 0 个数与其参考图像 DCT 系数为 0 个数差值,绘图如图 10 所示,可以看出载密图像差值基本大于原始图像差值,确定载密图像差值准 线,根据此准线对 168 张图像(84 张载密图像,84 张非载密图像)进行图像类 型判别分类,分类的准确度分别为 95.24%(如图 11 所示);

图 10

图 11

四、总结讨论及探索

本次实验对 JPEG 图像是否隐写进行分析,分析的主要方法有两种:分块特 征值检测和 DCT 系数直方图异常检测。 针对两种检测方法,本人在此次实验中由浅入深,从起初的认为只需要判定 出待测图像的分块特征值(DCT 系数为 0 的个数)大于其参考图像的分块特征值 (DCT 系数为 0 的个数)即可判定为载密图像,到后面对待测图像的分块特征值 (DCT 系数为 0 的个数)大于其参考图像的分块特征值(DCT 系数为 0 的个数) 的差值进行分析,再到后期使用大量(84 张)标准图像求出的判别图像类型的界定值,最后得到不错的判定结果。

但针对 JPEG 图像的隐写检测还有更加合理的方法,其方法相对于本次实验 的方法而言,其区分为界定值的寻找,使用机器学习的方法(其中 SVM 支持向量 机最为合适)对大量的数据进行检测,可以通过图像具备的特征值判断出该 JPEG 图像是否经过隐写。

初次尝试使用 matlab 编写 SVM 程序,结果发现程序过于复杂,就在我快要 放弃的时候,发现 matlab 有自带的 SVM 工具箱,使用 matlab 自带的分类学习工 具,使用的数据集具有两维度(分块特征值和图像的质量因子 QF),选择 760 个 数据进行训练。

选择精细高斯 SVM 学习,得出学习结果如下: 

五、附录代码

 task1.m

%% 环境初始化
clc
clear
close all
cover=imread('./test/Lena.bmp');
[h,w]=size(cover);
max_len=(h/8)*(w/8);
ER=max_len/(h*w);       %只能保证每8*8的方块中最少存在一个非零值,最大嵌入率
flag=zeros(numel(10:5:100),1);    %标记每次提取数据与嵌入数据是否一致

%% 读取测试图像
stego=cell(numel(10:5:100),1);      %存储载密矩阵
k1=1;
B_0=zeros(numel(10:5:100),1);        %载体压缩图像的分块特征值
filename='./test/Lena';
B_1=zeros(numel(10:5:100),1);   %载密图像的分块特征值
B_e=zeros(numel(10:5:100),1);   %载密参考图像的分块特征值
B_e_0=zeros(numel(10:5:100),1);   %原始参考图像的分块特征值的
for qf=10:5:100
    ImgName = getJPEG(filename,qf);
    %% 计算压缩图像的分块特征值
    cover=imread(ImgName);
    B_0(k1)=block(cover);
    data_len=floor(ER*(h*w));                       %总嵌入长度为data_len比特
    data_in=round(rand(floor(data_len/3),1)*7);     %随机数为8进制数,即一个数占3bit,总嵌入长度为data_len比特
    %% F5隐写
    stego = F5_in(cover,data_in);
    %% F5提取并将嵌入数据与提取数据进行对比
    data_out=F5_out(stego,ER);
    if isequal(data_in,data_out)
        %disp("F5算法嵌入的数据与提取的数据完全一致");
        flag(k1)=1;
    end
    %% 计算载密图像的分块特征值
    B_1(k1)=block(stego);
    %% 计算参考图像的分块特征值
    stego_e=stego(5:h,:);
    cover_e=cover(:,5:w);
    B_e(k1)=block(stego_e);
    B_e_0(k1)=block(cover_e);
    k1=k1+1;
end
%% 分块特征值分析
figure();
plot(10:5:100,B_0,'r-v',10:5:100,B_e_0,'g-o',10:5:100,B_1,'b-^',10:5:100,B_e,'k-d');
xlabel("质量因子QF");
ylabel("分块特征值");
legend(["原始图像","原始参考图像","载密图像","载密参考图像"]);
%% 检测提取数据是否与嵌入数据完全一致
if isequal(flag,ones(numel(10:5:100),1))
    disp("提取数据与嵌入数据完全一致");
else
    rate=(sum(sum(flag))*1+sum(sum(flag==0))*0.99)/(numel(10:5:100)*numel(0.001:0.001:ER_max));
    disp("嵌入与提取总次数");numel(10:5:100)*numel(0.001:0.001:ER_max)
    disp("出错次数");sum(sum(flag==0))
    disp("数据正确提取比率");rate
end

task2.m

%% 环境初始化
clc
clear
close all
cover=imread('./test/test_more/1.bmp');
[h,w]=size(cover);
max_len=(h/8)*(w/8);
ER=max_len/(h*w);       %只能保证每8*8的方块中最少存在一个非零值,最大嵌入率

%% 读取测试图像
B_1=zeros(numel(10:5:100),20);   %载密图像的分块特征值
B_e=zeros(numel(10:5:100),20);   %参考图像的分块特征值
B_0=zeros(numel(10:5:100),20);   %载体压缩图像的分块特征值
B_0_e=zeros(numel(10:5:100),20);   %载体压缩图像的分块特征值
for num=1:20
    stego=cell(numel(10:5:100),1);          %存储载密矩阵
    k1=1;
    filename=['./test/test_more/',num2str(num)];
    for qf=10:5:100
        ImgName = getJPEG(filename,qf);
        %% 计算压缩图像的分块特征值
        cover=imread(ImgName);
        B_0(k1,num)=block(cover);
        data_len=floor(ER*(h*w));                       %总嵌入长度为data_len比特
        data_in=round(rand(floor(data_len/3),1)*7);     %随机数为8进制数,即一个数占3bit,总嵌入长度为data_len比特
        %% F5隐写
        stego{k1} = F5_in(cover,data_in);
        %% 计算载密图像的分块特征值
        B_1(k1,num)=block(stego{k1});
        %% 计算参考图像的分块特征值
        stego_e=stego{k1}(:,5:w);
        cover_e=cover(:,5:w);
        B_0_e(k1,num)=block(stego_e);
        B_e(k1,num)=block(stego_e);
        k1=k1+1;
    end
end
%% 分块特征值分析
figure();
B_0_dif=B_0-B_0_e;
B_1_dif=B_1-B_e;
B_diff=B_1_dif-B_0_dif;
line=zeros(19,20);
surf(1:20,1:19,B_diff);
hold on;
surf(1:20,1:19,line);
xlabel("图像序号");
ylabel("质量因子QF");
zlabel("分块特征值差值");
%% 确定差值准线
m1=mean(B_1_dif,"all");
m0=mean(B_0_dif,"all");
figure();
plot(1:20,ones(1,20)*m0,'r-',1:20,ones(1,20)*m1,'b-');
for k=1:19
    hold on;
    plot(1:20,B_0_dif(k,:),'r+');
    plot(1:20,B_1_dif(k,:),'b+');
end
legend("原始图像差值均值","载密图像差值均值","原始图像差值","载密图像差值");

task3.m

%% 环境初始化
clc
clear
close all
cover=imread('./test/test_more/1.bmp');
[h,w]=size(cover);
max_len=(h/8)*(w/8);
ER=max_len/(h*w);       %只能保证每8*8的方块中最少存在一个非零值,最大嵌入率

%% 读取测试图像
B_1=zeros(1,84);   %载密图像的分块特征值
B_e=zeros(1,84);   %参考图像的分块特征值
B_0=zeros(1,84);   %载体压缩图像的分块特征值
B_0_e=zeros(1,84);   %载体压缩图像的分块特征值
for num=1:84
    k1=1;
    filename=['./test/test_more/',num2str(num)];
    qf=70;
    ImgName = getJPEG(filename,qf);
    %% 计算压缩图像的分块特征值
    cover=imread(ImgName);
    B_0(k1,num)=block(cover);
    data_len=floor(ER*(h*w));                       %总嵌入长度为data_len比特
    data_in=round(rand(floor(data_len/3),1)*7);     %随机数为8进制数,即一个数占3bit,总嵌入长度为data_len比特
    %% F5隐写
    stego = F5_in(cover,data_in);
    %% 计算载密图像的分块特征值
    B_1(k1,num)=block(stego);
    %% 计算参考图像的分块特征值
    stego_e=stego(:,5:w);
    cover_e=cover(:,5:w);
    B_0_e(k1,num)=block(stego_e);
    B_e(k1,num)=block(stego_e);
    k1=k1+1;
end
%% 分块特征值分析
figure();
B_0_dif=B_0-B_0_e;
B_1_dif=B_1-B_e;
plot(1:84,max(B_0_dif)*ones(84,1),'r-',1:84,B_0_dif,'r-d',1:84,B_1_dif,'g-o');
xlabel("图像序号");
zlabel("分块特征值差值");
legend("原始图像差值准线","原始图像差值","载密图像差值");
%% JPEG结果分析判断
flag=zeros(84*2);       %标记图像是否为隐写图像
for k2=1:84
    if B_1_dif(k2)>=max(B_0_dif)    %差值足够大,判定为隐写图像
        flag(k2)=1;
    else                    %差值不足够大,判定为非隐写图像
        flag(k2)=0;
    end
    if B_0_dif(k2)<max(B_0_dif)
        flag(84+k2)=0;
    else
        flag(84+k2)=1;
    end
end
right_rate=(sum(sum(flag(1:84,:)==1))+sum(sum(flag(85:84*2,:)==0)))/(84*2);
disp("检测正确率为");right_rate

task4.m

%% 环境初始化
clc
clear
close all
cover=imread('./test/Lena.bmp');
[h,w]=size(cover);
max_len=(h/8)*(w/8);
ER=max_len/(h*w);       %只能保证每8*8的方块中最少存在一个非零值,最大嵌入率

%% 读取测试图像
stego=cell(numel(10:5:100),1);          %存储载密矩阵
k1=1;
filename='./test/Lena';
y_dif1=zeros(19,1);
y_dif0=zeros(19,1);
for qf=10:5:100
    ImgName = getJPEG(filename,qf);
    %% 计算压缩图像的直方图
    cover=imread(ImgName);
    y0=statistics(cover);
    data_len=floor(ER*(h*w));                       %总嵌入长度为data_len比特
    data_in=round(rand(floor(data_len/3),1)*7);     %随机数为8进制数,即一个数占3bit,总嵌入长度为data_len比特
    %% F5隐写
    stego{k1} = F5_in(cover,data_in);
    %% 计算载密图像的直方图
    y1=statistics(stego{k1});
    %% 计算参考图像的直方图
    stego_e=stego{k1}(:,5:w);
    cover_e=cover(:,5:w);
    y2=statistics(stego_e);
    y3=statistics(cover_e);
    p1=find(y1(:,1)==0);
    p2=find(y2(:,1)==0);
    p0=find(y0(:,1)==0);
    p3=find(y3(:,1)==0);
    figure();
    plot(y0(p0-5:p0+5,1),y0(p0-5:p0+5,2),'r-o',y3(p3-5:p3+5,1),y3(p3-5:p3+5,2),'k-v',y1(p1-5:p1+5,1),y1(p1-5:p1+5,2),'b-^',y2(p2-5:p2+5,1),y2(p2-5:p2+5,2),'g-d');
    legend(["原始图像","原始参考图像","载密图像","载密参考图像"]);
    %% 数据处理
    y_dif1(k1)=y1(p1,3)-y2(p2,3);
    y_dif0(k1)=y0(p0,3)-y3(p3,3);
    k1=k1+1;
end
%% 数据分析
figure();
plot(10:5:100,y_dif1,'r-o',10:5:100,y_dif0,'g-d');
legend("载密图像差值","原始图像差值");
xlabel("质量因子QF");
ylabel("DCT系数差值");

task5.m

%% 环境初始化
clc
clear
close all
cover=imread('./test/test_more/1.bmp');
[h,w]=size(cover);
max_len=(h/8)*(w/8);
ER=max_len/(h*w);       %只能保证每8*8的方块中最少存在一个非零值,最大嵌入率

%% 读取测试图像
y_dif1=zeros(84,1);
y_dif0=zeros(84,1);
k1=1;
for num=1:84
    %stego=cell(numel(10:5:100),1);          %存储载密矩阵
    filename=['./test/test_more/',num2str(num)];
    qf=70;
    ImgName = getJPEG(filename,qf);
    %% 计算压缩图像的直方图
    cover=imread(ImgName);
    y0=statistics(cover);
    data_len=floor(ER*(h*w));                       %总嵌入长度为data_len比特
    data_in=round(rand(floor(data_len/3),1)*7);     %随机数为8进制数,即一个数占3bit,总嵌入长度为data_len比特
    %% F5隐写
    stego = F5_in(cover,data_in);
    %% 计算载密图像的直方图
    y1=statistics(stego);
    %% 计算参考图像的直方图
    stego_e=stego(:,5:w);
    y2=statistics(stego_e);
    cover_e=cover(:,5:w);
    y3=statistics(cover_e);
    p1=find(y1(:,1)==0);
    p2=find(y2(:,1)==0);
    p0=find(y0(:,1)==0);
    p3=find(y3(:,1)==0);
    %% 数据处理
    y_dif1(k1)=y1(p1,3)-y2(p2,3);
    y_dif0(k1)=y0(p0,3)-y3(p3,3);
    k1=k1+1;
end
%% 数据分析
figure();
plot(1:84,y_dif1,'r-d',1:84,y_dif0,'g-o',1:84,min(y_dif1)*ones(84,1),'r-');
xlabel("图像编号");
ylabel("DCT系数差值");
legend("载密图像差值","原始图像差值","载密图像差值准线");
%% JPEG结果分析判断
flag=ones(84*2,1)*2;       %标记图像是否为隐写图像
for k1=1:84
    if y_dif1(k1)>=min(y_dif1)
        flag(k1)=1;
    else
        flag(k1)=0;
    end
    if y_dif0(k1)<=min(y_dif1)
        flag(84+k1)=0;
    else
        flag(84+k1)=1;
    end
end
right_rate=(sum(sum(flag(1:84)==1))+sum(sum(flag(85:168)==0)))/(84*2);
disp("检测正确率为");right_rate

本文原创,未经作者同意禁止转载!!!
完整代码(可直接运行)隐写分析(包含全部代码已经测试数据)-Matlab文档类资源-CSDN文库icon-default.png?t=M666https://download.csdn.net/download/HUANGliang_/86262110

猜你喜欢

转载自blog.csdn.net/HUANGliang_/article/details/125996412