PHỤ LỤC - XỬ LÝ ẢNH
Phụ lục gồm listing chương trình trình bày một cách chi tiết các định dạng
ảnh: BMP, PCX, TIFF, GIF,... và các môđul chương trình thực hiện các công đoạn
của quá trình xử lý ảnh. Chương trình được viết trên C và Visual C và có thể coi như
một công cụ đơn giản minh hoạ các bước của xử lý ảnh. Các ảnh minh hoạ trong cuốn
sách này lấy từ kết quả thực hiện chương trình trên.
1. Nhóm chương trình nạp và lưu ảnh
Việc nạp ảnh từ tệp vào mảng số và lưu ảnh từ mảng lên tệp là cần thiết cho
mọi chức năng xử lý. Chính vì thế, phần chương trình có tổ chức 2 moduls riêng:
- BMP.H: Thực hiện việc mở và đọc ảnh số từ “tệp *.BMP” vào “mảng” 2
chiều.
- PCX.H: Thực hiện việc mở và đọc ảnh số từ “tệp *.PCX” vào “mảng” 2
chiều.
BMP.H
// Chứa các khai báo về file ảnh BMP & các thủ tục mở file. //
typedef unsigned int WORD;
typedef unsigned long DWORD;
typedef unsigned char BYTE;
typedef struct tagBITMAPFILEHEADER
{
WORD bfType;
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfoffBits;
} BITMAPFILEHEADER;
typedef struct tagBITMAPINFOHEADER
{
DWORD biSize;
long biWidth;
long biHeight;
//***************************************** //
//Mở file bitmap //
int OpenBitmapFile(char *fname,int *fh,BITMAPFILEHEADER
*bmfhd, BITMAPINFOHEADER *bmihd)
{int tmp;
*fh = _open(fname,O_RDONLY);
if(*fh == -1) return -1; // không mở được file
tmp = _read(*fh,bmfhd,sizeof(BITMAPFILEHEADER));
if (tmp == -1)
{ close(*fh); return -1;// lỗi đọc file
}
if(bmfhd->bfType != 0x4D42)
NhËp m«n xö lý ¶nh sè - §HBK Hµ néi 12
PHỤ LỤC - XỬ LÝ ẢNH
{
close(*fh);
return -2 ;// không phải dạng BMP
}
tmp = _read(*fh,bmihd,sizeof(BITMAPINFOHEADER));
if(tmp != sizeof(BITMAPINFOHEADER))
{
close(*fh);
return -2 ;//không phải dạng BMP
}
if (bmihd->biCompression == 0)
{
bmihd->biSizeImage = (bmfhd->bfSize-bmfhd-
>bfoffBits);
}
return 0;
tmp=_read(fh,buff,BytePerLine);
if(tmp != BytePerLine)
{return -1;
}
ppb=8/bih->biBitCount;
mask=(1 << bih->biBitCount)-1;
for(i=0,cx=0;i<BytePerLine;i++)
{nb=buff[i];
for(j=0;j<ppb;j++,cx++)
{cl=nb >> (bih->biBitCount * (ppb-1-j));
cl=cl & mask;
InImage[p++]= cl;
if(cx == bih->biWidth) break;
}
if(cx >= bih->biWidth) break;
}
free(buff); return 0;
}
//****************************************//
void SetRGBPalette(int index,int red ,int green,int blue)
{
int r,g,b,cl;
red >>= 6; r=(red & 1) << 5; r +=(red & 2) << 1 ;
green >>= 6; g= (green & 1) << 4; g += (green & 2);
blue >>= 6; b= (blue & 1) << 3; b += (blue & 2) >> 1;
cl=r+g+b;
_AX=0x1000;
_BL=index;
_BH=cl;
geninterrupt(0x10);
BytePerLine=bminfohdr.biSizeImage/bminfohdr.biHeight;
bmpalettes=(RGBQUAD far*)
malloc(numcolor*sizeof(RGBQUAD));
if(bmpalettes==NULL) return (3);
tmp=ReadBitmapPalette(bmfilehand,numcolor,bmpalettes);
if (tmp != 0) return(1);
SetRGBPalettes(bmpalettes,numcolor);
farfree(bmpalettes);
lseek(bmfilehand,bmfilehdr.bfoffBits,SEEK_SET);
NhËp m«n xö lý ¶nh sè - §HBK Hµ néi 15
PHỤ LỤC - XỬ LÝ ẢNH
if((InImage =(BYTE huge *)
farcalloc(bminfohdr.biHeight*bminfohdr.biWidth,
sizeof(BYTE)))==NULL)
return(3);
p= 0;
for(i=0;i<bminfohdr.biHeight;i++)
{ if (bminfohdr.biCompression==0)
tmp=GetScanLine(bmfilehand,BytePerLine,&bminfohdr);
}
close(bmfilehand);
return(0);
}
PCX.H
// Chứa các khai báo của File PCX
//
#define TRUE 1
#define FALSE 0
#define VIDEO 0x10
#define Enter 13
BYTE Green;
BYTE Blue;
}ColorRegister;
struct PCXFileHeader
{
BYTE Header;
BYTE Version;
BYTE Encode;
BYTE BitPerPix;
unsigned X1;
unsigned Y1;
unsigned X2;
unsigned Y2;
unsigned Hres;
unsigned Vres;
};
struct PCXInfo
{
BYTE Vmode;
BYTE NumOfPlanes;
unsigned BytesPerLine;
BYTE unused[60];
};
struct ExtendedPalette
{
BYTE ExtendedPalette;
NhËp m«n xö lý ¶nh sè - §HBK Hµ néi 17
PHỤ LỤC - XỬ LÝ ẢNH
ColorRegisterPalette[MAX256PALETTECOLORS];
};
WriteXYB(x,y,gtext,1,1,0,0,0,0);
return (x+inc+textwidth(gtext));
}
int Gwriteln(int x,int y,char *gtext)
{
NhËp m«n xö lý ¶nh sè - §HBK Hµ néi 18
PHỤ LỤC - XỬ LÝ ẢNH
WriteXYB(x,y,gtext,1,1,15,0,0,0);
return (y+10+textheight(gtext));
}
char *Gread(int x,int y)
{
char *gtext,text[2];
char ch;
gtext[0]=0x0;
do
{
ch=getch();
if (ch!=Enter)
{
if (ch!=BackSpace)
{
text[0]=ch;text[1]='\0';
x=Gwrite(x,y,text,0);
strcat(gtext,text);
}
else
if (strcmp(gtext,""))
{
text[0]=gtext[strlen(gtext)-1];text[1]='\0';
{
Gwrite(col,row,"Không tìm thấy File ",0);
return(EFileNotFound);
}
if(fread(&PCXData,sizeof(struct PCX_File),1,PCXFile)!=1)
{
Gwrite(col,row,"Lỗi đọc Header File ",0);
return(EReadFileHdr);
}
if(PCXData.PCXHeader.Header!=PCXHdrTag)
{
Gwrite(col,row,"Không phải PCX File ",0);
return(ENotPCXFile);
}
if (Verbose)
{
clrscr();
printf("PCX Image Information for file %s\n\n",Filename);
printf("\tVersion %d\n",PCXData.PCXHeader.Version);
printf("\tCompression %s\n",
PCXData.PCXHeader.Encode==0?"none":"RLL");
printf("\tBit per Pixel %d\n",PCXData.PCXHeader.BitPerPix);
printf("\tX1: %d\n",PCXData.PCXHeader.X1);
NhËp m«n xö lý ¶nh sè - §HBK Hµ néi 20
PHỤ LỤC - XỬ LÝ ẢNH
printf("\tY1: %d\n",PCXData.PCXHeader.Y1);
printf("\tX2: %d\n",PCXData.PCXHeader.X2);
printf("\tY2: %d\n",PCXData.PCXHeader.Y2);
printf("\tHoriz Resolution: %d\n",PCXData.PCXHeader.Hres);
printf("\tVert Resolution: %d\n",PCXData.PCXHeader.Vres);
{
NhËp m«n xö lý ¶nh sè - §HBK Hµ néi 21
PHỤ LỤC - XỬ LÝ ẢNH
printf("\tPalette[ %X ] : R=%6X G=%6X B=%6X
\n",Index,PCXData.Palette[Index].Red,
PCXData.Palette[Index].Green,PCXData.Palette[Index].Blue);
}
printf("\n\tHit any key to continue");
getch();
}
return(NoError);
}
static int ExpandScanLine(FILE *InFile)
{
register short BitNum;
register unsigned ByteNum;
register short CharRead;
unsigned InPtr,RepCount,PixelsData;
unsigned BytesToRead,PlaneNum;
unsigned ByteOffset,BitOffset;
BytesToRead=PCXData.Info.NumOfPlanes*PCXData.Info.BytesPerLin
e;
InPtr=0;
do
{
CharRead=getc(InFile);
if(CharRead==EOF) return(FALSE);
if((CharRead & 0xC0)==0xC0)
{
RepCount=CharRead & ~0xC0;
_ES=FP_SEG(&Color256Palette.Palette);
regs.x.dx=FP_OFF(&Color256Palette.Palette);
int86(VIDEO,®s,®s);
return(TRUE);
}
else
{
palette.size=MAXPALETTECOLORS;
for (Index=0;Index<MAXPALETTECOLORS;Index++)
{
palette.colors[Index]=Index;
PCXData.Palette[Index].Red>>=2;
PCXData.Palette[Index].Green>>=2;
PCXData.Palette[Index].Blue>>=2;
}
regs.h.ah=0x10;
regs.h.al=0x12;
regs.x.bx=0;
NhËp m«n xö lý ¶nh sè - §HBK Hµ néi 23
PHỤ LỤC - XỬ LÝ ẢNH
regs.x.cx=MAXPALETTECOLORS;
_ES=FP_SEG(&PCXData.Palette);
int86(VIDEO,®s,®s);
setallpalette(&palette);
return(TRUE);
}
}
else return(FALSE);
}
void DisplayPCXFile(char *FileName,int Verbose)
case 349: setgraphmode(VGAMED);
ImageHeight=350;break;
case 199: setgraphmode(VGALO);
ImageHeight=200;break;
}
}
CurrentPos=ftell(PCXFile);
fseek(PCXFile,-769,SEEK_END);
if(fread(&Color256Palette.ExtendedPalette,
sizeof(struct ExtendedPalette) ,1,PCXFile)==TRUE)
if(Color256Palette.ExtendedPalette==PCX256ColorTag)
Is256ColorFile=TRUE;
InstallPCXFilePalette();
fseek(PCXFile,CurrentPos,SEEK_SET);
for(ScanNum=0;ScanNum<ImageHeight;ScanNum++)
{
if(ExpandScanLine(PCXFile) != TRUE)
{
closegraph();
printf("\nScanLine corrupt in PCX file\n");
exit(ECorrupt);
}
PtrScreen=MK_FP(0xA000,0);
if(ImageWidth==320)
{
OffsetDisplay=ScanNum*ImageWidth;
for (ColNum=0;ColNum<ImageWidth;ColNum++)
PtrScreen[OffsetDisplay++]=ScanLine[ColNum];
}
else
//* ************************* *//
void manhinh(void)
{ km mang;int i;int ch;
button("",0,0,0,getmaxx(),30,2,15,8,12,RED);
rectangle(0+2,0+2,getmaxx()-2,30-2);
button("Image Processing System ",200,0+2,0+2,getmaxx()-4,30-4,
1,8,15,0,WHITE);
button("",200,0,460,getmaxx(),getmaxy(),1,0,13,0,WHITE);
outtextxy(70,465,
"Chon: <ENTER> Di Chuyen: <Up><Down><Left><Right>
Thoat:<ESC>");
}
NhËp m«n xö lý ¶nh sè - §HBK Hµ néi 26
PHỤ LỤC - XỬ LÝ ẢNH
//* ************************* //
void WriteText(int *x,int *y,char *s)
{ settextjustify(1,1);
outtextxy(*x,*y,s);
settextjustify(0,2);
*x+=textwidth(s); }
//------------------------------------------------//
void ReadText(int *x,int *y,char *s)
{int i=0;char ch[2];
ch[1]=0;
while(1)
{ch[0]=getch();
if((ch[0]==ENTER)||(ch[0]==ESCAPE)) break;
settextjustify(1,1);
WriteText(x,y,ch);
settextjustify(0,2);
}
//------------------------------------------------------------//
void Warning(void)
{ int x,y,y1= 190;
char *st,*st1;
st=" *** Process Running - Please wait ! ***";
st1="WARNING !!!";
int trai= (getmaxx()/2)-(textwidth(st)/2)-10;
int cao= 80; int phai= (getmaxx()/2)+(textwidth(st)/2)+10;
button("",0,trai,y1,phai,y1+cao,2,15,15,0,7);
rectangle(trai+1,y1+1,phai-1,y1+cao-1);
rectangle(trai+3,y1+3,phai-3,y1+cao-3);
y= y1+22;x= getmaxx()/2;
WriteText(&x,&y,st1);
y= y+textheight(st1)+25;x= getmaxx()/2;
WriteText(&x,&y,st);line(trai+3,y-17,phai-3,y-17);
}
PROCESS.H
// Chứa các thao tác chính : Hiện ảnh, Lọc TB, Trung bình KG, Lọc
Trung vị,
//Lọc Sobel, Lọc Homomorphie
int Averaging(BYTE huge *Image,unsigned cotbd,unsigned
hangbd,unsigned rong, unsigned cao,unsigned avecol,
unsigned averow,double *matran);
void DipslayImageInBuf(BYTE huge *Image,unsigned hang,
unsigned cot);
void DipslayPCXInBuf(BYTE huge *Image,unsigned hang,
unsigned cot);
BYTE ReadPixel(BYTE huge *Image,unsigned cot,unsigned hang);
NhËp m«n xö lý ¶nh sè - §HBK Hµ néi 28
BYTE ReadPixel(BYTE huge *Image,unsigned cot,unsigned hang)
{unsigned long p;
p= hang;
p*= chieurong;
p+= cot;
return(Image[p]);}
//Ghi 1 pixel vào buffer
NhËp m«n xö lý ¶nh sè - §HBK Hµ néi 29
PHỤ LỤC - XỬ LÝ ẢNH
void WritePixel(BYTE huge *Image,unsigned hang,unsigned
cot,unsigned color)
{ unsigned long p;
if ((cot<=chieurong) && (hang<=chieucao))
{ p= hang;
p*= chieurong;
p+= cot;
Image[p]= color;
}
else
{ Error(16);
getch();
}
}
void SortPixel(BYTE *a)
// Sắp xếp thứ tự hai pixels
{ BYTE i,j,tg;
for(i= 0;i<8;i++)
for(j=i;j<9;j++)
if(a[i]<a[j])
{ tg= a[i];a[i]= a[j];a[j]= tg;}
unsigned cao,unsigned avecol, unsigned averow,double *matran)
{ register unsigned i,j,k,l;//lc=(avecol+1)/2;
double *AvePtr;
double tong;
for(i=hangbd;i<cao;i++)
for (j=cotbd;j<rong;j++)
{
tong= 0;
AvePtr= matran;
for(k=0;k<avecol;k++)
for(l=0;l<averow;l++)
tong+=(ReadPixel(Image,j-k+2,i-l+2)*(*AvePtr++));
tong=fabs(tong);//10 la tham so chia cac gia tri cua loc
WritePixel(Image,i,j,(BYTE)tong);//doc 9 ghi 1
} //end of for
return(0);
}
// ***************************************************//
// Lọc Spatial Convolution
int SpatialConvolution(BYTE huge *Image,unsigned cotbd,unsigned
hangbd, unsigned rong,unsigned cao,unsigned KernelCol, unsigned
KernelRow, short *Kernel)
{ register unsigned i,j,k,l;
short *KernelPtr;
NhËp m«n xö lý ¶nh sè - §HBK Hµ néi 31
PHỤ LỤC - XỬ LÝ ẢNH
long tong;
for(i=hangbd;i<cao;i++)
for (j=cotbd;j<rong;j++)
{
for(i=hangbd;i<cao;i++)
for (j=cotbd;j<rong;j++)
NhËp m«n xö lý ¶nh sè - §HBK Hµ néi 32
PHỤ LỤC - XỬ LÝ ẢNH
{ A= ReadPixel(Image,j-1,i-1);
B= ReadPixel(Image,j,i-1);
C= ReadPixel(Image,j+1,i-1);
D= ReadPixel(Image,j-1,i);
E= ReadPixel(Image,j,i);
F= ReadPixel(Image,j+1,i);
G= ReadPixel(Image,j-1,i+1);
H= ReadPixel(Image,j,i+1);
I= ReadPixel(Image,j+1,i+1);
// Tính các giá trị sai phân //
LineAEIAveBelow= (D+G+H)/3;
LineAEIAveAbove= (B+C+F)/3;
LineAEIMaxDif= abs(LineAEIAveBelow- LineAEIAveAbove);
LineBEHAveBelow= (A+D+G)/3;
LineBEHAveAbove= (C+F+I)/3;
LineBEHMaxDif= abs(LineBEHAveBelow- LineBEHAveAbove);
LineCEGAveBelow= (F+H+I)/3;
LineCEGAveAbove= (A+B+D)/3;
LineCEGMaxDif= abs(LineCEGAveBelow- LineCEGAveAbove);
LineDEFAveBelow= (G+H+I)/3;
LineDEFAveAbove= (A+B+C)/3;
LineDEFMaxDif= abs(LineDEFAveBelow- LineDEFAveAbove);
/*Tìm giá trị lớn nhất*/
MaxDif= Max(LineAEIMaxDif,LineBEHMaxDif);
MaxDif= Max(LineCEGMaxDif,MaxDif);
MaxDif= Max(LineDEFMaxDif,MaxDif);
for(k=0;k<3;k++)
for(l=0;l<3;l++)
tong+=(ReadPixel(Image,j1+k,i1+l)*(*matranptr++));
tong= exp(tong);
tong=fabs(tong);
tong/=(double)(1<<0);
tong= (tong<0) ? 0:tong;
tong= (tong>255) ? 255:tong; //max là 63 vì là ảnh 16 màu
WritePixel(Image,i1,j1,(BYTE)tong);//doc 9 ghi 1
} //end of for
}
}
//==============================================//
void Addnoise(BYTE huge *theImage)
{
register i,r;
for(i=0;i<1000;i++)
{theImage[(long)random(chieucao)*chieurong+random(chieurong)] =
200+random(20);
putpixel(r+rand()%chieurong,r+59+rand()%chieucao,200+random(20));
NhËp m«n xö lý ¶nh sè - §HBK Hµ néi 34
PHỤ LỤC - XỬ LÝ ẢNH
}
}
// Tính Histogram của ảnh //
void TinhHisto(BYTE huge *Image,unsigned rong,unsigned cao,
long HISTO[])
{ register unsigned i,j;
for(i = 0; i < 256; i++) HISTO[i] = 0;
for(i = 0; i < cao; i++)