您的位置:

平滑滤波c语言,平滑滤波算法

本文目录一览:

c语言程序,本屌是初学者所以麻烦不要用太高级的语句谢谢QAQ

额 我的数字信号处理学的很差,但是我大概了解了下,是不是这个意思首先由两个sin函数构成了一个输入信号,在数字信号处理中叫做激励的东西,然后您给了一个平滑滤波的公式,于是您期望输出信号,也就是信号与系统中所说的Y(z)=H(z)*X(z)如果是的话。那么我就上图了。

首先我成功完成您所给的例子中的数据,由于其中关于序列长度的问题,我设定长度为128,这个和设定50没有什么区别,那么实现您期望的功能需要两个基本块和两个存储信号序列的数组,块1是如何生成一个smooth函数:

如下我写的语句,实现了一个smooth函数,该函数需要的 i,j,N即为公式中所提及的,InSignalBuffer则是一个输入参数,内部装有已经形成的序列,就是sin(0.05*Pi*x)+0.1*sin(0.7*Pi*x);所形成的的序列。OutSignalBuffer是经过smooth处理后这个点的值存到哪里,我用的指针表示。

int Smooth(int i,int j,int N,float *InSignalBuffer,float *OutSignalBuffer)

{

     float Reg=0;

     for(i=j;i=j+N-1;i++)

     {

        Reg+=*(InSignalBuffer+i);                   

     }

     Reg=Reg/(double)N;

     i=j;

     OutSignalBuffer[i]=Reg;

     

 return 0;

}

块2,如何生成激励函数,也就是之前您提及的离散信号序列的公式。如下函数,输入N以确定序列长度,之后计算出一条序列,将其存放到*OutSignalBuffer地址中。

int ExcitationSignal(int N,float *OutSignalBuffer)

{    

float Pi=3.14;  

  float x=0;  

    int i;    

    for(i=0;i=N;i++,x++) 

       {      

        *(OutSignalBuffer+i)=sin(0.05*Pi*x)+0.1*sin(0.7*Pi*x);                  }   

 return 0;  

}

存放序列的问题,存放序列言外之意,就是建立数组,或者是malloc一段空间,为了有广泛性,所以我用的malloc。如下,为开辟两个内存存放离散信号和平滑好的信号。每种能存放128个点的数据。这个可以自己定。

float *InS;

 InS=(float*)malloc(sizeof(float)*128);

 float *OutS;

 OutS=(float*)malloc(sizeof(float)*128);

我们看下函数主体:

其中我们已经说过开辟内存的问题了,那么ExcitationSignal(127,InS);就是生成一个128点的序列,从0-127的,所以是128点的。 Smooth(i,j,3,InS,OutS);从InS中取值然后经过运算有存入Outs中,这里就是3(如您所描述的:建议n值取3~4)。 Print(OutS,124);打印出先关值,也就是我的第一张图片所显示的。

void test()

{

 float *InS;

 InS=(float*)malloc(sizeof(float)*128);

 float *OutS;

 OutS=(float*)malloc(sizeof(float)*128);

 

 ExcitationSignal(127,InS);

 //Print(InS,127);

  

  

   int j,i;

   for(j=0;j124;j++)

   Smooth(i,j,3,InS,OutS);

   Print(OutS,124);

     

}

int main(void)

{

 test();

getchar();

 return 0;   

}

那么全部如下了:

#include windows.h

#include stdio.h

#include math.h

int Smooth(int i,int j,int N,float *InSignalBuffer,float *OutSignalBuffer)

{

     float Reg=0;

     for(i=j;i=j+N-1;i++)

     {

        Reg+=*(InSignalBuffer+i);                   

     }

     Reg=Reg/(double)N;

     i=j;

     OutSignalBuffer[i]=Reg;

     

 return 0;

}

int ExcitationSignal(int N,float *OutSignalBuffer)

{

    float Pi=3.14;

    float x=0;

    int i;

    for(i=0;i=N;i++,x++)

    {

       *(OutSignalBuffer+i)=sin(0.05*Pi*x)+0.1*sin(0.7*Pi*x); 

             

    }

   

 return 0;    

}

void Print(float *Buffer,int N)

{

 int i=0;

 for(i=0;iN;i++)

 printf("\t[%d]\t[%f]\n",i,*(Buffer+i));     

}

void test()

{

 float *InS;

 InS=(float*)malloc(sizeof(float)*128);

 float *OutS;

 OutS=(float*)malloc(sizeof(float)*128);

 

 ExcitationSignal(127,InS);

 //Print(InS,127);

   

   

   int j,i;

   for(j=0;j124;j++)

   Smooth(i,j,3,InS,OutS);

   Print(OutS,124);

      

}

