Migrating wiki contents from Google Code
This commit is contained in:
commit
f09d370441
328
1DAppx.md
Normal file
328
1DAppx.md
Normal file
@ -0,0 +1,328 @@
|
||||
# 1D Linear vs Nonlinear Approximation using dwt #
|
||||
|
||||
One of the important property of wavelets is that it gives better approximation results when N largest coefficients are considered instead of first N coefficients.
|
||||
|
||||
[A sample code](http://code.google.com/p/wavelet1d/source/browse/trunk/demo/wavedemo2.cpp) to compare the performance of linear vs. Non-linear approximations using dwt function is given below. The signal used is "Piecewise-Regular" function from Stanford University's Matlab Wavelab Toolbox.
|
||||
```
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include "wavelet.h"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std;
|
||||
|
||||
void findthresh(vector<double> vector1, int N, double& t){
|
||||
sort(vector1.begin(), vector1.end(), greater<double>());
|
||||
t = vector1.at(N-1);
|
||||
}
|
||||
|
||||
int main() {
|
||||
cout << "********J- LEVEL DISCRETE WAVELET TRANSFORM IMPLEMENTATION*********" << endl; // prints
|
||||
cout << "This program accepts signal from the user in a file format " << endl;
|
||||
cout << "and performs Discrete Wavelet Transform with specified " << endl;
|
||||
cout << "wavelet. " << endl;
|
||||
cout << " " << endl;
|
||||
cout << " The Following Wavelets are in the Database: " << endl;
|
||||
cout << " haar, db1, db2, db3, db4, db5, db6, db7, db8, db9, db10, " << endl;
|
||||
cout << " db11, db12, db13, db14, db15. " << endl;
|
||||
cout << " bior1.1, bio1.3, bior1.5, bior2.2, bior2.4,bior2.6,bior2.8, " << endl;
|
||||
cout << " bior3.1, bior3.3, bior3.5, bior3.7, bior3.9, bior4.4," << endl;
|
||||
cout << " bior5.5, bior6.8." << endl;
|
||||
cout << " coif1, coif2, coif3, coif4, coif5." << endl;
|
||||
cout << "Please Enter the Wavelet Name at the Prompt( No quotes) :" << endl;
|
||||
|
||||
string nm; // nm will store the name of Wavelet Family
|
||||
cin >> nm;
|
||||
cout << "Enter the name of signal file at the Prompt eg., signal.txt :" << endl;
|
||||
char inp[50];
|
||||
cin >> inp;
|
||||
vector<double> sig;
|
||||
ifstream sig_inp(inp);
|
||||
if ( !sig_inp.good()){
|
||||
cout << "The File doesn't exist"<< endl;
|
||||
exit(1);
|
||||
}
|
||||
while (sig_inp) {
|
||||
double temp;
|
||||
sig_inp >> temp;
|
||||
sig.push_back(temp);
|
||||
}
|
||||
sig.pop_back();
|
||||
vector<double> original;
|
||||
original = sig;
|
||||
cout << "Please Enter the Number of DWT Stages J :" << endl;
|
||||
|
||||
int J;
|
||||
cin >> J ;
|
||||
|
||||
vector<double> dwt_output, flag;
|
||||
|
||||
// perform J-Level DWT
|
||||
dwt(sig, J, nm, dwt_output,flag );
|
||||
|
||||
// Performing Linear Approximation by using only first 100 coefficients
|
||||
// Coefficients in dwt_output are stored as following
|
||||
// dwt_output =[ Appx(J-1) Detail(J-1) Detail(J-2) .... Detail(0)]
|
||||
|
||||
int n_coef = 100; // Number of significant coefficients
|
||||
|
||||
int n_non_sig= dwt_output.size() - n_coef; // Number of Coefficients that will
|
||||
// be set to zero
|
||||
dwt_output.erase(dwt_output.end()- n_non_sig,dwt_output.end());
|
||||
// Deleting last n_non_sig coefficients and replacing them with zeros
|
||||
dwt_output.insert(dwt_output.end(),n_non_sig,0);
|
||||
|
||||
ofstream linearsig("linsig.txt");
|
||||
for (unsigned int i = 0; i < dwt_output.size(); i++) {
|
||||
linearsig << dwt_output[i] << endl;
|
||||
|
||||
}
|
||||
|
||||
// Finding IDWT with approximated coefficients
|
||||
|
||||
vector<double> output;
|
||||
idwt(dwt_output, flag,nm,output);
|
||||
|
||||
unsigned int count = output.size();
|
||||
ofstream gnulinappx("gnulinappx.dat");
|
||||
for (unsigned int i = 0;i < count; i++) {
|
||||
gnulinappx << i << " " << output[i] << endl;
|
||||
}
|
||||
gnulinappx.close();
|
||||
|
||||
// Performing Non Linear Approximation by using only most
|
||||
// significant coefficients
|
||||
|
||||
vector<double> dwt_output2, flag2;
|
||||
|
||||
// perform J-Level DWT
|
||||
dwt(sig, J, nm, dwt_output2,flag2 );
|
||||
|
||||
double thresh = 0.0;
|
||||
|
||||
vector<double> temp_dwtoutput;
|
||||
for (unsigned int i =0; i < dwt_output2.size();i++){
|
||||
double temp = abs(dwt_output2[i]);
|
||||
temp_dwtoutput.push_back(temp);
|
||||
}
|
||||
/*
|
||||
for (unsigned int i =0; i < temp_dwtoutput.size(); i++){
|
||||
cout << temp_dwtoutput[i] << endl;
|
||||
}
|
||||
*/
|
||||
|
||||
findthresh(temp_dwtoutput,n_coef, thresh);
|
||||
|
||||
for (unsigned int i = 0; i < dwt_output2.size();i++){
|
||||
double temp = abs(dwt_output2[i]);
|
||||
if (temp < thresh){
|
||||
dwt_output2.at(i) = 0.0;
|
||||
|
||||
}
|
||||
}
|
||||
/*
|
||||
for (unsigned int i =0; i < dwt_output2.size(); i++){
|
||||
cout << dwt_output2[i] << endl;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
// Finding IDWT with approximated coefficients
|
||||
|
||||
vector<double> output2;
|
||||
idwt(dwt_output2, flag2,nm,output2);
|
||||
|
||||
unsigned int count2 = output2.size();
|
||||
cout << count2 << endl;
|
||||
ofstream gnunlappx("gnunlappx.dat");
|
||||
for (unsigned int i = 0;i < count2; i++) {
|
||||
gnunlappx << i << " " << output2[i] << endl;
|
||||
}
|
||||
gnunlappx.close();
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
This program computes DWT of the 256-point signal and then uses only 100 coefficients to reconstruct the signal. In the first case, first 100 coefficients are are used to compute linear approximation. In the second case, 100 largest coefficents are used by calculating a threshold that separates largest 100 coefficients from the other 156.The wavelet used is db3 and the signal is decomposed and reconstructd over 4 stages of DWT/IDWT. The results are plotted below.
|
||||
|
||||
Input Signal
|
||||
|
||||

|
||||
|
||||
Reconstructed Signal using only first 100 coefficients.(Linear Approximation)
|
||||
|
||||

|
||||
|
||||
Reconstructed Signal using largest 100 coefficients.(Non-Linear Approximation)
|
||||
|
||||

|
||||
|
||||
|
||||
# 1D Linear vs Nonlinear Approximation using dwt\_sym #
|
||||
|
||||
_Note- Symmetric Extension DWT Implementation dwt\_sym is not a N input N output system so it has more DWT coefficients which usually means you'll need more coefficients to match dwt approximation performance for same wavelet. the trade-off is better performance at signal boundaries. In this example same number of approximation coefficients (100) are considered._
|
||||
|
||||
We use the same signal and wavelet family as above.[Sample Code](http://code.google.com/p/wavelet1d/source/browse/trunk/demo/wavedemo_sym2.cpp) is available at the source page.
|
||||
|
||||
```
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include "wavelet.h"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std;
|
||||
|
||||
void findthresh(vector<double> vector1, int N, double& t){
|
||||
sort(vector1.begin(), vector1.end(), greater<double>());
|
||||
t = vector1.at(N-1);
|
||||
}
|
||||
|
||||
int main() {
|
||||
cout << "********J- LEVEL DISCRETE WAVELET TRANSFORM IMPLEMENTATION*********" << endl; // prints
|
||||
cout << "This program accepts signal from the user in a file format " << endl;
|
||||
cout << "and performs Discrete Wavelet Transform with specified " << endl;
|
||||
cout << "wavelet. " << endl;
|
||||
cout << " " << endl;
|
||||
cout << " The Following Wavelets are in the Database: " << endl;
|
||||
cout << " haar, db1, db2, db3, db4, db5, db6, db7, db8, db9, db10, " << endl;
|
||||
cout << " db11, db12, db13, db14, db15. " << endl;
|
||||
cout << " bior1.1, bio1.3, bior1.5, bior2.2, bior2.4,bior2.6,bior2.8, " << endl;
|
||||
cout << " bior3.1, bior3.3, bior3.5, bior3.7, bior3.9, bior4.4," << endl;
|
||||
cout << " bior5.5, bior6.8." << endl;
|
||||
cout << " coif1, coif2, coif3, coif4, coif5." << endl;
|
||||
cout << "Please Enter the Wavelet Name at the Prompt( No quotes) :" << endl;
|
||||
|
||||
string nm; // nm will store the name of Wavelet Family
|
||||
cin >> nm;
|
||||
cout << "Enter the name of signal file at the Prompt eg., signal.txt :" << endl;
|
||||
char inp[50];
|
||||
cin >> inp;
|
||||
vector<double> sig;
|
||||
ifstream sig_inp(inp);
|
||||
if ( !sig_inp.good()){
|
||||
cout << "The File doesn't exist"<< endl;
|
||||
exit(1);
|
||||
}
|
||||
while (sig_inp) {
|
||||
double temp;
|
||||
sig_inp >> temp;
|
||||
sig.push_back(temp);
|
||||
}
|
||||
sig.pop_back();
|
||||
vector<double> original;
|
||||
original = sig;
|
||||
cout << "Please Enter the Number of DWT Stages J :" << endl;
|
||||
|
||||
int J;
|
||||
cin >> J ;
|
||||
|
||||
vector<double> dwt_output, flag;
|
||||
vector<int> length1;
|
||||
int ext = 2;
|
||||
|
||||
// perform J-Level DWT
|
||||
dwt_sym(sig, J, nm, dwt_output,flag, length1,ext );
|
||||
|
||||
// Performing Linear Approximation by using only first 100 coefficients
|
||||
// Coefficients in dwt_output are stored as following
|
||||
// dwt_output =[ Appx(J-1) Detail(J-1) Detail(J-2) .... Detail(0)]
|
||||
|
||||
int n_coef = 100; // Number of significant coefficients
|
||||
|
||||
int n_non_sig= dwt_output.size() - n_coef; // Number of Coefficients that will
|
||||
// be set to zero
|
||||
dwt_output.erase(dwt_output.end()- n_non_sig,dwt_output.end());
|
||||
// Deleting last n_non_sig coefficients and replacing them with zeros
|
||||
dwt_output.insert(dwt_output.end(),n_non_sig,0);
|
||||
|
||||
ofstream linearsig("linsig.txt");
|
||||
for (unsigned int i = 0; i < dwt_output.size(); i++) {
|
||||
linearsig << dwt_output[i] << endl;
|
||||
|
||||
}
|
||||
|
||||
// Finding IDWT with approximated coefficients
|
||||
|
||||
vector<double> output;
|
||||
idwt_sym(dwt_output, flag,nm,output, length1);
|
||||
|
||||
unsigned int count = output.size();
|
||||
ofstream gnulinappx("gnulinappx.dat");
|
||||
for (unsigned int i = 0;i < count; i++) {
|
||||
gnulinappx << i << " " << output[i] << endl;
|
||||
}
|
||||
gnulinappx.close();
|
||||
|
||||
// Performing Non Linear Approximation by using only most
|
||||
// significant coefficients
|
||||
|
||||
vector<double> dwt_output2, flag2;
|
||||
vector<int> length2;
|
||||
|
||||
// perform J-Level DWT
|
||||
dwt_sym(sig, J, nm, dwt_output2,flag2,length2, ext );
|
||||
|
||||
double thresh = 0.0;
|
||||
|
||||
vector<double> temp_dwtoutput;
|
||||
for (unsigned int i =0; i < dwt_output2.size();i++){
|
||||
double temp = abs(dwt_output2[i]);
|
||||
temp_dwtoutput.push_back(temp);
|
||||
}
|
||||
/*
|
||||
for (unsigned int i =0; i < temp_dwtoutput.size(); i++){
|
||||
cout << temp_dwtoutput[i] << endl;
|
||||
}
|
||||
*/
|
||||
|
||||
findthresh(temp_dwtoutput,n_coef, thresh);
|
||||
|
||||
for (unsigned int i = 0; i < dwt_output2.size();i++){
|
||||
double temp = abs(dwt_output2[i]);
|
||||
if (temp < thresh){
|
||||
dwt_output2.at(i) = 0.0;
|
||||
|
||||
}
|
||||
}
|
||||
/*
|
||||
for (unsigned int i =0; i < dwt_output2.size(); i++){
|
||||
cout << dwt_output2[i] << endl;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
// Finding IDWT with approximated coefficients
|
||||
|
||||
vector<double> output2;
|
||||
idwt_sym(dwt_output2, flag2,nm,output2, length2);
|
||||
|
||||
unsigned int count2 = output2.size();
|
||||
cout << count2 << endl;
|
||||
ofstream gnunlappx("gnunlappx.dat");
|
||||
for (unsigned int i = 0;i < count2; i++) {
|
||||
gnunlappx << i << " " << output2[i] << endl;
|
||||
}
|
||||
gnunlappx.close();
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
Reconstructed Signal using only first 100 coefficients.(Linear Approximation)
|
||||
|
||||

|
||||
|
||||
Reconstructed Signal using largest 100 coefficients.(Non-Linear Approximation)
|
||||
|
||||

|
126
1DDWTdemo.md
Normal file
126
1DDWTdemo.md
Normal file
@ -0,0 +1,126 @@
|
||||
# 1D DWT/IDWT Demo using dwt function #
|
||||
|
||||
[A sample code](http://code.google.com/p/wavelet1d/source/browse/trunk/demo/wavedemo1.cpp) for DWT/IDWT for a given signal is given below. The signal used is "Piecewise-Regular" function from Stanford University's Matlab Wavelab Toolbox.
|
||||
|
||||
```
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include "wavelet.h"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <cmath>
|
||||
using namespace std;
|
||||
|
||||
int main() {
|
||||
cout << "********J- LEVEL DISCRETE WAVELET TRANSFORM IMPLEMENTATION*********" << endl; // prints
|
||||
cout << "This program accepts signal from the user in a file format " << endl;
|
||||
cout << "and performs Discrete Wavelet Transform with specified " << endl;
|
||||
cout << "wavelet. " << endl;
|
||||
cout << " " << endl;
|
||||
cout << " The Following Wavelets are in the Database: " << endl;
|
||||
cout << " haar, db1, db2, db3, db4, db5, db6, db7, db8, db9, db10, " << endl;
|
||||
cout << " db11, db12, db13, db14, db15. " << endl;
|
||||
cout << " bior1.1, bio1.3, bior1.5, bior2.2, bior2.4,bior2.6,bior2.8, " << endl;
|
||||
cout << " bior3.1, bior3.3, bior3.5, bior3.7, bior3.9, bior4.4," << endl;
|
||||
cout << " bior5.5, bior6.8." << endl;
|
||||
cout << " coif1, coif2, coif3, coif4, coif5." << endl;
|
||||
cout << "Please Enter the Wavelet Name at the Prompt( No quotes) :" << endl;
|
||||
|
||||
string nm; // nm will store the name of Wavelet Family
|
||||
cin >> nm;
|
||||
cout << "Enter the name of signal file at the Prompt eg., signal.txt :" << endl;
|
||||
char inp[50];
|
||||
cin >> inp;
|
||||
vector<double> sig;
|
||||
ifstream sig_inp(inp);
|
||||
if ( !sig_inp.good()){
|
||||
cout << "The File doesn't exist"<< endl;
|
||||
exit(1);
|
||||
}
|
||||
while (sig_inp) {
|
||||
double temp;
|
||||
sig_inp >> temp;
|
||||
sig.push_back(temp);
|
||||
}
|
||||
sig.pop_back();
|
||||
vector<double> original;
|
||||
original = sig;
|
||||
cout << "Please Enter the Number of DWT Stages J :" << endl;
|
||||
|
||||
int J;
|
||||
cin >> J ;
|
||||
|
||||
vector<double> dwt_output, flag;
|
||||
|
||||
// perform J-Level DWT
|
||||
dwt(sig, J, nm, dwt_output,flag );
|
||||
|
||||
|
||||
//Perform J-Level IDWT
|
||||
vector<double> output;
|
||||
idwt(dwt_output, flag,nm,output);
|
||||
|
||||
ofstream sig1("recon.txt");
|
||||
ofstream diff("diff.txt");
|
||||
|
||||
cout <<" Recon signal size" << output.size() << endl;
|
||||
for (unsigned int i = 0; i < output.size(); i++){
|
||||
sig1 << output[i] << endl;
|
||||
diff << output[i] - original[i] << endl;
|
||||
|
||||
}
|
||||
gnudwtplot(J);
|
||||
return 0;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
The program asks user for wavelet name, signal file and number of DWT stages. It then computes DWT of the input signal and then the IDWT from the wavelet coefficients so obtained. Running the program from Eclipse console :
|
||||
|
||||
```
|
||||
********J- LEVEL DISCRETE WAVELET TRANSFORM IMPLEMENTATION*********
|
||||
This program accepts signal from the user in a file format
|
||||
and performs Discrete Wavelet Transform with specified
|
||||
wavelet.
|
||||
|
||||
The Following Wavelets are in the Database:
|
||||
haar, db1, db2, db3, db4, db5, db6, db7, db8, db9, db10,
|
||||
db11, db12, db13, db14, db15.
|
||||
bior1.1, bio1.3, bior1.5, bior2.2, bior2.4,bior2.6,bior2.8,
|
||||
bior3.1, bior3.3, bior3.5, bior3.7, bior3.9, bior4.4,
|
||||
bior5.5, bior6.8.
|
||||
coif1, coif2, coif3, coif4, coif5.
|
||||
Please Enter the Wavelet Name at the Prompt( No quotes) :
|
||||
db3
|
||||
Enter the name of signal file at the Prompt eg., signal.txt :
|
||||
signal.txt
|
||||
Please Enter the Number of DWT Stages J :
|
||||
3
|
||||
```
|
||||
|
||||
gnudwtplot(J) is called which generates GNUPLOT script. GNUPLOT script is called from gnuplot as following.
|
||||
|
||||
gnuplot> cd '<Path to File Outputs>'
|
||||
|
||||
gnuplot> load "gnudwt.gnu.txt"
|
||||
|
||||
1. Input Signal : Piecewise-Regular signal from Stanford University Wavelab Toolbox.
|
||||
|
||||

|
||||
|
||||
2. Approximation and Detail coefficients at each iteration stage. Note- While the program is plotting approximation coefficients, the actual DWT doesn't store approximation values at each level for redundancy reasons. Only approximation coefficients at the Jth stage are stored.
|
||||
|
||||

|
||||
|
||||
3. Four filters associated with orthogonal db3 wavelet.
|
||||
|
||||

|
||||
|
||||
4. Reconstructed Signal.
|
||||
|
||||

|
||||
|
||||
|
||||
# 1D DWT/IDWT Demo using dwt\_sym function #
|
||||
|
||||
[Sample Code](http://code.google.com/p/wavelet1d/source/browse/trunk/demo/wavedemo_sym1.cpp) for DWT/IDWT using dwt\_sym function is also available.
|
91
1DSWTDemo.md
Normal file
91
1DSWTDemo.md
Normal file
@ -0,0 +1,91 @@
|
||||
# 1D Stationary Wavelet Transform Demo #
|
||||
|
||||
[Sample Code](http://code.google.com/p/wavelet1d/source/browse/trunk/demo/swtdemo.cpp)
|
||||
|
||||
```
|
||||
//============================================================================
|
||||
// Name : swtdemo.cpp
|
||||
// Author : Rafat Hussain
|
||||
// Version :
|
||||
// Copyright :
|
||||
// Description : 1D Stationary Wavelet Transform Demo
|
||||
//============================================================================
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include "wavelet.h"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <cmath>
|
||||
using namespace std;
|
||||
|
||||
int main() {
|
||||
cout << "********J- LEVEL DISCRETE WAVELET TRANSFORM IMPLEMENTATION*********" << endl; // prints
|
||||
cout << "This program accepts signal from the user in a file format " << endl;
|
||||
cout << "and performs Discrete Wavelet Transform with specified " << endl;
|
||||
cout << "wavelet. " << endl;
|
||||
cout << " " << endl;
|
||||
cout << " The Following Wavelets are in the Database: " << endl;
|
||||
cout << " haar, db1, db2, db3, db4, db5, db6, db7, db8, db9, db10, " << endl;
|
||||
cout << " db11, db12, db13, db14, db15. " << endl;
|
||||
cout << " bior1.1, bio1.3, bior1.5, bior2.2, bior2.4,bior2.6,bior2.8, " << endl;
|
||||
cout << " bior3.1, bior3.3, bior3.5, bior3.7, bior3.9, bior4.4," << endl;
|
||||
cout << " bior5.5, bior6.8." << endl;
|
||||
cout << " coif1, coif2, coif3, coif4, coif5." << endl;
|
||||
cout << "Please Enter the Wavelet Name at the Prompt( No quotes) :" << endl;
|
||||
|
||||
string nm; // nm will store the name of Wavelet Family
|
||||
cin >> nm;
|
||||
cout << "Enter the name of signal file at the Prompt eg., signal.txt :" << endl;
|
||||
char inp[50];
|
||||
cin >> inp;
|
||||
vector<double> sig;
|
||||
ifstream sig_inp(inp);
|
||||
if ( !sig_inp.good()){
|
||||
cout << "The File doesn't exist"<< endl;
|
||||
exit(1);
|
||||
}
|
||||
while (sig_inp) {
|
||||
double temp;
|
||||
sig_inp >> temp;
|
||||
sig.push_back(temp);
|
||||
}
|
||||
sig.pop_back();
|
||||
vector<double> original;
|
||||
original = sig;
|
||||
cout << "Please Enter the Number of DWT Stages J :" << endl;
|
||||
|
||||
int J;
|
||||
cin >> J ;
|
||||
|
||||
vector<double> swt_output;
|
||||
|
||||
// perform J-Level DWT
|
||||
int length;// All coefficients are of same length. Variable "length" returns length
|
||||
// of coefficients. It is not required for ISWT computations.
|
||||
|
||||
// If signal is not of dyadic length it is zeropadded as the algorithm is designed to
|
||||
// work with signals of 2^M length. These extra zeros can be removed after reconstruction.
|
||||
|
||||
|
||||
swt(sig, J, nm, swt_output, length);
|
||||
vector<double> iswt_output;
|
||||
iswt(swt_output,J, nm,iswt_output);
|
||||
gnuswtplot(J);
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
The signal is the same Piecewise Regular signal that is used in the [1D Decimated DWT Demo](http://code.google.com/p/wavelet1d/wiki/1DDWTdemo).
|
||||
|
||||

|
||||
|
||||
> The filter used is Daubechies db2 Orthogonal length=4 filter. The undecimated detail and approximation coefficients are plotted as following using GNUPLOT.
|
||||
|
||||

|
||||
|
||||
> There is a very obvious trade-off here. The Transform is good for signal analysis as details and approximation coefficients are of the same length as the original signal at every decomposition stage but the system is highly redundant.
|
||||
|
||||
> The Inverse SWT is perfect reconstruction.
|
||||
|
670
2DAppx.md
Normal file
670
2DAppx.md
Normal file
@ -0,0 +1,670 @@
|
||||
# Image Approximation using dwt\_2d #
|
||||
|
||||
[Sample Code](http://code.google.com/p/wavelet1d/source/browse/trunk/demo/imagedemo2.cpp)
|
||||
|
||||
```
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
#include "cv.h"
|
||||
#include "highgui.h"
|
||||
#include "cxcore.h"
|
||||
#include "wavelet.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
|
||||
void findthresh(vector<double> &vector1, int N, double& t){
|
||||
sort(vector1.begin(), vector1.end(), greater<double>());
|
||||
t = vector1.at(N-1);
|
||||
}
|
||||
|
||||
void* maxval(vector<vector<double> > &arr, double &max){
|
||||
max = 0;
|
||||
for (unsigned int i =0; i < arr.size(); i++) {
|
||||
for (unsigned int j =0; j < arr[0].size(); j++) {
|
||||
if (max <= arr[i][j]){
|
||||
max = arr[i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* minval(vector<vector<double> > &arr, double &min){
|
||||
min = 10000;
|
||||
for (unsigned int i =0; i < arr.size(); i++) {
|
||||
for (unsigned int j =0; j < arr[0].size(); j++) {
|
||||
if (min >= arr[i][j]){
|
||||
min = arr[i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main() {
|
||||
IplImage* img = cvLoadImage("lena512.bmp");
|
||||
if (!img){
|
||||
cout << " Can't read Image. Try Different Format." << endl;
|
||||
exit(1);
|
||||
}
|
||||
int height, width;
|
||||
height = img->height;
|
||||
width = img->width;
|
||||
int nc = img->nChannels;
|
||||
// uchar* ptr2 =(uchar*) img->imageData;
|
||||
int pix_depth = img->depth;
|
||||
CvSize size;
|
||||
size.width =width;
|
||||
size.height=height;
|
||||
cout << "depth" << pix_depth << "Channels" << nc << endl;
|
||||
|
||||
|
||||
cvNamedWindow("Original Image", CV_WINDOW_AUTOSIZE);
|
||||
cvShowImage("Original Image", img);
|
||||
cvWaitKey();
|
||||
cvDestroyWindow("Original Image");
|
||||
|
||||
|
||||
int rows =(int) height;
|
||||
int cols =(int) width;
|
||||
Mat matimg(img);
|
||||
|
||||
vector<vector<double> > vec1(rows, vector<double>(cols));
|
||||
|
||||
|
||||
int k =1;
|
||||
for (int i=0; i < rows; i++) {
|
||||
for (int j =0; j < cols; j++){
|
||||
unsigned char temp;
|
||||
temp = ((uchar*) matimg.data + i * matimg.step)[j * matimg.elemSize() + k ];
|
||||
vec1[i][j] = (double) temp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int rr1,cc1;
|
||||
string nm = "db3";
|
||||
// Finding DWT output dimensions as the DWT output is zeropadded
|
||||
dwt_output_dim(vec1, rr1, cc1 );
|
||||
int J = 5;
|
||||
vector<double> flag;
|
||||
vector<vector<double> > dwt_output(rr1, vector<double>(cc1));
|
||||
cout << rr1 << cc1 << "size of op" << endl;
|
||||
// Computing 2d DWT ( vec1 is the signal while dwt_output is the DWT output)
|
||||
dwt_2d(vec1, J, nm, dwt_output,flag );
|
||||
|
||||
cout << "dwt size" << dwt_output.size() << dwt_output[0].size() << endl;
|
||||
|
||||
double max,min;
|
||||
|
||||
maxval(dwt_output,max);
|
||||
minval(dwt_output,min);
|
||||
cout << "maxval" << max << " minval" << min << endl;
|
||||
|
||||
|
||||
|
||||
vector<vector<double> > dwt_coef1(rr1, vector<double>(cc1));
|
||||
vector<vector<double> > dwt_coef2(rr1, vector<double>(cc1));
|
||||
// Storing dwt_output for two different computations based on
|
||||
// different approximation values
|
||||
dwt_coef1 = dwt_output;
|
||||
dwt_coef2 = dwt_output;
|
||||
|
||||
|
||||
|
||||
//Displaying Scaled Image
|
||||
// Creating Image in OPENCV
|
||||
IplImage *cvImg; // image used for output
|
||||
CvSize imgSize; // size of output image
|
||||
|
||||
imgSize.width = cc1;
|
||||
imgSize.height = rr1;
|
||||
|
||||
cvImg = cvCreateImage( imgSize, 8, 1 );
|
||||
|
||||
// Setting coefficients of created image to the scaled DWT output values
|
||||
for (int i = 0; i < imgSize.height; i++ ) {
|
||||
for (int j = 0; j < imgSize.width; j++ ){
|
||||
if ( dwt_output[i][j] <= 0.0){
|
||||
dwt_output[i][j] = 0.0;
|
||||
}
|
||||
if ( i <= (imgSize.height/pow(2.0,double(J))) && j <= (imgSize.width/pow(2.0,double(J))) ) {
|
||||
((uchar*)(cvImg->imageData + cvImg->widthStep*i))[j] =
|
||||
(char) ( (dwt_output[i][j] / max) * 255.0);
|
||||
} else {
|
||||
((uchar*)(cvImg->imageData + cvImg->widthStep*i))[j] =
|
||||
(char) (dwt_output[i][j]) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// IMPORTANT -- dwt_output value has been modified above.
|
||||
|
||||
cvNamedWindow( "DWT Image", 1 ); // creation of a visualisation window
|
||||
cvShowImage( "DWT Image", cvImg ); // image visualisation
|
||||
cvWaitKey();
|
||||
cvDestroyWindow("DWT Image");
|
||||
|
||||
|
||||
// Case 1 : Only 10% of the largest coefficients are considered
|
||||
|
||||
// Total elements in the original image is rows * cols
|
||||
int n_coef1= int (( rows * cols)/ 10);
|
||||
|
||||
// Finding Threshold Value corresponding to n_coef1
|
||||
|
||||
vector<double> temp1;
|
||||
cout << "size: " << (int) temp1.size() << "\n";
|
||||
cout << "capacity: " << (int) temp1.capacity() << "\n";
|
||||
cout << "max_size: " << (int) temp1.max_size() << "\n";
|
||||
for (int i =0; i < rr1; i++) {
|
||||
for (int j = 0; j < cc1; j++){
|
||||
double tempval = abs(dwt_coef1[i][j]);
|
||||
temp1.push_back(tempval);
|
||||
}
|
||||
}
|
||||
|
||||
double thresh1= 0.0;
|
||||
findthresh(temp1,n_coef1,thresh1);
|
||||
ofstream temp("temp.txt");
|
||||
for (int i =0; i < rows * cols; i++){
|
||||
temp << temp1[i] << " " ;
|
||||
}
|
||||
// Reset coeffficients value depending on threshold value
|
||||
|
||||
|
||||
for (int i =0; i < rr1; i++) {
|
||||
for (int j = 0; j < cc1; j++){
|
||||
double temp = abs(dwt_coef1[i][j]);
|
||||
|
||||
if (temp < thresh1){
|
||||
dwt_coef1[i][j] = 0.0;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Finding IDWT
|
||||
vector<vector<double> > final(rr1, vector<double>(cc1));
|
||||
idwt_2d(dwt_coef1,flag, nm ,final);
|
||||
|
||||
// Removing Zeropadding
|
||||
|
||||
zero_remove(vec1,final);
|
||||
|
||||
double max1;
|
||||
maxval(final,max1);
|
||||
|
||||
//Displaying Reconstructed Image
|
||||
|
||||
IplImage *dvImg;
|
||||
CvSize dvSize; // size of output image
|
||||
|
||||
dvSize.width = final[0].size();
|
||||
dvSize.height = final.size();
|
||||
|
||||
dvImg = cvCreateImage( dvSize, 8, 1 );
|
||||
|
||||
for (int i = 0; i < dvSize.height; i++ ) {
|
||||
for (int j = 0; j < dvSize.width; j++ ){
|
||||
if ( final[i][j] <= 0.0){
|
||||
final[i][j] = 0.0;
|
||||
}
|
||||
((uchar*)(dvImg->imageData + dvImg->widthStep*i))[j] =
|
||||
(char) ((final[i][j]/max1) * 255) ;
|
||||
}
|
||||
}
|
||||
|
||||
cvNamedWindow( "10% Coeff Reconstructed Image", 1 ); // creation of a visualisation window
|
||||
cvShowImage( "10% Coeff Reconstructed Image", dvImg ); // image visualisation
|
||||
cvWaitKey();
|
||||
cvDestroyWindow("10% Coeff Reconstructed Image");
|
||||
|
||||
// Case 2 : Only 2% of the largest coefficients are considered
|
||||
|
||||
// Total elements in the original image is rows * cols
|
||||
int n_coef2= int (( rows * cols) / 50);
|
||||
|
||||
// Finding Threshold Value corresponding to n_coef1
|
||||
|
||||
vector<double> temp2;
|
||||
for (int i =0; i < rr1; i++) {
|
||||
for (int j = 0; j < cc1; j++){
|
||||
double tempval = abs(dwt_coef2[i][j]);
|
||||
temp2.push_back(tempval);
|
||||
}
|
||||
}
|
||||
double thresh2= 0.0;
|
||||
findthresh(temp2,n_coef2,thresh2);
|
||||
|
||||
// Reset coeffficients value depending on threshold value
|
||||
|
||||
for (int i =0; i < rr1; i++) {
|
||||
for (int j = 0; j < cc1; j++){
|
||||
double temp = abs(dwt_coef2[i][j]);
|
||||
|
||||
if (temp < thresh2){
|
||||
dwt_coef2[i][j] = 0.0;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Finding IDWT
|
||||
vector<vector<double> > final2(rr1, vector<double>(cc1));
|
||||
idwt_2d(dwt_coef2,flag, nm ,final2);
|
||||
|
||||
// Removing Zeropadding
|
||||
|
||||
zero_remove(vec1,final2);
|
||||
double max2;
|
||||
maxval(final2,max2);
|
||||
|
||||
//Displaying Reconstructed Image
|
||||
|
||||
IplImage *dvImg2;
|
||||
CvSize dvSize2; // size of output image
|
||||
|
||||
dvSize2.width = final2[0].size();
|
||||
dvSize2.height = final2.size();
|
||||
|
||||
dvImg2 = cvCreateImage( dvSize2, 8, 1 );
|
||||
|
||||
for (int i = 0; i < dvSize2.height; i++ ) {
|
||||
for (int j = 0; j < dvSize2.width; j++ ){
|
||||
if ( final2[i][j] <= 0.0){
|
||||
final2[i][j] = 0.0;
|
||||
}
|
||||
((uchar*)(dvImg2->imageData + dvImg2->widthStep*i))[j] =
|
||||
(char) ((final2[i][j]/ max2)* 255) ;
|
||||
}
|
||||
}
|
||||
|
||||
cvNamedWindow( "2% Coeff Reconstructed Image", 1 ); // creation of a visualisation window
|
||||
cvShowImage( "2% Coeff Reconstructed Image", dvImg2 ); // image visualisation
|
||||
cvWaitKey();
|
||||
cvDestroyWindow("2% Coeff Reconstructed Image");
|
||||
|
||||
cout << thresh1 << " " << thresh2 << endl;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
This code decomposes a 512X512 grayscale image to 6 levels and uses a) only 10% coefficients and b) only 2% coefficients to reconstruct the image.
|
||||
|
||||
Input Image
|
||||
|
||||

|
||||
|
||||
DWT of Input Image
|
||||
|
||||

|
||||
|
||||
Image Approximation using only 10% coefficients
|
||||
|
||||

|
||||
|
||||
Image Aprroximation using only 2% coefficients.
|
||||
|
||||

|
||||
|
||||
|
||||
# Image Approximation using dwt\_2d\_sym #
|
||||
|
||||
[Sample Code](http://code.google.com/p/wavelet1d/source/browse/trunk/demo/imagedemo_sym2.cpp)
|
||||
|
||||
```
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <complex>
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
#include "wavelet.h"
|
||||
#include "cv.h"
|
||||
#include "highgui.h"
|
||||
#include "cxcore.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
|
||||
void findthresh(vector<double> &vector1, int N, double& t){
|
||||
sort(vector1.begin(), vector1.end(), greater<double>());
|
||||
t = vector1.at(N-1);
|
||||
}
|
||||
|
||||
void* maxval(vector<vector<double> > &arr, double &max){
|
||||
max = 0;
|
||||
for (unsigned int i =0; i < arr.size(); i++) {
|
||||
for (unsigned int j =0; j < arr[0].size(); j++) {
|
||||
if (max <= arr[i][j]){
|
||||
max = arr[i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* maxval1(vector<double> &arr, double &max){
|
||||
max = 0;
|
||||
for (unsigned int i =0; i < arr.size(); i++) {
|
||||
if (max <= arr[i]){
|
||||
max = arr[i];
|
||||
}
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int main() {
|
||||
IplImage* img = cvLoadImage("lena512.bmp");
|
||||
if (!img){
|
||||
cout << " Can't read Image. Try Different Format." << endl;
|
||||
exit(1);
|
||||
}
|
||||
int height, width;
|
||||
height = img->height;
|
||||
width = img->width;
|
||||
int nc = img->nChannels;
|
||||
// uchar* ptr2 =(uchar*) img->imageData;
|
||||
int pix_depth = img->depth;
|
||||
CvSize size;
|
||||
size.width =width;
|
||||
size.height=height;
|
||||
cout << "depth" << pix_depth << "Channels" << nc << endl;
|
||||
|
||||
|
||||
cvNamedWindow("Original Image", CV_WINDOW_AUTOSIZE);
|
||||
cvShowImage("Original Image", img);
|
||||
cvWaitKey();
|
||||
cvDestroyWindow("Original Image");
|
||||
cvSaveImage("orig.bmp",img);
|
||||
|
||||
|
||||
int rows =(int) height;
|
||||
int cols =(int) width;
|
||||
Mat matimg(img);
|
||||
|
||||
vector<vector<double> > vec1(rows, vector<double>(cols));
|
||||
|
||||
|
||||
int k =1;
|
||||
for (int i=0; i < rows; i++) {
|
||||
for (int j =0; j < cols; j++){
|
||||
unsigned char temp;
|
||||
temp = ((uchar*) matimg.data + i * matimg.step)[j * matimg.elemSize() + k ];
|
||||
vec1[i][j] = (double) temp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
string nm = "db2";
|
||||
vector<double> l1,h1,l2,h2;
|
||||
filtcoef(nm,l1,h1,l2,h2);
|
||||
// unsigned int lf=l1.size();
|
||||
// int rows_n =(int) (rows+ J*(lf-1));
|
||||
// int cols_n =(int) (cols + J * ( lf -1));
|
||||
|
||||
// Finding 2D DWT Transform of the image using symetric extension algorithm
|
||||
// Extension is set to 0 (eg., int e = 0)
|
||||
|
||||
vector<int> length;
|
||||
vector<double> output,flag;
|
||||
int J =6;
|
||||
int e=0;
|
||||
dwt_2d_sym(vec1,J,nm,output,flag,length,e);
|
||||
|
||||
double max;
|
||||
vector<int> length2;
|
||||
// This algorithm computes DWT of image of any given size. Together with convolution and
|
||||
// subsampling operations it is clear that subsampled images are of different length than
|
||||
// dyadic length images. In order to compute the "effective" size of DWT we do additional
|
||||
// calculations.
|
||||
dwt_output_dim_sym(length,length2,J);
|
||||
// length2 is gives the integer vector that contains the size of subimages that will
|
||||
// combine to form the displayed output image. The last two entries of length2 gives the
|
||||
// size of DWT ( rows_n by cols_n)
|
||||
|
||||
int siz = length2.size();
|
||||
int rows_n=length2[siz-2];
|
||||
int cols_n = length2[siz-1];
|
||||
|
||||
vector<vector< double> > dwtdisp(rows_n, vector<double>(cols_n));
|
||||
dispDWT(output,dwtdisp, length ,length2, J);
|
||||
|
||||
// dispDWT returns the 2D object dwtdisp which will be displayed using OPENCV's image
|
||||
// handling functions
|
||||
|
||||
vector<vector<double> > dwt_output= dwtdisp;
|
||||
|
||||
// Stroing the DWT coefficients in two different vectors that will be used to approximate
|
||||
// Image with two different sets of chosen coefficients.
|
||||
|
||||
vector<double> dwt_coef1;
|
||||
vector<double> dwt_coef2;
|
||||
|
||||
dwt_coef1 = output;
|
||||
dwt_coef2 = output;
|
||||
|
||||
maxval(dwt_output,max);// max value is needed to take care of overflow which happens because
|
||||
// of convolution operations performed on unsigned 8 bit images
|
||||
|
||||
//Displaying Scaled Image
|
||||
// Creating Image in OPENCV
|
||||
IplImage *cvImg; // image used for output
|
||||
CvSize imgSize; // size of output image
|
||||
|
||||
imgSize.width = cols_n;
|
||||
imgSize.height = rows_n;
|
||||
|
||||
cvImg = cvCreateImage( imgSize, 8, 1 );
|
||||
// dwt_hold is created to hold the dwt output as further operations need to be
|
||||
// carried out on dwt_output in order to display scaled images.
|
||||
vector<vector<double> > dwt_hold(rows_n, vector<double>( cols_n));
|
||||
dwt_hold = dwt_output;
|
||||
// Setting coefficients of created image to the scaled DWT output values
|
||||
for (int i = 0; i < imgSize.height; i++ ) {
|
||||
for (int j = 0; j < imgSize.width; j++ ){
|
||||
if ( dwt_output[i][j] <= 0.0){
|
||||
dwt_output[i][j] = 0.0;
|
||||
}
|
||||
if ( i <= (length2[0]) && j <= (length2[1]) ) {
|
||||
((uchar*)(cvImg->imageData + cvImg->widthStep*i))[j] =
|
||||
(char) ( (dwt_output[i][j] / max) * 255.0);
|
||||
} else {
|
||||
((uchar*)(cvImg->imageData + cvImg->widthStep*i))[j] =
|
||||
(char) (dwt_output[i][j]) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cvNamedWindow( "DWT Image", 1 ); // creation of a visualisation window
|
||||
cvShowImage( "DWT Image", cvImg ); // image visualisation
|
||||
cvWaitKey();
|
||||
cvDestroyWindow("DWT Image");
|
||||
cvSaveImage("dwt.bmp",cvImg);
|
||||
|
||||
// Case 1 : Only 10% of the largest coefficients are considered
|
||||
|
||||
// Output is the 1D DWT vector
|
||||
|
||||
int n_coef1= int (output.size()/ 10);
|
||||
cout << n_coef1 << endl;
|
||||
|
||||
// Finding Threshold Value corresponding to n_coef1
|
||||
|
||||
vector<double> temp1;
|
||||
cout << "size: " << (int) temp1.size() << "\n";
|
||||
cout << "capacity: " << (int) temp1.capacity() << "\n";
|
||||
cout << "max_size: " << (int) temp1.max_size() << "\n";
|
||||
for (unsigned int i =0; i < dwt_coef1.size(); i++) {
|
||||
double tempval = abs(dwt_coef1[i]);
|
||||
temp1.push_back(tempval);
|
||||
|
||||
}
|
||||
|
||||
double thresh1= 0.0;
|
||||
findthresh(temp1,n_coef1,thresh1);
|
||||
cout << "thresh" << thresh1 << endl;
|
||||
|
||||
ofstream temp("temp.txt");
|
||||
for (unsigned int i =0; i < temp1.size(); i++){
|
||||
temp << temp1[i] << " " ;
|
||||
}
|
||||
|
||||
// Reset coeffficients value depending on threshold value
|
||||
|
||||
|
||||
for (unsigned int i =0; i < dwt_coef1.size(); i++) {
|
||||
double temp = abs(dwt_coef1[i]);
|
||||
|
||||
if (temp < thresh1){
|
||||
dwt_coef1.at(i)= 0.0;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Finding IDWT
|
||||
|
||||
vector<vector<double> > idwt_output(rows, vector<double>(cols));
|
||||
|
||||
idwt_2d_sym( dwt_coef1,flag, nm, idwt_output,length);
|
||||
|
||||
double max1;
|
||||
maxval(idwt_output,max1);
|
||||
|
||||
//Displaying Reconstructed Image
|
||||
|
||||
IplImage *dvImg;
|
||||
CvSize dvSize; // size of output image
|
||||
|
||||
dvSize.width = idwt_output[0].size();
|
||||
dvSize.height = idwt_output.size();
|
||||
|
||||
cout << idwt_output.size() << idwt_output[0].size() << endl;
|
||||
dvImg = cvCreateImage( dvSize, 8, 1 );
|
||||
|
||||
for (int i = 0; i < dvSize.height; i++ ){
|
||||
for (int j = 0; j < dvSize.width; j++ ){
|
||||
if ( idwt_output[i][j] <= 0.0){
|
||||
idwt_output[i][j] = 0.0;
|
||||
}
|
||||
((uchar*)(dvImg->imageData + dvImg->widthStep*i))[j] =
|
||||
(char) ((idwt_output[i][j] / max1) * 255 ) ;
|
||||
}
|
||||
}
|
||||
|
||||
cvNamedWindow( "10% Coeff Reconstructed Image", 1 ); // creation of a visualisation window
|
||||
cvShowImage( "10% Coeff Reconstructed Image", dvImg ); // image visualisation
|
||||
cvWaitKey();
|
||||
cvDestroyWindow("10% Coeff Reconstructed Image");
|
||||
cvSaveImage("recon.bmp",dvImg);
|
||||
|
||||
|
||||
// Case 2 : Only 2% of the largest coefficients are considered
|
||||
|
||||
// Output is the 1D DWT vector
|
||||
|
||||
int n_coef2= int (output.size()/ 50);
|
||||
cout << n_coef2 << endl;
|
||||
|
||||
// Finding Threshold Value corresponding to n_coef1
|
||||
|
||||
vector<double> temp2;
|
||||
|
||||
for (unsigned int i =0; i < dwt_coef2.size(); i++) {
|
||||
double tempval = abs(dwt_coef2[i]);
|
||||
temp2.push_back(tempval);
|
||||
|
||||
}
|
||||
|
||||
double thresh2= 0.0;
|
||||
findthresh(temp2,n_coef2,thresh2);
|
||||
cout << "thresh" << thresh2 << endl;
|
||||
|
||||
|
||||
// Reset coeffficients value depending on threshold value
|
||||
|
||||
|
||||
for (unsigned int i =0; i < dwt_coef2.size(); i++) {
|
||||
double temp = abs(dwt_coef2[i]);
|
||||
|
||||
if (temp < thresh2){
|
||||
dwt_coef2.at(i)= 0.0;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Finding IDWT
|
||||
|
||||
vector<vector<double> > idwt_output2(rows, vector<double>(cols));
|
||||
|
||||
idwt_2d_sym( dwt_coef2,flag, nm, idwt_output2,length);
|
||||
|
||||
double max2;
|
||||
maxval(idwt_output2,max2);
|
||||
|
||||
|
||||
|
||||
//Displaying Reconstructed Image
|
||||
|
||||
IplImage *dvImg2;
|
||||
CvSize dvSize2; // size of output image
|
||||
|
||||
dvSize2.width = idwt_output2[0].size();
|
||||
dvSize2.height = idwt_output2.size();
|
||||
|
||||
cout << idwt_output2.size() << idwt_output2[0].size() << endl;
|
||||
dvImg2 = cvCreateImage( dvSize2, 8, 1 );
|
||||
|
||||
for (int i = 0; i < dvSize2.height; i++ ) {
|
||||
for (int j = 0; j < dvSize2.width; j++ ) {
|
||||
if ( idwt_output2[i][j] <= 0.0){
|
||||
idwt_output2[i][j] = 0.0;
|
||||
}
|
||||
((uchar*)(dvImg2->imageData + dvImg2->widthStep*i))[j] =
|
||||
(char) ((idwt_output2[i][j]/ max2) * 255 ) ;
|
||||
}
|
||||
}
|
||||
|
||||
cvNamedWindow( "2% Coeff Reconstructed Image", 1 ); // creation of a visualisation window
|
||||
cvShowImage( "2% Coeff Reconstructed Image", dvImg2 ); // image visualisation
|
||||
cvWaitKey();
|
||||
cvDestroyWindow("2% Coeff Reconstructed Image");
|
||||
cvSaveImage("recon2.bmp",dvImg2);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
Same image is used as above. The decomposition level and wavelet family are same as well.
|
||||
|
||||
DWT of the Input Image
|
||||
|
||||

|
||||
|
||||
Image Approximation using only 10% coefficients
|
||||
|
||||

|
||||
|
||||
Image Aprroximation using only 2% coefficients.
|
||||
|
||||

|
421
2DDWTdemo.md
Normal file
421
2DDWTdemo.md
Normal file
@ -0,0 +1,421 @@
|
||||
# 2D DWT Demo using dwt\_2d #
|
||||
|
||||
_Note- I am using OPENCV to handle image I/O and other basic functionalities so most of the code will be different if you are using different libraries or software. Even if you are using OPENCV, you may not want to use the suboptimal algorithm I have used to tackle the UINT8 image coefficient overflow issues. This isn't something I have paid much attention to and this code is just to demonstrate DWT/IDWT functionality of the library._
|
||||
|
||||
[Sample Code](http://code.google.com/p/wavelet1d/source/browse/trunk/demo/imagedemo1.cpp) to compute DWT/IDWT of a 512X512 grayscale image is as following
|
||||
|
||||
```
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
#include "cv.h"
|
||||
#include "highgui.h"
|
||||
#include "cxcore.h"
|
||||
#include "wavelet.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
|
||||
void* maxval(vector<vector<double> > &arr, double &max){
|
||||
max = 0;
|
||||
for (unsigned int i =0; i < arr.size(); i++) {
|
||||
for (unsigned int j =0; j < arr[0].size(); j++) {
|
||||
if (max <= arr[i][j]){
|
||||
max = arr[i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* minval(vector<vector<double> > &arr, double &min){
|
||||
min = 10000;
|
||||
for (unsigned int i =0; i < arr.size(); i++) {
|
||||
for (unsigned int j =0; j < arr[0].size(); j++) {
|
||||
if (min >= arr[i][j]){
|
||||
min = arr[i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main() {
|
||||
IplImage* img = cvLoadImage("lena512.bmp");
|
||||
if (!img){
|
||||
cout << " Can't read Image. Try Different Format." << endl;
|
||||
exit(1);
|
||||
}
|
||||
int height, width;
|
||||
height = img->height;
|
||||
width = img->width;
|
||||
int nc = img->nChannels;
|
||||
// uchar* ptr2 =(uchar*) img->imageData;
|
||||
int pix_depth = img->depth;
|
||||
CvSize size;
|
||||
size.width =width;
|
||||
size.height=height;
|
||||
cout << "depth" << pix_depth << "Channels" << nc << endl;
|
||||
|
||||
|
||||
cvNamedWindow("Original Image", CV_WINDOW_AUTOSIZE);
|
||||
cvShowImage("Original Image", img);
|
||||
cvWaitKey();
|
||||
cvDestroyWindow("Original Image");
|
||||
cvSaveImage("orig.bmp",img);
|
||||
|
||||
|
||||
int rows =(int) height;
|
||||
int cols =(int) width;
|
||||
Mat matimg(img);
|
||||
|
||||
vector<vector<double> > vec1(rows, vector<double>(cols));
|
||||
|
||||
|
||||
int k =1;
|
||||
for (int i=0; i < rows; i++) {
|
||||
for (int j =0; j < cols; j++){
|
||||
unsigned char temp;
|
||||
temp = ((uchar*) matimg.data + i * matimg.step)[j * matimg.elemSize() + k ];
|
||||
vec1[i][j] = (double) temp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int rr1,cc1;
|
||||
string nm = "db4";
|
||||
// Finding DWT output dimensions as the DWT output is zeropadded
|
||||
dwt_output_dim(vec1, rr1, cc1 );
|
||||
int J = 2;
|
||||
vector<double> flag;
|
||||
vector<vector<double> > dwt_output(rr1, vector<double>(cc1));
|
||||
cout << rr1 << cc1 << "size of op" << endl;
|
||||
// Computing 2d DWT ( vec1 is the signal while dwt_output is the DWT output)
|
||||
dwt_2d(vec1, J, nm, dwt_output,flag );
|
||||
|
||||
cout << "dwt size" << dwt_output.size() << dwt_output[0].size() << endl;
|
||||
|
||||
double max,min;
|
||||
|
||||
maxval(dwt_output,max);
|
||||
minval(dwt_output,min);
|
||||
cout << "maxval" << max << " minval" << min << endl;
|
||||
|
||||
//Displaying Scaled Image
|
||||
// Creating Image in OPENCV
|
||||
IplImage *cvImg; // image used for output
|
||||
CvSize imgSize; // size of output image
|
||||
|
||||
imgSize.width = cc1;
|
||||
imgSize.height = rr1;
|
||||
|
||||
cvImg = cvCreateImage( imgSize, 8, 1 );
|
||||
// dwt_hold is created to hold the dwt output as further operations need to be
|
||||
// carried out on dwt_output in order to display scaled images.
|
||||
vector<vector<double> > dwt_hold(rr1, vector<double>(cc1));
|
||||
dwt_hold = dwt_output;
|
||||
|
||||
// Setting coefficients of created image to the scaled DWT output values
|
||||
for (int i = 0; i < imgSize.height; i++ ) {
|
||||
for (int j = 0; j < imgSize.width; j++ ){
|
||||
if ( dwt_output[i][j] <= 0.0){
|
||||
dwt_output[i][j] = 0.0;
|
||||
}
|
||||
if ( i <= (imgSize.height/pow(2.0,double(J))) && j <= (imgSize.width/pow(2.0,double(J))) ) {
|
||||
((uchar*)(cvImg->imageData + cvImg->widthStep*i))[j] =
|
||||
(char) ( (dwt_output[i][j] / max) * 255.0);
|
||||
} else {
|
||||
((uchar*)(cvImg->imageData + cvImg->widthStep*i))[j] =
|
||||
(char) (dwt_output[i][j]) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cvNamedWindow( "DWT Image", 1 ); // creation of a visualisation window
|
||||
cvShowImage( "DWT Image", cvImg ); // image visualisation
|
||||
cvWaitKey();
|
||||
cvDestroyWindow("DWT Image");
|
||||
cvSaveImage("dwt.bmp",cvImg);
|
||||
// Finding IDWT
|
||||
vector<vector<double> > final(rr1, vector<double>(cc1));
|
||||
idwt_2d(dwt_hold,flag, nm ,final);
|
||||
|
||||
// Removing Zeropadding
|
||||
|
||||
zero_remove(vec1,final);
|
||||
|
||||
//Displaying Reconstructed Image
|
||||
|
||||
IplImage *dvImg;
|
||||
CvSize dvSize; // size of output image
|
||||
|
||||
dvSize.width = final[0].size();
|
||||
dvSize.height = final.size();
|
||||
|
||||
dvImg = cvCreateImage( dvSize, 8, 1 );
|
||||
|
||||
for (int i = 0; i < dvSize.height; i++ )
|
||||
for (int j = 0; j < dvSize.width; j++ )
|
||||
((uchar*)(dvImg->imageData + dvImg->widthStep*i))[j] =
|
||||
(char) (final[i][j]) ;
|
||||
|
||||
cvNamedWindow( "Reconstructed Image", 1 ); // creation of a visualisation window
|
||||
cvShowImage( "Reconstructed Image", dvImg ); // image visualisation
|
||||
cvWaitKey();
|
||||
cvDestroyWindow("Reconstructed Image");
|
||||
cvSaveImage("recon.bmp",dvImg);
|
||||
ofstream diff("diff.dat");
|
||||
for (unsigned int i=0; i < final.size(); i++) {
|
||||
for (unsigned int j = 0; j < final[0].size(); j++) {
|
||||
diff << final[i][j]-vec1[i][j] << " " ;
|
||||
}
|
||||
diff << endl;
|
||||
}
|
||||
ofstream recon("recon.dat");
|
||||
for (unsigned int i=0; i < final.size(); i++) {
|
||||
for (unsigned int j = 0; j < final[0].size(); j++) {
|
||||
recon << (int)final[i][j] << " " ;
|
||||
}
|
||||
recon << endl;
|
||||
}
|
||||
ofstream orig("orig.dat");
|
||||
for (unsigned int i=0; i < vec1.size(); i++) {
|
||||
for (unsigned int j = 0; j < vec1[0].size(); j++) {
|
||||
orig << (int)vec1[i][j] << " " ;
|
||||
}
|
||||
orig << endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
Input Image in this example is 512X512 "Lena" grayscale image.
|
||||
|
||||

|
||||
|
||||
Two Level DWT of this image is computed with Daubechies' db4 wavelet.
|
||||
|
||||

|
||||
|
||||
Reconstructed Image is computed using idwt\_2d function.
|
||||
|
||||

|
||||
|
||||
_Additional Note About dwt\_2d- This implementation is a NXN input and NXN output system designed to work with dyadic lengths N. If the image dimensions are not dyadic, dwt\_2d will zeropad to make it NXN and you will end up with lots of zeros depending on the original size. The algorithm below (dwt\_2d\_sym) is designed to handle any image size but there are redundancies in the DWT stage as it is not a NXN I/O system._
|
||||
|
||||
# 2D DWT Demo using dwt\_2d\_sym #
|
||||
|
||||
[Sample Code](http://code.google.com/p/wavelet1d/source/browse/trunk/demo/imagedemo_sym.cpp) to compute DWT/IDWT using symmetric extension dwt\_2d\_sym is as follows
|
||||
|
||||
```
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <complex>
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
#include "wavelet.h"
|
||||
#include "cv.h"
|
||||
#include "highgui.h"
|
||||
#include "cxcore.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
|
||||
void* maxval(vector<vector<double> > &arr, double &max){
|
||||
max = 0;
|
||||
for (unsigned int i =0; i < arr.size(); i++) {
|
||||
for (unsigned int j =0; j < arr[0].size(); j++) {
|
||||
if (max <= arr[i][j]){
|
||||
max = arr[i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* maxval1(vector<double> &arr, double &max){
|
||||
max = 0;
|
||||
for (unsigned int i =0; i < arr.size(); i++) {
|
||||
if (max <= arr[i]){
|
||||
max = arr[i];
|
||||
}
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int main() {
|
||||
IplImage* img = cvLoadImage("Fig10.04(a).jpg");
|
||||
if (!img){
|
||||
cout << " Can't read Image. Try Different Format." << endl;
|
||||
exit(1);
|
||||
}
|
||||
int height, width;
|
||||
height = img->height;
|
||||
width = img->width;
|
||||
int nc = img->nChannels;
|
||||
// uchar* ptr2 =(uchar*) img->imageData;
|
||||
int pix_depth = img->depth;
|
||||
CvSize size;
|
||||
size.width =width;
|
||||
size.height=height;
|
||||
cout << "depth" << pix_depth << "Channels" << nc << endl;
|
||||
|
||||
|
||||
cvNamedWindow("Original Image", CV_WINDOW_AUTOSIZE);
|
||||
cvShowImage("Original Image", img);
|
||||
cvWaitKey();
|
||||
cvDestroyWindow("Original Image");
|
||||
cvSaveImage("orig.bmp",img);
|
||||
|
||||
|
||||
int rows =(int) height;
|
||||
int cols =(int) width;
|
||||
Mat matimg(img);
|
||||
|
||||
vector<vector<double> > vec1(rows, vector<double>(cols));
|
||||
|
||||
|
||||
int k =1;
|
||||
for (int i=0; i < rows; i++) {
|
||||
for (int j =0; j < cols; j++){
|
||||
unsigned char temp;
|
||||
temp = ((uchar*) matimg.data + i * matimg.step)[j * matimg.elemSize() + k ];
|
||||
vec1[i][j] = (double) temp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
string nm = "db3";
|
||||
vector<double> l1,h1,l2,h2;
|
||||
filtcoef(nm,l1,h1,l2,h2);
|
||||
// unsigned int lf=l1.size();
|
||||
// int rows_n =(int) (rows+ J*(lf-1));
|
||||
// int cols_n =(int) (cols + J * ( lf -1));
|
||||
|
||||
// Finding 2D DWT Transform of the image using symetric extension algorithm
|
||||
// Extension is set to 3 (eg., int e = 3)
|
||||
|
||||
vector<int> length;
|
||||
vector<double> output,flag;
|
||||
int J =3;
|
||||
int e=3;
|
||||
dwt_2d_sym(vec1,J,nm,output,flag,length,e);
|
||||
|
||||
double max;
|
||||
vector<int> length2;
|
||||
// This algorithm computes DWT of image of any given size. Together with convolution and
|
||||
// subsampling operations it is clear that subsampled images are of different length than
|
||||
// dyadic length images. In order to compute the "effective" size of DWT we do additional
|
||||
// calculations.
|
||||
dwt_output_dim_sym(length,length2,J);
|
||||
// length2 is gives the integer vector that contains the size of subimages that will
|
||||
// combine to form the displayed output image. The last two entries of length2 gives the
|
||||
// size of DWT ( rows_n by cols_n)
|
||||
|
||||
int siz = length2.size();
|
||||
int rows_n=length2[siz-2];
|
||||
int cols_n = length2[siz-1];
|
||||
|
||||
vector<vector< double> > dwtdisp(rows_n, vector<double>(cols_n));
|
||||
dispDWT(output,dwtdisp, length ,length2, J);
|
||||
|
||||
// dispDWT returns the 2D object dwtdisp which will be displayed using OPENCV's image
|
||||
// handling functions
|
||||
|
||||
vector<vector<double> > dwt_output= dwtdisp;
|
||||
|
||||
maxval(dwt_output,max);// max value is needed to take care of overflow which happens because
|
||||
// of convolution operations performed on unsigned 8 bit images
|
||||
|
||||
//Displaying Scaled Image
|
||||
// Creating Image in OPENCV
|
||||
IplImage *cvImg; // image used for output
|
||||
CvSize imgSize; // size of output image
|
||||
|
||||
imgSize.width = cols_n;
|
||||
imgSize.height = rows_n;
|
||||
|
||||
cvImg = cvCreateImage( imgSize, 8, 1 );
|
||||
// dwt_hold is created to hold the dwt output as further operations need to be
|
||||
// carried out on dwt_output in order to display scaled images.
|
||||
vector<vector<double> > dwt_hold(rows_n, vector<double>( cols_n));
|
||||
dwt_hold = dwt_output;
|
||||
// Setting coefficients of created image to the scaled DWT output values
|
||||
for (int i = 0; i < imgSize.height; i++ ) {
|
||||
for (int j = 0; j < imgSize.width; j++ ){
|
||||
if ( dwt_output[i][j] <= 0.0){
|
||||
dwt_output[i][j] = 0.0;
|
||||
}
|
||||
if ( i <= (length2[0]) && j <= (length2[1]) ) {
|
||||
((uchar*)(cvImg->imageData + cvImg->widthStep*i))[j] =
|
||||
(char) ( (dwt_output[i][j] / max) * 255.0);
|
||||
} else {
|
||||
((uchar*)(cvImg->imageData + cvImg->widthStep*i))[j] =
|
||||
(char) (dwt_output[i][j]) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cvNamedWindow( "DWT Image", 1 ); // creation of a visualisation window
|
||||
cvShowImage( "DWT Image", cvImg ); // image visualisation
|
||||
cvWaitKey();
|
||||
cvDestroyWindow("DWT Image");
|
||||
cvSaveImage("dwt.bmp",cvImg);
|
||||
|
||||
// Finding IDWT
|
||||
|
||||
vector<vector<double> > idwt_output(rows, vector<double>(cols));
|
||||
|
||||
idwt_2d_sym( output,flag, nm, idwt_output,length);
|
||||
|
||||
|
||||
|
||||
//Displaying Reconstructed Image
|
||||
|
||||
IplImage *dvImg;
|
||||
CvSize dvSize; // size of output image
|
||||
|
||||
dvSize.width = idwt_output[0].size();
|
||||
dvSize.height = idwt_output.size();
|
||||
|
||||
cout << idwt_output.size() << idwt_output[0].size() << endl;
|
||||
dvImg = cvCreateImage( dvSize, 8, 1 );
|
||||
|
||||
for (int i = 0; i < dvSize.height; i++ )
|
||||
for (int j = 0; j < dvSize.width; j++ )
|
||||
((uchar*)(dvImg->imageData + dvImg->widthStep*i))[j] =
|
||||
(char) (idwt_output[i][j]) ;
|
||||
|
||||
cvNamedWindow( "Reconstructed Image", 1 ); // creation of a visualisation window
|
||||
cvShowImage( "Reconstructed Image", dvImg ); // image visualisation
|
||||
cvWaitKey();
|
||||
cvDestroyWindow("Reconstructed Image");
|
||||
cvSaveImage("recon.bmp",dvImg);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
Input Image is a 486X486 grayscale image taken from [Image Processing Place Database](http://www.imageprocessingplace.com/root_files_V3/image_databases.htm).
|
||||
|
||||

|
||||
|
||||
3-Level DWT is computed using db4 wavelet.
|
||||
|
||||

|
||||
|
||||
Perfect Reconstruction is achieved using idwt\_2d\_sym function.
|
||||
|
||||

|
184
2DSWTdemo.md
Normal file
184
2DSWTdemo.md
Normal file
@ -0,0 +1,184 @@
|
||||
# 2D Stationary Wavelet Transform using swt\_2d #
|
||||
|
||||
[Sample Code](http://code.google.com/p/wavelet1d/source/browse/trunk/demo/swt2Ddemo.cpp)
|
||||
|
||||
```
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <complex>
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
#include "wavelet.h"
|
||||
#include "cv.h"
|
||||
#include "highgui.h"
|
||||
#include "cxcore.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
|
||||
void* maxval(vector<vector<double> > &arr, double &max){
|
||||
max = 0;
|
||||
for (unsigned int i =0; i < arr.size(); i++) {
|
||||
for (unsigned int j =0; j < arr[0].size(); j++) {
|
||||
if (max <= arr[i][j]){
|
||||
max = arr[i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main() {
|
||||
IplImage* img = cvLoadImage("cameraman.bmp");
|
||||
if (!img){
|
||||
cout << " Can't read Image. Try Different Format." << endl;
|
||||
exit(1);
|
||||
}
|
||||
int height, width;
|
||||
height = img->height;
|
||||
width = img->width;
|
||||
int nc = img->nChannels;
|
||||
// uchar* ptr2 =(uchar*) img->imageData;
|
||||
int pix_depth = img->depth;
|
||||
CvSize size;
|
||||
size.width =width;
|
||||
size.height=height;
|
||||
cout << "depth" << pix_depth << "Channels" << nc << endl;
|
||||
|
||||
|
||||
cvNamedWindow("Original Image", CV_WINDOW_AUTOSIZE);
|
||||
cvShowImage("Original Image", img);
|
||||
cvWaitKey();
|
||||
cvDestroyWindow("Original Image");
|
||||
cvSaveImage("orig.bmp",img);
|
||||
|
||||
|
||||
int rows =(int) height;
|
||||
int cols =(int) width;
|
||||
Mat matimg(img);
|
||||
|
||||
vector<vector<double> > vec1(rows, vector<double>(cols));
|
||||
|
||||
|
||||
int k =1;
|
||||
for (int i=0; i < rows; i++) {
|
||||
for (int j =0; j < cols; j++){
|
||||
unsigned char temp;
|
||||
temp = ((uchar*) matimg.data + i * matimg.step)[j * matimg.elemSize() + k ];
|
||||
vec1[i][j] = (double) temp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
string nm = "db2";
|
||||
// vector<double> l1,h1,l2,h2;
|
||||
// filtcoef(nm,l1,h1,l2,h2);
|
||||
|
||||
|
||||
vector<double> output;
|
||||
int J =3;
|
||||
swt_2d(vec1,J,nm,output);
|
||||
cout << "OUTPUT size" << output.size() << endl;
|
||||
cout << "LOOP OK" << endl;
|
||||
|
||||
int row,col;
|
||||
dwt_output_dim(vec1, row, col );
|
||||
|
||||
// Extract and Display Low Pass Image at the Jth stage
|
||||
|
||||
vector<vector<double> > blur(row,vector<double>(col));
|
||||
|
||||
for (int i=0;i < row; i++){
|
||||
for (int j=0; j < col;j++){
|
||||
double temp = output[i*col + j];
|
||||
blur[i][j]= temp;
|
||||
}
|
||||
}
|
||||
|
||||
double max;
|
||||
maxval(blur,max);
|
||||
|
||||
// Creating Image in OPENCV
|
||||
IplImage *cvImg; // image used for output
|
||||
CvSize imgSize; // size of output image
|
||||
|
||||
imgSize.width = col;
|
||||
imgSize.height = row;
|
||||
|
||||
cvImg = cvCreateImage( imgSize, 8, 1 );
|
||||
|
||||
for (int i = 0; i < imgSize.height; i++ ) {
|
||||
for (int j = 0; j < imgSize.width; j++ ){
|
||||
if ( blur[i][j] <= 0.0){
|
||||
blur[i][j] = 0.0;
|
||||
}
|
||||
|
||||
((uchar*)(cvImg->imageData + cvImg->widthStep*i))[j] =
|
||||
(char) ( (blur[i][j] / max) * 255.0);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
cvNamedWindow( "Low Pass Image", 1 ); // creation of a visualisation window
|
||||
cvShowImage( "Low Pass Image", cvImg ); // image visualisation
|
||||
cvWaitKey();
|
||||
cvDestroyWindow("Low Pass Image");
|
||||
|
||||
// Displaying BandPass Images
|
||||
|
||||
vector<vector<double> > detail(3*row,vector<double>(J * col));
|
||||
|
||||
for (int k=0; k < J; k++) {
|
||||
for (int i=0; i < 3*row; i++) {
|
||||
for(int j=0+ k*col; j < (k+1)*col; j++) {
|
||||
double temp = output[(3*k+1)*row*col+ i * col +j - k*col];
|
||||
detail[i][j]= temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
IplImage *dvImg; // image used for output
|
||||
CvSize imgSz; // size of output image
|
||||
|
||||
imgSz.width = J*col;
|
||||
imgSz.height = 3*row;
|
||||
|
||||
dvImg = cvCreateImage( imgSz, 8, 1 );
|
||||
|
||||
for (int i = 0; i < imgSz.height; i++ ) {
|
||||
for (int j = 0; j < imgSz.width; j++ ){
|
||||
if ( detail[i][j] <= 0.0){
|
||||
detail[i][j] = 0.0;
|
||||
}
|
||||
|
||||
((uchar*)(dvImg->imageData + dvImg->widthStep*i))[j] =
|
||||
(char) detail[i][j];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
cvNamedWindow( "Band Pass Image", 1 ); // creation of a visualisation window
|
||||
cvShowImage( "Band Pass Image", dvImg ); // image visualisation
|
||||
cvWaitKey();
|
||||
cvDestroyWindow("Band Pass Image");
|
||||
cvSaveImage("detail.bmp",dvImg);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
Stationary Wavelet Transform is a redundant transform as will be seen below. The image used is 256X256 grayscale "cameraman" image.
|
||||
|
||||

|
||||
|
||||
Three level Stationary Wavelet Transform is computed using db2 wavelet. Approximation coefficients are stored only for the final (J=3) stage while the three detail coefficients( Horizontal, Vertical and Diagonal) are stored for each value. All 10 sets of coefficients are 256X256.
|
||||
|
||||
Approximation Coefficient
|
||||
|
||||

|
||||
|
||||
Detail Coefficients at Levels 3,2,1. Coefficients are arranged Horizontal,Vertical and Diagonal from top to bottom.
|
||||
|
||||

|
516
Functions.md
Normal file
516
Functions.md
Normal file
@ -0,0 +1,516 @@
|
||||
_Note : Only first ten functions are available in the wave1d library and convfft is also not included. It is my recommendation that you use the latest library(wavelet.lib and libwavelet.a in wavelet-03.rar) even for 1D operations as 1D implementation is faster and more accurate._
|
||||
|
||||
# 1D Functions #
|
||||
|
||||
### 1. J-Level Discrete Wavelet Transform ###
|
||||
**`void* dwt(vector<double> &, int ,string , vector<double> &, vector<double> &)`**
|
||||
|
||||
Example Usage : **dwt(sig, J, nm, dwt\_output,flag )**
|
||||
|
||||
where,
|
||||
|
||||
**sig :** is the input signal . It is a `vector<double>` object.
|
||||
|
||||
**J :** Number of DWT Levels. Integer.
|
||||
|
||||
**nm :** Name of Wavelet. See function filtcoef for more information. String.
|
||||
|
||||
**dwt\_ouput:** is a `vector<double>` object that will return the DWT output.
|
||||
|
||||
**flag:** is a vector that contains two `vector<double>` values.
|
||||
|
||||
`flag[0]` - contains the number of zeros if the signal is zeropadded.
|
||||
|
||||
`flag[1]`- contains the number of decomposition levels. (J)
|
||||
|
||||
flag is used by IDWT to help process the DWT output.
|
||||
|
||||
Additional Outputs : In addition to above, the function also generates .txt and .dat files.
|
||||
|
||||
GNUPLOT ready .dat files
|
||||
|
||||
**gnusig.dat :** contains signal data
|
||||
|
||||
**gnufilt.dat:** Contains filters data.[Four filters are arranged columnwise in the file](All.md)
|
||||
|
||||
**gnuout.dat :** Contains DWT coefficients. It stores approximation and detail coefficients columnwise in alternating fashion. For example, three level of approximation and detail coefficients will result in gnuout.dat having 7 columns. First column is index followed by alternating approximation and detail columns.
|
||||
|
||||
Text Files : These two files are used by the code to generate gnuout.dat file.
|
||||
|
||||
**appx.txt :** Values of Approximation Coefficients from each stage. Values are appended after each stage.
|
||||
|
||||
**det.txt :** Values of Detail Coefficients after each stage. Values are likewise appended after each stage.
|
||||
|
||||
**dwtout.txt:** Stores the DWT ouput in text format. It contains Approximation coefficients at Jth level, followed by detail coefficients at Jthe, J-1,.... level 1.
|
||||
|
||||
**flag.txt:** Contains values of flags in text format.
|
||||
|
||||
### 2. 1-Level Discrete Wavelet Transform ###
|
||||
|
||||
**`void* dwt1(string, vector<double> &, vector<double> &, vector<double> &)`**
|
||||
|
||||
Example Usage: **dwt1(nm,sig, appx\_sig, det\_sig)**
|
||||
|
||||
**nm :** Wavelet Name. String
|
||||
|
||||
**sig :** Input Signal. `Vector<double>` Object.
|
||||
|
||||
**appx\_sig:** Approximation Coefficients. `Vector<double>` object.
|
||||
|
||||
**det\_sig:** Detail Coefficients. `Vector<double>` object.
|
||||
|
||||
Same Functionality can be achieved by setting J=1 in the dwt function but dwt1 directly outputs detail and approximation coefficients for one level of decomposition. This function will not generate any of GNUPLOT files but may be preferable in any number of scenarios.
|
||||
|
||||
### 3. Dyadic Zero-Padding ###
|
||||
|
||||
**`void* dyadic_zpad_1d(vector<double> &)`**
|
||||
|
||||
Example Usage: **dyadic\_zpad\_1d(sig)**
|
||||
|
||||
It zeropads signal sig such that its length is now dyadic. For example a signal with length 195 will be zeropadded to 256.
|
||||
|
||||
### 4. Convolution ###
|
||||
|
||||
Recommended -- **`double convfft(vector<double> &, vector<double> &, vector<double> &)`**
|
||||
|
||||
**-or-**
|
||||
|
||||
**`double convol(vector<double> &, vector<double> &, vector<double> &)`**
|
||||
|
||||
Example Usage: **convfft(signal,lpd,cA\_undec)**
|
||||
|
||||
where, signal and lpd are two inputs that are convolved and the convolution output is stored in cA\_undec. All three are `vector<double>` objects.
|
||||
|
||||
Important- **convfft** will not modify the value of signal while convol will. I have not corrected this as **convfft** is the faster, better implementation and should be used instead of **convol**.
|
||||
|
||||
### 5. Filter Coefficients ###
|
||||
|
||||
**`int filtcoef(string , vector<double> &, vector<double> &, vector<double> &, vector<double> &)`**
|
||||
|
||||
Example Usage: **filtcoef(nm,lpd,hpd,lpr,hpr)**
|
||||
|
||||
**nm:** Wavelet name.
|
||||
|
||||
**lpd:** Low Pass Decomposition Filter Coefficients.
|
||||
|
||||
**hpd:** High Pass Decomposition Filter Coefficients.
|
||||
|
||||
**lpr:** Low Pass Reconstruction Filter Coefficients.
|
||||
|
||||
**hpr:** High Pass Reconstruction Filter Coefficients.
|
||||
|
||||
All filters are `vector<double>` objects and can be obtained by specifying the wavelet name. Currently, following Wavelets are available:
|
||||
|
||||
Daubechies : db1,db2,.., ,db15
|
||||
|
||||
Biorthogonal: bior1.1 ,bior1.3 ,bior1.5 ,bior2.2 ,bior2.4 ,bior2.6 ,bior2.8 ,bior3.1 ,bior3.3 ,bior3.5 ,bior3.7 ,bior3.9 ,bior4.4 ,bior5.5 ,bior6.8
|
||||
|
||||
Coiflets: coif1,coif2,coif3,coif4,coif5
|
||||
|
||||
### 6. Downsampling ###
|
||||
|
||||
**`void downsamp(vector<double> &, int , vector<double> &)`**
|
||||
|
||||
Example Usage : **downsamp(cA\_undec, D, cA)**
|
||||
|
||||
**cA\_undec:** Signal to be downsampled. `Vector<double>`
|
||||
|
||||
**D :** Downsampling Factor. Integer
|
||||
|
||||
**cA:** Downsampled Signal. `Vector<double>`
|
||||
|
||||
### 7. Upsampling ###
|
||||
|
||||
**`void upsamp(vector<double> &, int, vector<double> &)`**
|
||||
|
||||
Example Usage : **upsamp(cA, U, cA\_up)**
|
||||
|
||||
**cA:** Signal to be upsampled. `Vector<double>`
|
||||
|
||||
**U :** Upsampling Factor. Integer
|
||||
|
||||
**cA\_up:** Upsampled Signal. `Vector<double>`
|
||||
|
||||
### 8. J-Level Inverse Discrete Wavelet Transform ###
|
||||
|
||||
**`void* idwt(vector<double> &,vector<double> &, string , vector<double> &)`**
|
||||
|
||||
Example Usage: **idwt(dwt\_output, flag,nm,output)**
|
||||
|
||||
**dwt\_output:** Output of DWT which serves as Input to the IDWT. `vector<double>`
|
||||
|
||||
**flag:** Contains values of J and zeropadding. `vector<double>`
|
||||
|
||||
**nm :** Wavelet name. String
|
||||
|
||||
**output:** Reconstructed IDWT Output. `vector<double>`
|
||||
|
||||
Additional .dat output
|
||||
|
||||
**gnurecon.dat :** GNUPLOT ready reconstructed signal.
|
||||
|
||||
### 9. 1-Level Inverse Discrete Wavelet Transform ###
|
||||
|
||||
**`void* idwt1(string wname, vector<double> &, vector<double> &, vector<double> &)`**
|
||||
|
||||
Example Usage : **idwt1(nm,idwt\_output, app,detail)**
|
||||
|
||||
**nm:** Wavelet Name.
|
||||
|
||||
**idwt\_output:** Outputs IDWT.
|
||||
|
||||
**app:** Approximation Coefficients.
|
||||
|
||||
**detail:** Detail Coefficients.
|
||||
|
||||
### 10. GNUDWTPLOT ###
|
||||
|
||||
**`void* gnudwtplot(int)`**
|
||||
|
||||
Example Usage: **gnudwtplot(J)**
|
||||
|
||||
Generates GNUPLOT script gnudwt.gnu.txt that contains plots of signals, filters and wavelet coefficients. it works if it is called following DWT and IDWT operations. To draw the plots, just load the script in gnuplot. See wavedemo1.cpp for more details.
|
||||
|
||||
|
||||
|
||||
# 1D Symmetric Extension DWT Functions #
|
||||
|
||||
### 11. J-Level Symmetric Extension DWT ###
|
||||
|
||||
**`void* dwt_sym(vector<double> &, int ,string , vector<double> &,vector<double> &,vector<int> &, int );`**
|
||||
|
||||
Example Usage: **dwt\_sym (signal, J,nm, dwt\_output, flag,length, e)**
|
||||
|
||||
Same as **dwt** function except it contains two more arguments and the output is a 1D vector. **length** is an integer vector which contains lengths of approximation and detail coefficients. **e** is the length of symmetric extension in each direction. **dwt\_output** stores coefficients in following format:
|
||||
**`[A(J) D(J) D(J-1) ..... D(1)]`**
|
||||
|
||||
> where **A(J)** is the approximation coefficient vector at the Jth level while **D(n)** are the detail coefficient vectors at the nth level. **length** contains the lengths of corresponding vectors. Last entry of the **length** vector is the length of the original signal.
|
||||
|
||||
### 12. J-Level Symmetric Extension IDWT ###
|
||||
|
||||
**`void* idwt_sym(vector<double> &,vector<double> &, string,vector<double> &, vector<int> &);`**
|
||||
|
||||
Example Usage: **idwt\_sym(dwtop,flag,nm,idwt\_output,length)**
|
||||
|
||||
**idwt\_sym** is identical to **idwt** above except that it contains one more argument in lengths of the coefficients vector **length**. It is the same vector described in **11**.
|
||||
|
||||
### 13. Symmetric Extension ###
|
||||
|
||||
**`void* symm_ext(vector<double> &, int )`**
|
||||
|
||||
Example Usage: **symm\_ext(signal,e)**
|
||||
|
||||
**symm\_ext** symmetrically extends the signal by length e in either direction.
|
||||
|
||||
# 1D Stationary Wavelet Transform #
|
||||
|
||||
### 14. J-Level Stationary Wavelet Transform ###
|
||||
|
||||
**`void* swt(vector<double> &, int , string , vector<double> &, int &) `**
|
||||
|
||||
Example Usage: **swt(sig,J,nm,swt\_output,length)**
|
||||
|
||||
This function works on dyadic length signal. All the coefficients are of equal lengths and that value is stored in **length**. **swt\_output** stores value in the same format as **11** - Approximation coefficient vector at level J is stored at the beginning of the **swt\_output** vector followed by detail coefficients vectors at levels J, J-1,...., 1. Additionally, ALL coefficient vectors(including redundant approximation vectors) are stored in **gnuout.dat** file. See **gnuswtplot** for more details.
|
||||
|
||||
### 15. J-Level Inverse Stationary Wavelet Transform ###
|
||||
|
||||
**`void* iswt(vector<double> &,int , string, vector<double> &)`**
|
||||
|
||||
Example Usage: **iswt(swtop,J,nm,iswt\_output)**
|
||||
|
||||
**swtop** is the output of SWT stage , J - number of levels and nm is the wavelet as before. Output of ISWT is stored in **iswt\_output** vector.
|
||||
|
||||
### 16. GNUSWTPLOT ###
|
||||
|
||||
**`void* gnuswtplot(int)`**
|
||||
|
||||
Example Usage: **gnuswtplot(J)**
|
||||
|
||||
Generates GNUPLOT script gnudwt.gnu.txt that contains plots of signals, filters and wavelet coefficients. it works if it is called following SWT and ISWT operations. To draw the plots, just load the script in gnuplot.
|
||||
|
||||
### 17. 1D Periodic Extension ###
|
||||
|
||||
**`void* per_ext(vector<double> &, int )`**
|
||||
|
||||
Example Usage: **per\_ext(sig,a)**
|
||||
|
||||
**per\_ext** periodically extends the signal **sig** by value **a** in either direction.
|
||||
|
||||
# 2D Functions #
|
||||
|
||||
There are three sets of 2D DWT options.
|
||||
|
||||
1. Regular decimated 2D DWT and IDWT. It works with dyadic length 2D signals and outputs 2D signals.(The DWT output is in the format of a dyadically decomposed image with cLL, the low pass output, in the top left corner) If the input signal isn't of dyadic length then it will be zeropadded and you can calculate output size by using **dwt\_output\_dim** function and remove zeros from the output by using the **zero\_remove** function. More on this will follow. For a N X N dydadic length signal, the output is N X N which is useful in many applications.
|
||||
|
||||

|
||||
|
||||
2. Symmetric Extension 2D DWT and IDWT signal. It works with signal of any length and DWT output is a 1D vector (just as in Matlab) which may make it easier to handle in certain situations. On the flip side, the output is not of the same size as input and so there are some redundancies. To display the image, you'll have to convert 1D vector into image format and also account for downsampling and convolution which result in non-linear variation of length across deocmposition levels. The functions **dispDWT** and **dwt\_output\_dim\_sym** will help in displaying the image. On the flip side, performing operations on 1D
|
||||
DWT output vector should be straightforward.
|
||||
|
||||
3. 2D Stationary Wavelet Transform. Inverse Stationary Transform is not implemented as of yet but 2d SWT should be good for image analysis, pattern recognition and edge detection operations that don't require ISWT for the most part.
|
||||
|
||||
### 18. J-Level 2D Discrete Wavelet Transform ###
|
||||
|
||||
**`void* dwt_2d(vector<vector<double> > &, int , string , vector<vector<double> > &, vector<double> &)`**
|
||||
|
||||
Example Usage: **dwt\_2d(vec1, J, nm, dwt\_output,flag )**
|
||||
|
||||
**vec1** is the 2D input signal.
|
||||
|
||||
**J** is the Decomposition level.
|
||||
|
||||
**nm** gives the name of wavelet family. See **filtcoef** for more details.
|
||||
|
||||
**dwt\_output** is the 2D output coefficients. They are arranged as shown in the figure above. The dimensions can be obtained by using **dwt\_output\_dim** function. A code fragment may look like this-
|
||||
```
|
||||
int rr1,cc1;
|
||||
string nm = "db4";
|
||||
// Finding DWT output dimensions as the DWT output is zeropadded
|
||||
dwt_output_dim(vec1, rr1, cc1 );// vec1 is the input image/matrix
|
||||
int J = 2;
|
||||
vector<double> flag;// Flag stores values including size of input and level of decomposition and this vector needs to be passed to idwt_2d function.
|
||||
vector<vector<double> > dwt_output(rr1, vector<double>(cc1));
|
||||
// Computing 2d DWT ( vec1is the signal while dwt_output is the DWT output)
|
||||
dwt_2d(vec1, J, nm, dwt_output,flag );
|
||||
```
|
||||
|
||||
### 19. J-Level 2D Inverse Discrete Wavelet Transform ###
|
||||
|
||||
**`void* idwt_2d(vector<vector<double> > &,vector<double> &, string ,vector<vector<double> > &)`**
|
||||
|
||||
Example Usage: **idwt\_2d(dwt\_output,flag, nm ,idwt\_output)**
|
||||
|
||||
**idwt\_output** is a 2D vector object and may require zeropadding removal depending on the size of input image/matrix. Continuing from above, code fragment for IDWT may look like following
|
||||
|
||||
```
|
||||
// Finding IDWT
|
||||
vector<vector<double> > final(rr1, vector<double>(cc1));
|
||||
idwt_2d(dwt_hold,flag, nm ,final);
|
||||
// Removing Zeropadding
|
||||
zero_remove(vec1,final);// vec1 is the input image/matrix
|
||||
```
|
||||
|
||||
### 20. 2D Dyadic Zero Padding ###
|
||||
|
||||
**`void* dyadic_zpad_2d(vector<vector<double> > &,vector<vector<double> > &)`**
|
||||
|
||||
Example Usage: **dyadic\_zpad\_2d(sig,sig2)**
|
||||
|
||||
This function makes the signal of dyadic length by adding zeros. In this particular DWT implementation **dwt\_2d**, the output **sig2** will be a NXN matrix which may require a lot of zeros being padded to the signal. It may be desirable to use **dwt\_2d\_sym** function in this case which operates on images/matrices of any size without any zero-padding.
|
||||
|
||||
### 21. Get Output Dimension ###
|
||||
|
||||
**`void* dwt_output_dim(vector<vector<double> >&, int &, int & )`**
|
||||
|
||||
Example Usage: **dwt\_output\_dim(vec1, rr1, cc1 )**
|
||||
|
||||
Because of zero-padding, the output image may not be equal in size to the input image. This function returns the dimensions of output matrix. If you are using dyadic length image then output will have the same dimensions as the input. This function works only with **dwt\_2d** functions and not with other DWT implementations.
|
||||
|
||||
### 22. 2D Zeropad Removal ###
|
||||
|
||||
**`void* zero_remove(vector<vector<double> > &,vector<vector<double> > &) `**
|
||||
|
||||
Example Usage: **zero\_remove(vec1,final)**
|
||||
|
||||
**vec1** is the input signal while **final** is the zeropadded IDWT output. **zero\_remove** will remove zeros based on the size of the input image/matrix.
|
||||
|
||||
### 23. Get 2D DWT coefficients at level N ###
|
||||
|
||||
**`void* getcoeff2d(vector<vector<double> > &, vector<vector<double> > &,vector<vector<double> > &,vector<vector<double> > &,vector<double> &, int &)`**
|
||||
|
||||
Example Usage: **getcoeff2d(dwtoutput,cH,cV,cD,flag,N)**
|
||||
|
||||
Given 2D DWT output **dwtoutput** and the Nth level of decomposition, **getcoeff2d** will return the three detail coefficients at the Nth level of decomposition. Works only with **dwt\_2d** function.
|
||||
|
||||
### 24. 1-Level 2D DWT ###
|
||||
|
||||
**`void* dwt2(string ,vector<vector<double> > &, vector<vector<double> > &,vector<vector<double> > &, vector<vector<double> > &, vector<vector<double> > &)`**
|
||||
|
||||
Example Usage: **dwt2(nm,sig,cA,cH,cV,cD)**
|
||||
|
||||
Given a 2D signal **sig** and wavelet name **nm**, **dwt2** will return the approximation(**cA**) and detail coefficients(**cH,cV,cD**) after 1 level of decomposition.
|
||||
|
||||
### 25. 1-Level 2D IDWT ###
|
||||
|
||||
**`void* idwt2(string ,vector<vector<double> > &, vector<vector<double> > &,vector<vector<double> > &, vector<vector<double> > &, vector<vector<double> > &)`**
|
||||
|
||||
Example Usage: **idwt2(nm,idwt\_output, cA, cH,cV,cD)**
|
||||
|
||||
This is the exact inverse of **dwt2** function. Inputs are the four approximation and detail coefficients while the output is the singke stage **idwt\_output**.
|
||||
|
||||
### 26. 2D Downsampling ###
|
||||
|
||||
**`void* downsamp2(vector<vector<double> > &,vector<vector<double> > &, int, int)`**
|
||||
|
||||
Example Usage: **downsamp2(vec1,vec2,rows\_dn,cols\_dn)**
|
||||
|
||||
**vec1** is the input, **rows\_dn** and **cols\_dn** are row and column downsampling factors. **vec2** is the downsampled matrix.
|
||||
|
||||
### 27. 2D Upsampling ###
|
||||
|
||||
**`void* upsamp2(vector<vector<double> > &,vector<vector<double> > &, int, int)`**
|
||||
|
||||
Example Usage: **upsamp2(vec1,vec2,rows\_up,cols\_up)**
|
||||
|
||||
**vec1** is the input, **rows\_up** and **cols\_up** are row and column upsampling factors. **vec2** is the upsampled matrix.
|
||||
|
||||
# 2D Symmetric Extension DWT Functions #
|
||||
|
||||
### 28. J-Level Symmetric Extension 2D DWT ###
|
||||
|
||||
**`void* dwt_2d_sym(vector<vector<double> > &, int , string , vector<double> &, vector<double> & ,vector<int> &, int )`**
|
||||
|
||||
Example Usage: **dwt\_2d\_sym(vec1,J,nm,output,flag,length,e)**
|
||||
|
||||
**vec1** Input Image/Matrix
|
||||
|
||||
**J** Number of Decomposition Levels
|
||||
|
||||
**nm** Wavelet Name
|
||||
|
||||
**flag** Stores values for IDWT function
|
||||
|
||||
**output** 1D vector that stores the output in the following format
|
||||
**`[A(J) D(J) D(J-1) ..... D(1)]`**
|
||||
|
||||
where **A(J)** is the approximation coefficient vector at the Jth level while **D(n)** are the detail coefficient vectors at the nth level. It is important to remember that approximation and detail coefficients are actually two dimensional so we need a length vector that stores rows and columns values of each coefficient element. The length vector is given by **length**.
|
||||
|
||||
For example, the first element of **output** vector is the approximation matrix stored as a vector and the first two elements of **length** vectors are row and column values of the approximation matrix. In other words, a 300 element approximation matrix ( 15 rows X 20 columns) can be extracted from the 300 element approximation vector.
|
||||
|
||||
**e** is the length of symmetric extension in all directions.
|
||||
|
||||
A code fragment is as following
|
||||
|
||||
```
|
||||
string nm = "db4";
|
||||
|
||||
// Finding 2D DWT Transform of the image using symmetric extension algorithm
|
||||
// Extension is set to 3 (eg., int e = 3)
|
||||
|
||||
vector<int> length;
|
||||
vector<double> output,flag;
|
||||
int J =3;
|
||||
int e=3;
|
||||
dwt_2d_sym(vec1,J,nm,output,flag,length,e);
|
||||
```
|
||||
|
||||
This DWT implementation works on image/matrices of any size and no dyadic zero padding is required.
|
||||
|
||||
### 29. J-Level Symmetric Extension 2D IDWT ###
|
||||
|
||||
**`void* idwt_2d_sym(vector<double> &,vector<double> &, string ,vector<vector<double> > &,vector<int> &)`**
|
||||
|
||||
Example Usage: **idwt\_2d\_sym(dwt\_output,flag, nm, idwt\_output,length)**
|
||||
|
||||
**idwt\_output** will have the same dimensions as the input image/matrix.
|
||||
|
||||
```
|
||||
// Finding IDWT
|
||||
|
||||
vector<vector<double> > idwt_output(rows, vector<double>(cols));// rows and cols are the rows and columns of the input image/matrix
|
||||
|
||||
idwt_2d_sym( output,flag, nm, idwt_output,length);
|
||||
```
|
||||
|
||||
> For more on other arguments, see 28.
|
||||
|
||||
### 30. 2D Symmetric Extension ###
|
||||
|
||||
**`void symm_ext2d(vector<vector<double> > &,vector<vector<double> > &, int )`**
|
||||
|
||||
Example Usage: **symm\_ext2d(origsig,sig, ext)**
|
||||
|
||||
**origsig** is the original signal, **sig** is the extended signal. It is extended by integer value **ext** in all directions.
|
||||
|
||||
### 31. Additional dwt\_2d\_sym Functions ###
|
||||
|
||||
**`void* dispDWT(vector<double> &,vector<vector<double> > &, vector<int> &, vector<int> &, int )`**
|
||||
|
||||
and
|
||||
|
||||
**`void* dwt_output_dim_sym(vector<int> &,vector<int> &, int )`**
|
||||
|
||||
> As we mentioned previously,DWT output of symmetric extension 2D DWT is a one dimensional vector. Additionally, the output isn't of dyadic length across different decomposition levels which makes the rectangular display of DWT output image a bit challenging and imprecise. **dispDWT** and **dwt\_output\_dim\_sym** are two functions that are used to return a rectangular set of coefficients arranged to display the DWT in traditional format. A code fragment that computes symmetric DWT and then rearranges coefficients is shown next
|
||||
|
||||
```
|
||||
string nm = "db4";
|
||||
|
||||
// Finding 2D DWT Transform of the image using symmetric extension algorithm
|
||||
// Extension is set to 3 (eg., int e = 3)
|
||||
|
||||
vector<int> length;
|
||||
vector<double> output,flag;
|
||||
int J =3;
|
||||
int e=3;
|
||||
dwt_2d_sym(vec1,J,nm,output,flag,length,e);
|
||||
|
||||
vector<int> length2;
|
||||
// This algorithm computes DWT of image of any given size. Together with convolution and
|
||||
// subsampling operations it is clear that subsampled images are of different length than
|
||||
// dyadic length images. In order to compute the "effective" size of DWT we do additional
|
||||
// calculations.
|
||||
dwt_output_dim_sym(length,length2,J);
|
||||
// length2 gives the integer vector that contains the size of subimages that will
|
||||
// combine to form the displayed output image. The last two entries of length2 gives the
|
||||
// size of DWT ( rows_n by cols_n)
|
||||
|
||||
int siz = length2.size();
|
||||
// The last two values of length2 vector give the dimensions of the DWT output.
|
||||
int rows_n=length2[siz-2];
|
||||
int cols_n = length2[siz-1];
|
||||
|
||||
vector<vector< double> > dwtdisp(rows_n, vector<double>(cols_n));
|
||||
dispDWT(output,dwtdisp, length ,length2, J);
|
||||
```
|
||||
|
||||
> There are ,obviously, other ways to display the DWT output. A more precise and more efficient way could be to display output separately at each level instead of trying to bruteforce them into one image.
|
||||
|
||||
# 2D Stationary Wavelet Transform Functions #
|
||||
|
||||
### 32. J-Level 2D Stationary Wavelet Transform ###
|
||||
|
||||
**`void* swt_2d(vector<vector<double> > &,int , string , vector<double> &)`**
|
||||
|
||||
Example Usage: **swt\_2d(vec1,J,nm,output)**
|
||||
|
||||
**output** is a 1D vector which is exactly equal to 1D DWT output vector of **dwt\_2d\_sym** except that in this case all coefficients are of same size. If **vec1** isn't a (2<sup>M)</sup> X (2<sup>M)</sup> image/matrix , it will be zeropadded to dyadic dimensions with rows = columns.
|
||||
|
||||
For example, a 3 level decomposition of 256X256 image yields 10 256X256 sets of coefficients - one approximation coefficient set at level 3 and three detail coefficients at each level.
|
||||
|
||||

|
||||
|
||||
_Approximation Coefficients at J=3 (256X256 Image)_
|
||||
|
||||

|
||||
|
||||
_Detail Coefficients at levels 3,2,1 respectively (768X768 image shown as 640X640)_
|
||||
|
||||
### 33. 2D Periodic Extension ###
|
||||
|
||||
**`void per_ext2d(vector<vector<double> > &,vector<vector<double> > &, int )`**
|
||||
|
||||
Example Usage: **per\_ext2d(origsig,sig, ext)**
|
||||
|
||||
**origsig** is the original signal, **sig** is the extended signal. It is extended by integer value **ext** in all directions.
|
||||
|
||||
# FFT Functions #
|
||||
|
||||
### 34. 1D FFT and IFFT ###
|
||||
|
||||
**`void* fft(vector<complex<double> > &,int ,unsigned int)`**
|
||||
|
||||
Example Usage: **fft(inp,1,N) -or- fft(inp,-1,N)**
|
||||
|
||||
**fft** performs in-place FFT operation on complex vector **inp**.
|
||||
|
||||
Second argument is 1 for forward FFT and -1 for Inverse FFT.
|
||||
|
||||
Third argument gives the length of the output. If N is larger than the length of **inp** then it will be zeropadded, FFT will be performed and N-length complex output will be returned.
|
||||
|
||||
### 35. Frequency Response ###
|
||||
|
||||
**`void* freq(vector<double> &, vector<double> &)`**
|
||||
|
||||
Example Usage: **freq(sig,fre\_oup)**
|
||||
|
||||
This function returns frequency response **fre\_oup** of signal **sig**. The function will also output a freq.dat file that can be directly plotted in GNUPLOT.
|
27
PageName.md
Normal file
27
PageName.md
Normal file
@ -0,0 +1,27 @@
|
||||
# 1D/2D Discrete Wavelet Transform Implementation in C++ #
|
||||
|
||||
1. 1D DWT and IDWT Implementation (Two Modes)
|
||||
1. 2D DWT and IDWT Implementation (Two Modes)
|
||||
1. 1D SWT and ISWT Implementation ( Stationary Wavelet Transform)
|
||||
1. 2D SWT Implementation
|
||||
1. Implemented using Danielson Lanczos FFT Algorithm
|
||||
|
||||
Libraries (Compiled using MinGW and MSVC++ 2010 compilers in Windows) are available in Downloads section while source code is available in the source "src" folder.
|
||||
|
||||
The libraries and source codes are available at http://code.google.com/p/wavelet1d/. I have tried to make this a more "user-friendly" implementation by keeping the functions as simple and descriptive as possible. Additionally, the 1D DWT/IDWT routines will output data that can be used easily with GNUPLOT. It causes redundancy and possibly some clutter if signal files are large but ,in my opinion, the trade-off is worth it. The accompanying script also works best only when DWT and IDWT routines are called in the same program.
|
||||
|
||||
I have used C++ vector objects to accept input, store and output data. This is done to overcome certain programming limitations associated with using arrays. Dynamic arrays were also an option but they require a lot of house-cleaning without having any advantages over vector objects. To learn more about vectors, please refer to excellent tutorial at http://www.cplusplus.com/reference/stl/vector/ Vectors and Arrays can be converted back and forth so even if you are more comfortable with arrays, using vectors should not really be a problem.
|
||||
|
||||
|**[List of Functions](http://code.google.com/p/wavelet1d/wiki/Functions)**| Lists all Functions available in the Library|
|
||||
|:-------------------------------------------------------------------------|:--------------------------------------------|
|
||||
|**[Example Code 1](http://code.google.com/p/wavelet1d/wiki/1DDWTdemo)**| 1D DWT/IDWT Demo Code|
|
||||
|**[Example Code 2](http://code.google.com/p/wavelet1d/wiki/1DAppx)**| 1D Signal Approximation Demo|
|
||||
|**[Example Code 3](http://code.google.com/p/wavelet1d/wiki/2DDWTdemo)**| 2D DWT/IDWT Demo Code|
|
||||
|**[Example Code 4](http://code.google.com/p/wavelet1d/wiki/2DAppx)**| Image Approximation Demo|
|
||||
|**[Example Code 5](http://code.google.com/p/wavelet1d/wiki/2DSWTdemo)**| 2D SWT Demo Code|
|
||||
|
||||

|
||||
|
||||
_J=3 Level Discrete Wavelet Transform of a 486X486 image using dwt\_2d\_sym function_
|
||||
|
||||
Image Processing Note : I have not implemented any image class in C++ as of yet so I'm using OPENCV to handle images. It happens to be a rather bulky package and if you are not already working in image processing area, there are other more convenient options that may be used to handle simple image operations( loading, displaying, saving and converting them to c++ STL formats).
|
54
ProjectHome.md
Normal file
54
ProjectHome.md
Normal file
@ -0,0 +1,54 @@
|
||||
# C++ 1D/2D DWT Implementation for Win32 and Linux #
|
||||
|
||||
### Wavelet2d / Wavelet2s Libraries ###
|
||||
1. 1D DWT and IDWT Implementation (Two Modes)
|
||||
1. 2D DWT and IDWT Implementation (Two Modes)
|
||||
1. 1D SWT and ISWT Implementation ( Stationary Wavelet Transform)
|
||||
1. 2D SWT Implementation
|
||||
1. Implemented using FFTW3 Library
|
||||
1. Shared(.so) and static(.a) libraries for Linux
|
||||
1. Shared(.dll) and static(.a) libraries for Win32 GCC (MinGW).
|
||||
1. Shared(.dll) libraries for Microsoft VC++
|
||||
|
||||
> This implementation uses C++ vector objects to accept input, store and output data. This is done to overcome certain programming limitations associated with using arrays. Dynamic arrays were also an option but they require a lot of house-cleaning without having any advantages over vector objects. To learn more about vectors, please refer to excellent tutorial at [CPLUSPLUS](http://www.cplusplus.com/reference/stl/vector/). Vectors and Arrays can be converted back and forth so even if you are more comfortable with arrays, using vectors should not really be a problem.
|
||||
|
||||
### Changes from Previous Version ###
|
||||
|
||||
Focus is on speed.
|
||||
|
||||
1. FFTW3 Library is used to improve computation speed.
|
||||
|
||||
2. No GNUPLOT outputs are generated.
|
||||
|
||||
3. Periodic and Symmetric functions take exactly same arguments unlike in previous versions. They will still be accessed by the same names, though.(dwt ,dwt\_sym etc.)
|
||||
|
||||
4. Focus on shared libraries. No static libraries for MSVC++ although MinGW and LINUX version will come with static as well as shared libraries.
|
||||
|
||||
5. These libraries work with signals or images of almost any size. Speed becomes an issue for very large images. Also click on "Issues" tab for more information on issues dealing with very small signal length.
|
||||
|
||||
|
||||
6. Functions take different arguments as compared to previous versions and extensions are done based on length of filter so signal extension length is no longer an input value. See Lists of functions and example codes.
|
||||
|
||||
wavelet2d - dynamic libraries( .so.1.0 and .dll)
|
||||
|
||||
wavelet2s - static libraries (.a)
|
||||
|
||||
|**[Overview](http://code.google.com/p/wavelet1d/wiki/install)**| Working with Libraries|
|
||||
|:--------------------------------------------------------------|:----------------------|
|
||||
|**[List of Functions](http://code.google.com/p/wavelet1d/wiki/newfunc)**| Lists all Functions available in the wavelib Library|
|
||||
|**[Example Code 1](http://code.google.com/p/wavelet1d/wiki/new1DDWTdemo)**| 1D DWT/IDWT Demo Code|
|
||||
|**[Example Code 2](http://code.google.com/p/wavelet1d/wiki/new1DAppx)**| 1D Signal Approximation Demo|
|
||||
|**[Example Code 3](http://code.google.com/p/wavelet1d/wiki/new2DDWTdemo)**| 2D DWT/IDWT Demo Code|
|
||||
|**[Example Code 4](http://code.google.com/p/wavelet1d/wiki/new2DAppx)**| Image Approximation Demo|
|
||||
|**[Example Code 5](http://code.google.com/p/wavelet1d/wiki/new2DSWTdemo)**| 2D SWT Demo|
|
||||
|**[Example Code 6](http://code.google.com/p/wavelet1d/wiki/new1DSWTDemo)**| 1D SWT Demo Code|
|
||||
|**[Previous Versions](http://code.google.com/p/wavelet1d/wiki/previous)**| Documentation (wavelet-03 and wavelet02 Libraries)|
|
||||
|**[DyadWaves GUI](http://code.google.com/p/dyadwaves/)**| Open Source Wavelet GUI for Windows and Linux |
|
||||
|**[Liftwave](http://code.google.com/p/liftwave/)**| An Alternative C++ Template based implementation of 1D/2D DWT using Lifting method|
|
||||
|
||||
|
||||

|
||||
|
||||
_J=2 Level Discrete Wavelet Transform of a 569X800 image using dwt\_2d\_sym function (Resized here for Display)_
|
||||
|
||||
Image Processing Note : I have not implemented any image class in C++ so I'm using OPENCV to handle images. It happens to be a rather bulky package and if you are not already working in image processing area, there are other more convenient options that may be used to handle simple image operations( loading, displaying, saving and converting them to c++ STL formats).
|
45
front.md
Normal file
45
front.md
Normal file
@ -0,0 +1,45 @@
|
||||
# C++ 1D/2D DWT Implementation for Win32 and Linux #
|
||||
|
||||
### Wavelet2d Libraries ###
|
||||
1. 1D DWT and IDWT Implementation (Two Modes)
|
||||
1. 2D DWT and IDWT Implementation (Two Modes)
|
||||
1. 1D SWT and ISWT Implementation ( Stationary Wavelet Transform)
|
||||
1. 2D SWT Implementation
|
||||
1. Implemented using FFTW3 Library
|
||||
1. Shared(.so) and static(.a) libraries for Linux
|
||||
1. Shared(.dll) and static(.a) libraries for Win32 GCC (MinGW).
|
||||
1. Shared(.dll) libraries for Microsoft VC++
|
||||
|
||||
> This implementation uses C++ vector objects to accept input, store and output data. This is done to overcome certain programming limitations associated with using arrays. Dynamic arrays were also an option but they require a lot of house-cleaning without having any advantages over vector objects. To learn more about vectors, please refer to excellent tutorial at [CPLUSPLUS](http://www.cplusplus.com/reference/stl/vector/). Vectors and Arrays can be converted back and forth so even if you are more comfortable with arrays, using vectors should not really be a problem.
|
||||
|
||||
### Changes from Previous Version ###
|
||||
|
||||
Focus is on speed.
|
||||
|
||||
1. FFTW3 Library is used to improve computation speed.
|
||||
|
||||
2. No GNUPLOT outputs are generated.
|
||||
|
||||
3. Periodic and Symmetric functions take same arguments. They will still be accessed by the same names, though.(dwt ,dwt\_sym etc.)
|
||||
|
||||
4. Focus on shared libraries. No static libraries for MSVC++ although MinGW and LINUX version will come with static as well as shared libraries.
|
||||
|
||||
|
||||
wavelet2d - dynamic libraries( .so and .dll)
|
||||
|
||||
wavelet2s - static libraries (.a)
|
||||
|
||||
|**[List of Functions](http://code.google.com/p/wavelet1d/wiki/newfunc)**| Lists all Functions available in the Library|
|
||||
|:-----------------------------------------------------------------------|:--------------------------------------------|
|
||||
|**[Example Code 1](http://code.google.com/p/wavelet1d/wiki/new1DDWTdemo)**| 1D DWT/IDWT Demo Code|
|
||||
|**[Example Code 2](http://code.google.com/p/wavelet1d/wiki/new1DAppx)**| 1D Signal Approximation Demo|
|
||||
|**[Example Code 3](http://code.google.com/p/wavelet1d/wiki/new2DDWTdemo)**| 2D DWT/IDWT Demo Code|
|
||||
|**[Example Code 4](http://code.google.com/p/wavelet1d/wiki/new2DAppx)**| Image Approximation Demo|
|
||||
|**[Example Code 5](http://code.google.com/p/wavelet1d/wiki/new2DSWTdemo)**| 2D SWT Demo|
|
||||
|**[Example Code 6](http://code.google.com/p/wavelet1d/wiki/new1DSWTDemo)**| 1D SWT Demo Code|
|
||||
|
||||

|
||||
|
||||
_J=2 Level Discrete Wavelet Transform of a 569X800 image using dwt\_2d\_sym function (Resized here for Display)_
|
||||
|
||||
Image Processing Note : I have not implemented any image class in C++ so I'm using OPENCV to handle images. It happens to be a rather bulky package and if you are not already working in image processing area, there are other more convenient options that may be used to handle simple image operations( loading, displaying, saving and converting them to c++ STL formats).
|
93
install.md
Normal file
93
install.md
Normal file
@ -0,0 +1,93 @@
|
||||
# Working with Wavelet Libraries #
|
||||
## Wavelet Libraries in Win32 Environment ##
|
||||
### Microsoft Visual C++ ###
|
||||
|
||||
This package contains two DLLs for MSVC++ - one Debug and one Release
|
||||
version.The list of required files in order to compile wavelet2d based programs-
|
||||
|
||||
#Header File- wavelet2d.h
|
||||
|
||||
#Import Library- wavelet2d.lib
|
||||
|
||||
#Wavelet DLL - wavelet2d.dll
|
||||
|
||||
#FFTW DLL - libfftw3-3.dll
|
||||
|
||||
Header file is in the source (’src’) folder. Wavelet Libraries are in the respective Debug and Release folders. FFTW DLL is in the FFTW3 folder. Alternatively, you may chose to install FFT library from www.fftw.org. The FFTW sourcecodes are also available at FFTW website under GNU-GPL license.
|
||||
|
||||
In order to use wavelet libraries, the easiest way is to add import library
|
||||
(wavelet2d.lib) to additional dependency in your project which in turn will
|
||||
handle the DLLs for you. The two DLLs must be in your program path.If you
|
||||
are new to MSVC, you may want to learn more about DLL search path at
|
||||
|
||||
[DLL Search Path](http://msdn.microsoft.com/en-us/library/7d83bc18(VS.71).aspx)
|
||||
|
||||
You may also chose to directly call DLLs from your program.Regardless
|
||||
of how you handle DLLs, mixing debug and release versions is not a good
|
||||
idea.Both versions are named wavelet2d.dll so putting them in system path is
|
||||
not a good idea either. Preferred way is to use Visual Studio project settings
|
||||
to link to the wavelet2d.lib file and put the release and debug wavelet2d dlls
|
||||
along with libfftw-3.3dll in the directory containing the respective release and
|
||||
debug executables of your project. Import library will open the DLLs.
|
||||
|
||||
### GNU-GCC (MinGW) Based Compilation ###
|
||||
|
||||
If you use GCC compiler either through MSYS or from one of the IDEs(Codeblocks,
|
||||
Eclipse, QTcreator, Netbeans etc.),I have also added both debug and release
|
||||
versions of wavelet2d DLLs and wavelet2s static libraries. Required Files for
|
||||
MinGW DLLS-
|
||||
|
||||
• Header Files- wavelet2d.h
|
||||
|
||||
• Import Library- libwavelet2d.dll.a
|
||||
|
||||
• Wavelet DLL - wavelet2d.dll
|
||||
|
||||
• FFTW DLL - libfftw3-3.dll (Import library is also included)
|
||||
|
||||
It is recommended that you link to the Release and Debug folders as they are.
|
||||
Once you link to import library and specify the folder location, wavelet import
|
||||
library should automatically open the two DLLs. Mixing Debug and Release
|
||||
versions shouldn’t pose any problems in this case.
|
||||
|
||||
Working with MinGW Static libraries is even more straightforward. You
|
||||
need to include wavelet2s.h header in your program , link to static .a library and you are set.
|
||||
|
||||
**Known Issue - Some newer versions of MinGW-g++ compiler have problem
|
||||
working with .o codes(and hence static libraries) compiled in older versions of MinGW (3.x). If you are facing this problem try MINGW4.5 compiled static libraries or build wavelet2d from the source code with your own compiler. You'll need to statically build fftw3 library first if you are going the source code way. The DLLs should be working fine in any case so that's always another option.**
|
||||
|
||||
|
||||
## Working in LINUX Environment ##
|
||||
|
||||
1. This package contains two wavelet libraries- libwavelet2d.so.1.0 (shared)
|
||||
and libwavelet2s.a (static) compiled essentially from the same source code.
|
||||
Source code is available in the ’src’ folder.
|
||||
|
||||
2. You may need to link to header files that are included with their respective libraries. They are also available in the ’src’ folder.
|
||||
|
||||
3. You may want to install shared library in one of your existing paths to
|
||||
make compilation easier. You can create sym links once inside the folder(
|
||||
eg., /usr/local/lib where you are installing libwavelet2d.so.1.0) by using following commands
|
||||
|
||||
> ln -sf libwavelet2d.so.1.0 libwavelet2d.so
|
||||
|
||||
> ln -sf libwavelet2d.so.1.0 libwavelet2d.so.1
|
||||
|
||||
> ldconfig
|
||||
|
||||
You will probably need superuser privileges to perform previous steps. If you
|
||||
don’t have su privilege then you can move libwavelet2d.so.1.0 to your work
|
||||
folder or where your source code is, create sym links as before and then put
|
||||
your folder in the path during runtime.
|
||||
|
||||
ln -sf libwavelet2d.so.1.0 libwavelet2d.so
|
||||
|
||||
ln -sf libwavelet2d.so.1.0 libwavelet2d.so.1
|
||||
|
||||
export LD\_LIBRARY\_PATH=.
|
||||
|
||||
|
||||
libwavelet2s.a :: Working with static library is pretty straightforward. You will
|
||||
only need to include wavelet2s.h in your program and specify the library
|
||||
(-lwavelet2s flag) , include path (-I<path to wavelet2s.h> flag) and library
|
||||
path (-L<path to libwavelet2s.a> flag).
|
197
new1DAppx.md
Normal file
197
new1DAppx.md
Normal file
@ -0,0 +1,197 @@
|
||||
# 1D Linear vs Nonlinear Approximation #
|
||||
|
||||
_Note_
|
||||
|
||||
1. dwt and dwt\_sym functions are interchangeable in the following code as they take the same arguments. You may have to make some trivial modifications due to different sized output coeffficients.
|
||||
|
||||
2. Please make sure that right header file is included. Following sample program links to wavelet2s.h which is the header for static libraries. wavelet2d.h must be included for shared libraries.
|
||||
|
||||
[Sample Code](http://code.google.com/p/wavelet1d/source/browse/trunk/wavelet2d/demo/wavedemo2.cpp)
|
||||
|
||||
```
|
||||
//============================================================================
|
||||
// Name : wavedemo2.cpp
|
||||
// Author : Rafat Hussain
|
||||
// Version :
|
||||
// Copyright :
|
||||
// Description : Wavelet Demo comparing linear and non-linear approximation properties
|
||||
// : of a given wavelet. Implemented using dwt and idwt. Interchangeable with
|
||||
// : dwt_sym and idwt_sym.
|
||||
//============================================================================
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include "wavelet2s.h"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std;
|
||||
|
||||
void findthresh(vector<double> vector1, int N, double& t){
|
||||
sort(vector1.begin(), vector1.end(), greater<double>());
|
||||
t = vector1.at(N-1);
|
||||
}
|
||||
|
||||
int main() {
|
||||
cout << "********J- LEVEL DISCRETE WAVELET TRANSFORM IMPLEMENTATION*********" << endl; // prints
|
||||
cout << "This program accepts signal from the user in a file format " << endl;
|
||||
cout << "and performs Discrete Wavelet Transform with specified " << endl;
|
||||
cout << "wavelet. " << endl;
|
||||
cout << " " << endl;
|
||||
cout << " The Following Wavelets are in the Database: " << endl;
|
||||
cout << " haar, db1, db2, db3, db4, db5, db6, db7, db8, db9, db10, " << endl;
|
||||
cout << " db11, db12, db13, db14, db15. " << endl;
|
||||
cout << " bior1.1, bio1.3, bior1.5, bior2.2, bior2.4,bior2.6,bior2.8, " << endl;
|
||||
cout << " bior3.1, bior3.3, bior3.5, bior3.7, bior3.9, bior4.4," << endl;
|
||||
cout << " bior5.5, bior6.8." << endl;
|
||||
cout << " coif1, coif2, coif3, coif4, coif5." << endl;
|
||||
cout << "Please Enter the Wavelet Name at the Prompt( No quotes) :" << endl;
|
||||
|
||||
string nm; // nm will store the name of Wavelet Family
|
||||
cin >> nm;
|
||||
cout << "Enter the name of signal file at the Prompt eg., signal.txt :" << endl;
|
||||
char inp[50];
|
||||
cin >> inp;
|
||||
vector<double> sig;
|
||||
ifstream sig_inp(inp);
|
||||
if ( !sig_inp.good()){
|
||||
cout << "The File doesn't exist"<< endl;
|
||||
exit(1);
|
||||
}
|
||||
while (sig_inp) {
|
||||
double temp;
|
||||
sig_inp >> temp;
|
||||
sig.push_back(temp);
|
||||
}
|
||||
sig.pop_back();
|
||||
vector<double> original;
|
||||
original = sig;
|
||||
cout << "Please Enter the Number of DWT Stages J :" << endl;
|
||||
|
||||
int J;
|
||||
cin >> J ;
|
||||
|
||||
vector<double> dwt_output, flag;
|
||||
vector<int> length1;
|
||||
|
||||
// perform J-Level DWT
|
||||
dwt(sig, J, nm, dwt_output,flag, length1);
|
||||
|
||||
// Performing Linear Approximation by using only first 100 coefficients
|
||||
// Coefficients in dwt_output are stored as following
|
||||
// dwt_output =[ Appx(J-1) Detail(J-1) Detail(J-2) .... Detail(0)]
|
||||
|
||||
int n_coef = 100; // Number of significant coefficients
|
||||
|
||||
int n_non_sig= dwt_output.size() - n_coef; // Number of Coefficients that will
|
||||
// be set to zero
|
||||
dwt_output.erase(dwt_output.end()- n_non_sig,dwt_output.end());
|
||||
// Deleting last n_non_sig coefficients and replacing them with zeros
|
||||
dwt_output.insert(dwt_output.end(),n_non_sig,0);
|
||||
|
||||
ofstream linearsig("linsig.txt");
|
||||
for (unsigned int i = 0; i < dwt_output.size(); i++) {
|
||||
linearsig << dwt_output[i] << endl;
|
||||
|
||||
}
|
||||
|
||||
// Finding IDWT with approximated coefficients
|
||||
|
||||
vector<double> output;
|
||||
idwt(dwt_output, flag,nm,output, length1);
|
||||
|
||||
unsigned int count = output.size();
|
||||
ofstream gnulinappx("gnulinappx.dat");
|
||||
for (unsigned int i = 0;i < count; i++) {
|
||||
gnulinappx << output[i] << endl;
|
||||
}
|
||||
gnulinappx.close();
|
||||
|
||||
// Performing Non Linear Approximation by using only most
|
||||
// significant coefficients
|
||||
|
||||
vector<double> dwt_output2, flag2;
|
||||
vector<int> length2;
|
||||
|
||||
// perform J-Level DWT
|
||||
dwt(sig, J, nm, dwt_output2,flag2,length2);
|
||||
|
||||
double thresh = 0.0;
|
||||
|
||||
vector<double> temp_dwtoutput;
|
||||
for (unsigned int i =0; i < dwt_output2.size();i++){
|
||||
double temp = abs(dwt_output2[i]);
|
||||
temp_dwtoutput.push_back(temp);
|
||||
}
|
||||
/*
|
||||
for (unsigned int i =0; i < temp_dwtoutput.size(); i++){
|
||||
cout << temp_dwtoutput[i] << endl;
|
||||
}
|
||||
*/
|
||||
|
||||
findthresh(temp_dwtoutput,n_coef, thresh);
|
||||
|
||||
for (unsigned int i = 0; i < dwt_output2.size();i++){
|
||||
double temp = abs(dwt_output2[i]);
|
||||
if (temp < thresh){
|
||||
dwt_output2.at(i) = 0.0;
|
||||
|
||||
}
|
||||
}
|
||||
/*
|
||||
for (unsigned int i =0; i < dwt_output2.size(); i++){
|
||||
cout << dwt_output2[i] << endl;
|
||||
}
|
||||
*/
|
||||
|
||||
ofstream nonlinsig("nonlinsig.txt");
|
||||
for (unsigned int i = 0; i < dwt_output2.size(); i++) {
|
||||
nonlinsig << dwt_output2[i] << endl;
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Finding IDWT with approximated coefficients
|
||||
|
||||
vector<double> output2;
|
||||
idwt(dwt_output2, flag2,nm,output2, length2);
|
||||
|
||||
unsigned int count2 = output2.size();
|
||||
cout << count2 << endl;
|
||||
ofstream gnunlappx("gnunlappx.dat");
|
||||
for (unsigned int i = 0;i < count2; i++) {
|
||||
gnunlappx << output2[i] << endl;
|
||||
}
|
||||
gnunlappx.close();
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
This program computes DWT of the 256-point signal and then uses only 100 coefficients to reconstruct the signal. In the first case, first 100 coefficients are are used to compute linear approximation. In the second case, 100 largest coefficients are used by calculating a threshold that separates largest 100 coefficients from the others.The wavelet used is db3 and the signal is decomposed and reconstructed over 5 stages of DWT/IDWT. The results are plotted below.
|
||||
|
||||

|
||||
_Console showing db3 5 level computation_
|
||||
|
||||

|
||||
_Length 256 Piecewise Regular signal from WaveLab_
|
||||
|
||||
In Linear Approximation case, only first 100 coefficients are retained. Others are set to zero.
|
||||
|
||||

|
||||
_Retained Coefficients for Linear Approximation case_
|
||||
|
||||

|
||||
_Reconstructed Signal using Linear Approximation_
|
||||
|
||||
In Non-Linear case, largest 100 coefficients are retained.
|
||||
|
||||

|
||||
_Retained Coefficients(Non-Linear Approximation case_
|
||||
|
||||

|
||||
_Reconstructed Signal(Non-Linear Approximation Case)_
|
111
new1DDWTdemo.md
Normal file
111
new1DDWTdemo.md
Normal file
@ -0,0 +1,111 @@
|
||||
# 1D DWT/IDWT Demo using dwt function #
|
||||
|
||||
_Notes_
|
||||
|
||||
1. dwt and dwt\_sym functions are interchangeable in the following code as they take the same arguments.
|
||||
|
||||
2. Please make sure that right header file is included. Following sample program links to wavelet2d.h which is the header for shared libraries. wavelet2s.h must be included for static libraries.
|
||||
|
||||
[Sample Code](http://code.google.com/p/wavelet1d/source/browse/trunk/wavelet2d/demo/wavedemo1.cpp)
|
||||
|
||||
```
|
||||
|
||||
//============================================================================
|
||||
// Name : wavedemo1.cpp
|
||||
// Author : Rafat Hussain
|
||||
// Version :
|
||||
// Copyright :
|
||||
// Description : 1D DWT Demo
|
||||
//============================================================================
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include "wavelet2d.h"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <cmath>
|
||||
using namespace std;
|
||||
|
||||
int main() {
|
||||
cout << "********J- LEVEL DISCRETE WAVELET TRANSFORM IMPLEMENTATION*********" << endl; // prints
|
||||
cout << "This program accepts signal from the user in a file format " << endl;
|
||||
cout << "and performs Discrete Wavelet Transform with specified " << endl;
|
||||
cout << "wavelet. " << endl;
|
||||
cout << " " << endl;
|
||||
cout << " The Following Wavelets are in the Database: " << endl;
|
||||
cout << " haar, db1, db2, db3, db4, db5, db6, db7, db8, db9, db10, " << endl;
|
||||
cout << " db11, db12, db13, db14, db15. " << endl;
|
||||
cout << " bior1.1, bio1.3, bior1.5, bior2.2, bior2.4,bior2.6,bior2.8, " << endl;
|
||||
cout << " bior3.1, bior3.3, bior3.5, bior3.7, bior3.9, bior4.4," << endl;
|
||||
cout << " bior5.5, bior6.8." << endl;
|
||||
cout << " coif1, coif2, coif3, coif4, coif5." << endl;
|
||||
cout << "Please Enter the Wavelet Name at the Prompt( No quotes) :" << endl;
|
||||
|
||||
string nm; // nm will store the name of Wavelet Family
|
||||
cin >> nm;
|
||||
cout << "Enter the name of signal file at the Prompt eg., signal.txt :" << endl;
|
||||
char inp[50];
|
||||
cin >> inp;
|
||||
vector<double> sig;
|
||||
ifstream sig_inp(inp);
|
||||
if ( !sig_inp.good()){
|
||||
cout << "The File doesn't exist"<< endl;
|
||||
}
|
||||
while (sig_inp) {
|
||||
double temp;
|
||||
sig_inp >> temp;
|
||||
sig.push_back(temp);
|
||||
}
|
||||
sig.pop_back();
|
||||
vector<double> original;
|
||||
original = sig;
|
||||
cout << "Please Enter the Number of DWT Stages J :" << endl;
|
||||
|
||||
int J;
|
||||
cin >> J ;
|
||||
|
||||
vector<double> dwt_output, flag;
|
||||
|
||||
// perform J-Level DWT
|
||||
vector<int> length;
|
||||
|
||||
dwt_sym(sig, J, nm, dwt_output,flag,length);
|
||||
ofstream dwtout("dwtout.txt");
|
||||
for (unsigned int i = 0; i < dwt_output.size(); i++){
|
||||
dwtout << dwt_output[i] << endl;
|
||||
|
||||
}
|
||||
|
||||
|
||||
//Perform J-Level IDWT
|
||||
vector<double> output;
|
||||
idwt_sym(dwt_output, flag,nm,output,length);
|
||||
|
||||
ofstream sig1("recon.txt");
|
||||
ofstream diff("diff.txt");
|
||||
|
||||
cout <<" Recon signal size" << output.size() << endl;
|
||||
for (unsigned int i = 0; i < output.size(); i++){
|
||||
sig1 << output[i] << endl;
|
||||
diff << output[i] - original[i] << endl;
|
||||
|
||||
}
|
||||
//gnudwtplot(J);
|
||||
return 0;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
This sample program asks user for wavelet name, signal file and number of DWT stages. It then computes DWT of the input signal and then the IDWT from the wavelet coefficients so obtained.
|
||||

|
||||
|
||||
As can be seen, outputs are in _.txt_ format but they can be modified and plotted with any software of your choice.
|
||||
|
||||

|
||||
_Length 256 Piecewise Regular signal from WaveLab_
|
||||
|
||||

|
||||
_2 Level DWT Decomposition Coefficients obtained using db2 wavelet_
|
||||
|
||||

|
||||
_Reconstructed Signal After IDWT computations_
|
111
new1DSWTDemo.md
Normal file
111
new1DSWTDemo.md
Normal file
@ -0,0 +1,111 @@
|
||||
# 1D Stationary Wavelet Transform Demo #
|
||||
|
||||
Notes
|
||||
|
||||
1. dwt and dwt\_sym functions are interchangeable in the following code as they take the same arguments.
|
||||
|
||||
2. Please make sure that right header file is included. Following sample program links to wavelet2d.h which is the header for shared libraries. wavelet2s.h must be included for static libraries.
|
||||
|
||||
[Sample Code](http://code.google.com/p/wavelet1d/source/browse/trunk/wavelet2d/demo/swtdemo.cpp)
|
||||
|
||||
```
|
||||
|
||||
//============================================================================
|
||||
// Name : swtdemo.cpp
|
||||
// Author : Rafat Hussain
|
||||
// Version :
|
||||
// Copyright :
|
||||
// Description : 1D Stationary Wavelet Transform Demo
|
||||
//============================================================================
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include "wavelet2d.h"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <cmath>
|
||||
using namespace std;
|
||||
|
||||
int main() {
|
||||
cout << "********J- LEVEL DISCRETE WAVELET TRANSFORM IMPLEMENTATION*********" << endl; // prints
|
||||
cout << "This program accepts signal from the user in a file format " << endl;
|
||||
cout << "and performs Discrete Wavelet Transform with specified " << endl;
|
||||
cout << "wavelet. " << endl;
|
||||
cout << " " << endl;
|
||||
cout << " The Following Wavelets are in the Database: " << endl;
|
||||
cout << " haar, db1, db2, db3, db4, db5, db6, db7, db8, db9, db10, " << endl;
|
||||
cout << " db11, db12, db13, db14, db15. " << endl;
|
||||
cout << " bior1.1, bio1.3, bior1.5, bior2.2, bior2.4,bior2.6,bior2.8, " << endl;
|
||||
cout << " bior3.1, bior3.3, bior3.5, bior3.7, bior3.9, bior4.4," << endl;
|
||||
cout << " bior5.5, bior6.8." << endl;
|
||||
cout << " coif1, coif2, coif3, coif4, coif5." << endl;
|
||||
cout << "Please Enter the Wavelet Name at the Prompt( No quotes) :" << endl;
|
||||
|
||||
string nm; // nm will store the name of Wavelet Family
|
||||
cin >> nm;
|
||||
cout << "Enter the name of signal file at the Prompt eg., signal.txt :" << endl;
|
||||
char inp[50];
|
||||
cin >> inp;
|
||||
vector<double> sig;
|
||||
ifstream sig_inp(inp);
|
||||
if ( !sig_inp.good()){
|
||||
cout << "The File doesn't exist"<< endl;
|
||||
}
|
||||
while (sig_inp) {
|
||||
double temp;
|
||||
sig_inp >> temp;
|
||||
sig.push_back(temp);
|
||||
}
|
||||
sig.pop_back();
|
||||
vector<double> original;
|
||||
original = sig; // Make a copy of the signal if you want to use original signal
|
||||
// later on. The other option is to use IDWT output as the SWt/ISWT system is
|
||||
// Perefect Reconstruction system.
|
||||
cout << "Please Enter the Number of DWT Stages J :" << endl;
|
||||
|
||||
int J;
|
||||
cin >> J ;
|
||||
|
||||
vector<double> swt_output;
|
||||
|
||||
// perform J-Level DWT
|
||||
int length;// All coefficients are of same length. Variable "length" returns length
|
||||
// of coefficients. It is not required for ISWT computations.
|
||||
|
||||
|
||||
|
||||
swt(sig, J, nm, swt_output, length);
|
||||
|
||||
ofstream swtcoeff("swtcoeff.txt");
|
||||
for (unsigned int i=0; i < swt_output.size(); i++) {
|
||||
swtcoeff << swt_output[i] << endl;
|
||||
}
|
||||
vector<double> iswt_output;
|
||||
iswt(swt_output,J, nm,iswt_output);
|
||||
ofstream sig1("recon.txt");
|
||||
ofstream diff("diff.txt");
|
||||
|
||||
cout <<" Recon signal size" << iswt_output.size() << endl;
|
||||
for (unsigned int i = 0; i < iswt_output.size(); i++){
|
||||
sig1 << iswt_output[i] << endl;
|
||||
diff << iswt_output[i] - original[i] << endl;
|
||||
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||

|
||||
_Console Running swt demo_
|
||||
|
||||

|
||||
_Input Signal(Length-256)_
|
||||
|
||||

|
||||
_SWT Coefficients for two level of Decomposition(Length 3 X 256)_
|
||||
|
||||

|
||||
_Reconstructed Signal_
|
361
new2DAppx.md
Normal file
361
new2DAppx.md
Normal file
@ -0,0 +1,361 @@
|
||||
# Image Approximation #
|
||||
|
||||
_Note_
|
||||
|
||||
1. dwt\_2d and dwt\_2d\_sym functions are interchangeable in the following code as they take the same arguments. You may have to make some trivial modifications due to different sized output coeffficients.
|
||||
|
||||
2. Please make sure that right header file is included. Following sample program links to wavelet2s.h which is the header for static libraries. wavelet2d.h must be included for shared libraries.
|
||||
|
||||
3. I'm using [OPENCV](http://opencv.willowgarage.com/wiki/) to handle images as i already use OPENCV for other image processing work. You may want to use some simpler image libraries as OPENCV is a full image processing suite and is very bulky or you can just use 2D matrices/build your own image classes. Regardless, DWT/IDWT operations are more important than the choice of libraries.
|
||||
|
||||
[Sample Code](http://code.google.com/p/wavelet1d/source/browse/trunk/wavelet2d/demo/imagedemo2.cpp)
|
||||
|
||||
```
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <complex>
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
#include "wavelet2s.h"
|
||||
#include "cv.h"
|
||||
#include "highgui.h"
|
||||
#include "cxcore.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
|
||||
void findthresh(vector<double> &vector1, int N, double& t){
|
||||
sort(vector1.begin(), vector1.end(), greater<double>());
|
||||
t = vector1.at(N-1);
|
||||
}
|
||||
|
||||
void* maxval(vector<vector<double> > &arr, double &max){
|
||||
max = 0;
|
||||
for (unsigned int i =0; i < arr.size(); i++) {
|
||||
for (unsigned int j =0; j < arr[0].size(); j++) {
|
||||
if (max <= arr[i][j]){
|
||||
max = arr[i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* maxval1(vector<double> &arr, double &max){
|
||||
max = 0;
|
||||
for (unsigned int i =0; i < arr.size(); i++) {
|
||||
if (max <= arr[i]){
|
||||
max = arr[i];
|
||||
}
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int main() {
|
||||
IplImage* img = cvLoadImage("lena512.bmp");
|
||||
if (!img){
|
||||
cout << " Can't read Image. Try Different Format." << endl;
|
||||
exit(1);
|
||||
}
|
||||
int height, width;
|
||||
height = img->height;
|
||||
width = img->width;
|
||||
int nc = img->nChannels;
|
||||
// uchar* ptr2 =(uchar*) img->imageData;
|
||||
int pix_depth = img->depth;
|
||||
CvSize size;
|
||||
size.width =width;
|
||||
size.height=height;
|
||||
cout << "depth" << pix_depth << "Channels" << nc << endl;
|
||||
|
||||
|
||||
cvNamedWindow("Original Image", CV_WINDOW_AUTOSIZE);
|
||||
cvShowImage("Original Image", img);
|
||||
cvWaitKey();
|
||||
cvDestroyWindow("Original Image");
|
||||
cvSaveImage("orig.bmp",img);
|
||||
|
||||
|
||||
int rows =(int) height;
|
||||
int cols =(int) width;
|
||||
Mat matimg(img);
|
||||
|
||||
vector<vector<double> > vec1(rows, vector<double>(cols));
|
||||
|
||||
|
||||
int k =1;
|
||||
for (int i=0; i < rows; i++) {
|
||||
for (int j =0; j < cols; j++){
|
||||
unsigned char temp;
|
||||
temp = ((uchar*) matimg.data + i * matimg.step)[j * matimg.elemSize() + k ];
|
||||
vec1[i][j] = (double) temp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
string nm = "db2";
|
||||
vector<double> l1,h1,l2,h2;
|
||||
filtcoef(nm,l1,h1,l2,h2);
|
||||
// unsigned int lf=l1.size();
|
||||
// int rows_n =(int) (rows+ J*(lf-1));
|
||||
// int cols_n =(int) (cols + J * ( lf -1));
|
||||
|
||||
// Finding 2D DWT Transform of the image using symetric extension algorithm
|
||||
// Extension is set to 0 (eg., int e = 0)
|
||||
|
||||
vector<int> length;
|
||||
vector<double> output,flag;
|
||||
int J =6;
|
||||
dwt_2d(vec1,J,nm,output,flag,length);
|
||||
|
||||
double max;
|
||||
vector<int> length2;
|
||||
// This algorithm computes DWT of image of any given size. Together with convolution and
|
||||
// subsampling operations it is clear that subsampled images are of different length than
|
||||
// dyadic length images. In order to compute the "effective" size of DWT we do additional
|
||||
// calculations.
|
||||
dwt_output_dim_sym(length,length2,J);
|
||||
// length2 is gives the integer vector that contains the size of subimages that will
|
||||
// combine to form the displayed output image. The last two entries of length2 gives the
|
||||
// size of DWT ( rows_n by cols_n)
|
||||
|
||||
int siz = length2.size();
|
||||
int rows_n=length2[siz-2];
|
||||
int cols_n = length2[siz-1];
|
||||
|
||||
vector<vector< double> > dwtdisp(rows_n, vector<double>(cols_n));
|
||||
dispDWT(output,dwtdisp, length ,length2, J);
|
||||
|
||||
// dispDWT returns the 2D object dwtdisp which will be displayed using OPENCV's image
|
||||
// handling functions
|
||||
|
||||
vector<vector<double> > dwt_output= dwtdisp;
|
||||
|
||||
// Storing the DWT coefficients in two different vectors that will be used to approximate
|
||||
// Image with two different sets of chosen coefficients.
|
||||
|
||||
vector<double> dwt_coef1;
|
||||
vector<double> dwt_coef2;
|
||||
|
||||
dwt_coef1 = output;
|
||||
dwt_coef2 = output;
|
||||
|
||||
maxval(dwt_output,max);// max value is needed to take care of overflow which happens because
|
||||
// of convolution operations performed on unsigned 8 bit images
|
||||
|
||||
//Displaying Scaled Image
|
||||
// Creating Image in OPENCV
|
||||
IplImage *cvImg; // image used for output
|
||||
CvSize imgSize; // size of output image
|
||||
|
||||
imgSize.width = cols_n;
|
||||
imgSize.height = rows_n;
|
||||
|
||||
cvImg = cvCreateImage( imgSize, 8, 1 );
|
||||
// dwt_hold is created to hold the dwt output as further operations need to be
|
||||
// carried out on dwt_output in order to display scaled images.
|
||||
vector<vector<double> > dwt_hold(rows_n, vector<double>( cols_n));
|
||||
dwt_hold = dwt_output;
|
||||
// Setting coefficients of created image to the scaled DWT output values
|
||||
for (int i = 0; i < imgSize.height; i++ ) {
|
||||
for (int j = 0; j < imgSize.width; j++ ){
|
||||
if ( dwt_output[i][j] <= 0.0){
|
||||
dwt_output[i][j] = 0.0;
|
||||
}
|
||||
if ( i <= (length2[0]) && j <= (length2[1]) ) {
|
||||
((uchar*)(cvImg->imageData + cvImg->widthStep*i))[j] =
|
||||
(char) ( (dwt_output[i][j] / max) * 255.0);
|
||||
} else {
|
||||
((uchar*)(cvImg->imageData + cvImg->widthStep*i))[j] =
|
||||
(char) (dwt_output[i][j]) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cvNamedWindow( "DWT Image", 1 ); // creation of a visualisation window
|
||||
cvShowImage( "DWT Image", cvImg ); // image visualisation
|
||||
cvWaitKey();
|
||||
cvDestroyWindow("DWT Image");
|
||||
cvSaveImage("dwt.bmp",cvImg);
|
||||
|
||||
// Case 1 : Only 10% of the largest coefficients are considered
|
||||
|
||||
// Output is the 1D DWT vector
|
||||
|
||||
int n_coef1= int (output.size()/ 10);
|
||||
cout << n_coef1 << endl;
|
||||
|
||||
// Finding Threshold Value corresponding to n_coef1
|
||||
|
||||
vector<double> temp1;
|
||||
cout << "size: " << (int) temp1.size() << "\n";
|
||||
cout << "capacity: " << (int) temp1.capacity() << "\n";
|
||||
cout << "max_size: " << (int) temp1.max_size() << "\n";
|
||||
for (unsigned int i =0; i < dwt_coef1.size(); i++) {
|
||||
double tempval = abs(dwt_coef1[i]);
|
||||
temp1.push_back(tempval);
|
||||
|
||||
}
|
||||
|
||||
double thresh1= 0.0;
|
||||
findthresh(temp1,n_coef1,thresh1);
|
||||
cout << "thresh" << thresh1 << endl;
|
||||
|
||||
ofstream temp("temp.txt");
|
||||
for (unsigned int i =0; i < temp1.size(); i++){
|
||||
temp << temp1[i] << " " ;
|
||||
}
|
||||
|
||||
// Reset coeffficients value depending on threshold value
|
||||
|
||||
|
||||
for (unsigned int i =0; i < dwt_coef1.size(); i++) {
|
||||
double temp = abs(dwt_coef1[i]);
|
||||
|
||||
if (temp < thresh1){
|
||||
dwt_coef1.at(i)= 0.0;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Finding IDWT
|
||||
|
||||
vector<vector<double> > idwt_output(rows, vector<double>(cols));
|
||||
|
||||
idwt_2d( dwt_coef1,flag, nm, idwt_output,length);
|
||||
|
||||
double max1;
|
||||
maxval(idwt_output,max1);
|
||||
|
||||
//Displaying Reconstructed Image
|
||||
|
||||
IplImage *dvImg;
|
||||
CvSize dvSize; // size of output image
|
||||
|
||||
dvSize.width = idwt_output[0].size();
|
||||
dvSize.height = idwt_output.size();
|
||||
|
||||
cout << idwt_output.size() << idwt_output[0].size() << endl;
|
||||
dvImg = cvCreateImage( dvSize, 8, 1 );
|
||||
|
||||
for (int i = 0; i < dvSize.height; i++ ){
|
||||
for (int j = 0; j < dvSize.width; j++ ){
|
||||
if ( idwt_output[i][j] <= 0.0){
|
||||
idwt_output[i][j] = 0.0;
|
||||
}
|
||||
((uchar*)(dvImg->imageData + dvImg->widthStep*i))[j] =
|
||||
(char) ((idwt_output[i][j] / max1) * 255 ) ;
|
||||
}
|
||||
}
|
||||
|
||||
cvNamedWindow( "10% Coeff Reconstructed Image", 1 ); // creation of a visualisation window
|
||||
cvShowImage( "10% Coeff Reconstructed Image", dvImg ); // image visualisation
|
||||
cvWaitKey();
|
||||
cvDestroyWindow("10% Coeff Reconstructed Image");
|
||||
cvSaveImage("recon.bmp",dvImg);
|
||||
|
||||
|
||||
// Case 2 : Only 2% of the largest coefficients are considered
|
||||
|
||||
// Output is the 1D DWT vector
|
||||
|
||||
int n_coef2= int (output.size()/ 50);
|
||||
cout << n_coef2 << endl;
|
||||
|
||||
// Finding Threshold Value corresponding to n_coef1
|
||||
|
||||
vector<double> temp2;
|
||||
|
||||
for (unsigned int i =0; i < dwt_coef2.size(); i++) {
|
||||
double tempval = abs(dwt_coef2[i]);
|
||||
temp2.push_back(tempval);
|
||||
|
||||
}
|
||||
|
||||
double thresh2= 0.0;
|
||||
findthresh(temp2,n_coef2,thresh2);
|
||||
cout << "thresh" << thresh2 << endl;
|
||||
|
||||
|
||||
// Reset coeffficients value depending on threshold value
|
||||
|
||||
|
||||
for (unsigned int i =0; i < dwt_coef2.size(); i++) {
|
||||
double temp = abs(dwt_coef2[i]);
|
||||
|
||||
if (temp < thresh2){
|
||||
dwt_coef2.at(i)= 0.0;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Finding IDWT
|
||||
|
||||
vector<vector<double> > idwt_output2(rows, vector<double>(cols));
|
||||
|
||||
idwt_2d( dwt_coef2,flag, nm, idwt_output2,length);
|
||||
|
||||
double max2;
|
||||
maxval(idwt_output2,max2);
|
||||
|
||||
|
||||
|
||||
//Displaying Reconstructed Image
|
||||
|
||||
IplImage *dvImg2;
|
||||
CvSize dvSize2; // size of output image
|
||||
|
||||
dvSize2.width = idwt_output2[0].size();
|
||||
dvSize2.height = idwt_output2.size();
|
||||
|
||||
cout << idwt_output2.size() << idwt_output2[0].size() << endl;
|
||||
dvImg2 = cvCreateImage( dvSize2, 8, 1 );
|
||||
|
||||
for (int i = 0; i < dvSize2.height; i++ ) {
|
||||
for (int j = 0; j < dvSize2.width; j++ ) {
|
||||
if ( idwt_output2[i][j] <= 0.0){
|
||||
idwt_output2[i][j] = 0.0;
|
||||
}
|
||||
((uchar*)(dvImg2->imageData + dvImg2->widthStep*i))[j] =
|
||||
(char) ((idwt_output2[i][j]/ max2) * 255 ) ;
|
||||
}
|
||||
}
|
||||
|
||||
cvNamedWindow( "2% Coeff Reconstructed Image", 1 ); // creation of a visualisation window
|
||||
cvShowImage( "2% Coeff Reconstructed Image", dvImg2 ); // image visualisation
|
||||
cvWaitKey();
|
||||
cvDestroyWindow("2% Coeff Reconstructed Image");
|
||||
cvSaveImage("recon2.bmp",dvImg2);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
This code decomposes a 512X512 grayscale image to 6 levels using db2 wavelets and uses a) only 10% coefficients and b) only 2% coefficients to reconstruct the image.
|
||||
|
||||
Input Image
|
||||
|
||||

|
||||
|
||||
DWT of Input Image
|
||||
|
||||

|
||||
|
||||
Image Approximation using only 10% coefficients
|
||||
|
||||

|
||||
|
||||
Image Approximation using only 2% coefficients.
|
||||
|
||||

|
216
new2DDWTdemo.md
Normal file
216
new2DDWTdemo.md
Normal file
@ -0,0 +1,216 @@
|
||||
# 2D DWT/IDWT Demo #
|
||||
|
||||
_Notes_
|
||||
|
||||
1. dwt\_2d and dwt\_2d\_sym functions are interchangeable in the following code as they take the same arguments.
|
||||
|
||||
2. Please make sure that right header file is included. Following sample program links to wavelet2d.h which is the header for shared libraries. wavelet2s.h must be included for static libraries.
|
||||
|
||||
3. I'm using [OPENCV](http://opencv.willowgarage.com/wiki/) to handle images as i already use OPENCV for other image processing work. You may want to use some simpler image libraries as OPENCV is a full image processing suite and is very bulky or you can just use 2D matrices/build your own image classes. Regardless, DWT/IDWT operations are more important than the choice of libraries.
|
||||
|
||||
[Sample Code](http://code.google.com/p/wavelet1d/source/browse/trunk/wavelet2d/demo/imagedemo1.cpp)
|
||||
|
||||
```
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <complex>
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
#include "wavelet2d.h"
|
||||
#include "cv.h"
|
||||
#include "highgui.h"
|
||||
#include "cxcore.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
|
||||
void* maxval(vector<vector<double> > &arr, double &max){
|
||||
max = 0;
|
||||
for (unsigned int i =0; i < arr.size(); i++) {
|
||||
for (unsigned int j =0; j < arr[0].size(); j++) {
|
||||
if (max <= arr[i][j]){
|
||||
max = arr[i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* maxval1(vector<double> &arr, double &max){
|
||||
max = 0;
|
||||
for (unsigned int i =0; i < arr.size(); i++) {
|
||||
if (max <= arr[i]){
|
||||
max = arr[i];
|
||||
}
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int main() {
|
||||
IplImage* img = cvLoadImage("snow.jpg");
|
||||
if (!img){
|
||||
cout << " Can't read Image. Try Different Format." << endl;
|
||||
exit(1);
|
||||
}
|
||||
int height, width;
|
||||
height = img->height;
|
||||
width = img->width;
|
||||
int nc = img->nChannels;
|
||||
// uchar* ptr2 =(uchar*) img->imageData;
|
||||
int pix_depth = img->depth;
|
||||
CvSize size;
|
||||
size.width =width;
|
||||
size.height=height;
|
||||
cout << "depth" << pix_depth << "Channels" << nc << endl;
|
||||
|
||||
|
||||
cvNamedWindow("Original Image", CV_WINDOW_AUTOSIZE);
|
||||
cvShowImage("Original Image", img);
|
||||
cvWaitKey();
|
||||
cvDestroyWindow("Original Image");
|
||||
cvSaveImage("orig.bmp",img);
|
||||
|
||||
|
||||
int rows =(int) height;
|
||||
int cols =(int) width;
|
||||
Mat matimg(img);
|
||||
|
||||
vector<vector<double> > vec1(rows, vector<double>(cols));
|
||||
|
||||
|
||||
int k =1;
|
||||
for (int i=0; i < rows; i++) {
|
||||
for (int j =0; j < cols; j++){
|
||||
unsigned char temp;
|
||||
temp = ((uchar*) matimg.data + i * matimg.step)[j * matimg.elemSize() + k ];
|
||||
vec1[i][j] = (double) temp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
string nm = "db3";
|
||||
vector<double> l1,h1,l2,h2;
|
||||
filtcoef(nm,l1,h1,l2,h2);
|
||||
// unsigned int lf=l1.size();
|
||||
// int rows_n =(int) (rows+ J*(lf-1));
|
||||
// int cols_n =(int) (cols + J * ( lf -1));
|
||||
|
||||
// Finding 2D DWT Transform of the image using symetric extension algorithm
|
||||
// Extension is set to 3 (eg., int e = 3)
|
||||
|
||||
vector<int> length;
|
||||
vector<double> output,flag;
|
||||
int J =3;
|
||||
dwt_2d_sym(vec1,J,nm,output,flag,length);
|
||||
|
||||
double max;
|
||||
vector<int> length2;
|
||||
// This algorithm computes DWT of image of any given size. Together with convolution and
|
||||
// subsampling operations it is clear that subsampled images are of different length than
|
||||
// dyadic length images. In order to compute the "effective" size of DWT we do additional
|
||||
// calculations.
|
||||
dwt_output_dim_sym(length,length2,J);
|
||||
// length2 is gives the integer vector that contains the size of subimages that will
|
||||
// combine to form the displayed output image. The last two entries of length2 gives the
|
||||
// size of DWT ( rows_n by cols_n)
|
||||
|
||||
int siz = length2.size();
|
||||
int rows_n=length2[siz-2];
|
||||
int cols_n = length2[siz-1];
|
||||
|
||||
vector<vector< double> > dwtdisp(rows_n, vector<double>(cols_n));
|
||||
dispDWT(output,dwtdisp, length ,length2, J);
|
||||
|
||||
// dispDWT returns the 2D object dwtdisp which will be displayed using OPENCV's image
|
||||
// handling functions
|
||||
|
||||
vector<vector<double> > dwt_output= dwtdisp;
|
||||
|
||||
maxval(dwt_output,max);// max value is needed to take care of overflow which happens because
|
||||
// of convolution operations performed on unsigned 8 bit images
|
||||
|
||||
//Displaying Scaled Image
|
||||
// Creating Image in OPENCV
|
||||
IplImage *cvImg; // image used for output
|
||||
CvSize imgSize; // size of output image
|
||||
|
||||
imgSize.width = cols_n;
|
||||
imgSize.height = rows_n;
|
||||
|
||||
cvImg = cvCreateImage( imgSize, 8, 1 );
|
||||
// dwt_hold is created to hold the dwt output as further operations need to be
|
||||
// carried out on dwt_output in order to display scaled images.
|
||||
vector<vector<double> > dwt_hold(rows_n, vector<double>( cols_n));
|
||||
dwt_hold = dwt_output;
|
||||
// Setting coefficients of created image to the scaled DWT output values
|
||||
for (int i = 0; i < imgSize.height; i++ ) {
|
||||
for (int j = 0; j < imgSize.width; j++ ){
|
||||
if ( dwt_output[i][j] <= 0.0){
|
||||
dwt_output[i][j] = 0.0;
|
||||
}
|
||||
if ( i <= (length2[0]) && j <= (length2[1]) ) {
|
||||
((uchar*)(cvImg->imageData + cvImg->widthStep*i))[j] =
|
||||
(char) ( (dwt_output[i][j] / max) * 255.0);
|
||||
} else {
|
||||
((uchar*)(cvImg->imageData + cvImg->widthStep*i))[j] =
|
||||
(char) (dwt_output[i][j]) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cvNamedWindow( "DWT Image", 1 ); // creation of a visualisation window
|
||||
cvShowImage( "DWT Image", cvImg ); // image visualisation
|
||||
cvWaitKey();
|
||||
cvDestroyWindow("DWT Image");
|
||||
cvSaveImage("dwt.bmp",cvImg);
|
||||
|
||||
// Finding IDWT
|
||||
|
||||
vector<vector<double> > idwt_output(rows, vector<double>(cols));
|
||||
|
||||
idwt_2d_sym(output,flag, nm, idwt_output,length);
|
||||
|
||||
|
||||
|
||||
//Displaying Reconstructed Image
|
||||
|
||||
IplImage *dvImg;
|
||||
CvSize dvSize; // size of output image
|
||||
|
||||
dvSize.width = idwt_output[0].size();
|
||||
dvSize.height = idwt_output.size();
|
||||
|
||||
cout << idwt_output.size() << idwt_output[0].size() << endl;
|
||||
dvImg = cvCreateImage( dvSize, 8, 1 );
|
||||
|
||||
for (int i = 0; i < dvSize.height; i++ )
|
||||
for (int j = 0; j < dvSize.width; j++ )
|
||||
((uchar*)(dvImg->imageData + dvImg->widthStep*i))[j] =
|
||||
(char) (idwt_output[i][j]) ;
|
||||
|
||||
cvNamedWindow( "Reconstructed Image", 1 ); // creation of a visualisation window
|
||||
cvShowImage( "Reconstructed Image", dvImg ); // image visualisation
|
||||
cvWaitKey();
|
||||
cvDestroyWindow("Reconstructed Image");
|
||||
cvSaveImage("recon.bmp",dvImg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Input Image is a low resolution 250X189 grayscale snow.jpg image.
|
||||
|
||||

|
||||
_Input 250X189 Image_
|
||||
|
||||

|
||||
_3-Level Decomposition using db3 wavelet_
|
||||
|
||||

|
||||
_Perfectly Reconstructed Image_
|
198
new2DSWTdemo.md
Normal file
198
new2DSWTdemo.md
Normal file
@ -0,0 +1,198 @@
|
||||
# 2D Stationary Wavelet Transform #
|
||||
|
||||
_Notes_
|
||||
|
||||
1. dwt\_2d and dwt\_2d\_sym functions are interchangeable in the following code as they take the same arguments.
|
||||
|
||||
2. Please make sure that right header file is included. Following sample program links to wavelet2d.h which is the header for shared libraries. wavelet2s.h must be included for static libraries.
|
||||
|
||||
3. I'm using OPENCV to handle images as i already use [OPENCV](http://opencv.willowgarage.com/wiki/) for other image processing work. You may want to use some simpler image libraries as OPENCV is a full image processing suite and is very bulky or you can just use 2D matrices/build your own image classes. Regardless, DWT/IDWT operations are more important than the choice of libraries.
|
||||
|
||||
[Sample Code](http://code.google.com/p/wavelet1d/source/browse/trunk/wavelet2d/demo/swt2Ddemo.cpp)
|
||||
|
||||
```
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <complex>
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
#include "wavelet2d.h"
|
||||
#include "cv.h"
|
||||
#include "highgui.h"
|
||||
#include "cxcore.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
|
||||
void* maxval(vector<vector<double> > &arr, double &max){
|
||||
max = 0;
|
||||
for (unsigned int i =0; i < arr.size(); i++) {
|
||||
for (unsigned int j =0; j < arr[0].size(); j++) {
|
||||
if (max <= arr[i][j]){
|
||||
max = arr[i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main() {
|
||||
IplImage* img = cvLoadImage("lena512.bmp");
|
||||
if (!img){
|
||||
cout << " Can't read Image. Try Different Format." << endl;
|
||||
exit(1);
|
||||
}
|
||||
int height, width;
|
||||
height = img->height;
|
||||
width = img->width;
|
||||
int nc = img->nChannels;
|
||||
// uchar* ptr2 =(uchar*) img->imageData;
|
||||
int pix_depth = img->depth;
|
||||
CvSize size;
|
||||
size.width =width;
|
||||
size.height=height;
|
||||
cout << "depth" << pix_depth << "Channels" << nc << endl;
|
||||
|
||||
|
||||
cvNamedWindow("Original Image", CV_WINDOW_AUTOSIZE);
|
||||
cvShowImage("Original Image", img);
|
||||
cvWaitKey();
|
||||
cvDestroyWindow("Original Image");
|
||||
cvSaveImage("orig.bmp",img);
|
||||
|
||||
|
||||
int rows =(int) height;
|
||||
int cols =(int) width;
|
||||
Mat matimg(img);
|
||||
|
||||
vector<vector<double> > vec1(rows, vector<double>(cols));
|
||||
|
||||
|
||||
int k =1;
|
||||
for (int i=0; i < rows; i++) {
|
||||
for (int j =0; j < cols; j++){
|
||||
unsigned char temp;
|
||||
temp = ((uchar*) matimg.data + i * matimg.step)[j * matimg.elemSize() + k ];
|
||||
vec1[i][j] = (double) temp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
string nm = "db2";
|
||||
// vector<double> l1,h1,l2,h2;
|
||||
// filtcoef(nm,l1,h1,l2,h2);
|
||||
|
||||
|
||||
vector<double> output;
|
||||
int J =3;
|
||||
swt_2d(vec1,J,nm,output);
|
||||
cout << "OUTPUT size" << output.size() << endl;
|
||||
cout << "LOOP OK" << endl;
|
||||
|
||||
int row,col;
|
||||
row=vec1.size();
|
||||
col=vec1[0].size();
|
||||
|
||||
// Extract and Display Low Pass Image at the Jth stage
|
||||
|
||||
vector<vector<double> > blur(row,vector<double>(col));
|
||||
|
||||
for (int i=0;i < row; i++){
|
||||
for (int j=0; j < col;j++){
|
||||
double temp = output[i*col + j];
|
||||
blur[i][j]= temp;
|
||||
}
|
||||
}
|
||||
|
||||
double max;
|
||||
maxval(blur,max);
|
||||
|
||||
// Creating Image in OPENCV
|
||||
IplImage *cvImg; // image used for output
|
||||
CvSize imgSize; // size of output image
|
||||
|
||||
imgSize.width = col;
|
||||
imgSize.height = row;
|
||||
|
||||
cvImg = cvCreateImage( imgSize, 8, 1 );
|
||||
|
||||
for (int i = 0; i < imgSize.height; i++ ) {
|
||||
for (int j = 0; j < imgSize.width; j++ ){
|
||||
if ( blur[i][j] <= 0.0){
|
||||
blur[i][j] = 0.0;
|
||||
}
|
||||
|
||||
((uchar*)(cvImg->imageData + cvImg->widthStep*i))[j] =
|
||||
(char) ( (blur[i][j] / max) * 255.0);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
cvNamedWindow( "Low Pass Image", 1 ); // creation of a visualisation window
|
||||
cvShowImage( "Low Pass Image", cvImg ); // image visualisation
|
||||
cvWaitKey();
|
||||
cvDestroyWindow("Low Pass Image");
|
||||
cvSaveImage("blur.bmp",cvImg);
|
||||
|
||||
// Displaying BandPass Images
|
||||
|
||||
vector<vector<double> > detail(3*row,vector<double>(J * col));
|
||||
|
||||
for (int k=0; k < J; k++) {
|
||||
for (int i=0; i < 3*row; i++) {
|
||||
for(int j=0+ k*col; j < (k+1)*col; j++) {
|
||||
double temp = output[(3*k+1)*row*col+ i * col +j - k*col];
|
||||
detail[i][j]= temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
IplImage *dvImg; // image used for output
|
||||
CvSize imgSz; // size of output image
|
||||
|
||||
imgSz.width = J*col;
|
||||
imgSz.height = 3*row;
|
||||
|
||||
dvImg = cvCreateImage( imgSz, 8, 1 );
|
||||
|
||||
for (int i = 0; i < imgSz.height; i++ ) {
|
||||
for (int j = 0; j < imgSz.width; j++ ){
|
||||
if ( detail[i][j] <= 0.0){
|
||||
detail[i][j] = 0.0;
|
||||
}
|
||||
|
||||
((uchar*)(dvImg->imageData + dvImg->widthStep*i))[j] =
|
||||
(char) detail[i][j];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
cvNamedWindow( "Band Pass Image", 1 ); // creation of a visualisation window
|
||||
cvShowImage( "Band Pass Image", dvImg ); // image visualisation
|
||||
cvWaitKey();
|
||||
cvDestroyWindow("Band Pass Image");
|
||||
cvSaveImage("detail.bmp",dvImg);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Three level Stationary Wavelet Transform is computed using db2 wavelet. Approximation coefficients are stored only for the final (J=3) stage while the three detail coefficients( Horizontal, Vertical and Diagonal) are stored for each value. All 10 sets of coefficients are 512X512.
|
||||
|
||||
Input Image
|
||||
|
||||

|
||||
|
||||
Approximation Coefficient at level J = 3
|
||||
|
||||

|
||||
|
||||
Detail Coefficients at Levels 3,2,1(L-R). Coefficients are arranged Horizontally,Vertically and Diagonally from top to bottom.
|
||||
|
||||

|
||||
|
||||
_Resized Image (Actual Dimensions 1536X1536)_
|
279
newfunc.md
Normal file
279
newfunc.md
Normal file
@ -0,0 +1,279 @@
|
||||
# List of Functions for wavelet2d Library #
|
||||
|
||||
## 1D DWT/IDWT Functions ##
|
||||
|
||||
Both periodic and symmetric extension methods for Decimated DWT take exactly same input arguments.The difference is that Output vector in periodic extension has usually the same size (~N) as the input vector(N) while output vector in symmetric extension case has redundancies with length depending on size of filter used.
|
||||
|
||||
### Periodic Extension ###
|
||||
|
||||
**1. DWT:** `void* dwt(vector<double> &sig, int J, string nm, vector<double> &dwt_output,vector<double> &flag, vector<int> &length )`
|
||||
|
||||
where,
|
||||
|
||||
_**sig**_ :: _Input Signal vector_
|
||||
|
||||
_**J**_ :: _Decomposition levels_
|
||||
|
||||
_**nm**_ :: _Wavelet Name_ _(See filtcoef for available wavelet families)_
|
||||
|
||||
_**length**_ :: _Lengths of respective approximation and detail vectors are stored in this integer vector._
|
||||
|
||||
_**dwt\_output**_ :: _Output of Discrete Wavelet Transform. It stores coefficients in following format:_
|
||||
|
||||
**`[A(J) D(J) D(J-1) ..... D(1)]`**
|
||||
|
||||
_where **A(J)** is the approximation coefficient vector at the Jth level while **D(n)** are the detail coefficient vectors at the nth level._**length**_contains the lengths of corresponding vectors. Last entry of the_**length**_vector is the length of the original signal._
|
||||
|
||||
_**flag**_ :: _Housekeeping vector. In this implementation it contains two values-_
|
||||
|
||||
_flag[0](0.md) is 0 if the signal is even and it is 1 if signal is odd and if it is made even by repeating the last value one more time_
|
||||
|
||||
_flag[1](1.md) - contains the decomposition levels._
|
||||
|
||||
_Housekeeping vector is a double vector as it was originally meant to store more values than it currently does_
|
||||
|
||||

|
||||
_DWT stats (periodic extension) for an input signal of length 256_
|
||||
|
||||
|
||||
|
||||
**2. IDWT:** `void* idwt(vector<double> &dwtop,vector<double> &flag, string nm,vector<double> &idwt_output,vector<int> &length)`
|
||||
|
||||
where,
|
||||
|
||||
_**dwtop**_ :: _is the DWT vector_
|
||||
|
||||
_**flag**_ :: _Same Housekeeping function as obtained from the DWT function_
|
||||
|
||||
_**nm**_ :: _Wavelet Used_
|
||||
|
||||
_**idwt\_output**_ :: _Output of IDWT_
|
||||
|
||||
_**length**_ :: _Length vector obtained from the DWT computations_
|
||||
|
||||
### Symmetric Extension ###
|
||||
|
||||
**3. DWT:** `void* dwt_sym(vector<double> &sig, int J, string nm, vector<double> &dwt_output,vector<double> &flag, vector<int> &length )`
|
||||
|
||||
where,
|
||||
|
||||
_**sig**_ :: _Input Signal vector_
|
||||
|
||||
_**J**_ :: _Decomposition levels_
|
||||
|
||||
_**nm**_ :: _Wavelet Name_ _(See filtcoef for available wavelet families)_
|
||||
|
||||
_**length**_ :: _Lengths of respective approximation and detail vectors are stored in this integer vector._
|
||||
|
||||
_**dwt\_output**_ :: _Output of Discrete Wavelet Transform. It stores coefficients in following format:_
|
||||
|
||||
**`[A(J) D(J) D(J-1) ..... D(1)]`**
|
||||
|
||||
_where **A(J)** is the approximation coefficient vector at the Jth level while **D(n)** are the detail coefficient vectors at the nth level._**length**_contains the lengths of corresponding vectors. Last entry of the_**length**_vector is the length of the original signal._
|
||||
|
||||
_**flag**_ :: _Housekeeping vector. In this implementation it contains two values-_
|
||||
|
||||
_flag[0](0.md) is 0 if the signal is even and it is 1 if signal is odd and if it is made even by repeating the last value one more time_
|
||||
|
||||
_flag[1](1.md) - contains the decomposition levels._
|
||||
|
||||
_Housekeeping vector is a double vector as it was originally meant to store more values than it currently does_
|
||||
|
||||
_**idwt\_output**_ :: _Output of the Inverse Discrete Wavelet Transform_
|
||||
|
||||
_**length**_ :: _Length Vector Obtained from the DWT computations_
|
||||
|
||||

|
||||
_DWT stats (symmetric extension) for an input signal of length 256_
|
||||
|
||||
**4. IDWT:** `void* idwt_sym(vector<double> &dwtop,vector<double> &flag, string nm,vector<double> &idwt_output,vector<int> &length)`
|
||||
|
||||
where,
|
||||
|
||||
_**dwtop**_ :: _is the DWT vector_
|
||||
|
||||
_**flag**_ :: _Same Housekeeping function as obtained from the DWT function_
|
||||
|
||||
_**nm**_ :: _Wavelet Used_
|
||||
|
||||
_**idwt\_output**_ :: _Output of IDWT_
|
||||
|
||||
_**length**_ :: _Length vector obtained from the DWT computations_
|
||||
|
||||
## 1D SWT/ISWT Functions ##
|
||||
|
||||
**5. SWT:** `void* swt(vector<double> &sig, int J, string nm, vector<double> &swt_output, int &length)`
|
||||
|
||||
> All the coefficients are of equal lengths and that value is stored in _**length**_. _**swt\_output**_ stores value in the same format as _**dwt**_ and _**dwt\_sym**_ functions - Approximation coefficient vector at level J is stored at the beginning of the **swt\_output** vector followed by detail coefficients vectors at levels J, J-1,...., 1. The signal length has to be divisible by 2^J for reliable results. You can use signal extension (see below) to make the lengths compatible with the SWT.
|
||||
|
||||
_Two Level SWT Decomposition of a 247 length signal vector_
|
||||
|
||||
**6. ISWT:** `void* iswt(vector<double> &swtop,int J, string nm, vector<double> &iswt_output)`
|
||||
|
||||
|
||||
_**swtop**_ is the output of SWT stage , _**J**_ - number of levels and _**nm**_ is the wavelet as before. Output of ISWT is stored in _**iswt\_output**_ vector.
|
||||
|
||||
## 2D DWT/IDWT Functions ##
|
||||
|
||||
As in 1D case, both periodic and symmetric extension methods for Decimated DWT take exactly same input arguments.The difference is that Output vector in periodic extension has usually the same size (~NXN) as the input vector(NXN) while output vector in symmetric extension case has redundancies with length/breadth depending on size of filter used.
|
||||
|
||||
### Periodic Extension ###
|
||||
|
||||
**7. 2D DWT:** `void* dwt_2d(vector<vector<double> > &origsig, int J, string nm, vector<double> &dwt_output,vector<double> &flag, vector<int> &length) `
|
||||
|
||||
_**origsig**_ :: _Input Image/Matrix_
|
||||
|
||||
_**J**_ :: _Number of Decomposition Levels_
|
||||
|
||||
_**nm**_ :: _Wavelet Name_
|
||||
|
||||
_**flag**_ :: _Stores values for IDWT function.Only flag[0](0.md) value is important as it contains decomposition levels._
|
||||
|
||||
_**dwt\_output**_ :: _1D vector that stores the output in the following format
|
||||
**A(J) D<sub>h</sub>(J) D<sub>v</sub>(J) D<sub>d</sub>(J) ..... D<sub>h</sub>(1) D<sub>v</sub>(1) D<sub>d</sub>(1)**_
|
||||
|
||||
where _**A(J)**_ is the approximation coefficient vector at the Jth level while _**D(n)**_ are the three detail coefficient vectors(horizontal,vertical and detail) at the nth level. It is important to remember that approximation and detail coefficients are actually two dimensional so we need a length vector that stores rows and columns values of each coefficient element. The length vector is given by _**length**_.
|
||||
|
||||
For example, the first element of _**output**_ vector is the approximation matrix stored as a vector and the first two elements of _**length**_ vectors are row and column values of the approximation matrix. In other words, a 300 element approximation matrix ( 15 rows X 20 columns) can be extracted from the 300 element approximation vector.
|
||||
|
||||

|
||||
_2D DWT computation using periodic extension_
|
||||
|
||||
**8. 2D IDWT:** `void* idwt_2d(vector<double> &dwtop,vector<double> &flag, string nm,vector<vector<double> > &idwt_output, vector<int> &length)`
|
||||
|
||||
where,
|
||||
|
||||
_**dwtop**_ :: _is the DWT vector_
|
||||
|
||||
_**flag**_ :: _Same Housekeeping function as obtained from the DWT function_
|
||||
|
||||
_**nm**_ :: _Wavelet Used_
|
||||
|
||||
_**idwt\_output**_ :: _Output of IDWT which should be defined to have the same number of rows and columns as the input image/matrix_
|
||||
|
||||
_**length**_ :: _Length vector obtained from the DWT computations_
|
||||
|
||||
### Symmetric Extension ###
|
||||
|
||||
**9. 2D DWT:** `void* dwt_2d_sym(vector<vector<double> > &origsig, int J, string nm, vector<double> &dwt_output,vector<double> &flag, vector<int> &length) `
|
||||
|
||||
_**origsig**_ :: _Input Image/Matrix_
|
||||
|
||||
_**J**_ :: _Number of Decomposition Levels_
|
||||
|
||||
_**nm**_ :: _Wavelet Name_
|
||||
|
||||
_**flag**_ :: _Stores values for IDWT function.Only flag[0](0.md) value is important as it contains decomposition levels._
|
||||
|
||||
_**dwt\_output**_ :: _1D vector that stores the output in the following format
|
||||
**A(J) D<sub>h</sub>(J) D<sub>v</sub>(J) D<sub>d</sub>(J) ..... D<sub>h</sub>(1) D<sub>v</sub>(1) D<sub>d</sub>(1)**_
|
||||
|
||||
where _**A(J)**_ is the approximation coefficient vector at the Jth level while _**D(n)**_ are the three detail coefficient vectors(horizontal,vertical and detail) at the nth level. It is important to remember that approximation and detail coefficients are actually two dimensional so we need a length vector that stores rows and columns values of each coefficient element. The length vector is given by _**length**_.
|
||||
|
||||
For example, the first element of _**output**_ vector is the approximation matrix stored as a vector and the first two elements of _**length**_ vectors are row and column values of the approximation matrix. In other words, a 300 element approximation matrix ( 15 rows X 20 columns) can be extracted from the 300 element approximation vector.
|
||||
|
||||

|
||||
_2D DWT computation using symmetric extension_
|
||||
|
||||
**10. 2D IDWT:** `void* idwt_2d_sym(vector<double> &dwtop,vector<double> &flag, string nm,vector<vector<double> > &idwt_output, vector<int> &length)`
|
||||
|
||||
where,
|
||||
|
||||
_**dwtop**_ :: _is the DWT vector_
|
||||
|
||||
_**flag**_ :: _Same Housekeeping function as obtained from the DWT function_
|
||||
|
||||
_**nm**_ :: _Wavelet Used_
|
||||
|
||||
_**idwt\_output**_ :: _Output of IDWT which should be defined to have the same number of rows and columns as the input image/matrix_
|
||||
|
||||
_**length**_ :: _Length vector obtained from the DWT computations_
|
||||
|
||||
## 2D SWT Function ##
|
||||
|
||||
**11. 2D SWT:** `void* swt_2d(vector<vector<double> > &sig,int J, string nm, vector<double> &swt_output)`
|
||||
|
||||
_**swt\_output**_ is a 1D vector which is arranged the same way as DWT output vector in the Decimated 2D cases above except that in this case all coefficients are of same size. This is a highly redundant transform as a three level decomposition of a 512X512 image results in 10 512X512 images - one approximation image and 9 detail images (three at each level).
|
||||
|
||||
## Convolution ##
|
||||
|
||||
**12. Convolution FFT\_ESTIMATE (Recommended):** `double convfft(vector<double> &a, vector<double> &b, vector<double> &c)`
|
||||
|
||||
Convolution function is pretty straightforward. _**a**_ and _**b**_ are input vectors and _**c**_ is the convolution output. _**convfft**_ uses FFT so it gives better results in most cases than the regular convolution which is implemented by _**convol**_ function.
|
||||
|
||||
|
||||
**13. Convolution Direct** (Use it for only smaller vectors)**:** `double convol(vector<double> &a, vector<double> &b, vector<double> &c)`
|
||||
|
||||
|
||||
**14. Convolution FFT\_MEASURE** (Recommended if you are going to perform convolutions of same length hundreds or thousands of time in one program)**:** `double convfftm(vector<double> &a, vector<double> &b, vector<double> &c)`
|
||||
|
||||
_**convfftm**_ is performed using MEASUREing capabilities of FFTW3 library so it is not recommended if you are going to convolve two vectors only once. This has some overhead but gives good results if multiple instances of same convolution are performed repeatedly.
|
||||
|
||||
## Wavelet Filters ##
|
||||
|
||||
**15. Filters:** `int filtcoef(string nm, vector<double> &lpd, vector<double> &hpd, vector<double> &lpr, vector<double> &hpr)`
|
||||
|
||||
|
||||
_**nm:**_ Wavelet name.
|
||||
|
||||
_**lpd:**_ Low Pass Decomposition Filter Coefficients.
|
||||
|
||||
_**hpd:**_ High Pass Decomposition Filter Coefficients.
|
||||
|
||||
_**lpr:**_ Low Pass Reconstruction Filter Coefficients.
|
||||
|
||||
_**hpr:**_ High Pass Reconstruction Filter Coefficients.
|
||||
|
||||
All filters are `vector<double>` objects and can be obtained by specifying the wavelet name. Currently, following Wavelets are available:
|
||||
|
||||
_**Daubechies :**_ db1,db2,.., ,db15
|
||||
|
||||
_**Biorthogonal:**_ bior1.1 ,bior1.3 ,bior1.5 ,bior2.2 ,bior2.4 ,bior2.6 ,bior2.8 ,bior3.1 ,bior3.3 ,bior3.5 ,bior3.7 ,bior3.9 ,bior4.4 ,bior5.5 ,bior6.8
|
||||
|
||||
_**Coiflets:**_ coif1,coif2,coif3,coif4,coif5
|
||||
|
||||
_**Symmlets:**_ sym2,........, sym10
|
||||
|
||||
## 1D Vector Manipulation ##
|
||||
|
||||
**16. Downsampling:** `void downsamp(vector<double> &sig, int M, vector<double> &sig_d)`
|
||||
|
||||
_**sig**_ :: Signal to be Downsampled
|
||||
|
||||
_**M**_ :: Downsampling factor
|
||||
|
||||
_**sig\_d**_ :: Downsampled signal
|
||||
|
||||
**17. Upsampling:** `void upsamp(vector<double> &sig, int M, vector<double> &sig_u)`
|
||||
|
||||
_**sig**_ :: Signal to be Upsampled
|
||||
|
||||
_**M**_ :: Upsampling factor
|
||||
|
||||
_**sig\_u**_ :: Upsampled signal
|
||||
|
||||
**18. Periodic Extension:** `void* per_ext(vector<double> &sig, int a) `
|
||||
|
||||
_**per\_ext**_ periodically extends the signal _**sig**_ by value _**a**_ in either direction.
|
||||
|
||||
**19. Symmetric Extension:** `void* symm_ext(vector<double> &sig, int a) `
|
||||
|
||||
_**symm\_ext**_ symmetrically extensd the signal _**sig**_ by value _**a**_ in either direction. This function needs refinement as it doesn't gives good results for smaller vectors.
|
||||
|
||||
## 2D Vector Manipulation ##
|
||||
|
||||
**20. 2D Downsampling:** `void* downsamp2(vector<vector<double> > & vec1,vector<vector<double> > & vec2, int rows_dn, int cols_dn) `
|
||||
|
||||
_**vec1**_ is the input, _**rows\_dn**_ and _**cols\_dn**_ are row and column downsampling factors. _**vec2**_ is the downsampled matrix.
|
||||
|
||||
**21. 2D Upsampling:** `void* upsamp2(vector<vector<double> > & vec1,vector<vector<double> > & vec2, int rows_up, int cols_up)`
|
||||
|
||||
_**vec1**_ is the input, _**rows\_up**_ and _**cols\_up**_ are row and column upsampling factors. _**vec2**_ is the upsampled matrix.
|
||||
|
||||
**22. 2D Periodic Extension:** `void* per_ext2d(vector<vector<double> > &signal,vector<vector<double> > &temp2, int a)`
|
||||
|
||||
_**signal**_ is extended by **_a_** in all directions and the result is returned in 2D vector _**temp2**_
|
||||
|
||||
**23. 2D Symmetric Extension:** `void* symm_ext2d(vector<vector<double> > &signal,vector<vector<double> > &temp2, int a)`
|
||||
|
||||
_**signal**_ is extended by **_a_** in all directions and the result is returned in 2D vector _**temp2**_
|
31
previous.md
Normal file
31
previous.md
Normal file
@ -0,0 +1,31 @@
|
||||
I have added a DWT GUI for windows user :: [dyadwaves ](http://code.google.com/p/dyadwaves/). Any feedback will be appreciated.
|
||||
|
||||
# 1D/2D Discrete Wavelet Transform Implementation in C++ #
|
||||
|
||||
1. 1D DWT and IDWT Implementation (Two Modes)
|
||||
1. 2D DWT and IDWT Implementation (Two Modes)
|
||||
1. 1D SWT and ISWT Implementation ( Stationary Wavelet Transform)
|
||||
1. 2D SWT Implementation
|
||||
1. Implemented using Danielson Lanczos FFT Algorithm
|
||||
|
||||
Libraries (Compiled using MinGW and MSVC++ 2010 compilers in Windows) are available in Downloads section while source code is available in the source "src" folder.
|
||||
|
||||
The libraries and source codes are available at http://code.google.com/p/wavelet1d/. I have tried to make this a more "user-friendly" implementation by keeping the functions as simple and descriptive as possible. Additionally, the 1D DWT/IDWT routines will output data that can be used easily with GNUPLOT. It causes redundancy and possibly some clutter if signal files are large but ,in my opinion, the trade-off is worth it. The accompanying script also works best only when DWT and IDWT routines are called in the same program.
|
||||
|
||||
I have used C++ vector objects to accept input, store and output data. This is done to overcome certain programming limitations associated with using arrays. Dynamic arrays were also an option but they require a lot of house-cleaning without having any advantages over vector objects. To learn more about vectors, please refer to excellent tutorial at http://www.cplusplus.com/reference/stl/vector/ Vectors and Arrays can be converted back and forth so even if you are more comfortable with arrays, using vectors should not really be a problem.
|
||||
|
||||
|**[List of Functions](http://code.google.com/p/wavelet1d/wiki/Functions)**| Lists all Functions available in the Library|
|
||||
|:-------------------------------------------------------------------------|:--------------------------------------------|
|
||||
|**[Example Code 1](http://code.google.com/p/wavelet1d/wiki/1DDWTdemo)**| 1D DWT/IDWT Demo Code|
|
||||
|**[Example Code 2](http://code.google.com/p/wavelet1d/wiki/1DAppx)**| 1D Signal Approximation Demo|
|
||||
|**[Example Code 3](http://code.google.com/p/wavelet1d/wiki/2DDWTdemo)**| 2D DWT/IDWT Demo Code|
|
||||
|**[Example Code 4](http://code.google.com/p/wavelet1d/wiki/2DAppx)**| Image Approximation Demo|
|
||||
|**[Example Code 5](http://code.google.com/p/wavelet1d/wiki/2DSWTdemo)**| 2D SWT Demo Code|
|
||||
|**[Example Code 6](http://code.google.com/p/wavelet1d/wiki/1DSWTDemo)**| 1D SWT Demo Code|
|
||||
|
||||

|
||||
|
||||
_J=2 Level Discrete Wavelet Transform of a 569X800 image using dwt\_2d\_sym function (Resized here for Display)_
|
||||
|
||||
Image Processing Note : I have not implemented any image class in C++ as of yet so I'm using OPENCV to handle images. It happens to be a rather bulky package and if you are not already working in image processing area, there are other more convenient options that may be used to handle simple image operations( loading, displaying, saving and converting them to c++ STL formats).
|
||||
|
BIN
wavedemo1-1.png
Normal file
BIN
wavedemo1-1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 23 KiB |
Loading…
Reference in New Issue
Block a user