1. 程式人生 > >opencv c++ 小波變換

opencv c++ 小波變換

國慶憋東西微笑微笑微笑不解釋  感冒已經好

小波變換 原理沒太懂 但是程式能用生氣生氣生氣

#include <opencv2\imgproc\imgproc.hpp>

#include <opencv2\highgui\highgui.hpp>
#include <opencv2\core\core.hpp>
#include <iostream>
#include <math.h>
using namespace cv;
using namespace std;
Mat WDT(const Mat &_src, const string _wname, const int _level);
void wavelet(const string _wname, Mat &_lowFilter, Mat &_highFilter);
Mat waveletDecompose(const Mat &_src, const Mat &_lowFilter, const Mat &_highFilter);
Mat waveletReconstruct(const Mat &_src, const Mat &_lowFilter, const Mat &_highFilter);
///  小波變換
Mat WDT(const Mat &_src, const string _wname, const int _level)
{
//int reValue = THID_ERR_NONE;
Mat src = Mat_<float>(_src);
Mat dst = Mat::zeros(src.rows, src.cols, src.type());
int N = src.rows;
int D = src.cols;


/// 高通低通濾波器
Mat lowFilter;
Mat highFilter;
wavelet(_wname, lowFilter, highFilter);


/// 小波變換
int t = 1;
int row = N;
int col = D;


while (t <= _level)
{
///先進行行小波變換
for (int i = 0; i<row; i++)
{
/// 取出src中要處理的資料的一行
Mat oneRow = Mat::zeros(1, col, src.type());
for (int j = 0; j<col; j++)
{
oneRow.at<float>(0, j) = src.at<float>(i, j);
}
oneRow = waveletDecompose(oneRow, lowFilter, highFilter);
/// 將src這一行置為oneRow中的資料
for (int j = 0; j<col; j++)
{
dst.at<float>(i, j) = oneRow.at<float>(0, j);
}
}
/// 小波列變換
for (int j = 0; j<col; j++)
{
/// 取出src資料的一行輸入
Mat oneCol = Mat::zeros(row, 1, src.type());
for (int i = 0; i<row; i++)
{
oneCol.at<float>(i, 0) = dst.at<float>(i, j);
}
oneCol =( waveletDecompose(oneCol.t(), lowFilter, highFilter)).t();


for (int i = 0; i<row; i++)
{
dst.at<float>(i, j) = oneCol.at<float>(i, 0);
}
}


/// 更新
row /= 2;
col /= 2;
t++;
src = dst;
}


return dst;
}


///  小波逆變換
Mat IWDT(const Mat &_src, const string _wname, const int _level)
{
//int reValue = THID_ERR_NONE;
Mat src = Mat_<float>(_src);
Mat dst = Mat::zeros(src.rows, src.cols, src.type());
int N = src.rows;
int D = src.cols;


/// 高通低通濾波器
Mat lowFilter;
Mat highFilter;
wavelet(_wname, lowFilter, highFilter);


/// 小波變換
int t = 1;
int row = N / std::pow(2., _level - 1);
int col = D / std::pow(2., _level - 1);


while (row <= N && col <= D)
{
/// 小波列逆變換
for (int j = 0; j<col; j++)
{
/// 取出src資料的一行輸入
Mat oneCol = Mat::zeros(row, 1, src.type());
for (int i = 0; i<row; i++)
{
oneCol.at<float>(i, 0) = src.at<float>(i, j);
}
oneCol = waveletReconstruct(oneCol.t(), lowFilter, highFilter);


for (int i = 0; i<row; i++)
{
dst.at<float>(i, j) = oneCol.at<float>(i, 0);
}
}


///行小波逆變換
for (int i = 0; i<row; i++)
{
/// 取出src中要處理的資料的一行
Mat oneRow = Mat::zeros(1, col, src.type());
for (int j = 0; j<col; j++)
{
oneRow.at<float>(0, j) = dst.at<float>(i, j);
}
oneRow = waveletReconstruct(oneRow, lowFilter, highFilter);
/// 將src這一行置為oneRow中的資料
for (int j = 0; j<col; j++)
{
dst.at<float>(i, j) = oneRow.at<float>(0, j);
}
}




row *= 2;
col *= 2;
src = dst;
}


return dst;
}




