⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 globalapi.cpp

📁 虹膜图像预处理
💻 CPP
📖 第 1 页 / 共 3 页
字号:

	// 最大梯度值
	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 + -