OpenCV实现数字水印的相关函数和示例代码

OpenCV计算机视觉开发实践:基于Qt C++ - 商品搜索 - 京东

实现数字水印的相关函数

用OpenCV来实现数字水印功能,需要使用一些位操作函数,我们需要先了解一下这些函数。

1. bitwise_and函数

bitwise_and函数是OpenCV中的位运算函数之一,用于对两幅二值图像进行按位与操作。具体来说,对于每个像素,将两幅输入图像相应位置的像素值分别进行按位与运算,输出的结果图像的对应像素值即为这两幅输入图像对应像素值的按位与结果。

bitwise_and函数的语法如下:

复制代码
void bitwise_and(InputArray src1, InputArray src2,

OutputArray dst, InputArray mask = noArray());

其中,src1和src2表示要进行按位与操作的两幅输入图像;mask是可选参数,如果指定了掩膜,则只对掩膜对应位置的像素进行按位与操作;dst表示按位与运算的结果。

【例14.1】创建空白图像进行按位与操作

打开Qt Creator,新建一个控制台项目,项目名称是test。

在main.cpp中输入如下代码:

复制代码
#include "opencv2/opencv.hpp"
using namespace cv;

int main()
{
    // 空白图像创建
    Mat m1 = Mat::zeros(Size(256, 256), CV_8UC3);
    Mat m2 = Mat::zeros(Size(256, 256), CV_8UC3);
    // 在图像内添加矩阵
    rectangle(m1, Rect(100, 100, 80, 80), Scalar(255, 255, 0), -1, LINE_8, 0);
    rectangle(m2, Rect(150, 150, 80, 80), Scalar(0, 255, 255), -1, LINE_8, 0);
    imshow("m1", m1);
    imshow("m2", m2);
    Mat dst;
    bitwise_and(m1, m2, dst); // 进行与操作,结果存于dst中
    imshow("result", dst);
    waitKey();
    return 0;
}

通过bitwise_and函数就能得到与操作的结果dst。

运行程序,结果如图14-1所示。

图14-1

再看个示例,对现有图片进行按位与操作,代码如下:

【例14.2】对现成图像进行按位与操作

打开Qt Creator,新建一个控制台项目,项目名称是test。

在main.py中输入如下代码:

复制代码
#include "opencv2/opencv.hpp"
using namespace cv;

int main()
{
    Mat dog,cat,img_and;
    resize(imread("cat.png"),cat, Size(400, 360));
    resize(imread("dog.png"),dog, Size(400, 360));
    bitwise_and(cat,dog,img_and); // 与运算 1 & 1 = 1, 其它为0
    imshow("result",img_and);
    waitKey(0);
    return 0;
}

保存程序并运行,结果如图14-2所示。

可以看出,与运算的结果是使图像变小,最后的图像也会偏暗。

2. bitwise_or函数

在OpenCV中进行或运算使用bitwise_or函数,其声明如下:

复制代码
void bitwise_or(InputArray src1, InputArray src2, OutputArray dst, InputArray mask = noArray());

其中输入参数src1和src2可为灰度图或彩色图,src1和src2大小需相同;输出参数dst存放或运算的结果,尺寸和类型与src保持一致;掩膜mask可通俗理解为一个遮罩,只对mask设定的有效区域进行操作。

图14-2

或运算 0 | 0 = 0,其他情况为1。下面将猫和狗的图片进行或运算。

【例14.3】对现成图像进行按位或操作

打开Qt Creator,新建一个控制台项目,项目名称是test。

在main.cpp中输入如下代码:

复制代码
#include "opencv2/opencv.hpp"
using namespace cv;

int main()
{
    Mat dog,cat,img_and;
    resize(imread("cat.png"),cat, Size(400, 360));
    resize(imread("dog.png"),dog, Size(400, 360));
    bitwise_or(cat,dog,img_and); // 或运算 1 & 1 = 1,其他为0
    imshow("result",img_and);
    waitKey(0);
    return 0;
}

保存程序并运行,结果如图14-3所示。

图14-3

可以看出,或运算的结果是使图像变大,最后的图像也偏亮。

代码实现数字水印

前面讲解了数字水印的嵌入过程和提取过程,步骤比较清晰。本节将根据这些步骤,通过代码来实现数字水印的嵌入和提取。

【例14.4】实现数字水印的嵌入和提取

打开Qt Creator,新建一个控制台项目,项目名称是test。

在main.cpp中输入如下代码:

