MATLAB_LSB_隐藏水印和提取,附代码
对图像的认识
图片是一个点阵图像,在屏幕上显示是RGB模式,打印模式为CMYK(彩色印刷)
图片格式分为很多种:bmp(无压缩的格式), jpg(经过压缩的格式),png。
一般的彩色图片,每个像素点都用三个0~255的值来表示red, green, blue,每个占一个字节,所以称为24位图,这里默认图片格式为bmp。
文件头
图片是以二进制存储数据的,通常在不同的图片格式中,文件头的格式以及包含的信息(图片的大小尺寸)都不同,这些信息,可以通过读取图片二进制内容获取。
bmp图片的文件头一般为54字节。
需要注意的是,要更改图片格式,并不是修改后缀名就可以,不同类型的图片自身编码格式不同,所以需要另一种方法改变图片格式:
-
可以在网上搜索在线修改图片格式为bmp的网站。
-
可以直接在画图工具中打开。
有一个软件《文件格式分析器》可以检测文件类型,直接拖拽进去就行。百度网盘地址为:链接:https://pan.baidu.com/s/17RQ-31dMTqagPrvxoXaDbA
提取码:ah42关于MATLAB的下载及安装,大家可以搜索微信公众号:软件安装管家
重点
今天我们讨论的水印加密最好需要转化成bmp图像进行操作,其次,为了简单起见,我们是使用灰度图,每个像素点用0~255的值来表示黑白颜色深度,图像本质并未有变化。
准备:MATLAB, 载体图片(彩色), 要隐藏的图片(黑白)
需要注意的点:
- 图像灰度处理的知识:图像灰度化
- 为什么要扩大被隐藏图片的大小
- 因为这里假设进行LSB加密和提取水印的不是同一个人,所以提取水印的人并不知道到底应该在载体图像中提取多少信息。
- 如果不考虑提取,只是添加水印,则这里不需要扩大图片的大小,而且同一个载体图片可以隐藏更多的信息。
- 使用MATLAB函数,只是在视觉上改变了图片的胖瘦,其信息仍然具有有效性。
- 二值化的相关知识
- 为了压缩水印。被隐藏的图片的每个像素是有不同的灰度阶,二值化之后,每个像素就只有0和1中的一种可能,就可以认为将图片的八个比特面压缩成了一个,这样更方便于嵌入到载体图像中.
附上MATLAB代码及注释
//加水印
%ary 表示那个比特面,1是最低比特位
ary = 1;
file_name1 = 'demo.bmp';
cover_object = imread(file_name1); %读取本人照片信息
cover_object = rgb2gray(cover_object); %得到灰度图信息
cover_object_ll = bitget(cover_object, ary); %得到最后1位比特
figure; %唤醒一个窗口
imshow(cover_object);
title('origin host picture'); %展示原图像形成的灰度图
figure;
imshow(255*cover_object_ll); %最低位左移到最高位
title('origin hot pic`lowest bit'); %展示原图像的最低位
file_name2 = 'Finger.bmp';
message = imread(file_name2);
figure;
imshow(message);
message = im2bw(message, graythresh(message)); %将指纹图像变为二值图
figure;
imshow(message);
title('hidden picture');
Mc = size(cover_object, 1); %Height 读取图片的大小
Nc = size(cover_object, 2); %Width
message = imresize(message, [Mc Nc]); %使被隐藏图片和载体图片等长宽
watermarked_image = cover_object;
%使得载体图片的最后一个比特位,与被隐藏图片的数据相等
for ii = 1 : Mc
for jj = 1 : Nc
if ii*jj < Mc * Nc %小于指纹信息的图片大小
if cover_object_ll(ii, jj) ~= message(ii, jj) %左右两端不相等,结果为一
if cover_object_ll(ii, jj) == 1
watermarked_image(ii, jj) = bitset(watermarked_image(ii,jj), ary, 0); %不相等改为0
else
watermarked_image(ii, jj) = bitset(watermarked_image(ii,jj), ary, 1);
end
end
end
end
end
figure;
imshow(watermarked_image);
title('watermarked picture');
saveas(gcf, 'ok.bmp');
figure;
watermarked_image_ll = bitget(watermarked_image, ary);
imshow(255 * watermarked_image_ll);
title('watermarked picture`s lowest bit');
提取水印的过程就更简单:
file = 'ok.bmp'
water_pic = imread(file); %待提取图像
water_pic_1 = bitget(water_pic, 1); %得到最后1位比特
figure;
imshow(water_pic);
figure;
imshow(255*water_pic_1);
saveas(gcf, 'abstarct.bmp');
但是这种做法,安全性很差,如果遇到中间人攻击,提取最后一个比特面的信息,就可以随意的获取,替换被隐藏的信息,所以最好在提取时,已知被隐藏图片的大小,这样可以提高安全性。
如果程序出现问题,可以私信我。
写文章之前也参考了其它博文,仅作学习。