193 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); 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); } 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 *)); for(i=0;i<N1;i++) *(b+i)=(float *)malloc(N1*sizeof(float)); wx=(unsigned char **)malloc(N1*sizeof(char *)); 194 for(i=0;i<N1;i++) *(wx+i)=(unsigned char *)malloc(image_width*sizeof(char)); wy=(float **)malloc(N1*sizeof(float *)); for(i=0;i<N1;i++) *(wy+i)=(float *)malloc(image_width*sizeof(float)); buff=(unsigned char *)malloc(image_width*sizeof(char)); bufft=(float *)malloc(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 filtered 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; break; case 'n' : gotoxy(1,yt+1); printf (" "); gotoxy(1,yt); printf(" "); gotoxy(1,yt); 195 printf("Enter file name >"); scanf("%s",file_name); ind=access(file_name,0); } } fptro=fopen(file_name, "wb"); fptrt=fopen( "temp.img","wb+"); /* Clearing input and output image transfer buffers. */ for(i=0;i<N1;i++) for(j=0;j<image_width;j++) { wx[i][j]=(char)0; wy[i][j]=(float)0.0; } max=(float)0.0; min=(float)1000.0; true_width=image_width-N1; true_length=image_length*0.9; for(n=0; n<image_length;n++) { fread(buff,image_width,1,fptri); gotoxy(1,yt+4); printf("Transferred line %d to input buffer.",n); for(j=0;j<image_width;j++) wx[0][j]=buff[j]; for(m=0;m<image_width;m++) { 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-j]; 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,image_width,sizeof(float),fptrt); 196 /* 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<image_length;n++) { gotoxy(1,yt+2); printf("Scaling line %d.",n); fread(bufft,image_width,sizeof(float),fptrt); for(m=0;m<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; } fwrite(buff,image_width,1,fptro); } fclose(fptri); fclose(fptro); fclose(fptrt); remove("temp.img"); } Bây giờ chúng ta hãy kiểm tra chương trình lọc IIR. Lần này chúng ta sẽ xem xét ảnh x-quang của lồng ngực trong hình 9.9. Bằng cách sử dụng chương trình 9.1 và 9.2 chúng ta có thể thiết kế một bộ lọc thông cao sử dụng kết quả đáp ứng biên độ nhận được từ hàm Butterworth với n = 1 và c = 1.0. Bậc của bộ lọc được thiết kế là 2 2. Hình 9.10 chỉ ra ảnh kết quả sau khi lọc. Trên ảnh đã lọc có nhiều chi tiết được làm rõ. ảnh được cho sẵn trên đĩa với tên file là "RIBS.IMG". 197 Hình 9.9 ảnh chụp x quang lồng ngực. Hình 9.10 ảnh lồng ngực sau khi được làm nổi. 198 Bài tập 9.2 Sử dụng ảnh "CAMEL.IMG" thu được trong chương 8 và áp dụng bộ lọc thông cao 2-D được thiết kế để xấp xỉ hàm Butterworth. Dùng n = 1 và n = 2 cho hàm Butterworth, và c = 0.6, 0.8 và 1.0. So sánh kết quả với kết quả thu được trong chương 8. Kiểu bộ lọc nào, IIR hay FIR, bạn nghĩ có thể được sử dụng để cho ảnh kết quả rõ hơn với cùng số hệ số, tại sao? Bài tập 9.3 Chương trình 9.4 đưa ra mã và giải thuật hiệu quả hơn những chương trình được viết cho bộ lọc FIR, ví dụ chương trình 3.1 (FIR.C) và 3.2 (FIRSYM.C). Nguyên nhân thứ nhất là trong chương trình 9.3 chúng ta sử dụng fread thay cho fgetc trong chương trình 3.1 và 3.2. Nguyên nhân thứ hai là mỗi một dòng ảnh mới được chuyển đổi thành dòng đầu tiên của bộ chuyển đổi ảnh vào thay thế cho dòng cuối cùng như chúng ta đã làm trong chương trình 3.1 và 3.2. Điều này có khuynh hướng đơn giản hoá công thức đệ qui sử dụng trong giải thuật. Viết lại chương trình 3.1 và 3.2 bằng cách thực hiện hai thay đổi này. Kiểm tra chương trình đã được viết lại và so sánh thời gian chạy. 9.8 Nhân đôi ảnh dùng bộ lọc IIR Trong phần này chúng ta sẽ tận dụng một phép tiếp cận xen kẽ để nhân đôi độ phân giải ảnh thay cho các phương pháp chúng ta đã nghiên cứu trước đây. Phép tiếp cận này cũng giống như cách tiếp cận FFT trong chương 7. Giải thuật bao gồm các bước sau : 1. Nhân đôi ảnh bằng cách sao chép các điểm và các đường nằm ngang, ví dụ, mỗi điểm được đọc từ bộ đệm ảnh được sao chép vào hai vị trí liên tục trên bộ đệm nhập vào của thuật toán, và tất cả các dòng nằm ngang được sao chép. Điều này bao gồm cả việc làm tăng chu kỳ lấy mẫu dòng và mành bằng cách nhân đôi giá trị của nó.Nếu T H = T V = T, thì trong ảnh mới phải có chu kỳ lấy mẫu là 2T theo mọi hướng. Bước này tương đương với áp dụng hàm nội suy hình vuông trong chương 7, hình 7.8. Trong miền tần số, phóng đại ảnh bằng bản sao có phổ tần số được mô tả bằng một miền chữ nhật TTTT 2222 21 Phổ này, như chúng ta đã biết, là tuần hoàn hai chiều . 2. Cho ảnh đã phóng qua bộ lọc thông thấp có đặc tuyến tần số biên độ như hình 9.11b. Điều này tương đương việc cộng các không vào phổ tần số như đã làm trong cách tiếp cận nội suy biến đổi Fourier. 199 3. nh phúng i c rỳt ra ging nh cỏch rỳt ra nh t cỏch tip cn FFT. Cỏc bc trờn ũi hi phi thit k b lc thụng thp kiu ỏp ng hỡnh vuụng. Chỳng ta cú th thay i chng trỡnh 9.1 tớnh ỏp ng xung ca b lc thụng thp ỏp ng hỡnh vuụng. iu ny cú th dựng vi chng trỡnh 9.2 v 9.3 thit k b lc ỏp ng hỡnh vuụng IIR. Bn cng cú th dựng hai b lc IIR 1-D thit k bt k kiu b lc no trong tham kho 3. Mt b lc 1-D phi l hm ca z 1 v b lc cũn li l hm ca z 2 . Mt b lc ỏp ng hỡnh ch nht thụng thp c trỡnh by hỡnh 9.12. B lc c thit k dựng chng trỡnh 9.1 v 9.2. B lc kớch thc 2 2 vi c =1.4 v c thit k ỏp ng hỡnh ch nht. Phng phỏp lp c dựng rỳt ra mt xp x tt hn (ba ln lp). Cỏc h s ca b lc cho bng 9.3. Thay i chng trỡnh 9.3 phúng i nh dựng cỏc bc trờn qua s sao chộp v sau ú s dng b lc thụng thp IIR c cho chng trỡnh 9.4. T 2T Mỗi điểm ảnh từ ảnh gốc ánh xạ vào 4 khu vực Chu kỳ lấy mẫu = T Chu kỳ lấy mẫu = 2T T T T 2 T 1 T Min mụ t ph tớn hiu ca nh gc T T 2 T 1 1 0 T 2 c tớnh biờn tn s ca b lc ni suy T 2 2 T 2 (a) ),( 21 H 200 Hình 9.11 (a) Phóng đại ảnh dựa trên các điểm ảnh riêng biệt; (b) Bộ lọc nội suy. Bảng 9.3 Các hệ số của bộ lọc có đáp ứng chỉ trên hình 9.12 a b 0.100672 1.000000 0.084601 - 0.628831 0.046073 0.402671 0.084601 - 0.628844 0.086782 0.577022 0.058304 - 0.346921 0.046072 0.402674 0.058302 - 0.346920 0.050166 0.221563 Chương trình dưới đây viết theo thuật toán lọc ảnh ở phần 9.7. Chương trình 9.4 “ENLGIIR.C”. Chương trình phóng to ảnh sử dụng bộ lọc OR thông thấp. /* Program 9.4 "ENLGIIR.C". Program for enlarging an image using OR low-pass filters. */ . - 0. 628 844 0.0867 82 0.577 022 0.058304 - 0.346 921 0.0460 72 0.4 026 74 0.0583 02 - 0.346 920 0.050166 0 .22 1563 Chương trình dưới đ y viết theo thuật toán lọc ảnh ở phần 9.7. Chương trình. l y mẫu = T Chu kỳ l y mẫu = 2T T T T 2 T 1 T Min mụ t ph tớn hiu ca nh gc T T 2 T 1 1 0 T 2 c tớnh biờn tn s ca b lc ni suy T 2 2 T 2 (a) ),( 21 H 20 0 . trình 9.3 chúng ta sử dụng fread thay cho fgetc trong chương trình 3.1 và 3 .2. Nguyên nhân thứ hai là mỗi một dòng ảnh mới được chuyển đổi thành dòng đầu tiên của bộ chuyển đổi ảnh vào thay