本文章的算法思路来自文章《彩色数字水印技术研究》,文章大体思路是对RGB宿主图像转换为HSV色彩空间后对三个通道分别做三级小波变换,水印图像的RGB三个通道数值归一化到[-1,1]后,乘以一个权重系数,分别整合到宿主图像HSV三个通道上,整合原则是优先选取低频分量,低频分量中优先选取系数大的,这样对宿主图像的视觉影响比较小。提取水印则是逆过程。
本次在MATLAB 2014b实现,由于水印图像尺寸比较大,三级小波的低频分量位置不够,所以只进行了一级小波变换。
输入宿主图像为512*512*3的RGB,格式为uint8,水印图像为140*200*3的RGB,格式为uint8
function [MarkedImg] = Hide_3(OriImg,Print)
% 功能 将Print中的携带的信息通过图像处理技术隐藏在OriImg中
% OriImg 输入参数,RGB彩色图像,uint8格式,大小为512*512*3,作为隐
% 藏信息的载体
% Print 输入参数,RGB彩色图像,uint8格式,大小为140*200*3,信息本
% 身所在
% MarkedImg 输出参数,RGB彩色图像,uint8格式,大小为512*512*3,经过
% 信息隐藏处理后的图像
%OriImg = imread('I2.jpg');
%Print = imread('m5.jpg');
OriImg = rgb2hsv(OriImg);
vlayer = OriImg(:,:,3);
vvalue = sum(sum(vlayer));
if vvalue > 2e5
alpha = 0.04;
elseif vvalue<1.5e5
alpha = 0.1;
else
alpha = 0.2;
end
MarkedImg = zeros(size(OriImg));
for i=1:3
Orilayer = OriImg(:,:,i);
Printlayer = Print(:,:,i);
Printlayer = (double(Printlayer)-128)/128; %归一到-1~1
[C,S] = wavedec2(Orilayer,1,'db2');
[rows, cols] = size(Printlayer);
totallength = rows*cols;
cA1 = appcoef2(C,S,'db2',1);
[cA1_r, cA1_c] = size(cA1);
part1length = cA1_r*cA1_c;
cA1 = C(1:part1length);
[~, IA] = sort(abs(cA1),'descend');
IA = IA(1:totallength);
flattenpri = reshape(Printlayer, 1, []);
C(IA) = C(IA)+alpha*flattenpri;
Outlayer = waverec2(C,S,'db2');
MarkedImg(:,:,i) = Outlayer;
end
Imgout = hsv2rgb(MarkedImg);
MarkedImg = im2uint8(Imgout);
imshow(MarkedImg);
end
function [Print] = Recover_3(MarkedImg, Rect, OriImg)
rec_row = Rect(2,1);
rec_col = Rect(2,2);
%OriImg = imread('I2.jpg');
OriImg = rgb2hsv(OriImg);
%MarkedImg = imread('testhid1.jpg');
MarkedImg = rgb2hsv(MarkedImg);
Print = zeros(rec_row, rec_col, 3);
vlayer = OriImg(:,:,3);
vvalue = sum(sum(vlayer));
if vvalue > 2e5
alpha = 0.04;
elseif vvalue<1.5e5
alpha = 0.1;
else
alpha = 0.2;
end
for i=1:3
Orilayer = OriImg(:,:,i);
Marklayer = MarkedImg(:,:,i);
[Co,So] = wavedec2(Orilayer,1,'db2');
coA1 = appcoef2(Co,So,'db2',1);
[cA1_r, cA1_c] = size(coA1);
part1length = cA1_r*cA1_c;
coA1 = Co(1:part1length);
[~, IAo] = sort(abs(coA1),'descend');
IAo = IAo(1:rec_row*rec_col);
[Cm,~] = wavedec2(Marklayer,1,'db2');
cmA1 = Cm(1:part1length);
flat_print = cmA1(IAo)-coA1(IAo);
Print_layer = reshape(flat_print, rec_row, rec_col)/alpha;
Print_layer = (Print_layer*128)+128;
Print(:,:,i) = Print_layer;
end
Print = uint8(Print);
figure(2)
imshow(Print);
end
OriImg
加入水印
水印图片
恢复出来的水印图片
实验证明,在经过中值滤波和JPG压缩后,水印依然有一定辨识能力