Xử lý ảnh
Chơng 8Thiết kế các bộ lọc FIR 2-D dùng FFT và các hàm cửa sổ8.1 Chỉ dẫnCác bộ lọc có điểm gẫy, hay còn gọi là các bộ lọc có dải chuyển tiếp dốc tạo nên các nhiễu gợn lên phổ biên độ cả ở dải thông lẫn dải chắn khi thiết kế với các phơng pháp mô tả ở các chơng trớc. Chúng đợc gọi là các dao động Gibbs làm ảnh hởng đến chất lợng của ảnh lọc. Vì vậy cần phải có một biện pháp làm giảm bớt và trơn tru các dao động này. Một biện pháp tỏ ra có hiệu quả là áp dụng các hàm cửa sổ. Hàm thu đợc khi nhân với đáp ứng xung bộ lọc với hàm này làm trơn các dao động Gibb. Chúng ta sẽ áp dụng các hàm này và so sánh phổ biên độ có dùng và không dùng hàm cửa sổ. Để tận dụng các thủ tục 2-D FFT trong chơng 6, chúng ta sẽ sử dụng chúng trong việc thiết kế bộ lọc FIR. Chúng ta cần chú ý rằng cách tiếp cận FFT nhanh hơn rất nhiều so với tích phân hai lớp ở chơng 2. Để cung cấp thêm một số kiến thức hoàn thiện cho công việc, chúng ta sẽ xem xét lĩnh vực về độ phân giải của ảnh. Lĩnh vực này đ có một số phát triển đã ợc biết dới với cái tên truyền hình độ phân giải cao (IDTV hoặc EDTV). Các hệ truyền hình này cho ngời xem một số dòng gấp đôi truyền hình thông thờng, và nh vậy là cho một hình ảnh đẹp hơn. Từ chơng 14 đến chơng 16 đề cập đến tín hiệu truyền hình và truyền hình độ phân giải cao cho xử lý ảnh hai chiều.8.2 Thiết kế bộ lọc FIR dùng FFT Một bộ lọc FIR có thể thiết kế theo các bớc sau đây :1. Mô tả phổ biên độ và phổ pha H(m,n) bằng một mảng có kích thớc M ì M mà điểm tần số zero (0,0) nằm tại điểm 2,2MM. M phải là bội số của 2.2. Rút ra IFFT của H(m,n)(-1)m+n. Kết quả là đáp ứng xung h(m,n)(-1)m+n có trung tâm nằm tại 2,2MM.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ừ 212,2)1(2NMNM đến ++212,2)1(2NMNM.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:146 w(m,n) = 1 với M NmM N212 212 + +M NnM N212 212 (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ớic 18,0 0),(222121sradH 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 ( )+=012cos1)(NnnWH (8.2) 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 : 14cos08,0012cos5,042,0)(++=NnNnnWB (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 147với |n|N 12với các trờng hợp còn lại.với |n|N 12với các trờng hợp còn lại với |n|N 12 với các trờng hợp còn lại =0)()()(00IInWK(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à = 1212nN I0(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ụ ã I0(x) = 1 + 1212kxkk!=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 n12222+ (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,n2) = w(n1)w(n2 ) (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(n1,n2) bằng h(n1,n2)w(n 1,n2). 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 148 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#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'));putch(ch1);149 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')); 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) {150 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')&&(ch!='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");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'){151 if(R2<Do) H=(float)0.0; else H=(float)1.0;} 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)); /* 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);152 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); 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)||153 ((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); printf ( " "); gotoxy(1,yt+3); printf("File exists. Wish to overwrite? (y or n)-->"); while(((ch1=tolower(getch()))!='y')&&(ch1!='n')); putch(ch1); switch(ch1) { case 'y': ind=1; break; case 'n' : gotoxy(1,yt+3); printf(" "); gotoxy(1,yt+2); printf(" "); gotoxy(1,yt+2); printf("Enter file name ---->"); scanf("%s",file_name); ind=access(file_name,0); } }fptri=fopen(file_name,"w");theta=pi/((float)N1*sqrt((double)2.0));for(i=0;i<N;i++) { ii=(i-N1)*(i-N1); for(j=0;j<N;j++) { jj=(j-N1)-(j-N1); nsq=(float)(ii+jj); nsqrt=sqrt((double)nsq)/sqrt((double)2.0); switch(ch) { case '1': break; case '2': win=0.5+0.5*cos((double)(theta*nsqrt)); h[i][j]*=win; break; case '3': win=0.54+0.46*cos((double)(theta*nsqrt));154 h[i][j]*=win; break; case '4': win=0.42+0.5*cos((double)(theta*nsqrt)) +0.08*cos((double)(2.0*theta*nsqrt)); h[i][j]*=win; break; case '5': if((i+i)==0); { printf("\n\nEnter a value for alpha (O to 8)-->"); scanf("%f",&alpha); alpha/=2.0; } beta=nsqrt/(float)N1; beta*=beta; beta=alpha*sqrt(fabs((double)(1.0-beta))); T=alpha ; sum1=1.0+T*T; for(k=2;k<11;k++) { T=(1.0/(float)k)*alpha*T; sum2+=T*T; } T=beta; sum2=1.0+T*T; for(k=2;k<11;k++) { T=(1.0/(float)k)*beta*T; sum2+=T*T; } win=sum2/sum1; h[i][j]*=win; break; } fprintf(fptri,"%f ",h[i][j]); } } printf("\n\nFIR filter's coefficients. "); for(i=0;i<N;i++) { printf ( "\n" ) ; for(j=0;j<N;j++) printf(" %f",h[i][i]); }fclose(fptri ) ;fclose(fptro);remove("FFT.DAT");remove("IFFT.DAT");remove("temp.dat");printf("\nDo you wish to store magnitude spectrum ");printf(" \n for 3-D plotting? (y or n)-->");while(((ch=getche())!='y')&&(ch!='n'));155 [...]... -0 .003200 -0 . 0104 64 -0 .000057 0.013089 -0 .000057 -0 . 0104 64 -0 .003200 -0 .009179 -0 .000057 0.079576 0.141409 0.079576 -0 .000057 -0 .009179 -0 .011698 0.013089 0.141409 0.235352 0.141409 -0 .009179 -0 .000057 0.079576 0.141409 0.079576 -0 .000057 -0 .009179 -0 .003200 -0 . 0104 64 -0 .000057 0.013089 -0 .011698 0.013089 -0 .000057 -0 . 0104 64 -0 .003200 0.000517 -0 .003200 -0 .009179 -0 .011698 -0 .009179 -0 .003200 0.000517... với ảnh thu đợc dùng FFT với các giả thiết mô tả trong chơng 7 6 Sử dụng các ảnh khác nhau (đợc cung cấp trong cuốn sách này hay của riêng bạn) để kiểm tra kết quả phóng đại ảnh dùng hệ số của bộ lọc đã chọn trong phần 4 Hình 8.9 Lọc thông thấp với c = 1.7 cho phép nội suy Bảng 8.3 Hệ số cho bộ lọc thông thấp của hình 8.9 0.000517 -0 .003200 -0 .009179 -0 .011698 -0 .009179 -0 .003200 0.000517 -0 .003200 -0 . 0104 64... phân giải của ảnh ảnh cho ở hình 8.5 là kết quả nhân đôi độ phân giải ảnh "CAMEL.IMG" qua phép nội suy ba chiều dùng bộ lọc thông cao có bậc 5 ì 5 thiết kế theo kiểu lọc Butterworth với c = 0.6 Hình 8.6 cho kết quả ảnh này cùng áp dụng các bớc tơng tự nhng với c = 0.8 So sánh ảnh thu đợc với ảnh rút ra từ các phép xấp xỉ FFT ta nhận thấy các ảnh này sáng hơn Nguyên nhân có thể là do ảnh gốc "CAMEL.IMG"... của bộ lọc này phải đủ cao để cho qua toàn bộ phổ của ảnh Phơng pháp dùng bộ lọc thông thấp nhân đôi độ phân giải ảnh tơng tự nh phép nội suy xấp xỉ ảnh này đầu tiên đợc căng ra bằng cách lu vào một mảng có kích thớc 2N ì 2N, ở đây N là chiều rộng hoặc chiều cao của ảnh Tất cả các hàng hoặc cột đều chứa các giá trị zero ở các vị trí còn trống Sau đó ảnh này đợc lọc qua một bộ lọc thông thấp, rồi đến một... trị khác nhau của c 158 Hình 8.5 ảnh "CAMEL.IMG" sau khi dùng bộ lọc thông cao Butterworth với c = 0.6 Hình 8.6 ảnh "CAMEL.IMG" sau khi dùng bộ lọc thông cao Butterworth với c = 0.8 159 Bài tập 8.3 Lập một chơng trình đa ra phép nội suy dùng bộ lọc thông thấp và thông cao FIR ảnh phóng đại ra bằng cách thêm các hàng zero và cột zero với các hàng và cột của ảnh gốc, ảnh đã lọc phải chứa trong bộ đệm... theo định lý lấy mẫu vì vậy theo lý thuyết thì kết quả cho ra sẽ tốt hơn Tuy nhiên, phơng pháp không gian dễ thực hiện hơn nhiều, mà lại cho ra kết quả tơng tự hoặc thậm chí tốt hơn Cần chú ý rằng mờ trên ảnh là một hàm của toán 157 tử nội suy và không phải là ảnh Do vậy, một bộ lọc thông cao đã đ ợc thiết kế cho kết quả thoả mãn với một hàm nội suy đặc biệt, nó có thể dùng cho tất cả các ảnh Hình 8.4... 5 ì 5 với cửa sổ hàm Kaiser với = 3 Bài tập 8.1 Phóng đại ảnh "CAMEL.IMG " dùng phép nội suy ba chiều áp dụng bộ lọc thông cao FIR dùng hàm cửa sổ Blackman và một tần số thông thấp chuyển tiếp dốc đứng với tần số cát c = 1,4 rad/đơn vị Bài tập 8.2 Cho ảnh nằm trên đĩa có tên "MAHER.IMG " Kích thớc của ảnh là 256 điểm ảnh 256 ì 1 Nhân đôi ảnh dùng phép nội suy hệ toạ độ ba chiều với bộ lọc thông cao... fprintf(fptro,"%e",(float)0.0), w=(float *)malloc((M1+1)*sizeof(float)); w[0]=-pi ; winc=2.0*pi/(float)M1; for(i=1;i . 0.000517 -0 .003200 -0 .009179 -0 .011698 -0 .009179 -0 .003200 0.00051 7-0 .003200 -0 . 0104 64 -0 .000057 0.013089 -0 .000057 -0 . 0104 64 -0 .00320 0-0 .009179 -0 .000057. -0 .000057 -0 .00917 9-0 .003200 -0 . 0104 64 -0 .000057 0.013089 -0 .000057 -0 . 0104 64 -0 .003200 0.000517 -0 .003200 -0 .009179 -0 .011698 -0 .009179 -0 .003200