📄 globalapi.cpp
字号:
// 最大梯度值
int nMaxMag ;
int nHighCount ;
nMaxMag = 0 ;
// 初始化
for(k=0; k<1024; k++)
{
nHist[k] = 0;
}
// 统计直方图,然后利用直方图计算阈值
for(y=0; y<nHeight; y++)
{
for(x=0; x<nWidth; x++)
{
// 只是统计那些可能是边界点,并且还没有处理过的象素
if(pUnchEdge[y*nWidth+x]==128)
{
nHist[ pnMag[y*nWidth+x] ]++;
}
}
}
nEdgeNb = nHist[0] ;
nMaxMag = 0 ;
// 统计经过“非最大值抑止(non-maximum suppression)”后有多少象素
for(k=1; k<1024; k++)
{
if(nHist[k] != 0)
{
// 最大梯度值
nMaxMag = k;
}
// 梯度为0的点是不可能为边界点的
// 经过non-maximum suppression后有多少象素
nEdgeNb += nHist[k];
}
// 梯度比高阈值*pnThdHigh小的象素点总数目
nHighCount = (int)(dRatioHigh * nEdgeNb +0.5);
k = 1;
nEdgeNb = nHist[1];
// 计算高阈值
while( (k<(nMaxMag-1)) && (nEdgeNb < nHighCount) )
{
k++;
nEdgeNb += nHist[k];
}
// 设置高阈值
*pnThdHigh = k ;
// 设置低阈值
*pnThdLow = (int)((*pnThdHigh) * dRationLow+ 0.5);
}
/*************************************************************************
* 函数名称:
* Hysteresis()
* 输入参数:
* int *pnMag - 梯度幅度图
* int nWidth - 图象数据宽度
* int nHeight - 图象数据高度
* double dRatioLow - 低阈值和高阈值之间的比例
* double dRatioHigh - 高阈值占图象象素总数的比例
* unsigned char *pUnchEdge - 记录边界点的缓冲区
* 说明:
* 本函数实现类似“磁滞现象”的一个功能,也就是,先调用EstimateThreshold
* 函数对经过non-maximum处理后的数据pUnchSpr估计一个高阈值,然后判断
* pUnchSpr中可能的边界象素(=128)的梯度是不是大于高阈值nThdHigh,如果比
* 该阈值大,该点将作为一个边界的起点,调用TraceEdge函数,把对应该边界
* 的所有象素找出来。最后,当整个搜索完毕时,如果还有象素没有被标志成
* 边界点,那么就一定不是边界点。
*
**************************************************************************/
void Hysteresis(int *pnMag, int nWidth, int nHeight, double dRatioLow,
double dRatioHigh, unsigned char *pUnchEdge)
{
// 循环控制变量
int y;
int x;
int nThdHigh ;
int nThdLow ;
int nPos;
// 估计TraceEdge需要的低阈值,以及Hysteresis函数使用的高阈值
EstimateThreshold(pnMag, nWidth, nHeight, &nThdHigh,
&nThdLow, pUnchEdge,dRatioHigh, dRatioLow);
// 这个循环用来寻找大于nThdHigh的点,这些点被用来当作边界点,然后用
// TraceEdge函数来跟踪该点对应的边界
for(y=0; y<nHeight; y++)
{
for(x=0; x<nWidth; x++)
{
nPos = y*nWidth + x ;
// 如果该象素是可能的边界点,并且梯度大于高阈值,该象素作为
// 一个边界的起点
if((pUnchEdge[nPos] == 128) && (pnMag[nPos] >= nThdHigh))
{
// 设置该点为边界点
pUnchEdge[nPos] = 255;
TraceEdge(y, x, nThdLow, pUnchEdge, pnMag, nWidth);
}
}
}
// 那些还没有被设置为边界点的象素已经不可能成为边界点
for(y=0; y<nHeight; y++)
{
for(x=0; x<nWidth; x++)
{
nPos = y*nWidth + x ;
if(pUnchEdge[nPos] != 255)
{
// 设置为非边界点
pUnchEdge[nPos] = 0 ;
}
}
}
}
/*************************************************************************
* 函数名称:
* Canny()
* 输入参数:
* unsigned char *pUnchImage - 图象数据
* int nWidth - 图象数据宽度
* int nHeight - 图象数据高度
* double sigma - 高斯滤波的标准方差
* double dRatioLow - 低阈值和高阈值之间的比例
* double dRatioHigh - 高阈值占图象象素总数的比例
* unsigned char *pUnchEdge - canny算子计算后的分割图
* 说明:
* canny分割算子,计算的结果保存在pUnchEdge中,逻辑1(255)表示该点为
* 边界点,逻辑0(0)表示该点为非边界点。该函数的参数sigma,dRatioLow
* dRatioHigh,是需要指定的。这些参数会影响分割后边界点数目的多少
**************************************************************************/
void Canny(unsigned char *pUnchImage, int nWidth, int nHeight, double sigma,
double dRatioLow, double dRatioHigh, unsigned char *pUnchEdge,double *CosTheta,double *SinTheta)
{
// 经过高斯滤波后的图象数据
unsigned char * pUnchSmooth ;
// 指向x方向导数的指针
int * pnGradX ;
// 指向y方向导数的指针
int * pnGradY ;
// 梯度的幅度
int * pnGradMag ;
pUnchSmooth = new unsigned char[nWidth*nHeight] ;
pnGradX = new int [nWidth*nHeight] ;
pnGradY = new int [nWidth*nHeight] ;
pnGradMag = new int [nWidth*nHeight] ;
// 对原图象进行滤波
GaussianSmooth(pUnchImage, nWidth, nHeight, sigma, pUnchSmooth) ;
// 计算方向导数
DirGrad(pUnchSmooth, nWidth, nHeight, pnGradX, pnGradY) ;
// 计算梯度的幅度
GradMagnitude(pnGradX, pnGradY, nWidth, nHeight, pnGradMag,CosTheta,SinTheta) ;
// 应用non-maximum 抑制
NonmaxSuppress(pnGradMag, pnGradX, pnGradY, nWidth, nHeight, pUnchEdge) ;
// 应用Hysteresis,找到所有的边界
Hysteresis(pnGradMag, nWidth, nHeight, dRatioLow, dRatioHigh, pUnchEdge);
// 释放内存
delete pnGradX ;
pnGradX = NULL ;
delete pnGradY ;
pnGradY = NULL ;
delete pnGradMag ;
pnGradMag = NULL ;
delete pUnchSmooth ;
pUnchSmooth = NULL ;
}
/*************************************************************************
* 函数名称:
* Hough()
* 输入参数:
* int x - 边界点的x坐标
* int y - 边界点的y坐标
* int *CosTheta - 梯度方向的余弦值
* int *SinTheta - 梯度方向的正弦值
* unsigned char *pUnchEdge - 记录边界点的缓冲区
* int Gao_temp1 - 记录圆心纵坐标
* int Gao_temp2 - 记录圆心横坐标
* int Gao_temp3 - 记录半径
**************************************************************************/
void Hough(int x,int y, int nWidth,int nHeight,double *CosTheta,double *SinTheta,unsigned char *pUnchEdge,int &Gao_temp1, int &Gao_temp2,int &Gao_temp3)
{
//半径
int Circle_R = 0;
//圆心(a,b)
int a = 0;
int b = 0;
//循环变量
int i;
int j;
int k;
//累加器
int (*Count)[320] = new int[nWidth * nHeight][320];
for(i=0; i<nHeight;i++)
{
for(j=0;j<nWidth; j++)
{
for(k=0;k<320;k++)
{
Count[i*nWidth+j][k] = 0;
}
}
}
//开始搜索
for(Circle_R = x; Circle_R < y; Circle_R ++)
{
for(i=0; i<nHeight; i++)
{
for(j=0; j<nWidth; j++)
{
//注意:pUnchEdge是canny检测得到的图像
if(pUnchEdge[i*nWidth+j] == 255)
{
a = (j - (int)(Circle_R * CosTheta[i*nWidth+j]));
b = (i - (int)(Circle_R * SinTheta[i*nWidth+j]));
if((a>0 && a<nWidth) && (b>0 && b<nHeight))
{
Count[b*nWidth+a][Circle_R]++;
}
}
}
}
}
//确定圆心和半径
int MaxCount;
MaxCount = Count[0][x];
for(i=0;i<nHeight; i++)
{
for(j=0;j<nWidth; j++)
{
for(k=x;k<y;k++)
{
if(Count[i*nWidth+j][k] > MaxCount)
{
MaxCount = Count[i*nWidth+j][k];
Gao_temp1 = i; // 圆心纵坐标
Gao_temp2 = j; // 圆心横坐标
Gao_temp3 = k; // 半径
}
}
}
}
// 释放内存
delete []Count;
Count = NULL;
}
/*************************************************************************
* 函数名称:
* Bresenham()
* 输入参数:
* int Gao_temp1 - 记录圆心纵坐标
* int Gao_temp2 - 记录圆心横坐标
* int Gao_temp3 - 记录半径
* unsigned char *pUnchEdge - 记录原图像的缓冲区
**************************************************************************/
void Bresenham(int Gao_temp1, int Gao_temp2,int Gao_temp3,int nWidth,int nHeight,unsigned char *HoughImage)
{
int Bresenham_x = 0;
int Bresenham_y = Gao_temp3;
int Delta_D;
int Delta_1;
int Delta_2;
int direction;
Delta_D = (Bresenham_x +1)*(Bresenham_x +1) + (Bresenham_y -1)*(Bresenham_y -1) - Gao_temp3*Gao_temp3;
while(Bresenham_y >= 0)
{
HoughImage[(Gao_temp1+Bresenham_y)*nWidth+(Gao_temp2+Bresenham_x)] = 255;
HoughImage[(Gao_temp1-Bresenham_y)*nWidth+(Gao_temp2+Bresenham_x)] = 255;
HoughImage[(Gao_temp1-Bresenham_y)*nWidth+(Gao_temp2-Bresenham_x)] = 255;
HoughImage[(Gao_temp1+Bresenham_y)*nWidth+(Gao_temp2-Bresenham_x)] = 255;
if(Delta_D<0)
{
Delta_1 = 2*(Delta_D+Bresenham_y)-1;
if(Delta_1<=0)
direction = 1;
else
direction = 2;
}
else if(Delta_D>0)
{
Delta_2 = 2*(Delta_D-Bresenham_x)-1;
if(Delta_2<=0)
direction = 2;
else
direction = 3;
}
else
{
direction = 2;
}
switch(direction)
{
case 1:
Bresenham_x ++;
Delta_D += 2*Bresenham_x + 1;
break;
case 2:
Bresenham_x ++;
Bresenham_y --;
Delta_D += 2*(Bresenham_x - Bresenham_y + 1);
break;
case 3:
Bresenham_y --;
Delta_D += ((-2)*Bresenham_y + 1);
break;
}
}
}
/*************************************************************************
* 函数名称:
* Gradient()
* 输入参数:
* int Gao_temp1 - 记录内圆圆心纵坐标
* int Gao_temp2 - 记录内圆圆心横坐标
* int Gao_temp3 - 记录内圆半径
* int Gao_temp4 - 记录外圆圆心纵坐标
* int Gao_temp5 - 记录外圆圆心横坐标
* int Gao_temp6 - 记录外圆半径
* unsigned char *pUnchEdge - 记录原图像的缓冲区
**************************************************************************/
void Gradient(int Gao_temp1,int Gao_temp2,int Gao_temp3,int nWidth,int nHeight,unsigned char *HoughImage,int &Gao_temp4,int &Gao_temp5,int &Gao_temp6)
{
//循环变量
int i = 0;
int j = 0;
int k = 0;
int Big_R = Gao_temp3 + 55;
double MaxCount = 0.0;
double (*grey)[120] = new double[nHeight*nWidth][120];
double (*grad)[119] = new double[nHeight*nWidth][119];
for(i=0; i<nHeight*nWidth; i++)
{
for(j=0; j<120; j++)
{
grey[i][j] = 0.0;
}
}
for(i=0; i<nHeight*nWidth; i++)
{
for(j=0; j<119; j++)
{
grad[i][j] = 0.0;
}
}
for(i=0; i<nHeight; i++) // 纵坐标
{
for(j=0; j<nWidth; j++) // 横坐标
{
if((i-Gao_temp1)*(i-Gao_temp1)+(j-Gao_temp2)*(j-Gao_temp2) <= Gao_temp3*Gao_temp3)
{
for(k=Big_R; k<120; k++)
{
int count = 0;
double sum = 0;
int Bresenham_x = 0; // 横坐标
int Bresenham_y = k; // 纵坐标
int Delta_D;
int Delta_1;
int Delta_2;
int direction;
Delta_D = (Bresenham_x +1)*(Bresenham_x +1) + (Bresenham_y -1)*(Bresenham_y -1) - Gao_temp3*Gao_temp3;
while(Bresenham_y >= 0)
{
sum = sum + double(HoughImage[(i+Bresenham_y)*nWidth+(j+Bresenham_x)] + HoughImage[(i-Bresenham_y)*nWidth+(j+Bresenham_x)]
+ HoughImage[(i-Bresenham_y)*nWidth+(j-Bresenham_x)] + HoughImage[(i+Bresenham_y)*nWidth+(j-Bresenham_x)]);
count = count + 4;
if(Delta_D<0)
{
Delta_1 = 2*(Delta_D+Bresenham_y)-1;
if(Delta_1<=0)
direction = 1;
else
direction = 2;
}
else if(Delta_D>0)
{
Delta_2 = 2*(Delta_D-Bresenham_x)-1;
if(Delta_2<=0)
direction = 2;
else
direction = 3;
}
else
{
direction = 2;
}
switch(direction)
{
case 1:
Bresenham_x ++;
Delta_D += 2*Bresenham_x + 1;
break;
case 2:
Bresenham_x ++;
Bresenham_y --;
Delta_D += 2*(Bresenham_x - Bresenham_y + 1);
break;
case 3:
Bresenham_y --;
Delta_D += ((-2)*Bresenham_y + 1);
break;
}
}
grey[i*nWidth+j][k] = sum/count;
}
}
}
}
for(i=0; i<nHeight; i++) // 纵坐标
{
for(j=0; j<nWidth; j++) // 横坐标
{
for(k=Big_R; k<119; k++)
{
if(grey[i*nWidth+j][k]!=0)
{
grad[i*nWidth+j][k] = grey[i*nWidth+j][k+1] - grey[i*nWidth+j][k];
}
}
}
}
MaxCount = fabs(grad[0][0]);
for(i=0; i<nHeight; i++) // 纵坐标
{
for(j=0; j<nWidth; j++) // 横坐标
{
for(k=0; k<119; k++)
{
if(fabs(grad[i*nWidth+j][k]) >= MaxCount)
{
MaxCount = fabs(grad[i*nWidth+j][k]);
Gao_temp4 = i; // 虹膜圆心纵坐标
Gao_temp5 = j; // 虹膜圆心横坐标
Gao_temp6 = k; // 虹膜半径
}
}
}
}
//释放内存
delete []grey;
grey = NULL;
delete []grad;
grad = NULL;
}
/*************************************************************************
* 函数名称:
* Normalization()
* 输入参数:
* int Gao_temp1 - 记录瞳孔圆心纵坐标
* int Gao_temp2 - 记录瞳孔圆心横坐标
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -