C++:图片数字水印-基于OpenCV+LSB

由于之前在网上看到的关于LSB的方法大都是以MATLAB||Python写的,于是博主基于其思路改编后得出以下的内容:


一、原理:

1.首先准备一张彩色的图片(2px*2px)

一张2*2像素的图片
为了方便展示,我用PS准备了一张(2px * 2px)的图片,图片的每个像素里的RGB值分别为:

位置 R G B
[0,0] 10 100 200
[0,1] 200 100 10
[1,0] 200 10 100
[1,1] 100 10 200

图片格式保存为bmp(无损压缩),保存jpg时会对图片内容产生压缩

2.在终端上查看这张图片

需要注意的是这里查看的代码不是cv::imshow(),而是用cout

int main(int argc, char* argv[]) {
   
	if (argc < 2) return -1;
	cv::Mat img = imread(argv[1],cv::IMREAD_COLOR);
	cout << img << endl;
	return 0;
}

$ ./a.out test.bmp

[200, 100,  10,  10, 100, 200;
 100,  10, 200, 200,  10, 100]

由此我们可以知道:

  1. Mat里面彩色图片的每个像素都按照B、G、R的图层顺序存储的
  2. 存储的每个单位的值都介于0~255之间
  3. 一行中的所有像素以及每个像素的三个图层之间都以逗号分开
  4. 行与行之间以分号隔开

得知上述信息后就好办了~为了方便解释,我们将上面得到的矩阵用二进制的形式展示一下:

[11001000, 01100100, 00001010, 00001010, 01100100, 11001000;
 01100100, 00001010, 11001000, 11001000, 00001010, 01100100]

到了这一步就可以来愉快的解释LSB了,假设我们把每个单元里的最低有效位都归零,然后再按照需求填入我们想要的信息
LSB 最低有效位
如果改变的是最后一位,那在最终的数值上只是±1,对图片的颜色而言,肉眼几乎不会感到有什么变化。即便修改的是倒数第二位,最终的数值上也就±3,感觉还可以(在最后测试的时候会放上效果图)。修改倒数第三位的话,最终的数值±5,以此类推……

3.准备一张水印图片(黑白)

一张2*2像素的图片
为了方便演示,我将水印图和原图的大小设为一样的了。下方的代码不用担心水印图和原图尺寸不一致的问题~
假设上图是我要加的水印,信息只有黑白两色,那么我们可以将黑色定义为0;白色定义为1。然后把信息写入原图当中~

4.为原图添加水印信息
原图:
[11001000, 01100100, 00001010, 00001010, 01100100, 11001000;
 01100100, 00001010, 11001000, 11001000, 00001010, 01100100]
 水印图:
[00000001, 00000001, 00000001, 00000000, 00000000, 00000000;
 00000000, 00000000, 00000000, 00000001, 00000001, 00000001]
 原图 + 水印图:
[11001001, 01100101, 00001011, 00001010, 01100100, 11001000;
 01100100, 00001010, 11001000, 11001001, 00001011, 01100101]
原图:

一张2*2像素的图片

添加水印后的图片:

LSB生成后的图片

还原之后的水印:

还原之后的水印
这样水印的信息就已经添加到了图片里面,但肉眼几乎看不出有什么区别。
需要注意的是,图片的保存格式最好选择bmp格式,若以其它格式保存(jpeg/png)会压缩失真。
失真后的图片水印也不会像之前那么清楚,这也是这个方法测试下来的一大缺点!

二、源码C:

/*************************************************************************
    > File Name: 001_waterMarkLSB.cpp
    > Author: PeterShen
    > Mail: peter704678976@126.com 
    > Created Time: 2019年08月25日 星期日 00时00分09秒
 ************************************************************************/

#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <typeinfo>
#include <opencv2/core/utility.hpp>
#include <opencv2/video/tracking.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/highgui.hpp>

#include "opencv2/imgproc/types_c.h"

using namespace cv;

template<typename _Tp>
vector<_Tp> convertMatToVector(const Mat &mat) {
   
	return (vector<_Tp>)(mat.<
  • 10
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值