Periodic DWT Code Modified
ChangeLog ver 0.3 A couple of major changes and a few minor tweaks. 1. Periodic DWT code changed. The issue was Perfect Reconstruction wasn't working when filter length became larger than decmated signal. Code changed to implement actual periodic extension instead of using circular shift to mimic periodic extension. Change is strictly under the hood and header file remains unchanged. 2. Dyadic Zero padding is changed to padding the signal by the last value of the signal instead of zeros.
This commit is contained in:
parent
d26770e025
commit
efc1d49cfe
206
src/wavelet.cpp
206
src/wavelet.cpp
@ -441,7 +441,7 @@ void* iswt(vector<double> &swtop,int J, string nm, vector<double> &iswt_output)
|
||||
void* swt(vector<double> &sig, int J, string nm, vector<double> &swt_output, int &length) {
|
||||
vector<double> lpd, hpd, lpr, hpr;
|
||||
|
||||
dyadic_zpad_1d(sig);
|
||||
// dyadic_zpad_1d(sig);
|
||||
int N = sig.size();
|
||||
length = N;
|
||||
|
||||
@ -1738,18 +1738,19 @@ void* dwt(vector<double> &sig, int J, string nm, vector<double> &dwt_output
|
||||
, vector<double> &flag ) {
|
||||
|
||||
int Max_Iter;
|
||||
Max_Iter = (int) ceil(log( double(sig.size()))/log (2.0));
|
||||
Max_Iter = (int) ceil(log( double(sig.size()))/log (2.0)) - 1;
|
||||
if ( Max_Iter < J) {
|
||||
cout << J << " Iterations are not possible with signal of length " << sig.size() << endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
vector<double> original_copy, appx_sig, det_sig;
|
||||
vector<double> original_copy,orig, appx_sig, det_sig;
|
||||
original_copy = sig;
|
||||
|
||||
// Zero Pad the Signal to nearest 2^ M value ,where M is an integer.
|
||||
unsigned int n_size = sig.size();
|
||||
flag.push_back(0);
|
||||
|
||||
double int_n_size = log10 (static_cast<double> (n_size)) / log10(2.0);
|
||||
if ( (pow(2.0, double(int(ceil(int_n_size)))) - pow(2.0, int_n_size)) != 0) {
|
||||
dyadic_zpad_1d(sig);
|
||||
@ -1759,6 +1760,7 @@ void* dwt(vector<double> &sig, int J, string nm, vector<double> &dwt_output
|
||||
}
|
||||
|
||||
flag.push_back(J);
|
||||
orig = sig;
|
||||
|
||||
ofstream appx("appx.txt", ios::trunc);
|
||||
appx.close();
|
||||
@ -1769,8 +1771,9 @@ void* dwt(vector<double> &sig, int J, string nm, vector<double> &dwt_output
|
||||
// Storing Signal for Gnuplot
|
||||
unsigned int count = sig.size();
|
||||
ofstream gnusig("gnusig.dat");
|
||||
for (unsigned int i = 0;i < count; i++) {
|
||||
gnusig << i << " " << sig[i] << endl;
|
||||
unsigned int ct_orig=original_copy.size();
|
||||
for (unsigned int i = 0;i < ct_orig; i++) {
|
||||
gnusig << i << " " << original_copy[i] << endl;
|
||||
}
|
||||
gnusig.close();
|
||||
|
||||
@ -1787,7 +1790,7 @@ void* dwt(vector<double> &sig, int J, string nm, vector<double> &dwt_output
|
||||
|
||||
|
||||
for (int iter = 0; iter < J; iter++) {
|
||||
dwt1(nm,sig, appx_sig, det_sig);
|
||||
dwt1(nm,orig, appx_sig, det_sig);
|
||||
dwt_output.insert(dwt_output.begin(),det_sig.begin(),det_sig.end());
|
||||
|
||||
|
||||
@ -1799,8 +1802,8 @@ void* dwt(vector<double> &sig, int J, string nm, vector<double> &dwt_output
|
||||
// vector<double> lp1,hp1,lp2,hp2;
|
||||
// filtcoef(nm,lp1,hp1,lp2,hp2);
|
||||
// gnudwtplot(sig, appx_sig, det_sig,lp1,hp1,lp2,hp2);
|
||||
sig.clear();
|
||||
sig = appx_sig;
|
||||
// sig.clear();
|
||||
orig = appx_sig;
|
||||
appx_sig.clear();
|
||||
det_sig.clear();
|
||||
|
||||
@ -1879,7 +1882,7 @@ void* dwt(vector<double> &sig, int J, string nm, vector<double> &dwt_output
|
||||
}
|
||||
|
||||
void circshift(vector<double> &sig_cir, int L){
|
||||
if ( abs(L) > sig_cir.size()) {
|
||||
if ( abs(L) >(signed int) sig_cir.size()) {
|
||||
L = sign(L) * (abs(L) % sig_cir.size());
|
||||
}
|
||||
|
||||
@ -1961,8 +1964,9 @@ void* dwt1(string wname, vector<double> &signal, vector<double> &cA, vector<doub
|
||||
int len_lpfilt = lpd.size();
|
||||
int len_hpfilt = hpd.size();
|
||||
int len_avg = (len_lpfilt + len_hpfilt) / 2;
|
||||
|
||||
// cout << len_lpfilt << "Filter" << endl;
|
||||
circshift(signal,-len_avg / 2); // Signal is shifted circularly in order to perform
|
||||
per_ext(signal,len_avg / 2); // Periodic Extension
|
||||
// computations designed to deal with boundary distortions
|
||||
|
||||
// Low Pass Filtering Operations in the Analysis Filter Bank Section
|
||||
@ -1974,14 +1978,10 @@ void* dwt1(string wname, vector<double> &signal, vector<double> &cA, vector<doub
|
||||
|
||||
// Downsampling by 2 gives cA
|
||||
downsamp(cA_undec, D, cA);
|
||||
int L = len_lpfilt / 2;
|
||||
int N = len_sig / 2;
|
||||
|
||||
for (int i = 0; i < L; i++) {
|
||||
cA[i] = cA[N+i]+cA[i];
|
||||
}
|
||||
cA.resize(N);
|
||||
circshift(cA,len_avg/2 );
|
||||
cA.erase(cA.begin(),cA.begin()+len_avg/2);
|
||||
cA.erase(cA.end()-len_avg/2,cA.end());
|
||||
|
||||
// High Pass Filtering Operations in the Analysis Filter Bank Section
|
||||
// int len_cA =(int) floor(double (len_sig + len_lpfilt -1) / double (2));
|
||||
@ -1994,13 +1994,8 @@ void* dwt1(string wname, vector<double> &signal, vector<double> &cA, vector<doub
|
||||
// Downsampling by 2 gives cA
|
||||
downsamp(cD_undec, D, cD);
|
||||
|
||||
int Lh = len_hpfilt / 2;
|
||||
|
||||
for (int i = 0; i < Lh; i++) {
|
||||
cD[i] = cD[N+i]+cD[i];
|
||||
}
|
||||
cD.resize(N);
|
||||
circshift(cD,len_avg/2 );
|
||||
cD.erase(cD.begin(),cD.begin()+len_avg/2);
|
||||
cD.erase(cD.end()-len_avg/2,cD.end());
|
||||
|
||||
|
||||
// File Outputs
|
||||
@ -2024,11 +2019,12 @@ void* dyadic_zpad_1d(vector<double> &signal) {
|
||||
int D = (int) ceil(M);
|
||||
double int_val = pow(2.0, double(D)) - pow(2.0, M);
|
||||
|
||||
int zeros = (int) int_val;
|
||||
int z = (int) int_val;
|
||||
vector<double>::iterator a_it;
|
||||
a_it = signal.end();
|
||||
// double val = signal[N-1];
|
||||
signal.insert(a_it,zeros,0);
|
||||
double val = signal[N-1];
|
||||
// double val = 0;
|
||||
signal.insert(a_it,z,val);
|
||||
return 0;
|
||||
|
||||
}
|
||||
@ -2087,9 +2083,8 @@ void* idwt(vector<double> &dwtop,vector<double> &flag, string nm,
|
||||
vector<double> app;
|
||||
vector<double> detail;
|
||||
unsigned int app_len = dwtop.size() / int(pow(2.0,J));
|
||||
vector<double>::iterator dwt;
|
||||
dwt = dwtop.begin();
|
||||
app.assign(dwt,dwtop.begin()+app_len);
|
||||
|
||||
app.assign(dwtop.begin(),dwtop.begin()+app_len);
|
||||
detail.assign(dwtop.begin()+app_len, dwtop.begin()+ 2* app_len);
|
||||
|
||||
for (int i = 0; i < J; i++) {
|
||||
@ -2133,14 +2128,14 @@ void* idwt1(string wname, vector<double> &X, vector<double> &cA, vector<double>
|
||||
int len_lpfilt = lpr1.size();
|
||||
int len_hpfilt = hpr1.size();
|
||||
int len_avg = (len_lpfilt + len_hpfilt) / 2;
|
||||
unsigned int N = 2 * cA.size();
|
||||
//unsigned int N = 2 * cA.size();
|
||||
int U = 2; // Upsampling Factor
|
||||
|
||||
// Operations in the Low Frequency branch of the Synthesis Filter Bank
|
||||
|
||||
vector<double> cA_up;
|
||||
vector<double> X_lp;
|
||||
circshift(cA,-len_avg/2);
|
||||
per_ext(cA,len_avg/2);
|
||||
|
||||
upsamp(cA, U, cA_up);
|
||||
convfft(cA_up, lpr1, X_lp);
|
||||
@ -2150,39 +2145,21 @@ void* idwt1(string wname, vector<double> &X, vector<double> &cA, vector<double>
|
||||
|
||||
vector<double> cD_up;
|
||||
vector<double> X_hp;
|
||||
circshift(cD,-len_avg/2);
|
||||
per_ext(cD,len_avg/2);
|
||||
upsamp(cD, U, cD_up);
|
||||
convfft(cD_up, hpr1, X_hp);
|
||||
|
||||
|
||||
// Operations to obtain reconstructed signal by folding back and circular shifting
|
||||
|
||||
|
||||
for (unsigned int i = 0 ; i < X_lp.size() - N ; i++){
|
||||
X_lp[i] = X_lp[N+i] + X_lp[i];
|
||||
}
|
||||
|
||||
for (unsigned int i = 0 ; i < X_hp.size() - N; i++){
|
||||
X_hp[i] = X_hp[N+i] + X_hp[i];
|
||||
}
|
||||
|
||||
X_lp.resize(N);
|
||||
X_hp.resize(N);
|
||||
|
||||
// for (unsigned int i =0 ; i < N ; i++){
|
||||
// X[i] = X_lp[i] + X_hp[i];
|
||||
// }
|
||||
vecsum(X_lp,X_hp,X);
|
||||
// Work on circular shift
|
||||
circshift(X,len_avg +len_avg / 2 -1);
|
||||
// Remove periodic extension
|
||||
|
||||
X.erase(X.begin(),X.begin()+len_avg+len_avg/2-1);
|
||||
X.erase(X.end()-len_avg-len_avg/2,X.end());
|
||||
|
||||
|
||||
|
||||
/*
|
||||
for (unsigned int i = 0; i < N; i++){
|
||||
sig << X[i] << endl;
|
||||
}
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -2521,96 +2498,76 @@ void* branch_lp_hp_up(string wname,vector<double> &cA, vector<double> &cD, vecto
|
||||
int len_lpfilt = lpr1.size();
|
||||
int len_hpfilt = hpr1.size();
|
||||
int len_avg = (len_lpfilt + len_hpfilt) / 2;
|
||||
unsigned int N = 2 * cA.size();
|
||||
//unsigned int N = 2 * cA.size();
|
||||
int U = 2; // Upsampling Factor
|
||||
|
||||
// Operations in the Low Frequency branch of the Synthesis Filter Bank
|
||||
|
||||
vector<double> cA_up;
|
||||
vector<double> X_lp;
|
||||
circshift(cA,-len_avg/2);
|
||||
per_ext(cA,len_avg/2);
|
||||
|
||||
upsamp(cA, U, cA_up);
|
||||
convfft(cA_up, lpr1, X_lp);
|
||||
|
||||
|
||||
// Operations in the High Frequency branch of the Synthesis Filter Bank
|
||||
|
||||
vector<double> cD_up;
|
||||
vector<double> X_hp;
|
||||
circshift(cD,-len_avg/2);
|
||||
per_ext(cD,len_avg/2);
|
||||
upsamp(cD, U, cD_up);
|
||||
convfft(cD_up, hpr1, X_hp);
|
||||
|
||||
|
||||
// Operations to obtain reconstructed signal by folding back and circular shifting
|
||||
|
||||
|
||||
for (unsigned int i = 0 ; i < X_lp.size() - N ; i++){
|
||||
X_lp[i] = X_lp[N+i] + X_lp[i];
|
||||
}
|
||||
|
||||
for (unsigned int i = 0 ; i < X_hp.size() - N; i++){
|
||||
X_hp[i] = X_hp[N+i] + X_hp[i];
|
||||
}
|
||||
|
||||
X_lp.resize(N);
|
||||
X_hp.resize(N);
|
||||
|
||||
// for (unsigned int i =0 ; i < N ; i++){
|
||||
// X[i] = X_lp[i] + X_hp[i];
|
||||
// }
|
||||
vecsum(X_lp,X_hp,X);
|
||||
// Work on circular shift
|
||||
circshift(X,len_avg +len_avg / 2 -1);
|
||||
return 0;
|
||||
// Remove periodic extension
|
||||
|
||||
X.erase(X.begin(),X.begin()+len_avg+len_avg/2-1);
|
||||
X.erase(X.end()-len_avg-len_avg/2,X.end());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* branch_hp_dn(string wname, vector<double> &signal, vector<double> &sigop) {
|
||||
|
||||
vector<double> lpd1,hpd1,lpr1,hpr1;
|
||||
filtcoef(wname,lpd1,hpd1,lpr1,hpr1);
|
||||
vector<double> lpd, hpd, lpr, hpr;
|
||||
|
||||
filtcoef(wname,lpd,hpd,lpr,hpr);
|
||||
// for (unsigned int i = 0; i < signal.size(); i++) {
|
||||
// cout << signal[i] << endl;
|
||||
// out2 << signal[i] <<endl;
|
||||
// }
|
||||
|
||||
unsigned int temp_len = signal.size();
|
||||
|
||||
if ( (temp_len % 2) != 0) {
|
||||
double temp = 0;
|
||||
double temp =signal[temp_len - 1];
|
||||
signal.push_back(temp);
|
||||
}
|
||||
|
||||
int len_sig = signal.size();
|
||||
int len_hpfilt = hpd1.size();
|
||||
int len_avg = len_hpfilt;
|
||||
int len_lpfilt = lpd.size();
|
||||
int len_hpfilt = hpd.size();
|
||||
int len_avg = (len_lpfilt + len_hpfilt) / 2;
|
||||
|
||||
// cout << len_lpfilt << "Filter" << endl;
|
||||
circshift(signal,-len_avg / 2); // Signal is shifted circularly in order to perform
|
||||
per_ext(signal,len_avg / 2); // Periodic Extension
|
||||
// computations designed to deal with boundary distortions
|
||||
|
||||
|
||||
|
||||
// High Pass Filtering Operations in the Analysis Filter Bank Section
|
||||
// int len_cA =(int) floor(double (len_sig + len_lpfilt -1) / double (2));
|
||||
|
||||
vector<double> sig_undec;
|
||||
// Low Pass Filtering Operations in the Analysis Filter Bank Section
|
||||
// int len_cA =(int) floor(double (len_sig + len_lpfilt -1) / double (2));
|
||||
vector<double> cA_undec;
|
||||
// convolving signal with lpd, Low Pass Filter, and O/P is stored in cA_undec
|
||||
convfft(signal,hpd1,sig_undec);
|
||||
// Downsampling Factor is 2
|
||||
int D =2 ;
|
||||
convfft(signal,hpd,cA_undec);
|
||||
int D = 2; // Downsampling Factor is 2
|
||||
|
||||
// Downsampling by 2 gives cA
|
||||
downsamp(sig_undec, D, sigop);
|
||||
|
||||
int Lh = len_hpfilt / 2;
|
||||
int N = len_sig / 2;
|
||||
|
||||
|
||||
for (int i = 0; i < Lh; i++) {
|
||||
sigop[i] = sigop[N+i]+sigop[i];
|
||||
}
|
||||
sigop.resize(N);
|
||||
circshift(sigop,len_avg/2 );
|
||||
|
||||
|
||||
filtcoef(wname,lpd1,hpd1,lpr1,hpr1);
|
||||
|
||||
downsamp(cA_undec, D, sigop);
|
||||
|
||||
sigop.erase(sigop.begin(),sigop.begin()+len_avg/2);
|
||||
sigop.erase(sigop.end()-len_avg/2,sigop.end());
|
||||
return 0;
|
||||
|
||||
|
||||
@ -2618,43 +2575,42 @@ return 0;
|
||||
}
|
||||
void* branch_lp_dn(string wname, vector<double> &signal, vector<double> &sigop){
|
||||
|
||||
vector<double> lpd1,hpd1,lpr1,hpr1;
|
||||
vector<double> lpd, hpd, lpr, hpr;
|
||||
|
||||
filtcoef(wname,lpd1,hpd1,lpr1,hpr1);
|
||||
filtcoef(wname,lpd,hpd,lpr,hpr);
|
||||
// for (unsigned int i = 0; i < signal.size(); i++) {
|
||||
// cout << signal[i] << endl;
|
||||
// out2 << signal[i] <<endl;
|
||||
// }
|
||||
|
||||
unsigned int temp_len = signal.size();
|
||||
|
||||
if ( (temp_len % 2) != 0) {
|
||||
double temp = 0;
|
||||
double temp =signal[temp_len - 1];
|
||||
signal.push_back(temp);
|
||||
}
|
||||
|
||||
int len_sig = signal.size();
|
||||
int len_lpfilt = lpd1.size();
|
||||
int len_avg = len_lpfilt;
|
||||
int len_lpfilt = lpd.size();
|
||||
int len_hpfilt = hpd.size();
|
||||
int len_avg = (len_lpfilt + len_hpfilt) / 2;
|
||||
|
||||
// cout << len_lpfilt << "Filter" << endl;
|
||||
circshift(signal,-len_avg / 2); // Signal is shifted circularly in order to perform
|
||||
per_ext(signal,len_avg / 2); // Periodic Extension
|
||||
// computations designed to deal with boundary distortions
|
||||
|
||||
// Low Pass Filtering Operations in the Analysis Filter Bank Section
|
||||
// int len_cA =(int) floor(double (len_sig + len_lpfilt -1) / double (2));
|
||||
vector<double> sig_undec;
|
||||
// int len_cA =(int) floor(double (len_sig + len_lpfilt -1) / double (2));
|
||||
vector<double> cA_undec;
|
||||
// convolving signal with lpd, Low Pass Filter, and O/P is stored in cA_undec
|
||||
convfft(signal,lpd1,sig_undec);
|
||||
convfft(signal,lpd,cA_undec);
|
||||
int D = 2; // Downsampling Factor is 2
|
||||
|
||||
// Downsampling by 2 gives cA
|
||||
downsamp(sig_undec, D, sigop);
|
||||
int L = len_lpfilt / 2;
|
||||
int N = len_sig / 2;
|
||||
downsamp(cA_undec, D, sigop);
|
||||
|
||||
for (int i = 0; i < L; i++) {
|
||||
sigop[i] = sigop[N+i]+ sigop[i];
|
||||
}
|
||||
sigop.resize(N);
|
||||
circshift(sigop,len_avg/2 );
|
||||
sigop.erase(sigop.begin(),sigop.begin()+len_avg/2);
|
||||
sigop.erase(sigop.end()-len_avg/2,sigop.end());
|
||||
|
||||
filtcoef(wname,lpd1,hpd1,lpr1,hpr1);
|
||||
|
||||
return 0;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user