72 y1=abs(y1); y2=abs(y2); zn2=(y1>y2)?y1:y2; putc(zn2,fptr1); /* The buffer is imPlicit in this last statement. */ } /* Shift rows of w */ temp=*w; for(j=0; j<2; j++) *(w+j)=*(w+j+1); *(w+2)=temp; } gotoxy(70,25); textattr(WHITE+(BLACK<<4)); cputs ( " "); gotoxy(1,8); fclose(fptr); /* close input image file */ fclose(fptr1); /* close output-image file */ } Chơng trình cho các phép xử lý Kirsh cũng đợc trình bày ở dới đây. Chơng trình 5.2 KIRSH.C Chơng trình cho phát hiện đờng biên ảnh dùng toán tử Kirsh. /*Program 5.2 "KIRSH.C". Program for edge detection using the Kirsh operators.*/ /* This program is for obtaining the edges using Kirsh Compass operator. */ #include <stdio.h> #include <stdlib.h> #include <math.h> #include <alloc.h> #include <conio.h> #include <io.h> #include <ctype.h> /* Kirsh operators. */ int T[8][3][3]={ { {5,5,5}, 73 {-3,0,-3}, {-3,-3,-3},}, {{5,5,-3}, {5,0,-3}, {-3,-3,-3}, }, {{5,-3,-3}, {5,0,-3}, {5,-3,-3},}, {{-3,-3,-3}, {5,0,-3}, {5,5,-3},}, {{-3,-3,-3}, {-3,0,-3}, {5,5,5},}, {{-3,-3,-3}, {-3,0,5}, {-3,5,5},}, {{-3,5,5}, {-3,0,5}, {-3,-3,5},}, {{-3,5,5}, {-3,0,5}, {-3,-3,-3},} }; void main() { int i,j,n1,n2,image_width, image_length,k1,k2,ind; char file_name[14],ch; unsigned char **w; unsigned char *temp,tmp; int y[8] ; float nsq; unsigned int zn2; FILE *fptr, *fptr1; 74 clrscr (); printf("Enter file name for input image ->"); scanf("%s",file_name); if((fptr=fopen(file_name,"rb"))==NULL) { printf("%s does not exist.", file_name); printf("\nPress any key to exit."); getch (); exit(1); } nsq=filelength(fileno(fptr)); printf("Is this a square image ?"); printf ("\n i.e. Is image_length=image_width (y or n)? ->"); while(((ch=tolower(getch()))!='y')&&(ch!='n')); putch(ch); switch(ch) { case 'y': image_length=image_width=sqrt(nsq); printf("\n Image size = %d x %d",image_length, image_width); break; case 'n': printf("\nEnter image_width >"); scanf("%d",&image_width); image_length=nsq/image_width; printf("image length is %d", image_length); break; } printf("\nEnter file name for filtered image ->"); scanf("%s",file_name); ind=access(file_name,0); while(!ind) { gotoxy(1,6); printf("File exists. Wish to overwrite? (y or n) >"); while(((ch=tolower(getch()))!='Y')&&(ch!='n')); putch(ch); switch(ch) { case 'y': 75 ind=1; break; case 'n': gotoxy(1,6); printf (" "); gotoxy(1,5); printf(" "); gotoxy(1,5); printf("Enter file name >"); scanf("%s",file_name); ind=access(file_name,0); } } fptr1=fopen(file_name,"wb"); gotoxy(70,25); textattr(WHITE+(GREEN<<4)+BLINK); cputs("WAIT"); /* Allocating memory for Image Transfer Buffer, w. */ w=(unsigned char **)malloc(3*sizeof(char *)); for(i=0;i<3;i++) *(w+i)=(char *)calloc(image_width,sizeof(char)); /* Clear Image Transfer Buffer. */ for(i=0;i<3;i++) for(j=0;j<image_width;j++) *((*(w+i))+j)=(unsigned char)0; /* Algorithm */ for(n1=0; n1<image_length;n1++) { gotoxy(1,9); printf(" Transfered line %-4d to image transfer buffer. ",n1); /* Transfer row n2 of the image to the last row of w. */ for(j=0;j<image_width;j++) { ch=(char)fgetc(fptr); *((*(w+2))+j) = (unsigned char)ch; } for(n2=0; n2<image_width; n2++) { 76 for(j=0;j<8;j++) y[j]=(int)0.0; for(k1=-1; k1<=1; k1++) for(k2=-1; k2<=1; k2++) { if( ((n2+k2)<0) || ((n2+k2-1)>=image_width) ) continue; tmp=(*((*(w+1+k1))+(n2+k2-1))); for(j=0;j<8;j++) y[j]+=T[j][1+k1][1+k2]*tmp; } for(j=0;j<8;j++) y[j]=abs(y[j]); zn2=y[0]; for(j=1;j<8;j++) if(y[j]>zn2) zn2=y[j]; putc(zn2,fptr1); /* The buffer is implicit in this last statement. */ } /* shift rows of w */ temp=*w; for(j=0; j<2; j++) *(w+j)=*(w+j+1); *(w+2)=temp; } gotoxy(70,25); textattr(WHITE+(BLACK<<4)); cputs(" "); gotoxy(1,8); fclose(fptr); /* close input image file */ fclose(fptr1); /* close output-image file*/ } Để kiểm tra chơng trình này, chúng ta dùng ảnh trong hình 4.19 chơng 4. Kết quả dùng các phơng pháp Sobel và Kirsh đợc cho trong hình 5.5 a và 5.5 b. Bạn sẽ nhận thấy rằng các xử lý của Kirsh có vẻ nh cung cấp cho ta nhiều chi tiết hơn về ảnh. Cũng nh thế ta nhận thấy rằng phơng pháp dùng các xử lý không gian cho một kết quả tốt hơn là kỹ thuật dùng các bộ lọc thông cao. Mặc dù các mặt nạ trên dùng giả thiết là chỉ có kích thớc 3 3, tuy nhiên ta có thể mở rộng để ảnh có kích thớc bất kỳ nhng thờng là không quá lớn. 77 Bài tập 5.1 Lập một chơng trình C cho phép lựa chọn sử dụng các kỹ thuật phát hiện đờng biên không gian. Bài tập 5.2 Phơng pháp S. Sarker và K. L. Boyer đợc phát triển thành bộ lọc tách lấy đờng biên tốt nhất sử dụng bộ lọc có đáp ứng xung vô hạn (IIR). Chúng ta sẽ nói về IIR trong chơng 9; tuy nhiên, để hiểu đợc kết quả cho bởi Sarker và Boyer chúng ta cha cần phải đọc chơng 9. 1. Dựa trên kết quả phép lấy đạo hàm của chúng, phát triển bộ lọc FIR để phát hiện đờng biên ảnh. 2. Sử dụng những bộ lọc này cho ảnh 4.19 của chơng 4. 3. So sánh kết quả thu đợc qua việc tiếp cận với phơng pháp đợc nói đến trong chơng này. 78 H×nh 5.5 (a) KÕt qu¶ thu ®îc khi dïng xö lý Sobel trªn h×nh 4.19. (b) KÕt qu¶ cña xö lý Kirsh trªn h×nh 4.19. . k1++) for(k2=-1; k2<=1; k2++) { if( ((n2+k2)<0) || ((n2+k2-1)>=image_width) ) continue; tmp=(*((*(w+1+k1))+(n2+k2-1))); for(j=0;j<8;j++) y[j]+=T[j][1+k1][1+k2]*tmp; }. 72 y1=abs(y1); y2=abs(y2); zn2=(y1>y2)?y1:y2; putc(zn2,fptr1); /* The buffer is imPlicit in this last statement. */ } /* Shift rows of w */ temp=*w; for(j=0; j< ;2; . Transfer row n2 of the image to the last row of w. */ for(j=0;j<image_width;j++) { ch=(char)fgetc(fptr); *((*(w +2) )+j) = (unsigned char)ch; } for(n2=0; n2<image_width; n2++) {