使用DWT Haar变换方法隐藏系数内的文本

时间:2016-03-24 17:55:54

标签: matlab image-processing steganography haar-wavelet dwt

我编写了下面的代码,该代码对图像进行Haar变换,并在系数的最低有效位中逐位嵌入一条秘密消息。要使用bitset函数,我将双系数转换为uint64,并在嵌入后将其更改回来。

function DwtSteg(address,message)

      coverImage=imread(address);
      ascii=uint8(message);

      [LL LH HL HH]=dwt2(coverImage,'haar');

      LH=round(LH);
      HL=round(HL);

      subplot(1,2,1)
      imshow(LH)

      [r c]=size(LL);

      wc=1;
      bc=1;
      done=false;
      for i=1:r        
          if(done)
              break
          end
          for j=1:c                      

              if(bc==8)
                 bc=1;
                 wc=wc+1;

              end

              if(wc==length(message))
                  done=true;
                  break;
              end

              xb = typecast(LH(i,j), 'uint64' );
              xb=bitset(xb,1,bitget(ascii(wc),bc));
              xb%***
              LH(i,j)=typecast(xb, 'double');  
              bc=bc+1;                    
          end    

      end

      subplot(1,2,2)
      imshow(LH)

      stegoImage=idwt2(LL ,HL,LH, HH,'haar');

      figure(2)
      imshow(uint8(stegoImage));

      imwrite(uint8(stegoImage),'stegoImage.tiff');

end

但是当我在代码下面运行以从Image中提取我的消息时。系数与转换后的系数相同。(考虑' ***'对于这两个函数):

function [ str ] = DwtDesteg( address)
    str='';
    image=imread(address);
    [LL LH HL HH]=dwt2(image,'haar');

      [r c]=size(LL);
      LH=round(LH);
      bc=1;
      ch=0;
      for i=1:r                
          for j=1:c                                                          
              if(bc==8)
                 bc=1;
                 str=strcat(str,ch);
                 char(ch)

              end
              xb = typecast(LH(i,j), 'uint64');
              xb%***
              ch=bitset(ch,bc,bitget(xb,1));
              bitget(xb,1)                        

              bc=bc+1;

          end    

      end

end

1 个答案:

答案 0 :(得分:0)

由于您将DWT系数操作为整数,因此您可以使用整数变换IWT。所以,而不是做

[LL LH HL HH]=dwt2(coverImage,'haar');

使用lwt2()的提升方案。

% set up a Haar integer lifting scheme
els = {'p',[-0.125 0.125],0};
lshaarInt = liftwave('haar','int2int');
lsnewInt = addlift(lshaarInt,els);
% transform away!
[LL,LH,HL,HH] = lwt2(double(image),lsnewInt);

此时,您不必进行任何舍入,例如LH = round(LH)。只需直接嵌入即可。

imread()将图像加载为uint8类型。当您将其传递给dwt2()时,它会将所有内容转换为double。但是,如果您尝试将uint8矩阵传递给lwt2(),它会抱怨,因此您必须手动将其转换为double。对于inverse transform,只需执行

image = ilwt2(LH,LH,HL,HH,lsnewInt);
image = uint8(image);

现在,您的代码还有一些其他错误,例如将LH系数强制转换为uint64会使得bitsetting混乱。追逐一切有点麻烦,所以我重写了你的功能。

<强> embed.m

function embed(filein,fileout,message)
image = imread(filein);
message = double(message);

els = {'p',[-0.125 0.125],0};
lshaarInt = liftwave('haar','int2int');
lsnewInt = addlift(lshaarInt,els);
[LL,LH,HL,HH] = lwt2(double(image),lsnewInt);

col = size(LH,2);
r = 1;
c = 1;

for i = 1:length(message);
    letter = message(i);
    for b = 8:-1:1;
        LH(r,c) = bitset(LH(r,c),1,bitget(letter,b));
        c = c + 1;
        if (c > col)
            r = r + 1;
            c = 0;
        end
    end
end

stego = uint8(ilwt2(LL,LH,HL,HH,lsnewInt));

imshow(stego);
imwrite(stego,fileout);
end

<强> extract.m

function extract(filename,messageLength)
image = imread(filename);

els = {'p',[-0.125 0.125],0};
lshaarInt = liftwave('haar','int2int');
lsnewInt = addlift(lshaarInt,els);
[LL,LH,HL,HH] = lwt2(double(image),lsnewInt);

col = size(LH,2);
r = 1;
c = 1;

secret = zeros(messageLength,1);
for i = 1:messageLength;
    letter = 0;
    for b = 8:-1:1;
        letter = bitset(letter,b,bitget(LH(r,c),1));
        c = c + 1;
        if (c > col)
            r = r + 1;
            c = 0;
        end
    end
    secret(i) = char(letter);
end

disp(char(secret'));
end

您会注意到提取功能需要将消息长度作为参数。这是因为您的嵌入方法不以任何方式编码何时停止提取位。如果您不希望接收器依赖于该参数的知识,就像他不应该这样,您有几个选择。但是,我将把这个实现留给你,因为它超出了这个问题的范围。

  1. 在嵌入期间,在像素中放置一些位,转换为消息长度,例如,前16位/小波系数。因此,当提取开始时,它会读取前16位,将它们转换为整数,然后继续进行消息提取。
  2. 随着你的消息,嵌入一些额外的位,例如8个零,这样当你提取秘密时,你就知道在遇到它们时就停止了。