标签:sub 奇数 lap while height block 下标 字符串转换 end
使用分块进行信息隐藏,因为在对角线上的分块上进行的隐藏,所以
可以明显看到在对角线上有一条线,
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);
标签:sub 奇数 lap while height block 下标 字符串转换 end
原文地址:https://www.cnblogs.com/YKang/p/9250960.html