递归双边滤波是双边滤波的一种加速算法,加速比非常大,就像高斯模糊快速算法一样,加速起来,速度跟原算法相比,提高了十几倍。双边滤波的加速算法很多,文献都比较老旧,我这边主要讲一下比较新的算法:递归双边滤波,对应的paper为:《Recursive Bilateral Filtering》
这个算法比我另外一篇博文将的双指数滤波快一点,两篇文献的基本思想一样:
递归公式跟双指数的递归公式基本上一样。于是写代码就轻轻松松了,之前写过双指数的算法,接着只要在双指数的基础上,把代码改一改就OK了,这里就不详细讲解算法流程了,有兴趣的同学可以到paper的作者主页上,里面有代码,不过他的代码好像是要实现立体匹配的,把里面的相关的代码扣出来就可以了,下面是部分重要函数的代码。
void CBRF::recursive_bilateral_filter(double *data,unsigned char**disparity,double***in,unsigned char***texture,double sigma_spatial,double sigma_range,int height,int width,int nr_channel,double***temp,double***temp_2w) { double yp[100]; double alpha=exp(-sqrt(2.0)/(sigma_spatial*width));//filter kernel size double inv_alpha=(1-alpha); double range_table[256]; for(int i=0;i<=255;i++) range_table[i]=exp(-double(i)/(sigma_range*255)); BYTE* p0 =m_pImage; const int nChannel = 4; int m_length =m_nWidth*m_nHeight; //水平迭代滤波 //double***in_=in;/*horizontal filtering*/ //double***out_=temp; double ***out=new double**[m_nHeight]; for (int i=0;i<m_nHeight;i++) { out[i]=new double*[m_nWidth]; } for (int i=0;i<m_nHeight;i++) { for (int j=0;j<m_nWidth;j++) { out[i][j]=new double [3]; } } double ***out=new double**[m_nHeight]; for(int i=0;i<m_nHeight;i++) { BYTE* p0 =m_pImage+i*m_nWidth; memcpy(out[i][0],p0,sizeof(double)*m_nWidth*nChannel); for(int j=1;j<width;j++) { double weight=range_table[euro_dist_rgb_max(out[i][j],out[i][j-1])]; double alpha_=weight*alpha; for(int k=0;k<nChannel;k++) { double ycc=inv_alpha*m_pImage[i*m_nWidth*nChannel+j*nChannel+k]+alpha_*yp[k]; out[i][j][k]=ycc yp[k]=ycc; } } int w1=width-1; for(int c=0;c<nr_channel;c++) out[y][w1][c]=0.5*(out[y][w1][c]+in[y][w1][c]); memcpy(yp,out_[y][w1],sizeof(double)*nr_channel); for(int x=width-2;x>=0;x--) { double weight=range_table[euro_dist_rgb_max(texture[y][x],texture[y][x+1])]; double alpha_=weight*alpha; for(int c=0;c<nr_channel;c++) { double ycc=inv_alpha*in_[y][x][c]+alpha_*yp[c]; out_[y][x][c]=0.5*(out_[y][x][c]+ycc); yp[c]=ycc; } } } //垂直迭代滤波 /*in_=temp; alpha=exp(-sqrt(2.0)/(sigma_spatial*height));//filter kernel size inv_alpha=(1-alpha); double**ycy,**ypy,**xcy,**xpy; unsigned char**tcy,**tpy; memcpy(out[0][0],in_[0][0],sizeof(double)*width*nr_channel); for(int y=1;y<height;y++) { tpy=texture[y-1]; tcy=texture[y]; xcy=in_[y]; ypy=out[y-1]; ycy=out[y]; for(int x=0;x<width;x++) { double weight=range_table[euro_dist_rgb_max(tcy[x],tpy[x])]; double alpha_=weight*alpha; for(int c=0;c<nr_channel;c++) ycy[x][c]=inv_alpha*xcy[x][c]+alpha_*ypy[x][c]; } } int h1=height-1; ycy=temp_2w[0]; ypy=temp_2w[1]; memcpy(ypy[0],in_[h1][0],sizeof(double)*width*nr_channel); for(int x=0;x<width;x++) { unsigned char disp=0; double min_cost=0.5*(out[h1][x][0]+ypy[x][0]); for(int c=1;c<nr_channel;c++) { double cost=0.5*(out[h1][x][c]+ypy[x][c]); if(cost<min_cost) { min_cost=cost; disp=c; } } disparity[h1][x]=disp; } for(int y=h1-1;y>=0;y--) { tpy=texture[y+1]; tcy=texture[y]; xcy=in_[y]; for(int x=0;x<width;x++) { double weight=range_table[euro_dist_rgb_max(tcy[x],tpy[x])]; double alpha_=weight*alpha; unsigned char disp=0; double min_cost=255; for(int c=0;c<nr_channel;c++) { ycy[x][c]=inv_alpha*xcy[x][c]+alpha_*ypy[x][c]; double cost=0.5*(out[y][x][c]+ycy[x][c]); if(cost<min_cost) { min_cost=cost; disp=c; } } disparity[y][x]=disp; } memcpy(ypy[0],ycy[0],sizeof(double)*width*nr_channel); }*/ } unsigned char CBRF::euro_dist_rgb_max(unsigned char *a,unsigned char *b) { unsigned char x,y,z; x=abs(a[0]-b[0]); y=abs(a[1]-b[1]); z=abs(a[2]-b[2]); return(max(max(x,y),z)); }
看一些我用这个算法写的demo的测试结果:
原图
美图秀秀
递归双边滤波
最后人一定要靠自己,想要深入理解一个算法,让记忆更深,一定要自己把代码敲过一遍,既然选择了IT,就要坚持写代码。本文地址:http://blog.csdn.net/hjimce/article/details/45421207 作者:hjimce 联系qq:1393852684 更多资源请关注我的博客:http://blog.csdn.net/hjimce 原创文章,转载请保留这几行信息