%主要实现水印的嵌入.
clear ;
close all;
image = imread('Baby.tif'); %载入图像的值
w = 3; %w放大的是竖直方向
l = 3; %l放大的是水平方向
newimage=extenRGB(image,w,l);
newimage = uint8(newimage);%格式转换,否则无法显示
figure,imshow(image),title('原始图像'); %显示原始图像,使用figure,imshow可以同时显示多个imshow
figure,imshow(newimage),title('放大图像'); %显示放大图像
imwrite(image,'原始图像.tif');
imwrite(newimage,'载体图像.tif');
Carrier=imread('载体图像.tif');
figure,imshow(Carrier),title('载体图像');
%将图像放大,这样两个相邻的像素点之间的像素差值更小,峰值更高
%接下来构建差值直方图,并研究如何嵌入;
%分组
[m,n]=size(Carrier);%m是行,n是列
%倒S扫描,将扫描路径经过的像素值存储在一个数组中
loc=1;%表示当前扫描的总像素个数
flg=0;%表示扫描方向,默认向右
for i = 1 : m
if flg==0
for j = 1 : n
A(loc)=Carrier(i,j);
loc=loc+1;
end
flg=1;
else
for j = n:-1:1
A(loc)=Carrier(i,j);
loc=loc+1;
end
flg=0;
end
end
loc
k=1;
block=floor(m*n/3);%获得总的分组数
for i = 1 : block
for j = 1 : 3
B(i,j) = A(k);%每三个像素一组,将数据放到B中
k=k+1;
end
end
loc=1;
%由于m*n可能不是整除3,所以将没被存储起来的数据单独放起来,用于更准确的恢复图像
if mod(m*n,3)~= 0
num = mod(m*n,3);
for i=(m*n-num+1):m*n
Omission(loc) = A(i);
loc=loc+1;
end
end
%找到三个数中值最小的那个数与中间位置的数换
for i = 1 : block
[min_,pos] = min(B(i,:));%pos获取最小值所在位置,min获取最小值,此处不使用,仅为凑函数
if pos~= 2
t = B(i, 2);
B(i, 2) = B(i,pos);
B(i,pos) = t;
%将交换的位置记录下来
REC(i,1) = 1;
REC(i,2) = pos;
end
%计算每三个数之间的差值并存到数组difference
difference(i,1)=B(i,1)-B(i,2);
difference(i,2)=B(i,3)-B(i,2);
end
%构建差值直方图
figure,imhist(difference),title('差值直方图');
%嵌入水印,并进行直方图平移
%找到top值和bottom,此时就找到了最多的像素数,这样就可以容纳最多的嵌入元素
h = imhist(difference);
top = find(h==max(h(:)));
bottom=find(h==min(h(:)));
bottom=min(bottom);%差值直方图的样子是规定好了的,一定从0-255高度由高变低,top与bottom都是直方图的下标
%输出top与bottom用于提取水印时使用,Baby图片的top=2,bottom=28
top
bottom
watermark=imread('水印.png');%经过测试,这个位图是一个二值水印图,全图要么是白色,要么是黑色,不存在灰色
%扫描要嵌入的图像,对它的扫描顺序可以是任意的,只要嵌入时的扫描顺序与恢复顺序一致即可
%先将图像转为而二值图像
watermarkstander=graythresh(watermark); %thresh1=0.5216
watermark = im2bw(watermark,watermarkstander);
%获取水印图像的大小
[p,q]=size(watermark);
marksum=p*q;
%将水印图像所有的像素从上到下,从左到右扫面成一个一维数组
loc=1;
for i=1:p
for j=1:q
mark(loc)=watermark(i,j);
loc=loc+1;
end
end
%水印的嵌入,峰值点处嵌入水印(嵌入水印的过程就是如果要嵌入的是1,就同样将其向右平移,如果是0则无需移动)
%不是峰值点处并且处在top与bottom之间的就向右平移,
%如果左右都需要向右平移,则修改中间像素的值,如果只平移左右中的一个,则只改左或者右的值,使其差增加1即可
%如果改变的是中间的,可能是1.左右皆为top,嵌入两个1 2.左top
loc = 1;
for i = 1 : block
%如果两个都是峰值点,则可以嵌入两个水印信息
if(loc < marksum - 1)
if difference(i, 1) == top && difference(i, 2) == top
%相当于GAP(i,1)+ 1,GAP(i,2 + 1)即向右平移一个单位
%因为嵌入就要平移 差值直方图平移就意味着原始图像块的像素值要改变
%来使它们之间的差值发生变化
if mark(loc) == 1 && mark(loc + 1) == 1
B(i,2) = B(i, 2) - 1;
end
if mark(loc) == 1 && mark(loc + 1) == 0
B(i,1) = B(i, 1) + 1;
end
if mark(loc) == 0 && mark(loc + 1) == 1
B(i,3) = B(i, 3) + 1;
end
%如果loc与loc+1位置上的只都是0的话则不需要平移,就不用管了
loc = loc + 2;
end
end
%只有左边的差值是top 只能嵌入一个水印
if(loc < marksum)
if difference(i, 1) == top && difference(i, 2) ~= top
if mark(loc) == 1 && (difference(i,2) > top && difference(i,2) < bottom) == 1
B(i, 2) = B(i, 2) - 1;
end
if mark(loc) == 1 && (difference(i,2) > top && difference(i,2) < bottom) == 0
B(i, 1) = B(i, 1) + 1;
end
if mark(loc) == 0 && (difference(i,2) > top && difference(i,2) < bottom) == 1
B(i, 3) = B(i, 3) + 1;
end
loc = loc + 1;
end
end
%只有一个峰值点的情况二 只能嵌入一个水印
if(loc < marksum)
if difference(i, 1) ~= top && difference(i, 2) == top
if mark(loc) == 1 && (difference(i,1) > top && difference(i,1) < bottom) == 1
B(i, 2) = B(i, 2) - 1;
end
if mark(loc) == 1 && (difference(i,1) > top && difference(i,1) < bottom) == 0
B(i, 3) = B(i, 3) + 1;
end
if mark(loc) == 0 && (difference(i,1) > top && difference(i,1) < bottom) == 1
B(i, 1) = B(i, 1) + 1;
end
loc = loc + 1;
end
end
%不嵌入水印但是也要平移
if(loc < marksum)
if difference(i, 1) ~= top && difference(i, 2) ~= top
if (difference(i,1) > top && difference(i,1) < bottom) == 1 && (difference(i,2) > top && difference(i,2) < bottom) == 1
B(i, 2) = B(i, 2) - 1;
end
if (difference(i,1) > top && difference(i,1) < bottom) == 1 && (difference(i,2) > top && difference(i,2) < bottom) == 0
B(i, 1) = B(i, 1) + 1;
end
if (difference(i,1) > top && difference(i,1) < bottom) == 0 && (difference(i,2) > top && difference(i,2) < bottom) == 1
B(i, 3) = B(i, 3) + 1;
end
end
end
end
%将所有的元素重新整合,包括omission中的
%先根据REC中的记录将所有调整过位置的元素位置换过来
for i=1:block
if REC(i,2)~=0
t=B(i,2);
B(i,2)=B(i,REC(i,2));
B(i,REC(i,2))=t;
end
end
%m是原始图像的行,n是原始图像的列,先放到一维数组中,然后在组装
loc=1;
for i=1:block
for j=1:3
UpdateA(loc)=B(i,j);
loc=loc+1;
end
end
%将原来多出来的没放在B数组中的元素添加上
if mod(m*n,3)~= 0
num = mod(m*n,3);
for i=1:num
UpdateA(loc)=Omissiom(i);
loc=loc+1;
end
end
%将所有数据统一到AddPating数组中
flg=0;%设定填装方向,初始方向为向右
loc=1;
for i=1:m
if flg==0
for j=1:n
AddPating(i,j)=UpdateA(loc);
loc=loc+1;
end
flg=1;
else
for j = n:-1:1
AddPating(i,j)=UpdateA(loc);
loc=loc+1;
end
flg=0;
end
end
%显示添加水印的图片
figure,imshow(AddPating),title('嵌入水印的图像');
%因为嵌入程序与提取复原程序不在一个文件中,所以将嵌入水印的图像写入计算机,通过另外一个程序对该图像进行水印提取
imwrite(AddPating,'嵌入水印后的图像.tif');