int main(void)

{

 test(); 

getchar();

 return 0;    

}

我程序中子函数中malloc但是没有free,你可以看情况free下。

平滑滤波的滤波方法

图像的噪声滤波器有很多种,常用的有线性滤波器,非线性滤波器。采用线性滤波如邻域平滑滤波,对受到噪声污染而退化的图像复原,在很多情况下是有效的。但大多数线性滤波器具有低通特性,去除噪声的同时也使图像的边缘变模糊了。而另一种非线性滤波器如中值滤波,在一定程度上可以克服线性滤波器所带来的图像模糊问题,在滤除噪声的同时,较好地保留了图像的边缘信息。

邻域平滑滤波原理

邻域平均法[2]是一种利用Box模版对图像进行模版操作(卷积运算)的图像平滑方法,所谓Box模版是指模版中所有系数都取相同值的模版,常用的3×3和5×5模版如下:

邻域平均法的数学含义是:

(式4-1)

式中:x,y=0,1,…,N-1;S是以(x,y)为中心的邻域的集合,M是S内的点数。

邻域平均法的思想是通过一点和邻域内像素点求平均来去除突变的像素点,从而滤掉一定噪声,其优点是算法简单,计算速度快,其代价会造成图像在一定程度上的模糊。

中值滤波原理

中值滤波[2]就是用一个奇数点的移动窗口,将窗口的中心点的值用窗口内的各点中值代替。假设窗口内有五点,其值为80、90、200、110和120,那么此窗口内各点的中值及为110。

设有一个一维序列f1,f2,…,fn,取窗口长度(点数)为m(m为奇数),对其进行中值滤波,就是从输入序列中相继抽出m个数fi-v,…,fi-1,fi,fi+1,…,fi+v(其中fi为窗口中心值,v=(m-1)/2),再将这m个点按其数值大小顺序排序,取其序号的中心点的那个数作为滤波输出。数学公式表示为:

Yi=Med{fi-v,…,fi-1,fi,fi+1,…,fi+v} i∈N v=(m-1)/2 (式4-2)

Yi称为序列fi-v,…,fi-1,fi,fi+1,…,fi+v的中值

例如,有一序列{0,3,4,0,7},重新排序后为{0,0,3,4,7}则Med{0,0,3,4,7}=3。此列若用平滑滤波,窗口也取5,那么平滑滤波输出为(0+3+4+0+7)/5=2.8。

把一个点的特定长度或形状的邻域称作窗口。在一维情况下,中值滤波器是一个含有奇数个像素的滑动窗口。中值滤波很容易推广到二维,此时可以利用二维形式的窗口。

对于平面图像采用的二维中值滤波可以由下式表示:

(式4-3)

式中:A为窗口,{fij}为二维数据序列,即数字图像各点的灰度值。

对于本系统,由于采集到的是24位真彩色图像,每个像素点分别有R、G、B三个灰度分量,故要在窗口内分别找到这三个分量的中值,分别用这三个中值去代替窗口中心像素点的R、G、B三个灰度分量的值。

如何用C语言实现PCM编码

PCM 脉冲编码调制是Pulse Code Modulation的缩写。脉冲编码调制是数字通信的编码方式之一。主要过程是将话音、图像等模拟信号每隔一定时间进行取样,使其离散化,同时将抽样值按分层单位四舍五入取整量化,同时将抽样值按一组二进制码来表示抽样脉冲的幅值。

模拟信号数字化必须经过三个过程,即抽样、量化和编码,以实现话音数字化的脉冲编码调制(PCM,Pulse Coding Modulation)技术。

抽样(Sampling)

抽样是把模拟信号以其信号带宽2倍以上的频率提取样值,变为在时间轴上离散的抽样信号的过程。例如,话音信号带宽被限制在0.3~3.4kHz内,用 8kHz的抽样频率(fs),就可获得能取代原来连续话音信号的抽样信号。对一个正弦信号进行抽样获得的抽样信号是一个脉冲幅度调制(PAM)信号,如下图对模拟正弦信号的抽样所示。对抽样信号进行检波和平滑滤波,即可还原出原来的模拟信号。

量化(quantizing)

抽样信号虽然是时间轴上离散的信号,但仍然是模拟信号,其样值在一定的取值范围内,可有无限多个值。显然,对无限个样值一一给出数字码组来对应是不可能的。为了实现以数字码表示样值,必须采用“四舍五入”的方法把样值分级“取整”,使一定取值范围内的样值由无限多个值变为有限个值。这一过程称为量化。

量化后的抽样信号与量化前的抽样信号相比较,当然有所失真,且不再是模拟信号。这种量化失真在接收端还原模拟信号时表现为噪声,并称为量化噪声。量化噪声的大小取决于把样值分级“取整”的方式,分的级数越多,即量化级差或间隔越小,量化噪声也越小。

