實(shí)現(xiàn)haar小波
參考文章中講解了haar小波的原理奥洼,比較易懂廓奕,實(shí)現(xiàn)了多級(jí)haar小波分解茴她,本文參照它進(jìn)行了練習(xí)存皂,同時(shí)添加了小波重建晌坤。
# include<iostream>
# include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
Mat src = imread("F:\\testdata\\pic\\16.jpg");
Mat HSV;
cvtColor(src, HSV, CV_BGR2HSV);
vector<Mat> channels;
split(HSV, channels);
Mat img = channels.at(1);
//上述是獲取HSV中的飽和度圖像,按需修改
namedWindow("img", 0);
imshow("img", img);
int height = img.rows;
int width = img.cols;
int depth = 2;
int depthcount = 1;
Mat tmp = Mat::ones(Size(width, height), CV_32FC1);
Mat wavelet = Mat::ones(Size(width, height), CV_32FC1);
Mat imgtmp = img.clone();
imgtmp.convertTo(imgtmp, CV_32FC1);
//---------------------------------------小波分解-----------------------------//
while (depthcount <= depth)
{
height = img.rows / pow(2,depthcount-1);
width = img.cols / pow(2,depthcount-1);
//水平方向變換
for (int i = 0; i < height; ++i)
{
for (int j = 0; j < width / 2; ++j)
{
tmp.at<float>(i, j) = (imgtmp.at<float>(i, 2 * j) + imgtmp.at<float>(i, 2 * j + 1)) / 2;
tmp.at<float>(i, j+width/2) = (imgtmp.at<float>(i, 2 * j) - imgtmp.at<float>(i, 2 * j + 1)) / 2;
}
}
//垂直方向變換
for (int i = 0; i < height / 2; ++i)
{
for (int j = 0; j < width; ++j)
{
wavelet.at<float>(i, j) = (tmp.at<float>(2 * i, j) + tmp.at<float>(2 * i + 1, j)) / 2;
wavelet.at<float>(i+height/2, j) = (tmp.at<float>(2 * i, j) - tmp.at<float>(2 * i + 1, j)) / 2;
}
}
/*
//低通濾波旦袋,選用高斯低通濾波器
Mat ROI = wavelet(Rect(0, 0, width, height));
GaussianBlur(ROI, ROI, Size(7, 7), 0.5);
Mat dst(wavelet, Rect(0, 0, width, height));
ROI.copyTo(dst);
*/
imgtmp = wavelet;
depthcount++;
}
//------------------------------------------小波重建--------------------------------------//
while (depth > 0)
{
height = img.rows / pow(2, depth - 1);
width = img.cols / pow(2, depth - 1);
//列逆變換
for (int i = 0; i < height/2; ++i)
{
for (int j = 0; j < width; ++j)
{
float value1 = imgtmp.at<float>(i, j);
float value2 = imgtmp.at<float>(i+height/2, j);
tmp.at<float>(2 * i, j) = value1 + value2;
tmp.at<float>(2 * i+1, j) = value1 - value2;
}
}
//行逆變換
for (int i = 0; i < height; ++i)
{
for (int j = 0; j < width / 2; ++j)
{
float value1 = tmp.at<float>(i, j);
float value2 = tmp.at<float>(i , j+width/2);
wavelet.at<float>(i, 2*j) = value1 + value2;
wavelet.at<float>(i , 2*j+1) = value1 - value2;
}
}
Mat ROI=wavelet(Rect(0, 0, width, height));
Mat dst(imgtmp, Rect(0, 0, width, height));
ROI.copyTo(dst);
depth--;
}
namedWindow("res", 0);
imgtmp.convertTo(imgtmp, CV_8UC1);
imshow("res", imgtmp);
waitKey(0);
return 0;
}
開(kāi)源代碼實(shí)現(xiàn)多種小波函數(shù)的小波變換
- C++ wavelet library
- 可以選擇按照其文檔中的配置方法骤菠,調(diào)用動(dòng)態(tài)鏈接庫(kù),但是我的嘗試不成功疤孕,出現(xiàn)了內(nèi)存異常商乎,所以本文直接將其源碼放入自己的項(xiàng)目中,和自己的項(xiàng)目一起編譯祭阀,可以實(shí)現(xiàn)同樣的功能鹉戚。需要注意的是鲜戒,需要配置好FFTW這個(gè)依賴(lài),方法見(jiàn)VS2015配置FFTW
- 函數(shù)說(shuō)明
- 利用這個(gè)庫(kù)中的函數(shù)可以得到小波分解的
近似系數(shù)
和細(xì)節(jié)系數(shù)
使用示例
重要的只有如下兩行函數(shù)調(diào)用
dwt_2d(data, depth, name, output, flag, length);
idwt_2d(output, flag, name, res, length);
#include <iostream>
#include <fstream>
#include "wavelet2d.h"
#include <vector>
#include <string>
#include <cmath>
#include<opencv2\opencv.hpp>
using namespace std;
using namespace cv;
int main() {
//讀入圖片抹凳,獲取飽和度
Mat src = imread("F:\\testdata\\poreImgV3\\10.jpg");
resize(src, src, Size(450, 450));
Mat HSV;
cvtColor(src, HSV, CV_BGR2HSV);
vector<Mat> channels;
channels.resize(3);
split(HSV, channels);
Mat saturation = channels.at(1);
namedWindow("s", 0);
imshow("s", saturation);
waitKey(0);
//將飽和度圖像數(shù)據(jù)存入vector<vector<double>>中,一行一行放置
int row = saturation.rows;
int col = saturation.cols;
//分配大小
vector<vector<double>> data;
data.resize(row);
for (int i = 0; i < data.size(); ++i)
{
data[i].resize(col);
}
//放入數(shù)據(jù)
for (int i = 0; i < row; ++i)
{
for (int j = 0; j < col; ++j)
{
data[i][j] = saturation.at<uchar>(i, j);
}
}
int depth = 2;
string name = "haar";
vector<double> output;
//output.resize(row*col);
vector<double> flag;
vector<int> length;
//小波分解
dwt_2d(data, depth, name, output, flag, length);
vector<vector<double>> res;
res.resize(row);
for (int i = 0; i < res.size(); ++i)
{
res[i].resize(col);
}
//----------------------------------------------------------------------------------
//小波重建
idwt_2d(output, flag, name, res, length);
//寫(xiě)回原圖像中
Mat recovery(src.size(), CV_8UC1);
for (int i = 0; i < row; ++i)
{
for (int j = 0; j < col; ++j)
{
recovery.at<uchar>(i, j) = (uchar)res[i][j];
}
}
imshow("res", recovery);
waitKey(0);
system("pause");
return 0;
}