基於DCT的圖片數字水印實驗

1. 實驗類別

設計型實驗:MATLAB設計並實現基於DCT的圖像數字水印算法。算法

2. 實驗目的

 

瞭解基於DCT的圖像數字水印技術,掌握基於DCT係數關係的圖像水印算法原理,設計並實現一種基於DCT的數字水印算法。函數

 

3. 實驗條件

(1) Windows 2000或Windows Xp以上操做系統;ui

(2) MATLAB 6.5以上版本軟件;spa

(3)圖像文件操作系統

4. 實驗原理

 基於DCT的圖像數字水印設計

在信號的頻域(變換域)中隱藏信息要比在時域中嵌入信息具備更好的魯棒性。一幅圖像通過時域到頻域的變換後,可將待隱藏信息嵌入圖像的顯著區域,這種算法更具抗攻擊能力,並且保持了人類感官的不可察覺性。經常使用的變換域方法有離散餘弦變換、離散小波變換和離散傅立葉變換等。3d

本實驗介紹一種提取祕密信息的時候不須要原始圖像的盲水印算法,算法的思想是利用載體中兩個特定的DCT係數的相對大小來表示隱藏的信息。首先載體圖像分爲8*8分塊,進行二維DCT變換,分別選擇其中約定的兩個位置,好比用(u1,v1)和(u2,v2)表明所選定的兩個係數的座標。若是Bi(u1,v1)< Bi(u2,v2),表明隱藏1。若是Bi(u1,v1)> Bi(u2,v2),表明隱藏0。code

提取的時候接收者對包含水印的圖像文件進行二維DCT變換,比較每一塊中約定位置的DCT係數值,根據其相對大小,若是Bi(u1,v1)< Bi(u2,v2),則提取1;若是Bi(u1,v1)> Bi(u2,v2),則提取0。最終獲得隱藏信息的比特串,從而恢復出祕密信息。對象

在上述算法過程當中,若是有一對係數大小相差很是少,每每難以保證攜帶圖像在保存和傳輸的過程當中以及提取祕密信息的過程當中不發生變化。所以在實際的設計過程當中,通常都是引入一個Alpha變量對係數的差值進行控制,將兩個係數的差值放大,能夠保證提取祕密信息的正確性。blog

 

1.DCT數字水印嵌入.m腳本代碼:

