二值信息隱藏(分塊和遊程編碼實現)
阿新 • • 發佈:2018-07-01
cfa pen play res 上一個 hose 開始 info roc
View Code
View Code
View Code
使用分塊進行信息隱藏,因為在對角線上的分塊上進行的隱藏,所以
可以明顯看到在對角線上有一條線,
200*200的二值圖像
512*512的二值圖像
(二)使用遊程編碼,書上的代碼邏輯上有錯誤,還有一些函數錯誤,根本不能運行出結果
自己修改了得到以下結果
200*200的隱藏160位,可以看到微小的變化
512*512的隱藏160位,基本看不到變化
二值對角線分塊隱藏代碼
clc; clear; msgfid = fopen(‘hidden.txt‘,‘r‘); % 隱藏信息 [msg, count] = fread(msgfid); fclose(msgfid); msg = dec2bin(msg,8); %將讀入的每個字節轉換成二進制 msg = str2num(msg(:)); watermarklen = count*8; % 需要隱藏的數目 [fn,pn] = uigetfile({‘*.bmp‘,‘bmpfile(*.bmp)‘;},‘chose file‘); filename = strcat(pn,fn); I = imread(filename); % 將載體分成 count*count 個小塊,在對角線隱藏信息 [row,col] =size(I); block(1) = floor(row/watermarklen); % block的row block(2) = floor(col/watermarklen); % block的col pixelcount = block(1)*block(2); % 一塊的像素數 % 閾值,1的個數必須大於等於此值才能說明隱藏的是1 % 0 的個數必須大於等於此值才能說明隱藏的是 0 if mod(pixelcount, 2) == 0 threshold = pixelcount/2 + 1; else threshold = ceil(pixelcount/2); end carrier = I; % 修改的操作都在carrier上 zeroCount = zeros(1,watermarklen) ; % 用來記錄每小塊上0的個數 oneCount = zeros(1,watermarklen); % 用來記錄每小塊上1的個數 % 統計對角線上的小塊的0和1 for n=1:watermarklen %使用求和來算出每個小塊有多少個·1 oneCount(1,n) = sum(sum(I(block(1)*(n-1)+1:block(1)*n, block(2)*(n-1)+1:block(2)*n))); zeroCount(1,n) = pixelcount - oneCount(1,n); end %隱藏信息 for n=1:watermarklen if msg(n,1) == 1; % 嵌入1 if oneCount(1,n) < threshold; % 但是1小於閾值 modifycount = threshold - oneCount(1,n); % 需要修改的數目 k =1; for i =block(1)*(n-1)+1:block(1)*n for j =block(2)*(n-1)+1:block(2)*n if(carrier(i,j) == 0 && k<=modifycount) carrier(i,j) = 1; k = k+1; end end end end else % 嵌入0 if zeroCount(1,n) < threshold; % 0的個數小於閾值時需要改 modifycount = threshold - zeroCount(1,n); k =1; for i =block(1)*(n-1)+1:block(1)*n for j =block(2)*(n-1)+1:block(2)*n if(carrier(i,j) ==1 && k<=modifycount) carrier(i,j) = 0; k = k+1; end end end end end end %顯示結果 imwrite(carrier,‘bwmarked.bmp‘); figure; imshow(filename); title(‘原圖‘); figure; imshow(‘bwmarked.bmp‘); title(‘載體‘);
提取代碼
clc; clear; [fn,pn] = uigetfile({‘*.bmp‘,‘bmpfile(*.bmp)‘;},‘chose file‘); filename = strcat(pn,fn); I = imread(filename); % 將載體分成 count*count 個小塊,在對角線隱藏信息 watermarklen = 160; % 隱藏的數目 [row,col] =size(I); block(1) = floor(row/watermarklen); % block的row block(2) = floor(col/watermarklen); % block的col pixelcount = block(1)*block(2); % 一塊的像素數 % 閾值,1的個數必須大於等於此值才能說明隱藏的是1 % 0 的個數必須大於等於此值才能說明隱藏的是 0 if mod(pixelcount, 2) == 0 threshold = pixelcount/2 + 1; else threshold = ceil(pixelcount/2); end %提取出的隱藏信息 hideInfo = zeros(1,watermarklen); for n=1:watermarklen %使用求和來算出每個小塊有多少個·1 oneCount = sum(sum(I(block(1)*(n-1)+1:block(1)*n, block(2)*(n-1)+1:block(2)*n))); if oneCount >= threshold % 1的數目大於閾值,則隱藏的信息為1 hideInfo(1, n) = 1; else % 0的數目大於閾值,則隱藏的信息為0 hideInfo(1, n) = 0; end end hideInfo = reshape(hideInfo,length(hideInfo)/8,8); %將二進制字符串分成n行,8列 bin = num2str(hideInfo); % 二進制數值轉變成二進制字符串 dec = bin2dec(bin);%二進制字符串轉換成十進制數組 recoverdata = native2unicode(dec);% 本機編碼轉換成unicode fprintf(1, ‘恢復出的信息: %s\n‘,recoverdata);
遊程編碼隱藏代碼
clc; clear; threshold = 10; [fn,pn] = uigetfile({‘*.bmp‘,‘bmpfile(*.bmp)‘;},‘chose file‘); filename = strcat(pn,fn); oi = imread(filename); si = size(oi); % 保存讀入圖像的行列,以便恢復圖像 oi = oi(:); % 變成一列, 按列變 [len, col] = size(oi); %len= row,1 carrier = oi; % 以後數據的修改都在carrier上 j=1; i=1; %統計遊程長度 while(i <= len) last = oi(i); % 依次取出每個數 count = 1; while( i+1 <= len && oi(i+1)== last) % 下一個與上一個相同 i = i + 1; count = count + 1; end RLE(j) = count; j = j + 1; i = i + 1; end msgfid = fopen(‘hidden.txt‘, ‘r‘); [msg, msgcount] = fread(msgfid); fclose(msgfid); msg = dec2bin(msg,8); %將讀入的每個字節轉換成二進制 msg = str2num(msg(:)); % msgcount = msgcount*8; % 需要隱藏的數目 i = 1; % msg 的索引 count = 1; % RLE的索引,只為奇數 1 3 5... sum = 0; while count < length(RLE)-1 addSum = RLE(count) + RLE(count+1); %相鄰兩個數相加的和,從1開始 if count >= 3 sum = sum + RLE(count - 1) + RLE(count - 2); % 當前count的在數組中的下標-1 end if(addSum >= threshold) % 只有當相鄰遊程和大於給定數的時候,才隱藏信息 if RLE(count) >= RLE(count+1) modifyPoint = sum + RLE(count); % 修改兩個遊程的臨界值,長的那邊的 else modifyPoint = sum + RLE(count) + 1; end if(msg(i) == 0) % 嵌入的信息為0,但是遊程為奇數,需要修改 if(mod(RLE(count), 2) == 1) %RLE(count) == ‘奇數‘ carrier(modifyPoint) = mod(carrier(modifyPoint)+1 ,2); % 修改點的值取反 mod(carrier(modifyPoint)+1 ,2) end else % 嵌入的信息為1,但是遊程為偶數,需要修改 if mod(RLE(count), 2) == 0 %RLE(count) == ‘偶數‘ carrier(modifyPoint) = mod(carrier(modifyPoint) + 1 ,2); % 修改點的值取反 mod(carrier(modifyPoint)+1 ,2) end end i = i + 1; % 隱藏一個位後, msg索引加1 end count = count + 2; %不管有沒有隱藏信息,count都要增加 if i == msgcount % 所有的信息都已隱藏就退出循環 break; end end if i < msgcount error(‘不能隱藏全部信息!‘); end imwrite(reshape(carrier, si(1),si(2)), ‘hide.bmp‘); figure; subplot(121); imshow(reshape(oi, si(1),si(2))); title(‘原圖‘); subplot(122); imshow(‘hide.bmp‘); title(‘載體‘);
提取代碼
clc; clear; %也可以增大隱藏信息的間隔 count 1 5 9 13 以後實現 threshold = 3; [fn,pn] = uigetfile({‘*.bmp‘,‘bmpfile(*.bmp)‘;},‘chose file‘); filename = strcat(pn,fn); oi = imread(filename); oi = oi(:); % 變成一列, 按列變 [len, col] = size(oi); %len= row,1 j=1; i=1; %統計遊程長度 while(i <= len) last = oi(i); % 依次取出每個數 count = 1; while( i+1 <= len && oi(i+1)== last) % 下一個與上一個相同 i = i + 1; count = count + 1; end RLE(j) = count; j = j + 1; i = i + 1; end i = 1; msgcount = 160; msg = zeros(msgcount,1); count = 1; % RLE的索引,只為奇數 1 3 5... while i <= msgcount addSum = RLE(count) + RLE(count+1); %相鄰兩個數相加的和,從1開始 if(addSum >= threshold) % 只有當相鄰遊程和大於給定數的時候,才隱藏信息 if mod(RLE(count),2) == 0 msg(i) = 0; else msg(i) = 1; end i = i + 1; end count = count + 2; end hideInfo = reshape(msg,length(msg)/8,8); %將二進制字符串分成n行,8列 bin = num2str(hideInfo); % 二進制數值轉變成二進制字符串 dec = bin2dec(bin);%二進制字符串轉換成十進制數組 recoverdata = native2unicode(dec);% 本機編碼轉換成unicode fprintf(1, ‘恢復出的信息: %s\n‘,recoverdata);View Code
二值信息隱藏(分塊和遊程編碼實現)