小波學習
小波去噪
方法一
原理:因爲噪聲通常位於圖像的高頻部分,去除圖像的高頻部分,使用低頻部分恢復圖像。
方法:對圖像進行多級小波分解,捨去圖像的水平細節子帶,垂直細節子帶,和對角線細節子帶,只使用圖像的近似子帶去重構圖像。
缺點:因爲捨棄了細節子帶的一些信息,也容易引起圖像的模糊。
代碼
%裝載原始圖像信號並圖示
X = imread('7.png') ;
subplot(2,2,1);
image(mat2gray(X));
title('原始圖像');
axis square;
%==============================
%生成含噪圖像並圖示
init=2055615866;
rand('seed',init);
noise = 12*randn(size(X));
XX=uint8(double(X)+noise);
subplot(2,2,2);
image(mat2gray(XX));
title('含噪圖像');
axis square;
%==============================
%首先用sym4小波函數對XX進行2層分解
[c,l]=wavedec2(XX,2,'sym4');
%實現低通濾波消噪
a1=wrcoef2('a',c,l,'sym4',1);
%再次實現低通濾波消噪
a2=wrcoef2('a',c,l,'sym4',2);
%==============================
%圖示消噪處理後的結果
subplot(2,2,3);
image(mat2gray(a1));
title('第一次消噪圖像');
axis square;
subplot(2,2,4);
image(a2);
title('第二次消噪圖像');
axis square;
方法二
原理:因爲噪聲的集中在高頻階段,對高頻部分進行閾值處理,使用wthcoef2函數。
方法:對圖像進行多級小波分解,對每級的細節進行閾值處理。
缺點:閾值的設置需要人手動調節,往往是經驗值,或者選取高頻部分的幅值的百分比進行裁剪。
代碼
load gatlin2;
subplot(2,2,1);
image(X);
colormap(map);
title('原始圖像');
axis square;
%生成含噪圖像並圖示
init=2055615866;
randn('seed',init);
XX=X+8*randn(size(X));
subplot(2,2,2);
image(XX);
colormap(map);
title('含噪圖像');
axis square;
%對圖像進行消噪處理
%用小波函數coif2對圖像XX進行2層分解
[c,l]=wavedec2(XX,2,'coif2');
n=[1,2];%設置尺度向量
p=[10.28,24.08];%設置閾值向量
%對三個高頻係數進行閾值處理
nc=wthcoef2('h',c,l,n,p,'s');
nc=wthcoef2('v',nc,l,n,p,'s');
nc=wthcoef2('d',nc,l,n,p,'s');
X1=waverec2(nc,l,'coif2');
subplot(2,2,3);
image(X1);
colormap(map);
title('第一次消噪後的圖像');
axis square;
%再次對三個高頻係數進行閾值處理
nc=wthcoef2('h',nc,l,n,p,'s');
nc=wthcoef2('v',nc,l,n,p,'s');
nc=wthcoef2('d',nc,l,n,p,'s');
%對更新後的小波分解結構進行重構並圖示結果
X2=waverec2(nc,l,'coif2');
subplot(2,2,4);
image(X2);
colormap(map);
title('第二次消噪後的圖像');
axis square;
方法三
盲去噪,使用默認值進行圖像去噪或壓縮,函數ddencmp(Default values for denoising or compression)
語法:[THR,SORH,KEEPAPP,CRIT] = ddencmp(IN1,IN2,X)
當IN1是‘den’該函數式去噪,當‘cmp’該函數是壓縮。IN2是‘wv’和‘wp’是小波包,x是數據。THR是閾值,SORH是軟或硬閾值方法。KEEPAPP是允許保留的近似係數。
小波和小波包的區別
軟閾值和硬閾值方法
matlab中有wthresh(Soft or hard thresholding)的方法,
語法如下:Y = wthresh(X,SORH,T)
Y = wthresh(X,SORH,T) returns the soft (if SORH = ‘s’) or hard (if
SORH = ‘h’) thresholding of the input vector or matrix X. T is the
threshold value.
Y = wthresh(X,’s’,T) returns , soft thresholding is wavelet shrinkage ( (x)+ = 0 if x < 0; (x)+ = x, if x ≥ 0 ).
Y = wthresh(X,’h’,T) returns , hard thresholding is cruder.
代碼
%裝載原始圖像
img=imread('11.png');
x = img ;
%x包含原始圖像
%產生噪聲圖像
init=2055615866;
rand('seed',init);
noise = 12*randn(size(x));
x=uint8(double(x)+noise);
subplot(1,3,1),image(mat2gray(x));
title('含噪圖像');
%使用wdencmp進行圖像去噪
%得到x的小波分解結構
n=2;
w='db5';
[c,l]=wavedec2(x,n,w);
%小波係數的閾值處理
[thr,sorh,keepapp]=ddencmp('den','wv',x);
[xd,cxd,lxd,perf0,perfl2]=wdencmp('gbl',c,l,w,n,thr,'s',l);
%畫出去噪後的圖象
subplot(1,3,2),image(mat2gray(xd));
title('去噪後的圖像');
小波增強
思想:
Make the small coefficients very small and the large coefficients very
large. Apply a nonlinear mapping function to the coefficients.
這應該是一篇論文的效果,但是我還沒看到論文,是在密歇根大學的關於小波PPT上面找到的:
小波圖像去霧
這是看到一些中文文章給出的一些小波增強的方法,但試了效果不好,雖然可以消除一些噪聲,但會引起圖像模糊。(囧,暫時不方便傳代碼)
效果
附哈爾小波的C語言實現
#include <iostream>
#include <cmath>
using namespace std;
/** The 1D Haar Transform **/
void haar1d(float *vec, int n)
{
int i=0;
int w=n;
float *vecp = new float[n];
for(i=0;i<n;i++)
vecp[i] = 0;
while(w>1)
{
w/=2;
for(i=0;i<w;i++)
{
vecp[i] = (vec[2*i] + vec[2*i+1])/sqrt(2.0);
vecp[i+w] = (vec[2*i] - vec[2*i+1])/sqrt(2.0);
}
for(i=0;i<(w*2);i++)
vec[i] = vecp[i];
}
delete [] vecp;
}
/** A Modified version of 1D Haar Transform, used by the 2D Haar Transform function **/
void haar1(float *vec, int n, int w)
{
int i=0;
float *vecp = new float[n];
for(i=0;i<n;i++)
vecp[i] = 0;
w/=2;
for(i=0;i<w;i++)
{
vecp[i] = (vec[2*i] + vec[2*i+1])/sqrt(2.0);
vecp[i+w] = (vec[2*i] - vec[2*i+1])/sqrt(2.0);
}
for(i=0;i<(w*2);i++)
vec[i] = vecp[i];
delete [] vecp;
}
/** The 2D Haar Transform **/
void haar2(float **matrix, int rows, int cols)
{
float *temp_row = new float[cols];
float *temp_col = new float[rows];
int i=0,j=0;
int w = cols, h=rows;
while(w>1 || h>1)
{
if(w>1)
{
for(i=0;i<h;i++)
{
for(j=0;j<cols;j++)
temp_row[j] = matrix[i][j];
haar1(temp_row,cols,w);
for(j=0;j<cols;j++)
matrix[i][j] = temp_row[j];
}
}
if(h>1)
{
for(i=0;i<w;i++)
{
for(j=0;j<rows;j++)
temp_col[j] = matrix[j][i];
haar1(temp_col, rows, h);
for(j=0;j<rows;j++)
matrix[j][i] = temp_col[j];
}
}
if(w>1)
w/=2;
if(h>1)
h/=2;
}
delete [] temp_row;
delete [] temp_col;
}
/** Here's an example on how to use these functions **/
int main(int argc, char **argv)
{
int i=0;
float vec3[4] = {4,2,5,5};
haar1d(vec3,4);
cout << "The 1D Haar Transform: " << endl;
for(i=0;i<4;i++)
cout << vec3[i] << " ";
cout << endl;
cout << "\n\nThe 2D Haar Transform: " << endl;
float **mat = new float*[4];
for(int m=0;m<4;m++)
mat[m] = new float[4];
mat[0][0] = 5; mat[0][1] = 6; mat[0][2] = 1; mat[0][3] = 2;
mat[1][0] = 4; mat[1][1] = 2; mat[1][2] = 5; mat[1][3] = 5;
mat[2][0] = 3; mat[2][1] = 1; mat[2][2] = 7; mat[2][3] = 1;
mat[3][0] = 6; mat[3][1] = 3; mat[3][2] = 5; mat[3][3] = 1;
haar2(mat,4,4);
for(i=0;i<4;i++)
{
for(int j=0;j<4;j++)
cout << mat[i][j] << " ";
cout << endl;
}
cout << endl;
return 0;
}
參考資料
關於小波,我這裏有一個多倫多大學的PPT講義,以哈爾小波爲例,講的十分通俗易懂。點此下載
An Introduction to Wavelets and the Haar Transform by Musawir Ali
轉載保留聲明
作者 | 日期 | 聯繫方式 |
---|---|---|
風吹夏天 | 2015年7月31日 | [email protected] |