MATLAB_LSB_隐藏水印和提取,附代码

MATLAB_LSB_隐藏水印和提取,附代码

对图像的认识

​ 图片是一个点阵图像,在屏幕上显示是RGB模式,打印模式为CMYK(彩色印刷)

​ 图片格式分为很多种:bmp(无压缩的格式), jpg(经过压缩的格式),png。

​ 一般的彩色图片,每个像素点都用三个0~255的值来表示red, green, blue,每个占一个字节,所以称为24位图,这里默认图片格式为bmp。

文件头

​ 图片是以二进制存储数据的,通常在不同的图片格式中,文件头的格式以及包含的信息(图片的大小尺寸)都不同,这些信息,可以通过读取图片二进制内容获取。

​ bmp图片的文件头一般为54字节。

需要注意的是,要更改图片格式,并不是修改后缀名就可以,不同类型的图片自身编码格式不同,所以需要另一种方法改变图片格式

  1. 可以在网上搜索在线修改图片格式为bmp的网站。

  2. 可以直接在画图工具中打开。

    有一个软件《文件格式分析器》可以检测文件类型,直接拖拽进去就行。百度网盘地址为:链接:https://pan.baidu.com/s/17RQ-31dMTqagPrvxoXaDbA
    提取码:ah42

    关于MATLAB的下载及安装,大家可以搜索微信公众号:软件安装管家

重点

​ 今天我们讨论的水印加密最好需要转化成bmp图像进行操作,其次,为了简单起见,我们是使用灰度图,每个像素点用0~255的值来表示黑白颜色深度,图像本质并未有变化。

​ 准备:MATLAB, 载体图片(彩色), 要隐藏的图片(黑白)

​ 需要注意的点:

  1. 图像灰度处理的知识:图像灰度化
  2. 为什么要扩大被隐藏图片的大小
    1. 因为这里假设进行LSB加密和提取水印的不是同一个人,所以提取水印的人并不知道到底应该在载体图像中提取多少信息。
    2. 如果不考虑提取,只是添加水印,则这里不需要扩大图片的大小,而且同一个载体图片可以隐藏更多的信息。
    3. 使用MATLAB函数,只是在视觉上改变了图片的胖瘦,其信息仍然具有有效性。
  3. 二值化的相关知识
    1. 为了压缩水印。被隐藏的图片的每个像素是有不同的灰度阶,二值化之后,每个像素就只有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');

但是这种做法,安全性很差,如果遇到中间人攻击,提取最后一个比特面的信息,就可以随意的获取,替换被隐藏的信息,所以最好在提取时,已知被隐藏图片的大小,这样可以提高安全性。

如果程序出现问题,可以私信我。

写文章之前也参考了其它博文,仅作学习。

猜你喜欢

转载自blog.csdn.net/weixin_41249411/article/details/83451465