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. */