clc;
clear all;
pic_path = input('請輸入要嵌入水印的圖片絕對路徑(要加單引號):');
watermark_txt = input('請輸入水印所在文件絕對路徑(要加單引號):');
msgfid=fopen(watermark_txt,'r');  %打開祕密文件,讀入祕密信息
[key,count]=fread(msgfid,'ubit1');
alpha=0.01;
block = 8;
fclose(msgfid);
[len,col]=size(key);
io=imread(pic_path);                   %讀取載體彩色圖像
io=double(io)/255;
output=io;
i1=io(:,:,1);                           %取圖像的第1層來隱藏,彩色圖像空間RGB三層
T=dctmtx(block);                            %生成一個8*8 DCT變換矩陣
DCTrgb=blkproc(i1,[block block],'P1*x*P2',T,T');% x就是每個分紅的8*8大小的塊,P1*x*P2至關於像素塊的處理函數(記爲fun),p1=T p2=T’,也就是fun=p1*x*p2=T*x*T'的功能是進行離散餘弦變換,T,T'就是前面函數fun參數
[row,col]=size(DCTrgb);
row=floor(row/block);
col=floor(col/block);
contents = row * col;                    %contents表示圖像矩陣能嵌入的最大比特數
if count > contents
    disp('Warning: 圖像容量沒法嵌入全部水印信息! 按enter退出matlab!');
    pause;
    quit;
else
    disp(['該圖像能嵌入的水印信息最大值爲:',num2str(contents),' bits']);
end
%縱向順序信息嵌入
cow1 = 5;
cow2 = 4;
column1 = 2;
column2 = 3;
key_counter = 1;
temp = 0;
round_counter = 0;
total_marked_bits = 0;
if mod(count,row) == 0
    round = floor(count/row); % round記錄須要圖像矩陣多少列來嵌入水印(這裏以一個8*8矩陣爲一個bit嵌入單元)
else
    round = floor(count/row)+1; % round記錄須要圖像矩陣多少列來嵌入水印(這裏以一個8*8矩陣爲一個bit嵌入單元)
end

for ii=1:1:round
    for jj=1:1:row
        if DCTrgb(cow1,column1) == DCTrgb(cow2,column2)
            DCTrgb(cow1,column1) = DCTrgb(cow1,column1) - 0.0002;
        end
        
        if key(key_counter,1) == 1
            if DCTrgb(cow1,column1) > DCTrgb(cow2,column2)
                temp =  DCTrgb(cow1,column1);
                DCTrgb(cow1,column1) = DCTrgb(cow2,column2);
                DCTrgb(cow2,column2) = temp;
                DCTrgb(cow1,column1) = DCTrgb(cow1,column1) - alpha;% 擴大差距
            else
                DCTrgb(cow1,column1) = DCTrgb(cow1,column1) - alpha;% 擴大差距
            end
        elseif key(key_counter,1) == 0
             if DCTrgb(cow1,column1) < DCTrgb(cow2,column2)
                temp = DCTrgb(cow1,column1);
                DCTrgb(cow1,column1) = DCTrgb(cow2,column2);
                DCTrgb(cow2,column2) = temp;
                DCTrgb(cow2,column2) = DCTrgb(cow2,column2) - alpha;% 擴大差距
            else
                DCTrgb(cow2,column2) = DCTrgb(cow2,column2) - alpha;% 擴大差距
             end
         else
             disp('BitValueError: key bit value is invalid , neither 0 nor 1 !');
             disp('按 enter 退出matlab.');
             pause;
             quit;
         end
         cow1 = cow1 + block;
         cow2 = cow2 + block;
         key_counter = key_counter + 1;
         total_marked_bits = total_marked_bits + 1;
         if key_counter > count
             break;
         end
     end   %內層for
     round_counter =  round_counter + 1;
     disp(['當前嵌入輪數 :', num2str(round_counter)]);
     if key_counter > count
         disp(['水印嵌入正常結束!共嵌入:',num2str(total_marked_bits),' bits']);
         break;
     end
     cow1 = 5;
     cow2 = 4;
     column1 = column1 + block;
     column2 = column2 + block;
 end %外層for
%將信息寫回並保存
wi=blkproc(DCTrgb,[block block],'P1*x*P2',T',T);%對DCTrgb進行逆變換
output(:,:,1)=wi;
imwrite(output,'E:\new\dct_watermarked.bmp');
figure;
subplot(1,2,1);
imshow(pic_path);
title('原始圖像');
subplot(1,2,2);
imshow('E:\new\dct_watermarked.bmp');
title('嵌入水印圖像');

運行截圖:

 

 

 

2.DCT水印提取腳本代碼:

clc;
clear all;
watermarked_picpath = input('請輸入待提取的dct水印圖片絕對路徑(要加單引號):');
watermarked_bits = input('請輸入嵌入的水印比特數:');
i=imread(watermarked_picpath);
i=double(i)/255;
i1=i(:,:,1);
block = 8;
T=dctmtx(block);
DCTcheck=blkproc(i1,[block block],'P1*x*P2',T,T');%對圖像分塊進行DCT變換
key = zeros(watermarked_bits,1);
[row,col]=size(DCTcheck);
row=floor(row/block);
col=floor(col/block);
cow1 = 5;
cow2 = 4;
column1 = 2;
column2 = 3;
key_counter = 1;
round_counter = 0;
total_get_bits = 0;
if mod(watermarked_bits,row) == 0
    round = floor(watermarked_bits/row); % round記錄須要圖像矩陣多少列來嵌入水印(這裏以一個8*8矩陣爲一個bit嵌入單元)
else
    round = floor(watermarked_bits/row)+1; % round記錄須要圖像矩陣多少列來嵌入水印(這裏以一個8*8矩陣爲一個bit嵌入單元)
end
for ii=1:1:round  
    for jj=1:1:row
         if DCTcheck(cow1,column1) <= DCTcheck(cow2,column2)
             key(key_counter,1) = 1;
         else
             key(key_counter,1) = 0;
         end
         total_get_bits = total_get_bits + 1;
         key_counter = key_counter + 1;
         if key_counter > watermarked_bits
             break;
         end
         cow1 = cow1 + block;
         cow2 = cow2 + block;
     end %內層for
     round_counter =  round_counter + 1;
     disp(['當前提取輪數 :', num2str(round_counter)]);
     if key_counter > watermarked_bits 
          disp(['水印提取正常結束!共提取水印:',num2str(total_get_bits),' bits']);
          break;
     end
     cow1 = 5;
     cow2 = 4;
     column1 = column1 + block;
     column2 = column2 + block;
end %外層for

fid=fopen('E:\new\dct_watermark_msg.txt','wt');
fwrite(fid,key,'bit1');
fclose(fid);

提取水印信息與原信息對比:

DCT水印實驗遇到的問題及要點:

1.該實驗對象是彩色RGB圖像,任須要提取一層進行嵌入.

2.該實驗中對每一個矩陣塊中的固定2個像素值比較時要考慮相等的狀況,如若相等嵌入時先將其中任意一個減少少許,而後再比較大小考慮是否要互換像素值;最後提取時理論上是不會出現2個像素值同樣的狀況,但實驗發現可能出現相等的狀況,if DCTcheck(cow1,column1) <= DCTcheck(cow2,column2)代碼中若去掉等號則提取的水印信息不正確.至今沒明白爲何?

上述腳本在matlab6.5能正確運行.

若您以爲對您有幫助,不妨點個支持👍唄!

相關文章
相關標籤/搜索