%%附全部源代码%%%%%%%%%%%%%%
% seek.m
% F5算法提取秘密图像(灰度)
% Written by Steward Kwok in Jul, 2009
% [email]signallock@gmail.com[/email]
clear;
clc;
% 标准量化表
mask1 = [16 11 10 16 24 40 51 61
12 12 14 19 26 58 60 55
14 13 16 24 40 57 59 56
14 17 22 29 51 87 80 62
18 22 37 56 68 109 103 77
24 35 55 64 81 104 113 92
49 64 78 87 103 121 120 101
72 92 95 98 112 100 103 99];
mask = mask1;
T = dctmtx(8); % DCT变换矩阵
% k应该在提取之前确定下来,相当于一个密钥
k = 1 % 打印k的值%%%%%%%%%%%%%%%%%%这个值需要提前知道
n = 2^k - 1;
% 读取密写图像,并将其转换到频域
stego = imread('stego_weibo.jpg');
subplot(1,2,1), imshow(stego); % 在左边显示stego-image
stego = double(stego);
stego = stego - 128; % 到现在我还是没彻底明白为什么要减去128……
stego = blkproc(stego, [8 8], 'f1', T, T'); % f1()还有下面的f2()、f3()功能非常简单,可以直接看它们的源代码
stego = blkproc(stego, [8 8], 'f2', mask);
stego = round(stego);
% 首先,要提取32比特的都信息,里面存储了秘密图像的大小,前16比特是行数,后16比特是列数
head = zeros(1, 32 + k); % 之所以加上k,是因为提取的时候有可能超过32比特,一位要提取的信息大小是k的整数倍
r = 1; % DCT系数指针
c = 1;
A = zeros(1, n); % 提取的方法注释可参见“hide.m”(实在懒得再注释一遍了……)
a = zeros(1, n);
[stego_r, stego_c] = size(stego);
for i = 1:1:ceil(32/k)
% 得到下面n个非零AC系数
for j = 1:1:n
while (stego(r,c) == 0) || ((mod(r-1, 8) == 0) && (mod(c-1, 8) == 0))
c = c + 1;
if c > stego_c
r = r + 1;
c = 1;
end
end
A(1,j) = stego(r,c);
if A(1,j) > 0
if mod(A(1,j), 2) == 0
a(1,j) = 0;
else
a(1,j) = 1;
end
else
if mod(A(1,j), 2) == 0
a(1,j) = 1;
else
a(1,j) = 0;
end
end
c = c + 1;
if c > stego_c
r = r + 1;
c = 1;
end
end
% 计算m,之后表示成二进制比特流,就是一组k比特秘密信息
m = 0;
for j = 1:1:n
m = bitxor(m, a(1,j) * j);
end
for j = 1:1:k
head(1, (i-1)*k+j) = bitget(abs(m), k-j+1);
end
end
sec_r = uint16(0); % 行数和列数
sec_c = uint16(0);
for i = 1:1:16
sec_r = bitset(abs(sec_r), i, head(1, 16-i+1));
sec_c = bitset(abs(sec_c), i, head(1, 32-i+1));
end
sec_size = sec_r * sec_c * 8
% 秘密信息的大小(比特数)
sec_size1=int32(sec_size)
ceil1=ceil(sec_size1/9.0)
%这里结果应该是2223啊 总是差1 不知道为什么
floor1=floor(sec_size/9)
sec_size=(ceil(sec_size / 9)+1) * 9 /3 *7
%新的大小,这里不知道为什么会差1
% 接下来提取秘密图像
buffer = zeros(1, sec_size + k); % buffer用来存放提取的二进制0-1串
for i = 1:1:floor((sec_size+k-1) / k)
% 得到下一组(n个)非零AC系数
for j = 1:1:n
while (stego(r,c) == 0) || ((mod(r-1, 8) == 0) && (mod(c-1, 8) == 0))
c = c + 1;
if c > stego_c
r = r + 1;
c = 1;
end
end
A(1,j) = stego(r,c);
if A(1,j) > 0
if mod(A(1,j), 2) == 0
a(1,j) = 0;
else
a(1,j) = 1;
end
else
if mod(A(1,j), 2) == 0
a(1,j) = 1;
else
a(1,j) = 0;
end
end
c = c + 1;
if c > stego_c
r = r + 1;
c = 1;
end
end
% 计算m,m就是k比特的秘密信息
m = 0;
for j = 1:1:n
m = bitxor(m, a(1,j) * j);
end
for j = 1:1:k
buffer(1, (i-1)*k+j) = bitget(abs(m), k-j+1);
end
end
% 之后,从buffer中复制sec_size比特到sec中
sec = zeros(1, sec_size);
for i = 1:1:sec_size
sec(1,i) = buffer(1,i);
end
%RS 解码部分开始
sec_size = sec_r * sec_c * 8; % 秘密信息的真大小 为了去除填充位用
sec=sec';%转置变为列向量
dec = comm.RSDecoder;
dec.BitInput= true;
decodedData = step (dec,sec);
release(dec);
decodedData([(sec_size+1):(ceil(sec_size / 9) * 9)],:)=[];%去除填充的行
sec=decodedData';
% 最后,把这些比特流转换成图像矩阵
secimg = zeros(sec_r, sec_c);
secimg = uint8(secimg);
for i = 1:1:sec_r
for j = 1:1:sec_c
for k = 1:1:8
% 又是一句貌似比较复杂的式子……作用就是把sec数组中的8个比特转换成secimg(i,j)
secimg(i,j) = bitset(abs(secimg(i,j)), k, sec(1,((i-1)*sec_c+j-1)*8+9-k));
end
end
end
% 保存秘密图像
imwrite(secimg, 'secimg_weibo.jpg', 'jpg');
subplot(1,2,2), imshow(secimg); % 在右边显示提取的秘密图像