Tải bản đầy đủ (.pdf) (10 trang)

Giáo trình xử lý ảnh y tế Tập 1a P19 docx

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (243.98 KB, 10 trang )

147

3. Để bộ lọc có bậc N

N, N lẻ, hệ số bộ lọc (giá trị của h(m,n)) chứa trong
một cửa sổ kéo dài từ










2
1
2
,
2
)1(
2
NMNM
đến











2
1
2
,
2
)1(
2
NMNM
.
4. Các bước trên có liên quan đến việc sử dụng hàm cửa sổ hình chữ nhật mà
nó có thể được mô tả như sau:
w(m,n) = 1 với
M N
m
M N
2
1
2 2
1
2









  














 







  














M N
n
M N
2
1
2 2
1
2
(8.1)
= 0 với các trường hợp còn lại.
Các hệ số của bộ lọc cho bởi
h(m,n)w(m,n)
Hình 8.1 chỉ ra phổ biên độ của bộ lọc 5  5 được thiết kế sử dụng cửa sổ
hình chữ nhật và tận dụng các đặc điểm:









l¹i. cßn hîp trêng c¸ccho
víi
c
1
8,0 0
),(
2
2
2
1
21
srad
H



Những dao động trong giải thông rất đáng được chú ý. Các dao động do sự
hội tụ chậm của các hệ số trong chuỗi Fourier cho sự chuyển đổi đột ngột về
đặc tính tần số -biên độ. Nhắc lại rằng đáp ứng tần số được coi như tuần hoàn
và IFFT về cơ bản cùng dẫn đến hệ số Fourier của hàm tuần hoàn. Đây cũng là
đáp ứng xung hay hệ số của bộ lọc FIR.
8.3 Hàm cửa sổ
Các hàm cửa sổ để làm giảm bớt các dao động Gibbs được rút ra từ thiết kế
của bộ lọc FIR 1-D. Các hàm cửa sổ hay được được sử dụng nhất sẽ không liệt
kê theo bảng dưới đây cùng sự mở rộng của chúng sang trường hợp 2-D.

¦Cửa sổ Hann và Hamming. Cửa sổ Hann và Hamming cho bởi



 








0
1
2
cos1
)(
N
n
nW
H



(8.2)
v
ới |n|


N 1
2

với các trường hợp còn lại.

148

Có hai lựa chọn khác nhau của . Trong cửa sổ Hann  = 0.5 và trong cửa
sổ Hamming  = 0. 54. Bậc của bộ lọc được cho là N.

¦Cửa sổ Blackmann. Cửa sổ Blackmann cho bởi :

1
4
cos08,0
0
1
2
cos5,042,0)(











N
n
N
n
nW

B

(8.3)
Các thành phần cosin thêm vào dẫn đến sự suy giảm biên độ của các dao
động Gibbs.


¦Cửa sổ Kaiser. Cửa sổ Kaiser cho bởi







0
)(
)(
)(
0
0


I
I
nW
K
(8.4)



Hình 8.1 Đáp ứng tần số của bộ lọc FIR với 
c
= 0.8.
ở đây  là tham số độc lập và

 
 







1
2
1
2
n
N

với |n| 

N 1
2

với các trường hợp còn
l
ại


v
ới |n|

N 1
2

v
ới các trường hợp còn lại
149

I
0
(x) là hàm Bessel bậc 0 loại 1. Nó có thể ước lượng đến độ chính xác bất
kỳ bởi dùng một dãy hội tụ
I
0
(x) = 1 +
1
2
1
2
k
x
k
k
!



















Hàm cửa sổ 2-D cơ bản dựa trên các hàm cửa sổ 1-D cung cấp ở trên. Sự
mở rộng của bất kỳ hàm cửa sổ 1-D nào ở trên sang 2-D được tiến hành bằng
cách thay thế n bằng

n n
1
2
2
2
2


(8.5)
Chia cho
2
để đảm bảo rằng giá trị của n không vượt quá (N - 1)/2, giá trị

lớn nhất trong trường hợp 1-D.
Hàm cửa sổ 2-D được sinh ra từ hàm cửa sổ 1-D qua các biểu thức:
w(n
1
,n
2
) = w(n
1
)w(n
2
) (8.6)
Ứng dụng của hàm cửa sổ trên được rút ra đơn giản bằng thay thế đáp ứng
xung h(n
1
,n
2
) bằng h(n
1
,n
2
)w(n
1
,n
2
). Chương trình sau cho phép bạn thiết kế
bất kỳ bộ lọc cửa sổ chữ nhật hay bất kỳ cửa sổ nào được mô tả trong phần
trước bằng cách dùng biểu thức (8.5) để mở rộng từ 1-D sang 2-D. Bộ lọc
trong chương trình này được thiết kế dùng FFT 2-D, loại cửa sổ được chọn bởi
người dùng.


Chương trình 8.1 "FIRD.C" Thiết kế các bộ lọc dùng FFT và các hàm
cửa sổ.

/* Program for designing FIR filter using FFT on
prescribed frequency specifications.Option for
selecting a Window function is provided.
For the magnitude-frequency specifications you can
either supply your own data or select from a menu of
standard functions.
If you supply your own data the first two values
should be the dimensions of the 2-D array e.g. 32
32.
These dimensions should be equal to some power of
2. The data that follows is the magnitude
specifications in "%f " format stored in a row by
row fashion with no return code after every row.*/

#define pi 3.141592654

150

#include <stdio.h>
#include <math.h>
#include <alloc.h>
#include <stdlib.h>
#include <io.h>
#include <conio.h>
#include <ctype.h>
#include <conio.h>
#include <string.h>


void bit_reversal(unsigned int *, int , int);
void WTS(float *, float *, int, int);
void FFT(float *xr, float *xi, float *, float *,int,
int) ;
void transpose(FILE *, int, int);
void FFT2D(FILE *, FILE *, float *, float *,
unsigned int *,
int,int , int) ;

void main()
{
int M,M1,m,n2,i,j,ii,jj,k;
int Nt,n,M2,M3,N,N1,ind,yt;
unsigned int *L;
float *wr,*wi,Do,winc,Do1,Do2;
float win,T,alpha,beta,sum1,sum2;
float nsq,nsqrt;
FILE *fptri,*fptro,*fptr;
float *buffi,*buffo,R2,H;
float xrm,xim,xrn,xin,zrt,zit,mag,theta;
float *w,**h,r1,im;
unsigned char file_name[14],
ch,ch1,choice,file_name1[14];

clrscr() ;
printf("Freq. response can be calculated using
standard \n");
printf(" functions which you can select from a menu
if your\n");

printf(" reply to the following question is
negative.\n");
printf("Is freq. response provided in a file? (y or
n) >");
while(((ch1=getch())!='y')&&(ch1!='n'));
151

putch(ch1);
switch(ch1)
{
case 'n':
printf("\n Enter # of points to be generated
(e.g. 32x32) >");
scanf("%dx%d",&M1,&M1);
break ;
case 'y':
printf("\nEnter name of file storing magnitude
response >");
scanf("%s",file_name1);
fptr=fopen(file_name1,"r");
fscanf(fptr,"%d %d 11,01,&Mi");
}
M=M1>>1 ;
yt=wherey();
again1 :
gotoxy(1,yt);
printf( "
");
gotoxy(1,yt);
printf("Enter file name for storing impulse

response >");
scanf("%s",file_name);
if(((stricmp("FFT.DAT",file_name))==0)||
((stricmp("TEMP.DAT",file_name))==0)||
((stricmp("IFFT.DAT",file_name))==0))
printf("This is a reserved file name. Use some
other name.");
goto again1;
gotoxy(1,yt);
printf ( "
");
ind=access(file_name,0);
while(!ind)
{
gotoxy(1,yt+1);
printf ( "
");
gotoxy(1,yt+1);
printf("File exists. Wish to overwrite? (y or n)-
->");
while(((ch=tolower(getch()))!='y')&&(ch1='n'));
152

putch(ch);
switch(ch)
{
case 'y' :
ind=1 ;
break;


case 'n' :
gotoxy(1,yt+1);
printf("
");
gotoxy(1,yt);
printf("Enter file name >");
scanf("file_name");
ind=access(file_name,0);
}
}

fptri=fopen("FFT.DAT","wb+");
fptro=fopen("IFFT.DAT","wb+");
buffi=(float *)malloc((M1<<1)*sizeof(float));
switch(ch1)
{
case 'n': /*Generating data for IFFT.*/
printf("\nEnter choice (1,2 etc.):\n");
printf(" 1. Low-pass.\n");
printf(" 2. High-pass.\n");
printf(" 3. Band-pass.\n");
printf(" 4. Band-reject >");

while(((ch=getche())!='1')&&(ch!='2')&&(ch!='3')&&(c
h!='4'));
switch(ch)
{
case '1' :
case '2' :
printf("\nEnter cut-off freq. in

rad./sec.(cut-off <= n.)->");
scanf("%f",&Do);
Do=(Do/pi)*(float)M;
Do*=Do;
printf("Enter choice:\n");
printf(" 1. Abrupt transition.\n");
printf(" 2. Butterworth.\n");
153

printf(" Enter 1 or 2 >");
while(((choice=getche())!='1')&&(choice!='2'));
printf("\n");
break;
case '3':
case '4':
printf
("\nEnter lower cut-off freq. in rad./sec.
(cut-off <=n.");
scanf("%f",&Do1);
Do1=(Do/pi)*(float)M;
Do1*=Do1;
printf
("\nEnter upper cut-off freq. in
rad./sec.cut-off<= n.)->");
scanf("%f",&Do2);
Do2=(Do/pi)*(float)M;
Do2*=Do2;
}

for(i=0;i<M1;i++)

{
ii=(i-M)*(i-M);
for(j=0;j<M1;j++)
{
R2=(float)((j-M)*(j-M)+ii);
switch(ch)
{
case '1': /* low-pass. */
if(choice=='1')
{
if(R2<Do) H=(float)1.0;
else H=(float)0.0;
}
if(choice=='2')
H=0.414*Do/(R2+0.414*Do);
break;

case '2': /* high-pass. */
if(choice=='1')
{
if(R2<Do) H=(float)0.0;
else H=(float)1.0;
}
154

if(choice=='2')
H=R2/(R2+0.414*Do);
break;

case '3': /* Band-pass. */

if(R2<Do1) H=(float)0.0;
else if (R2>Do2) H=(float)0.0;
else H=(float)1.0;
break;

case '4': /* Band-reject. */
if(R2<Do1) H=(float)1.0;
else if (R2>Do2) H=(float)1.0;
else H=(float)0.0;
break;
}
jj=j <<1;
buffi[jj]=H;
buffi[jj+1]=0.0;
}
fwrite(buffi,M1,2*sizeof(float),fptri);
}
break;

case 'y' :
for(i=0;i<M1;i++)
{
for(j=0;j<M1;j++)
{
fscanf(fptr,"%f ",&H);
jj=j<<1 ;
buffi[jj]=H;
buffi[jj+1]=(float)0.0;
}
fwrite(buffi,M1,2*sizeof(float),fptri);

}
fclose(fptr);
}
rewind(fptri);
m=(int)(log10((double)M1)/log10((double)2));

/* Allocating memory for bit reversal LUT. */
L=(unsigned int *)malloc(M1*sizeof(unsigned
int));
155


/* Generate Look-up table for bit reversal. */
bit_reversal(L,m,M1);

/* Allocating memory for twiddle factors. */
n2=M1-1;
wr=(float *)malloc(n2*sizeof(float));
wi=(float *)malloc(n2*sizeof(float));

/* Generating twiddle factor.*/
WTS(wr,wi,M1,1);
clrscr();
FFT2D(fptri,fptro,wr,wi,L,M1,m,1);
clrscr();
fptri=fopen("IFFT.DAT","rb");
fptro=fopen("temp.dat","wb+");
nsq=(float)(M1*M1);
buffo=(float *)malloc(M1*sizeof(float));
for(i=0;i<M1;i++)

{
fread(buffi,M1,2*sizeof(float),fptri);
for(j=0;j<M1;j++)
buffo[j]=(float)(buffi[2*j]/nsq);
fwrite(buffo,M1,sizeof(float),fptro);
}
fclose(fptri);
rewind(fptro);
printf("Enter order of FIR filter (odd
numbers).");
printf(" \n >(e.g. 3x3, 5x5) ");
scanf("%dx%d",&N,&N);
N1=(N-1)/2;
M2=M-N1;
M3=M+N1;

h=(float **)malloc(N*sizeof(float));
for(i=0;i<N;i++)
*(h+i)=(float *)malloc(N*sizeof(float));

/* Reading in the impulse response. */
buffo=(float *)malloc(M1*sizeof(float));

fseek(fptro,(long)(M2)*(long)(M1*sizeof(float)),SEEK
_SET);
156

for(i=M2;i<=M3;i++)
{
fread(buffo,M1,sizeof(float),fptro);

for(j=M2;j<=M3;j++)
h[(i-M2)][j-M2]=buffo[j];
}

/* Selection of Window functions. */
printf("\nEnter selection of window function:");
printf("\n 1.Rectangular.");
printf("\n 2.Hann.");
printf("\n 3.Hamming,");
printf("\n 4.Blackmann.");
printf("\n 5.Kaiser.");
printf("\nEnter (1,2 etc.) >");
while(((ch=getche())!='1')&&(ch!='2')
&&(ch!='3')&&(ch!='4')&&(ch!='5'));
yt=wherey();

/* Storing impulse response of FIR filter.*/
again :
gotoxy(1,yt+2);
printf("
");
gotoxy(1,yt+2);
printf("\nEnter file name to store FIR filter
coefficients >");
scanf("%s",file_name);
if(((stricmp("FFT.DAT",file_name))==0)||
((stricmp("temp.DAT",file_name))==0)||
((stricmp("IFFT.DAT",file_name))==0))
{
printf("This is a reserved file name. Use some

other name.");
goto again;
}
gotoxy(1,yt+2);
printf("
");
ind=access(file_name,0);
while(!ind)
{
gotoxy(1,yt+3);

×