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 }

浙公网安备 33010602011771号