基于扩频的数字视频水印嵌入和检测算法matlab仿真

发布时间 2023-10-10 23:44:52作者: 简简单单做算法

1.算法运行效果图预览

 

2.算法运行软件版本

matlab2022a

 

3.算法理论概述

      在MPEG压缩标准中,数据流是以多路复合流的格式存储和传输的。多路复合流由音频流和视频流复合组成。多路复合流的基本单位时包,而一个包由三个组组成。组分为视频组和音频组,在此只介绍视频组。它采用分层的语法定义,每一层包括一个或多个从属层。

 

       由于视频流被分成多个图片组,每个组包含特征相近的一些图像帧的集合,帧又被分成画面,再分成宏块。画面内编码的基本单位是宏块,一个宏块由6个8*8像素块构成:四个亮度块Y0, Y1, Y2, Y3,一个色度块U,一个色度块V。注意,四个亮度块覆盖的画面区域与每个色度块覆盖的画面区域是相同的,原因是由于色度信息的信息量比亮度信息少,为了提高数据压缩率而对色度信息作了适合人类视觉系统灵敏度的亚采样。

 

      MPEG视频压缩编码的目的是为了在保持较好画面质量的同时获得较高的压缩比。由于在编码过程中不能保持精确的像素值,所以该算法是有失真的,视频压缩的最优性能依赖于高质t画面、高压缩比与数据流读取三者之间矛盾的折衷。

 

         原始视频信号的数据量非常大,不利于存储和传输,所以视频信号需要进行数据压缩。为了获得高压缩比,就必须有效的去掉视频在时域和空域上的冗余。MPEG-2采用基于块的运动补偿以减少时域冗余。运动补偿用于对当前画面作相对于前一幅画面的因果预测,对当前画面作相对于后一幅画面的非因果预测,或作相对于前、后画面的差补预测。对每一个8*8像素的画面区域均定义一个运动矢量,以保证能有效恢复画面。用DCT变换对差值信号(即预测误差)作进一步压缩,以消除空域冗余:然后以一个不可逆的过程对DCT系数量化,删去不太重要的信息;最后,将运动矢量与DCT信息结合,并用变长码进行嫡编码,得到压缩的视频流。

 

         在MPEG视频中,由于视频的I帧上色度的离散余弦变换DCT的直流系数DC是一个始终在视频流中存在而且很鲁棒的参数,我们将水印信息经m序列调制后加入到I帧的色度DCT的直流系数中,这样水印信息在不影响视频效果的情况下一般是难以去除的,所以鲁棒性是足够的,这里我们采用了扩频的方法,以方便有效的检测水印,另外有效的抵抗各种攻击及干扰。这里关键问题是色度DCT的直流系数DC是一个对于视觉系统很敏感的参数,我们在色度DCT的直流系数DC上加水印相当于对其加入微量干扰,必须使这种千扰低于一定的门限制,使得人眼的视觉系统对视频中色度的微小变化感觉不到,所以我们将根据直流系数的大小自适应的加上不同程度的水印,以提高数字水印检测率并且提高了视频的效果。下面分别给出水印嵌入和提取的算法:

 

       由于使用了伪随机序列调制水印,水印信号类似于白噪声,水印对未授杠来说是很难检测、定位、移除和处理的。图描述了扩频水印的嵌入过程。

 

 

 

       水印的提取通过把嵌入水印的视频流与相同懂得伪随机序列作相关运算,根据相关值的大小来判定水印的比特值。水印的提取框图如图所示。

 

 

 

4.部分核心程序

for j =1:length(attens)
    j
    atten      = attens(j);
    %读取水印 
    msg0       = imresize(imread('bupt.bmp'),1);
    [row2,col2]= size(msg0);
    msg        = msg0(:);
 
 
    load mpeg2_toolbox\mpeg_avi.mat
    MPEG2_I_frame       = MPEG2_avi{1};
    MPEG2_I_frame1      = imresize(MPEG2_I_frame,5);
    [row,col] = size(MPEG2_I_frame1);
    s_len     = row*col;
    %generate msg to be embedded
    i=1;
    while floor(s_len/(row2*col2)) > 2^i
        i=i+1;
    end
    frag    = 2^(i-1); 
    msg_len = floor(s_len/frag);
    degree  = 5;%degree为m序列的级数
    pn0     = 2*pn_gen([degree,2,0],[zeros(1,degree-1),1],0)-1;
    pn1     = 2*pn_gen([degree,2,0],[zeros(1,degree-1),1],1)-1;
 
    for i = 1:1
 
        %读取视频
        MPEG2_I_frame       = MPEG2_avi{i};
        MPEG2_I_frame1      = imresize(MPEG2_I_frame,5);
        s         = MPEG2_I_frame1;
        [row,col] = size(MPEG2_I_frame1);
        s_len     = row*col;
        len       = row2*col2;
        %帧间运动检测,加入水印
        
        bld       = func_add_sy(frag,msg,len,s,atten,pn0,pn1);
        
        
        %进行攻击
        out0      = double(vedio_attack(bld,SEL));
        %提取水印
        out       = func_del_sy(frag,out0,len,pn0,pn1)';
        om        = Vector2Matrix(out,col2,1);
%         figure(1);
%         subplot(221);
%         imshow(MPEG2_I_frame1,[]);title('原始视频');
%         subplot(222);
%         imshow(msg0);title('水印');    
%         subplot(223);
%         imshow(bld,[]);title('原始视频加入水印');
%         subplot(224);   
%         imshow(om);title('提取水印');     
        %计算提取误差
        ERR1(j) =  1/mean(mean(abs(MPEG2_I_frame1-out0)));
        ERR2(j) =  mean(mean(abs(om-msg0)));
        PSNR(j) = psnr(MPEG2_I_frame1, out0);
    end
end
figure;
plot(attens,PSNR,'b');
grid on
xlabel('水印嵌入强度');
ylabel('视频质量');
figure;
semilogx(attens,ERR1,'b');
grid on
xlabel('水印嵌入强度');
ylabel('视频质量');
%  PSNR = psnr(MPEG2_I_frame1, bld)
figure;
semilogx(attens,ERR2,'b');
grid on
xlabel('攻击强度');
ylabel('水印嵌入强度');
%  PSNR = psnr(MPEG2_I_frame1, bld)
if SEL==1
   save R1.mat attens ERR1 ERR2 PSNR
end
if SEL==2
   save R2.mat attens ERR1 ERR2 PSNR
end
if SEL==3
   save R3.mat attens ERR1 ERR2 PSNR
end