📄 imageprocess.cpp
字号:
//***********************************************************
BOOL Image_Binary_Erosion(BYTE *image,int ImgW,int ImgH,BYTE *Mask,int MaskSize,BYTE TargetGray)
{
int Imagesize=ImgW*ImgH;
if (image==NULL || Imagesize==0) return FALSE;
BYTE *tmpImage = new BYTE[Imagesize], *tm;
BYTE **S_RowAddress = new BYTE*[ImgH];
BYTE **D_RowAddress = new BYTE*[ImgH];
int i, j, i1, j1, MaskR= MaskSize/2;
BOOL KillIt;
S_RowAddress[0] = image;
D_RowAddress[0] = tmpImage;
for(i=1 ; i<ImgH ;i++)
{
D_RowAddress[i] = D_RowAddress[i-1] + ImgW;
S_RowAddress[i] = S_RowAddress[i-1] + ImgW;
}
memset(tmpImage, ~TargetGray, Imagesize);
for(j=MaskR; j<ImgH-MaskR; j++)
{
for(i=MaskR; i<ImgW-MaskR; i++)
{
if(S_RowAddress[j][i]==TargetGray)
{
tm = Mask;
KillIt = FALSE;
for(j1=-MaskR; j1<=MaskR; j1++)
{
for(i1=-MaskR; i1<=MaskR; i1++)
{
if(*tm++)
{
if(S_RowAddress[j+j1][i+i1]!=TargetGray)
{
KillIt=TRUE;
j1 = i1 = MaskR + 1;
}
}
}
}
if(KillIt) D_RowAddress[j][i] =~TargetGray;
else D_RowAddress[j][i] = TargetGray;
}
}
}
memcpy(image, tmpImage, Imagesize);
if( tmpImage!=NULL) delete []tmpImage;
if(S_RowAddress!=NULL) delete []S_RowAddress;
if(D_RowAddress!=NULL) delete []D_RowAddress;
return TRUE;
}
//***********************************************************
//函数类别: 二值图像的处理
//函数名称:
// Binary_Dilation
//函数用途:
// 进行二值图Binary_Dilation膨胀运算
//
//参数说明:
//调用函数:
//
//被调函数:
// some function , at all, I don't know
//原始作者: 陆宏伟
//原始日期: 21/4/1999
//***********************************************************
BOOL Image_Binary_Dilation(BYTE *image,int ImgW,int ImgH,BYTE *Mask,int MaskSize,BYTE TargetGray)
{
int Imagesize=ImgW*ImgH;
if (image==NULL || Imagesize==0) return FALSE;
BYTE *tmpImage = new BYTE[Imagesize], *tm;
BYTE **S_RowAddress = new BYTE*[ImgH];
BYTE **D_RowAddress = new BYTE*[ImgH];
int i, j, i1, j1, MaskR= MaskSize/2;
S_RowAddress[0] = image;
D_RowAddress[0] = tmpImage;
for(i=1 ; i<ImgH ;i++)
{
D_RowAddress[i] = D_RowAddress[i-1] + ImgW;
S_RowAddress[i] = S_RowAddress[i-1] + ImgW;
}
memset(tmpImage, ~TargetGray, Imagesize);
for(j=MaskR; j<ImgH-MaskR; j++)
{
for(i=MaskR; i<ImgW-MaskR; i++)
{
if(S_RowAddress[j][i]==TargetGray)
{
tm = Mask;
for(j1=-MaskR; j1<=MaskR; j1++)
{
for(i1=-MaskR; i1<=MaskR; i1++)
{
if(*tm++)
{
D_RowAddress[j+j1][i+i1] = TargetGray;
}
}
}
}
}
}
memcpy(image, tmpImage, Imagesize);
if( tmpImage!=NULL) delete []tmpImage;
if(S_RowAddress!=NULL) delete []S_RowAddress;
if(D_RowAddress!=NULL) delete []D_RowAddress;
return TRUE;
}
//***********************************************************
//函数类别: 二值图像的处理
//函数名称:
// Binary_grass_label
//函数用途:
// 二值图中的区域的标记函数;
//
//原始作者: 陆 宏 伟
//原始日期: 21/1 /1999
//修改日期: 25/6 /1999 以后再也不会发生堆栈溢出的情况了, Ha Ha Ha!!!
//***********************************************************
int px =0 , py = 0;
int Image_Binary_grass_label(BYTE *image, // 数据的指针
int imgW , // 数据的宽度(列数)
int imgH, // 数据的高度(行数)
BYTE TargetGray)// 目标的灰度值(是白目标还是黑目标)
{
int i, j, k, l; // 常用循环变量
int Nowx, Nowy; // 当前的图像坐标位置
int PixelNum; // 记录递归的次数
int Neighbor; // 邻域点的个数
int AreaLabel= 1;// 标记的值
BYTE **S_RowAddress = new BYTE*[imgH]; //定义指向图像数据每行行首的地址,用来加快运算速度
BYTE GLabel; // 记录邻域中像素点的标记值
//给指向图像数据每行行首的地址赋值
S_RowAddress[0] = image;
for(i=1 ; i<imgH ;i++)
{
S_RowAddress[i] = S_RowAddress[i-1] + imgW;
}
BOOL GrassOk = false; //定义递归调用是否成功的标志位
for(i=0; i<imgW; i++)
{
for(j=0; j<imgH; j++)
{
// 如果是目标点,则继续,否则进行下一次循环
if(S_RowAddress[j][i] != TargetGray) continue;
//判断当前点邻域内是否有标记过的点
Neighbor = PixelNum = 0;
for(k=-1; k<=1; k++)
{
for(l=-1; l<=1; l++)
{
Nowx = i + k;
Nowy = j + l;
//防止指针越界
if( Nowx >= 0 && Nowx < imgW &&
Nowy >= 0 && Nowy < imgH &&
S_RowAddress[Nowy][Nowx] > 0 &&
S_RowAddress[Nowy][Nowx] < 255 )
{
// 如果该点的邻域有标记过的点,
// 则Neighbor加1,并将该标记值
// 记录在变量GLabel
GLabel = S_RowAddress[Nowy][Nowx];
Neighbor++;
}
}
}//*/
// 如果该点的邻域有标记过的点,
// 则仍然用该标记值从当前点开始进行标记
// 否则使用新的标记值
if(Neighbor)
{
GrassOk = Image_Binary_grass( S_RowAddress, imgW, imgH,
TargetGray, i, j, GLabel, PixelNum);
AreaLabel--;
}
else//*/
{
px = i, py = j;
do
{
Neighbor = PixelNum = 0;
for(k=-1; k<=1; k++)
{
for(l=-1; l<=1; l++)
{
Nowx = px + k;
Nowy = py + l;
//防止指针越界
if( Nowx >= 0 && Nowx < imgW &&
Nowy >= 0 && Nowy < imgH &&
S_RowAddress[Nowy][Nowx] > 0 &&
S_RowAddress[Nowy][Nowx] < 255 )
{
// 如果该点的邻域有标记过的点,
// 则Neighbor加1,并将该标记值
// 记录在变量GLabel
GLabel = S_RowAddress[Nowy][Nowx];
Neighbor++;
}
}
}//*/
if( Neighbor )
GrassOk = Image_Binary_grass( S_RowAddress, imgW, imgH,
TargetGray, px, py, GLabel, PixelNum);
else
GrassOk = Image_Binary_grass( S_RowAddress, imgW, imgH,
TargetGray, px, py, AreaLabel, PixelNum);
//如果标记成功,则标记值加1
} while( !GrassOk );
//if(GrassOk)
if( GrassOk )
AreaLabel++;
}
// 如果标记的区域大于253个,返回
if(AreaLabel >= 255)
{
if(S_RowAddress!=NULL) delete []S_RowAddress;
return 254;
}
}
}
// 收回分配的内存
if(S_RowAddress!=NULL) delete []S_RowAddress;
// 返回标记的区域的数目
return AreaLabel == 1 ? GrassOk : AreaLabel - 1;
}
//***********************************************************
//函数类别: 二值图像的处理
//函数名称:
// Binary_grass
//函数用途:
// 二值图中的区域的标记函数
// (采用递归形式)
//
//原始作者: 陆 宏 伟
//原始日期: 21/1 /1999
//修改日期: 25/6 /1999 以后再也不会发生堆栈溢出的情况了, Ha Ha Ha!!!
//***********************************************************
BOOL Image_Binary_grass(BYTE **image, // 数据的指针
int imgW , // 数据的宽度(列数)
int imgH, // 数据的高度(行数)
BYTE TargetGray,// 目标的灰度值(是白目标还是黑目标)
int Startx, // 起始点的x坐标
int Starty, // 起始点的y坐标
int AreaLabel, // 区域的标记值
int &PixelNum) // 当前区域已标记过的点数目
{
int i, j; // 常用循环变量
int Nowx, Nowy; // 当前的图像坐标位置
PixelNum ++; // 递归的次数加1
if(PixelNum==6000)
{
px = Startx;
py = Starty;
return false;
}
else if(PixelNum>6000) return false;
image[Starty][Startx] = AreaLabel;// 将当前像素点标记
for(i=-1; i<=1; i++)
{
for(j=-1; j<=1; j++)
{
Nowx = Startx + i;
Nowy = Starty + j;
if( Nowx >= 0 && Nowx < imgW &&
Nowy >= 0 && Nowy < imgH &&
image[Nowy][Nowx] == TargetGray )
{
Image_Binary_grass(image, imgW, imgH, TargetGray,
Nowx, Nowy, AreaLabel, PixelNum);
}
}
}
return (PixelNum>6000) ? false : true;
}
void Image_Binary_Get_Area_Attrib(BYTE *image, int imgW, int imgH, struct AreaAttrib *attrib, int PtNum)
{
int i,j ,ImageSize=imgW*imgH;
int *minx = new int[PtNum];
int *maxx = new int[PtNum];
int *miny = new int[PtNum];
int *maxy = new int[PtNum];
int *Sumx = new int[PtNum];
int *Sumy = new int[PtNum];
int *Area = new int[PtNum];
memset(maxx,0,sizeof(int)*PtNum);
memset(maxy,0,sizeof(int)*PtNum);
memset(Sumx,0,sizeof(int)*PtNum);
memset(Sumy,0,sizeof(int)*PtNum);
memset(Area,0,sizeof(int)*PtNum);
for(i=0;i<PtNum;i++)
{
minx[i] = ImageSize;
miny[i] = ImageSize;
}
for(j=0; j<imgH; j++)
{
BYTE *temp = image + j*imgW;
for(i=0; i<imgW; i++)
{
BYTE gray = temp[i];
if(gray>0&&gray<=PtNum)
{
gray--;
Sumx[gray]+=i;
Sumy[gray]+=j;
Area[gray]++;
if(i<minx[gray]) minx[gray] = i;
if(i>maxx[gray]) maxx[gray] = i;
if(j<miny[gray]) miny[gray] = j;
if(j>maxy[gray]) maxy[gray] = j;
}
}
}
for(i=0;i<PtNum;i++)
{
attrib[i].Centerx = (double)Sumx[i]/(double)Area[i];
attrib[i].Centery = (double)Sumy[i]/(double)Area[i];
attrib[i].Outline.top = miny[i];
attrib[i].Outline.left = minx[i];
attrib[i].Outline.bottom = maxy[i];
attrib[i].Outline.right = maxx[i];
attrib[i].Area = (double)Area[i];
}
if(Sumx!=NULL) delete []Sumx;
if(Sumy!=NULL) delete []Sumy;
if(Area!=NULL) delete []Area;
if(minx!=NULL) delete []minx;
if(maxx!=NULL) delete []maxx;
if(miny!=NULL) delete []miny;
if(maxy!=NULL) delete []maxy;
}
void Image_Edge_RotateInvariantOperator(BYTE *InputImage, int ImgW, int ImgH, int Masksize)
{
int Imagesize=ImgW*ImgH;
if (InputImage==NULL || Imagesize==0) return ;
int i,j;
int Area = Masksize*Masksize;
int HalfArea = Area/2;
int r=Masksize/2;
BYTE *tmpImage = new BYTE[Imagesize];
BYTE **RowAddress = new BYTE*[ImgH];
//initialize
double *Operatorx = new double[Area];
double *Operatory = new double[Area];
memset(tmpImage, 0, Imagesize);
memset(Operatorx, 0, Area*sizeof(double));
memset(Operatory, 0, Area*sizeof(double));
double *tmpOpx = Operatorx , *tmpOpy = Operatory;
double Coef1 = PI/double(r+1), Mr;
int dx, dy, R02=r*r, Radius, nG;
for(dy=-r; dy<=r; dy++)
{
for(dx=-r; dx<=r; dx++)
{
Radius = dx*dx +dy*dy;
if(Radius<=R02)
{
Mr = sqrt(Radius);
*tmpOpx = cos(2*Mr*Coef1)*sin(dx*Coef1);
*tmpOpy = cos(2*Mr*Coef1)*sin(dy*Coef1);
}
tmpOpx++;
tmpOpy++;
}
}
RowAddress[0] = InputImage;
for(i=1 ; i<ImgH ;i++)
{
RowAddress[i] = RowAddress[i-1] + ImgW;
}
CProgressDlg * MsgHandler = new CProgressDlg();
MsgHandler->Create(NULL);
MsgHandler->SetStatus("旋转不变量算子检测边缘处理");
double gx, gy;
BYTE *Image = tmpImage + r*ImgW;
for(j=r; j<ImgH-r; j++)
{
for(i=r; i<ImgW-r; i++)
{
gx = gy = 0;
tmpOpx = Operatorx;
tmpOpy = Operatory;
for(dy=-r; dy<=r; dy++)
{
for(dx=-r; dx<=r; dx++)
{
gx += (*tmpOpx++)* RowAddress[j+dy][i+dx];
gy += (*tmpOpy++)* RowAddress[j+dy][i+dx];
}
}
nG = int(sqrt(gx*gx+gy*gy) + 0.5);
Image[i] = (nG>255) ? 255: nG;
}
Image += ImgW;
MsgHandler->SetPos(100 * j /ImgH );
}
memcpy(InputImage,tmpImage,Imagesize);
if(tmpImage!=NULL) delete []tmpImage;
if(RowAddress!=NULL) delete []RowAddress;
if(Operatorx!=NULL) delete []Operatorx;
if(Operatory!=NULL) delete []Operatory;
MsgHandler->DestroyWindow();
delete MsgHandler;
}
//***********************************************************
//函数类别: 图像分割
//函数名称:
// Image_EdgeOrention_RotateInvariantOperator
//函数用途:
// 用来进行图像边缘方向角度的计算,各个方向的角度表示
// 类似于各种图像处理书籍中的介绍。
//
//参数说明:
// BYTE * InputImage 数据的指针
// int ImgW 数据的宽度(行数)
// int ImgH 数据的高度(列数)
//
//原始作者: 陆宏伟
//原始日期: 25/5/1999
//***********************************************************
void Image_EdgeOrention_RotateInvariantOperator(BYTE *InputImage, int ImgW, int ImgH, int Masksize)
{
int Imagesize=ImgW*ImgH;
if (InputImage==NULL || Imagesize==0) return ;
int i,j;
int Area = Masksize*Masksize;
int HalfArea = Area/2;
int r=Masksize/2;
BYTE *Image1, *Image2;
BYTE *MagntiudeImage = new BYTE[Imagesize];
BYTE *OrientationImage = new BYTE[Imagesize];
BYTE **RowAddress = new BYTE*[ImgH];
//initialize
memset(MagntiudeImage, 0, Imagesize);
memset(OrientationImage, 0, Imagesize);
//initialize
double *Operatorx = new double[Area];
double *Operatory = new double[Area];
memset(Operatorx, 0, Area*sizeof(double));
memset(Operatory, 0, Area*sizeof(double));
double *tmpOpx = Op
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -