201 /* This program is for eN1arging images using 2-D iir filters. The filter's coefficients can be obtained from iird.exe or iirditer.exe. */ #include <stdio.h> #include <math.h> #include <conio.h> #include <io.h> #include <stdlib.h> #include <alloc.h> #include <ctype.h> #include <string.h> void main() { FILE *fptri,*fptro,*fptrt; unsigned char *buff,**wx,ch,*temp1; double nsq; float **wy,**a,**b,*temp2,*bufft; float max,min,scale,tt; int n,m,image_length,image_width,i,j,N,N1,ind; int true_length,true_width,yt,k; char file_name[14]; clrscr(); printf("Enter file name for image >"); scanf("%s",file_name); fptri=fopen(file_name, "rb"); if(fptri==NULL) { printf("No such image file exists.\n"); exit(1); } nsq=(double)filelength(fileno(fptri)); printf("Is image length equal to image width ? (y or n) >"); while(((ch=getche())!='y')&&(ch!='n')); switch(ch) { case 'y' : image_length=image_width=(int)sqrt(nsq); break; case 'n': printf("\nEnter image_width >"); scanf("%d",&image_width); 202 image_length=(int)(nsq/(float)image_width); } printf("\n Image size %dx%d. " , image_length, image_width); printf ( "\nEnter file name for filter's coefficients >" ) ; scanf("%s",file_name); fptro=fopen(file_name,"r"); if(fptro==NULL) { printf("\nNo such file exists.\n"); exit(1); } Hình 9.12 Bộ lọc nội suy đáp ứng tần số kích thước 2 2 thiết kế từ đáp ứng vuông với miền chuyển tiếp dốc và c = 1.4. fscanf(fptro," %d",&N); printf("IIR filter has an order of %dx%d.",N,N); N1=N+1; /* Allocating memory space. */ a=(float **)malloc(N1*sizeof(float *)); for(i=0;i<N1;i++) *(a+i)=(float *)malloc(N1*sizeof(float)), b=(float **)malloc(N1*sizeof(float *)); 203 for(i=0;i<N1;i++) *(b+i)=(float *)malloc(N1*sizeof(float)); wx=(unsigned char **)malloc(N1*sizeof(char *)); for(i=0;i<N1;i++) *(wx+i)=(unsigned char *)malloc(2*image_width*sizeof(char)); wy=(float **)malloc(N1*sizeof(float *)); for(i=0;i<N1;i++) *(wy+i)=(float *)malloc(2*image_width*sizeof(float)); buff=(unsigned char *)malloc(image_width*sizeof(char)); bufft=(float *)malloc(2*image_width*sizeof(float)); for(i=0;i<=N;i++) for(j=0;j<=N;j++) fscanf(fptro," %f %f",&a[i][j],&b[i][j]); fclose(fptro); yt=wherey()+1; again: gotoxy(1,yt); printf ( " "); gotoxy(1,yt); printf("Enter file name for eN1arged image ->"); scanf("%s",file_name); if((stricmp("temp.img",file_name))==0) { printf( "This is a reserved file name. Use some other name."); goto again; } gotoxy(1,yt+1); printf ( " "); ind=access(file_name,0); while(!ind) { gotoxy(1,yt+1); printf("File exists. Wish to overwrite? (y or n) >"); while(((ch=tolower(getch()))!='y')&&(ch!='n')); putch(ch); switch(ch) { case 'y': ind=1; 204 break; case 'n': gotoxy(1,yt+1); printf(" "); gotoxy(1,yt); printf(" "); gotoxy(1,yt); printf("Enter file name >"); scanf("%s",file_name); ind=access(file_name,0); } } fptro=fopen(file_name,"wb"); fptrt=fopen("temp.imq","wb+"); /* Clearing input and output image transfer buffers. */ for(i=0;i<N1;i++) for(j=0;j<(2*image_width);j++) { wx[i][j]=(char)0; wy[i][j]=(float)0.0; } max=(float)0.0; min=(float)1000.0; true_width=2*image_width-N1; true_length=2*image_length*0.9; for(n=0; n<(2*image_length); n++) { if((n%2)==0) fread(buff,image_width,1,fptri); /* Read the same line for odd or even pixels.*/ gotoxy(1,yt+4); printf("Transferred line %d to input buffer.",n); k=0; for(j=0;j<(2*image_width);j++) { if((j%2)==0) wx[0][j]=buff[k++]; else wx[0][j]=wx[0][j-1]; } for(m=0;m<(2*image_width);m++) 205 { wy[0][m]=(float)0.0; for(i=0;i<=N;i++) for(j=0;j<=N;j++) { if((m-j)<0) continue; wy[0][m]+=a[i][j]*(float)wx[i][m-i]; if((i+j)==0) continue; wy[0][m]-=b[i][j]*(float)wy[i][m-i]; } bufft[m]=wy[0][m]; if((m>N1)&&(m<true_width)&&(n>N1)&&(n<true_length)) { if(bufft[m]>max) max=wy[0][m]; if(bufft[m]<min) min=wy[0][m]; } } fwrite(bufft,2*image_width,sizeof(float),fptrt); /* Shifting. */ temp1=*(wx+N); for(i=0;i<N;i++) *(wx+N-i)=*(wx+(N-1)-i); *wx=temp1; temp2=*(wy+N); for(i=0;i<N;i++) *(wy+N-i)=*(wy+(N-1)-i); *wy=temp2; } printf("\n\n Scaling "); yt=wherey(); rewind(fptrt); scale=(float)250.0/(max-min); for(n=0;n<(2*image_length);n++) { gotoxy(1,yt+2); printf("Scaling line %d.",n); fread(bufft,2*image_width,sizeof(float),fptrt); for(m=0;m<(2*image_width);m++) { tt=(bufft[m]-min)*scale; if(tt>255.0) tt=255.0; if(tt<0.0) tt=0.0; buff[m]=(unsigned char)tt; 206 } fwrite(buff,2*image_width,1,fptro); } fclose(fptri); fclose(fptro); fclose(fptrt), remove("temp.img"); } Bài tập 9.4 Chạy thử chương trình 9.4 trên ảnh "CAMEL.IMG" và "MAHER.IMG" sử dụng: 1. Bộ lọc IIR thông thấp đáp ứng vuông với c = /2.0. 2. Bộ lọc thông thấp đối xứng tuần hoàn với c = /2.0. Đầu tiên dùng đáp ứng có miền chuyển tiếp dốc, và sau đó dùng hàm Butterworth. So sánh kết quả với phương pháp FFT được mô tả trong chương 7. Chú ý: Để thiết kế được bộ lọc trước tiên bạn cần chạy "IMPULSE.EXE" theo "IIRD.EXE". Với đáp ứng vuông bạn sẽ cần phải hoặc là thêm một số thay đổi vào chương trình hoặc là viết một chương trình riêng để sinh và lưu trữ dữ liệu biên độ tần số trong một file. Chương trình IMPULSE.C cho phép đọc dữ liệu được sinh ra từ bên ngoài. Một chương trình mẫu để sinh ra dữ liệu phù hợp với IMPULSE.C được cho trong chương trình 9.5. Chương trình 9.5 “GEN-DATA.C”. Chương trình mẫu tạo tạo dữ liệu đáp ứng tần số cho “IMPULSE.C”. /* Program 9.5 "GEN-DATA.C". Sample program for generating frequency- response data for "IMPULSE.C". */ #define pi 3.141592654 #include <stdio.h> #include <conio.h> main() { int i,j,ii,jj,N,N1,kk; float Do,H; FILE *fptr; 207 char file_name[14]; clrscr(); printf ("\nEnter number of data points to be generated (e.g. 32x32) >"); scanf("%dx%d",&N1,&N1); printf("Enter file name for storing mag. response >"); scanf("%s",file_name); fptr=fopen(file_name,"w"); N=N1/2; printf ( "Enter cut-off ( less than pi ) >"); scanf("%f",&Do); kk=(int)((Do/pi)*(float)N); kk*=kk; Hình 9.13 Đáp ứng tần số của bộ lọc nội suy 2 2 từ đáp ứng hình vuông với miền chuyển tiếp dốc và c = 1.4. fprintf(fptr,"%d %d ",N1,N1); for(i=0;i<N1;i++) { ii=(i-N)*(i-N); for(j=0;j<N1;j++) { jj=(j-N)*(j-N); if((ii<=kk)&&(jj<=kk)) H=1.0; 208 else H=0.0; fprintf(fptr,"%f ",H); } } fclose(fptr); } Trước khi kết thúc chương này chúng ta sẽ thiết kế lại bộ lọc của hình 9.12 sử dụng thay cho bộ lọc FIR. Đáp ứng biên độ tần số của bộ lọc FIR kích thước 5 5 sử dụng cửa sổ Blackmann được chỉ trên hình 9.13. Rõ ràng là giải chuyển đổi có độ dốc hơn nhiều so với hình 9.12. Bộ lọc FIR 5 5 có 25 hệ số so với 17 hệ số của bộ lọc FIR kích thước 2 2. Mặc dù vậy bộ lọc FIR có nhiều lợi thế so với bộ lọc IIR, chúng linh động hơn và có bậc cao hơn nhiều. Vấn đề khó khăn của bộ IIR là độ ổn định không được bảo đảm, và pha tuyến tính thực sự là không có thể. Tuy nhiên, phương pháp được mô tả trong chương này, mặc dù không đảm bảo tính ổn định, nhưng dường như ổn định với pha gần tuyến tính. Bài tập 9.5 Viết chương trình để nhân đôi độ phân giải ảnh sử dụng bộ kiểu lọc FIR, dùng phương pháp được mô tả trong mục 9.8. Bài tập 9.6 Lặp lại bài tập 9.4 dùng bộ lọc FIR để thay thế. Thử những hàm cửa sổ khác nhau. Bài tập 9.7 Đảo ngược từng bước giải thích trong phần này để thu được sự thay đổi ảnh. Điều này rất hữu ích cho ứng dụng TV trong đó chúng được biết như ảnh trong ảnh, ở đó một ảnh nhỏ đặt lên trên một ảnh lớn trên màn hình hiển thị của một kênh khác. Bạn sẽ cần phải đảo lọc, và bộ lọc đảo có thể không ổn định. Nếu đây là một vấn đề bạn cần phải thiết kế một bộ lọc mới để xấp xỉ bộ lọc thông cao miền chuyển tiếp dốc với đối xứng vuông, và một vài kết quả ở tần số 0,0. Sau khi lọc, các điểm khác và các dòng khác được sử dụng để hiển thị ảnh. Bài tập 9.8 Tham khảo 5 (trang 482- 483) cung cấp bộ lọc nội suy 2-D cho việc phóng đại ảnh. Tận dụng bộ lọc IIR trình bày trên trang đó và so sánh kết quả. Tác giả cũng đề nghị rằng bộ lọc nội suy theo bộ lọc thông cao. Thực hiện lời đề . temp2=*(wy+N); for(i=0;i<N;i++) *(wy+N-i)=*(wy+(N-1)-i); *wy=temp2; } printf("
Scaling "); yt=wherey(); rewind(fptrt); scale=(float )25 0.0/(max-min); for(n=0;n< (2* image_length);n++). Bài tập 9.7 Đảo ngược từng bước giải thích trong phần n y để thu được sự thay đổi ảnh. Điều n y rất hữu ích cho ứng dụng TV trong đó chúng được biết như ảnh trong ảnh, ở đó một ảnh nhỏ. gotoxy(1,yt +2) ; printf("Scaling line %d.",n); fread(bufft ,2* image_width,sizeof(float),fptrt); for(m=0;m< (2* image_width);m++) { tt=(bufft[m]-min)*scale; if(tt> ;25 5.0)