本文目錄一覽:
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;
}
什麼是平滑濾波?
平滑濾波是低頻增強的空間域濾波技術。它的目的有兩類:一類是模糊;另一類是消除噪音。空間域的平滑濾波一般採用簡單平均法進行,就是求鄰近像元點的平均亮度值。鄰域的大小與平滑的效果直接相關,鄰域越大平滑的效果越好,但鄰域過大,平滑會使邊緣信息損失的越大,從而使輸出的圖像變得模糊,因此需合理選擇鄰域的大小。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/194254.html