本文章的算法思路来自文章《彩色数字水印技术研究》,文章大体思路是对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压缩后,水印依然有一定辨识能力