分享一下之前做过的基于DCT变换的水印提取程序。开始先用python实现了一下,但发现提取的速度太慢,对100KB左右的单幅图像处理速度在50ms左右,于是用C++重写了一下,用到了opencv3.4.5,和NumCpp插件来实现python中numpy中的数学计算功能。
定义了一个WM类,用来做水印提取和相关的计算,先看头文件
#pragma once
#ifndef __WM__
#define __WM__
#include <iostream>
#include "stdlib.h"
#include <iomanip>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <list>
#include "NumCpp.hpp"
#ifdef _DEBUG
#pragma comment(lib,"opencv_world345d.lib")
#else
#pragma comment(lib,"opencv_world345.lib")
#endif
using namespace std;
using namespace cv;
using namespace nc;
class WM
{
private:
nc::NdArray<int> _gene_signature();
double calc_sim(nc::NdArray<int>sig1, list<nc::NdArray<int>> sig2s);
nc::NdArray<int> TransNdArrayBoolToInt(nc::NdArray<bool> src);
int GetSum(nc::NdArray<bool> src);
double extract(Mat ori_wmimage, int key);
list<nc::NdArray<int>> inner_extract(Mat rgbChannels,int size, nc::NdArray<int> signature);
Mat ExctArray(Mat srcArray, int i, int j, int size);
public:
bool GetSig(char* imgName);
};
#endif
通过计算获取到水印图像的特征向量,与目标图像进行校验,来判别图像中是否含有目标水印,是一种有参照的提取方法。
#include "WM.h"
nc::NdArray<int> WM::_gene_signature() {
Mat new_wm;
cv::Size cvSize;
cvSize.height = size;
cvSize.width = size;
cv::resize(wm, new_wm,cvSize);
auto n_wm = nc::NdArray<nc::uint8>(new_wm.data, new_wm.rows, new_wm.cols);
nc::NdArray<double> wU;
nc::NdArray<double> wS;
nc::NdArray<double> wV;
nc::linalg::svd(n_wm.astype<double>(),wU,wS,wV);
auto sumU = nc::sum<double>(wU, nc::Axis::ROW);
auto