编码(Coding)

量化后的抽样信号在一定的取值范围内仅有有限个可取的样值,且信号正、负幅度分布的对称性使正、负样值的个数相等,正、负向的量化级对称分布。若将有限个 量化样值的绝对值从小到大依次排列,并对应地依次赋予一个十进制数字代码(例如,赋予样值0的十进制数字代码为0),在码前以“+”、“-”号为前缀,来 区分样值的正、负,则量化后的抽样信号就转化为按抽样时序排列的一串十进制数字码流,即十进制数字信号。简单高效的数据系统是二进制码系统,因此,应将十 进制数字代码变换成二进制编码。根据十进制数字代码的总个数,可以确定所需二进制编码的位数,即字长。这种把量化的抽样信号变换成给定字长的二进制码流的 过程称为编码。

例程:

#include iostream

using namespace std;

int main()

{

 const int sect = 8;       //number of segement.

 const int startingVol[sect+1] = {0,16,32,64,128,256,512,1024,2048};

        // the starting value of every segement.

 const int quanIntvl[sect] = {1,1,2,4,8,16,32,64}; 

   //quantity interval of every Segments, 1 equeal to 1/2048.

 int pcmInd = 0;         //pcm code's index.

 int pcmCode[sect] = {0,0,0,0,0,0,0,0};  // 8 bit of pcm codes.

 int sampleValue = 1270;

 int startPoint; //starting point of the segement starting piont

     //such as startingVol[startPoint] = 16 or 128  etc.

 int finePoint;   //the starting point of inner segement code.

int quanValue; // it's used to store the final quantity value. 

 int quanError; //error caused by quantity.

//the following four variables is used in geting the segmentCode

 int low = 0;

 

 int high = sect;

 

 int mid;

 int loopInd1 = 0;     //loop index to get segment code

 int loopInd2 = 0;   //loop index to get inner segment codes

//get the first_digit code of polarity

 (sampleValue  0) ? (pcmCode[pcmInd++] = 1) : (pcmCode[pcmInd] = 0);

 

 sampleValue = abs(sampleValue);  //make sure the voltage is positive

    //get the segment code  using modified halve search

 while(loopInd1  3)  //only need 3 loops the segmentCode can be got 

 {

  mid = (low + high)/2;  

   //after 3 loops, sampeValue falls in startingVol[mid] - startingVol[mid] or

    //in startingVol[mid-1] - startingVol[mid]

  if(sampleValue  startingVol[mid])

  {

   pcmCode[pcmInd++] = 0;

   high = mid; 

   startPoint = mid - 1 ;

  }

  else

  {

   pcmCode[pcmInd++] = 1;

   low = mid;

   startPoint = mid;

  }

  loopInd1++;

 }//end while

//get the last four bits codes of pcm 

 low = 0;

 high = 16;  //every segment is split into 16 small segments of the same size

 

 while(loopInd2  4)

 {

  mid = (low + high)/2;

  

  //make the compare progress clear using the following two setences.

  quanValue = startingVol[startPoint] + mid * quanIntvl[startPoint];

  coutstartingVol[startPoint]" + "quanIntvl[startPoint]" * "mid" = "

   quanValue " ? "sampleValueendl;

     //make the compare progress clear using the above two setences.

  

  if(sampleValue  startingVol[startPoint] + mid * quanIntvl[startPoint])

  {

   pcmCode[pcmInd++] = 0;

   high = mid;

   finePoint = mid -1;

  }

  else

  {

   pcmCode[pcmInd++] = 1;

   low = mid;

   finePoint = mid;

  }

  loopInd2++;

 }//end while

 quanValue = startingVol[startPoint] + finePoint * quanIntvl[startPoint];

 

 quanValue += quanIntvl[startPoint] / 2; //final quantity value.

 quanError = abs( sampleValue - quanValue); // error of quantity.

 cout"Final quantity value is: "quanValueendl;

 cout"Error of quantity  is: "quanErrorendl;

 cout"PCM codes are: ";

for(int i = 0; i  8; i++)

  

 {

  coutpcmCode[i]" ";

 }//end for

 coutendl;

return 0;

}

什么是平滑滤波?

平滑滤波是低频增强的空间域滤波技术。它的目的有两类:一类是模糊;另一类是消除噪音。空间域的平滑滤波一般采用简单平均法进行,就是求邻近像元点的平均亮度值。邻域的大小与平滑的效果直接相关,邻域越大平滑的效果越好,但邻域过大,平滑会使边缘信息损失的越大,从而使输出的图像变得模糊,因此需合理选择邻域的大小。