408 Hình 13.20 Trình bày các bước thực hiện mã hoá nén ảnh và giải nén ảnh. Một thuật toán dựa trên giả thiết một nửa quãng cho thiết kế một ma trận xác định bit, mà ma trận này chứa phân bố bit cho các hệ số bộ lọc trong các khối được trình bày như sau: 1. Xác định bpp. 2. Tính B = bpp NB NB. 3. Bắt đầu với các giá trị vị trí nhỏ cho . Chúng ta dùng 0.01. 4. Tính phân bố bit dựa trên biểu thức (13.69). 5. Tính Bs = tổng của các phân bố bit được rút ra. 6. Tính Error = Bs - B. 7. Nếu Error > 0.0 thì xn = , nếu không xp = . 8. Tăng bằng một giá trị cố định, và lặp lại các bươc từ bước 4 đến bước 6, cho đến khi “Error” đạt đến giá trị thích hợp. 9. Bắt đầu giả thiết một nửa quãng theo: a. Tính một nửa quãng cụ thể = (xp + xn)/2. b. Lặp lại các bước từ bước 3 đến bước 4 để tính Erro. c. Nếu |Error| < lưu lại ma trận phân bố bit và thoát. d. Nếu Error > 0.0 thì xp = ; Ngược lại xn = . e. Quay lại bước 9.a. Chương trình 13.14 tính ma trận phân bố bit dựa trên thuật toán trên. Chương trình này đòi hỏi FCT của ảnh như là một giá trị đầu vào, và số các khối được dùng. Hội tụ nhanh cho trong trường hợp này, được coi như là một bài tập để bạn có kinh nghiệm. Chương trình 13.14. "BITALLOC.C". Phân bố bit. /* Program for bit allocation.*/ #include <stdio.h> #include <process.h> #include <math.h> #include <alloc.h> #include <conio.h> #include <io.h> 409 void main() { FILE *fptri,*fptro; float nsq,sum,*sigma,bpp; float B,error,theta,xp,xn; float *sumd,*sumdsq,*buffi,denom; int *b,i,j,k,NB,N,Nt,k2; int m,N1,NS,NC,xt,yt,kk,kk2,loc1,k1; int loc,max,min,Bs,sign1,sign2; char file_name[14]; clrscr(); printf("Enter name of input file containing 2-D FCT results->"); scanf("w",file_name); fptri=fopen(file_name,"rb"); if(fptri==NULL) { printf("\nNo such file exists.\n"); exit(1); } nsq=filelength(fileno(fptri)); /* Assume image is square. */ N=(int)sqrt((double)(nsq/sizeof(float))); m=(int)(log10((double)N)/log10((double)2.0)); k=1 ; for(i=0;i<m;i++) k<<=1; if (k!=N) { printf("\nTransformed Image should have dimensions"); printf("\nthat are multiples of 2. Check size of \n"); printf("original image used in the transform."); exit (1); } printf("\nEnter block size used (e.g. 8x8, 16x16, etc.) >"); scanf("%dx%d",&NB,&NB); Nt=NB*NB; /* size of block.*/ N1=N/NB; /* # of blocks in the horizontal or vertical directions*/ 410 NS=NB*N; /* Size of input buffer. */ NC=N1*N1; /* Total # of blocks in image.*/ /*Allocating memory.*/ buffi=(float *)malloc(NS*sizeof(float)); sumd=(float *)malloc(Nt*sizeof(float)); sumdsq=(float *)malloc(Nt*sizeof(float)); sigma=(float *)malloc(Nt*sizeof(float)); xt=wherex(); yt=wherey(); gotoxy(70,25); textattr(WHITE+(GREEN<<4)+BLINK); cputs("WAIT"); gotoxy(xt,yt); for(j=0;j<Nt;j++) { sumd[j]=0.0; sumdsq[j]=0.0; } for(i=0;i<N1;i++) { fread(buffi,sizeof(float),NS,fptri); for(j=0;j<N1;j++) { kk=j*NB ; for(k1=0;k1<NB;k1++) { loc1=kk+k1*N; kk2=k1*NB ; for(k2=0;k2<NB;k2++) { loc=loc1+k2; k=kk2+k2 ; sumd[k]+=buffi[loc]; sumdsq[k]+=buffi[loc]*buffi[loc]; } /* k2 loop. */ } /* k1 loop. */ } /*j-loop.*/ } /* i loop*/ /* Compute o for each coefficient.*/ printf ( "\nComputing the Standard deviation for " ); printf ("each coefficient. \n" ) ; denom=(float) NC*(float) (NC -1.0); for(i=0; i<Nt ; i++) 411 { sigma[i]=fabs((((float)NC)*sumdsq[i]- (sumd[i]*sumd[i]))/denom); sigma[i]=(float)sqrt( (double)sigma[i]); if(sigma[i]==0.0) sigma[i]=1.0e-10 ; } free(sumd); free(sumdsq); fclose(fptri); xt=wherex(); yt=wherey(); gotoxy(70,25); textattr(WHITE+(BLACK<<4)); cputs( " ") ; gotoxy (xt , yt ) ; printf ( " \ nDone."); b=(int *)malloc(Nt*sizeof(int)); k=0 ; printf("\n\nEnter bpp >"); scanf("%f",&bpp); printf("\nEnter file name to store bit allocation matrix >"); scanf("%s",file_name); fptro=fopen(file_name ,"w"); B=bpp*Nt; theta=0.01; for(i=0;i<Nt;i++) { sum=0.5*log10((double)(sigma[i]*sigma[i]/theta)) /log10(2.0); b[i]=(sum>0.0)?(int)sum:0; } Bs=0 ; for(i=0;i<Nt;i++) Bs+=b[i]; error=Bs-(float)B; if(error>0) xp=theta; else xn=theta; sign1=(error>0.0)?1:-1; theta=1.0; while(1) { for(i=0;i<Nt;i++) { 412 sum=0.5*log10((double)(sigma[i]*sigma[i]/theta)) /log10(2.0); b[i]=(sum>0.0)?(int)sum:0; } Bs=0; for(i=0;i<Nt;i++) Bs+b[i]; error=Bs-(float)B; sign2=(error>0.0)?1:-1; if((sign1+sign2)==0) break; theta+=1; } if(error>0.0) xp=theta; else xn=theta; /* Half-interval method. */ k=0; while(1) { k++; theta=(xp+xn)/2.0; for(i=0;i<Nt;i++) { sum=0.5*log10((double)(sigma[i]*sigma[i]/theta)) /log10(2.0); b[i]=(sum>0.0)?(int)sum:0; } Bs=0; for(i=0;i<Nt;i++) Bs+=b[i]; error=Bs-(float)B; if((fabs(error)<0.5)||(k>=200)) break; if(error>0.0) xp=theta; else xn=theta; } clrscr(); printf("\n%d\n",Bs); printf("\n\n Bit allocation matrix.\n"); k=0; for(i=0;i<NB;i++) { for(j=0;j<NB;j++) printf(" %3d",b[k++]); printf("\n"); } 413 error=B-Bs; printf("\nError in total bit allocation=%f bits\n",error); k=0; for(i=0;i<NB;i++) { for(j=0;j<NB;j++) fprintf(fptro,"%d ",b[k++]); fprintf(fptro,"\n"); } } Chạy chương trình 13.14 trên KARENFCT.IMG, chúng ta rút ra ma trận phân bố bit giới thiệu trong bảng 13.2 với bpp lần lượt bằng 1 và 0.5. Bài tập 13.15 1. Lập một chương trình C dùng phương pháp ma trận phân bố bit để nén ảnh. Chú ý là bạn sẽ không cần thay đổi các hệ số FCT. Mỗi hệ số bạn sẽ dùng các bướm chuẩn của nó và dùng lượng tử hoá Lloyd-Max. Nếu một hệ số, chiếm bốn bít trong bảng phân bố, thì bạn sẽ dùng lượng tử hoá 4 bit. Chú ý, phân bố cho các hệ số đồng thời được mô tả tốt nhất bằng một hàm Gauss (thoả mãn biểu thức này). Đồng thời tạo ra phần header của file đúng quy tắc cho lượng tử hoá ngược. 2. Lập một ma trận lượng tử hoá ngược cho phương pháp này. 3. So sánh các kết quả việc khôi phục các ảnh dùng phương pháp trước và phương pháp này với 0.5 bpp, 1 bpp và 1.5 bpp. Như bạn đã thấy, đây là chương dài nhất trong cuốn sách này. Nguyên nhân chủ đề này liên quan nhiều đến công nghiệp và các lĩnh vực nghiên cứu công nghiệp. Tuy nhiên, tôi không nói đến tất cả các phương pháp viết về lĩnh vực này như lượng tử hoá vector với hệ code-book, phương pháp này có giá trị của nó, và điều mã xung có phân biệt (DPCM). Những phương pháp tôi đề cập đến trong chương này là những phương pháp được sử dụng rộng rãi. Những độc giả quan tâm đến những thông tin hơn nữa có thể tìm kiếm và tham khảo những sách và báo đề cập đến chủ đề này. Có thể tham khảo trang có liên quan đến lượng tử hoá vector ở phần 15. Chủ đề lượng tử hoá vector được nói đến trong phần 14. DPCM đề cập đến ở phần 4 và 16. Bảng 13.12 Phân bố bit cho KAREN.IMG. (a) 1 bpp; (b) 0.5 bpp. 6 4 3 2 2 1 1 0 4 3 2 2 1 1 0 0 3 3 2 2 1 1 0 0 2 2 2 1 1 0 0 0 414 2 2 1 1 0 0 0 0 1 1 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 (a) 5 3 2 1 1 0 0 0 3 2 2 1 0 0 0 0 2 2 1 1 0 0 0 0 2 1 1 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 (b) Có nhiều chuẩn trong việc nén ảnh; đặc biệt là chuẩn được được JPEG (Joint Photographic Experts Group) đề xuất đang bắt đầu áp dụng trong một số ứng dụng. Trong chuẩn JPEG ảnh được nén như sau: 1. Khối điểm kích thước 8 8 của DCT trên ảnh nguyên gốc được tính. 2. Hệ số chuyển đổi được tiêu chuẩn hoá bằng cách áp dụng một mảng do người sử dụng định nghĩa nó được định trước cho tất cả các khối. 3. Hệ số DC được mã hóa với lược đồ DPCM. 4. Mỗi khối được sắp xếp lại sử dụng mã zigzag (xem hình 13.21). Điều này là theo RLC và lược đồ mã Huffman. Để nén một ảnh màu, JPEG đề xuất rằng mỗi thành phần được mã hoá một cách độc lập với nhau. Trong chuẩn JPEG, người sử dụng cần phải cung cấp mảng tiêu chuẩn hoá. Điều này là một phần khó khăn của bài toán còn để lại cho người sử dụng. Hai mục trên nói về vi mạch đã được phát triển trong công nghệ phục vụ việc nén/giải nén ảnh thời gian thực được đề cập trong phần tham khảo 18 và 19. Chúng được dựa trên cơ sở những chuẩn được đề xuất bởi JPEG. 415 Hình 13.21 Mã Zigzag. . } Ch y chương trình 13. 14 trên KARENFCT.IMG, chúng ta rút ra ma trận phân bố bit giới thiệu trong bảng 13. 2 với bpp lần lượt bằng 1 và 0.5. Bài tập 13. 15 1. Lập một chương trình C dùng. Chương trình n y đòi hỏi FCT của ảnh như là một giá trị đầu vào, và số các khối được dùng. Hội tụ nhanh cho trong trường hợp n y, được coi như là một bài tập để bạn có kinh nghiệm. Chương trình. Hình 13. 20 Trình b y các bước thực hiện mã hoá nén ảnh và giải nén ảnh. Một thuật toán dựa trên giả thiết một nửa quãng cho thiết kế một ma trận xác định bit, mà ma trận n y chứa phân