复制代码
#include "opencv2/opencv.hpp"
using namespace cv;

int main()
{
    Mat gray1H7,dst,getWatermark;
    Mat src= imread("src.bmp",0);
    // 读取水印图像
    Mat watermark= imread("watermark.bmp",0);
    // 将水印图像内的正值处理为1,以方便嵌入,相当于把水印图像变成二值图像
    for(int i=0;i<watermark.rows;i++)
    {
            for(int j=0;j<watermark.cols;j++)
            {
                if(watermark.at<uchar>(i,j)>0)
                    watermark.at<uchar>(i,j)=1;
            }
     }
    // 读取原始载体图像的行和列
    int r=src.rows;
    int c=src.cols;

    // ----------------------嵌入过程------------------------
    // 生成元素值都是254的数组
    Mat t254 = Mat::ones(r, c, CV_8UC1) * 254;
    // 获取gray1H7图像的高七位
    bitwise_and(src,t254,gray1H7);
    // 将watermark嵌入gray1H7内
    bitwise_or(gray1H7,watermark,dst);
    // ----------------------提取过程--------------------------
    // 生成元素值都是1的数组
    Mat t1=  Mat::ones(r, c, CV_8UC1);
    // 从目标载体图像内提取水印图像
    bitwise_and(dst,t1,getWatermark);
    // 将水印图像内的正值处理为255,以方便显示
    for(int i=0;i<getWatermark.rows;i++)
    {
            for(int j=0;j<getWatermark.cols;j++)
            {
                if(getWatermark.at<uchar>(i,j)>0)
                    getWatermark.at<uchar>(i,j)=255;
            }
     }
    // ---------显示结果--------
    imshow("srcImg",src);
    imshow("watermark",watermark*255); // 当前watermark内最大值为1
    imshow("dstImg",dst);
    imshow("getWatermark",getWatermark);
    waitKey();
    destroyAllWindows();

    waitKey(0);
    return 0;
}

可以看出,上述代码是按照嵌入过程的步骤和提取过程的步骤来实现的。我们把一副水印图像(watermark.bmp)嵌入原始载体图像(src.bmp)中变为目标载体图像(也称含水印的载体图像)dst,然后从dst中提取出水印数据存于getWatermark中,最后显示4种图像。

运行程序,结果如图14-4所示。

从图14-4中可以看到,原始载体图像(src)和含水印的载体图像(dst)肉眼是看不出区别的。下面再看水印图像,如图14-5所示。

图14-4

图14-5

在图14-5中,左边是原来的数字水印图像,右边是从目标载体图像中提取出来的数字水印图像,可以发现两者并没有变化。这样我们就实现了把一副数字水印图像嵌入载体图像再提取出的过程。

相关推荐
牛客企业服务几秒前
2025年AI面试推荐榜单,数字化招聘转型优选
人工智能·python·算法·面试·职场和发展·金融·求职招聘
视觉语言导航31 分钟前
RAL-2025 | 清华大学数字孪生驱动的机器人视觉导航!VR-Robo:面向视觉机器人导航与运动的现实-模拟-现实框架
人工智能·深度学习·机器人·具身智能
**梯度已爆炸**41 分钟前
自然语言处理入门
人工智能·自然语言处理
ctrlworks1 小时前
楼宇自控核心功能:实时监控设备运行,快速诊断故障,赋能设备寿命延长
人工智能·ba系统厂商·楼宇自控系统厂家·ibms系统厂家·建筑管理系统厂家·能耗监测系统厂家
BFT白芙堂2 小时前
睿尔曼系列机器人——以创新驱动未来,重塑智能协作新生态(上)
人工智能·机器学习·机器人·协作机器人·复合机器人·睿尔曼机器人
aneasystone本尊2 小时前
使用 MCP 让 Claude Code 集成外部工具
人工智能
静心问道2 小时前
SEW:无监督预训练在语音识别中的性能-效率权衡
人工智能·语音识别
羊小猪~~2 小时前
【NLP入门系列五】中文文本分类案例
人工智能·深度学习·考研·机器学习·自然语言处理·分类·数据挖掘
xwz小王子2 小时前
从LLM到WM:大语言模型如何进化成具身世界模型?
人工智能·语言模型·自然语言处理
我爱一条柴ya2 小时前
【AI大模型】深入理解 Transformer 架构:自然语言处理的革命引擎
人工智能·ai·ai作画·ai编程·ai写作