////////////////////////////////////////////////////////////////////////////////////////////


/// 呼叫函式


/// 生成不同型別的小波,現在只有haar,sym2
void wavelet(const string _wname, Mat &_lowFilter, Mat &_highFilter)
{
if (_wname == "sym2")
{
int N = 4;
float h[] = { -0.483, 0.836, -0.224, -0.129 };
float l[] = { -0.129, 0.224, 0.837, 0.483 };


_lowFilter = Mat::zeros(1, N, CV_32F);
_highFilter = Mat::zeros(1, N, CV_32F);


for (int i = 0; i<N; i++)
{
_lowFilter.at<float>(0, i) = l[i];
_highFilter.at<float>(0, i) = h[i];
}


}
}


/// 小波分解
Mat waveletDecompose(const Mat &_src, const Mat &_lowFilter, const Mat &_highFilter)
{
assert(_src.rows == 1 && _lowFilter.rows == 1 && _highFilter.rows == 1);
assert(_src.cols >= _lowFilter.cols && _src.cols >= _highFilter.cols);
Mat &src = Mat_<float>(_src);


int D = src.cols;


Mat &lowFilter = Mat_<float>(_lowFilter);
Mat &highFilter = Mat_<float>(_highFilter);




/// 頻域濾波,或時域卷積;ifft( fft(x) * fft(filter)) = cov(x,filter) 
Mat dst1 = Mat::zeros(1, D, src.type());
Mat dst2 = Mat::zeros(1, D, src.type());


filter2D(src, dst1, -1, lowFilter);
filter2D(src, dst2, -1, highFilter);




/// 下采樣
Mat downDst1 = Mat::zeros(1, D / 2, src.type());
Mat downDst2 = Mat::zeros(1, D / 2, src.type());


resize(dst1, downDst1, downDst1.size());
resize(dst2, downDst2, downDst2.size());




/// 資料拼接
for (int i = 0; i<D / 2; i++)
{
src.at<float>(0, i) = downDst1.at<float>(0, i);
src.at<float>(0, i + D / 2) = downDst2.at<float>(0, i);
}


return src;
}


/// 小波重建
Mat waveletReconstruct(const Mat &_src, const Mat &_lowFilter, const Mat &_highFilter)
{
assert(_src.rows == 1 && _lowFilter.rows == 1 && _highFilter.rows == 1);
assert(_src.cols >= _lowFilter.cols && _src.cols >= _highFilter.cols);
Mat &src = Mat_<float>(_src);


int D = src.cols;


Mat &lowFilter = Mat_<float>(_lowFilter);
Mat &highFilter = Mat_<float>(_highFilter);


/// 插值;
Mat Up1 = Mat::zeros(1, D, src.type());
Mat Up2 = Mat::zeros(1, D, src.type());


/// 插值為0
//for ( int i=0, cnt=1; i<D/2; i++,cnt+=2 )
//{
//    Up1.at<float>( 0, cnt ) = src.at<float>( 0, i );     ///< 前一半
//    Up2.at<float>( 0, cnt ) = src.at<float>( 0, i+D/2 ); ///< 後一半
//}


/// 線性插值
Mat roi1(src, Rect(0, 0, D / 2, 1));
Mat roi2(src, Rect(D / 2, 0, D / 2, 1));
resize(roi1, Up1, Up1.size(), 0, 0, INTER_CUBIC);
resize(roi2, Up2, Up2.size(), 0, 0, INTER_CUBIC);


/// 前一半低通,後一半高通
Mat dst1 = Mat::zeros(1, D, src.type());
Mat dst2 = Mat::zeros(1, D, src.type());
filter2D(Up1, dst1, -1, lowFilter);
filter2D(Up2, dst2, -1, highFilter);


/// 結果相加
dst1 = dst1 + dst2;


return dst1;


}
void main()
{
Mat I;
I = imread("D:\\ymrf\\enhance\\paper\\test_img\\flower.jpg");
int height = I.rows;
int width = I.cols;
namedWindow("wddt", 0);
namedWindow("原始影象", 0);
imshow("原始影象", I);
Mat img_wdt;
Mat I_gray;
cvtColor(I, I_gray, CV_RGB2GRAY);
img_wdt=WDT(I_gray, "sym2", 2);
imshow("wddt", img_wdt);
waitKey(0);
}