C++ OpenCV 基于频率域(DCT)的数字水印

基于频域(DCT)的水印技术相较于基于空间域的水印技术有着很好的鲁棒性,不会因为图像的压缩或变换导致提取水印失败

具体实现如下所示:

 1 #include <iostream>
 2 #include <opencv2/opencv.hpp>
 3 using namespace std;
 4 using namespace cv;
 5 
 6 /**
 7  * \brief 嵌入水印函数
 8  * \param image 原始图像
 9  * \param waterMark 待嵌入水印图像
10  * \param alpha 嵌入系数
11  * \return 嵌入水印后的图像
12  */
13 Mat embeding_watermark(const Mat& image, const Mat& waterMark, float alpha = 0.1)
14 {
15     Mat watermarked = Mat::zeros(waterMark.size(), CV_32F);
16     Mat dct_image;
17     dct(image, dct_image);
18     for(int i=0;i< dct_image.rows;++i) {
19         for(int j=0;j< dct_image.cols;++j) {
20             //在频域中将原始图像每个像素都与水印图像像素相加或相减
21             watermarked.at<float>(i, j) = dct_image.at<float>(i, j) + alpha * waterMark.at<float>(i, j);
22         }
23     }
24 
25     idct(watermarked, watermarked);
26     return watermarked;
27 }
28 
29 /**
30  * \brief 水印提取函数
31  * \param image 原始图像
32  * \param watermarked 嵌入水印后的图像
33  * \param alpha 嵌入系数
34  * \return 水印图像
35  */
36 Mat extract_watermark(const Mat&image, const Mat &watermarked,float alpha=0.1)
37 {
38     Mat watermark = Mat::zeros(watermarked.size(), CV_32F);
39     Mat org_dct_image;
40     dct(image, org_dct_image);
41     Mat dct_image;
42     dct(watermarked, dct_image);
43     for(int i=0;i<watermarked.rows;++i) {
44         for(int j=0;j<watermarked.cols;++j) {
45             //嵌入水印操作的逆运算
46             watermark.at<float>(i, j) = (dct_image.at<float>(i, j) - org_dct_image.at<float>(i, j)) / alpha;
47         }
48     }
49     return watermark;
50 }
51 
52 
53 int main()
54 {    //读取原始图像
55     Mat image = imread(R"(C:\Users\Zafir\Desktop\lena.png)");
56     //读取待嵌入水印图像
57     Mat waterMark = imread(R"(C:\Users\Zafir\Desktop\people.jpg)");
58     //统一图像尺寸
59     resize(image, image, Size(512, 512));
60     resize(waterMark, waterMark, Size(512, 512));
61     //转换为灰度图像
62     cvtColor(image, image, COLOR_BGR2GRAY);
63     cvtColor(waterMark, waterMark, COLOR_BGR2GRAY);
64     //由于是基于频域DCT变换,因此要将图像格式转换为浮点型
65     image.convertTo(image, CV_32F);
66     waterMark.convertTo(waterMark, CV_32F);
67 
68     //嵌入水印后的图像
69     Mat watermarked = embeding_watermark(image, waterMark);
70     //从嵌入水印后的图像提取水印
71     Mat water_mark = extract_watermark(image, watermarked);
72 
73     //转换为可显的格式
74     watermarked.convertTo(watermarked, CV_8U);
75     water_mark.convertTo(water_mark, CV_8U);
76     imshow("watermarked", watermarked);
77     imshow("water_mark", water_mark);
78     waitKey(0);
79     destroyAllWindows();
80     return 0;
81 }

 

posted @ 2024-11-22 10:37  Zafir_Tan  阅读(260)  评论(0)    收藏  举报