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

📄 preprocess.cpp

📁 指纹算法引擎(内含指纹预处理和比对算法)本程序是由VC++编程的
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// DIP.cpp: implementation of the DIP class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "FP.h"
#include "preprocess.h"
#include "math.h"


int  g_DDSite[12][7][2] = {
	-3, 0,  -2, 0,  -1, 0,   0, 0,   1, 0,   2, 0,   3, 0,
	-3,-1,  -2,-1,  -1, 0,   0, 0,   1, 0,   2, 1,   3, 1,
	-3,-2,  -2,-1,  -1,-1,   0, 0,   1, 1,   2, 1,   3, 2,
	-3,-3,  -2,-2,  -1,-1,   0, 0,   1, 1,   2, 2,   3, 3,
	-2,-3,  -1,-2,  -1,-1,   0, 0,   1, 1,   1, 2,   2, 3,
	-1,-3,  -1,-2,   0,-1,   0, 0,   0, 1,   1, 2,   1, 3,
	 0,-3,   0,-2,   0,-1,   0, 0,   0, 1,   0, 2,   0, 3,
	-1, 3,  -1, 2,   0, 1,   0, 0,   0,-1,   1,-2,   1,-3,
	-2, 3,  -1, 2,  -1, 1,   0, 0,   1,-1,   1,-2,   2,-3,
	-3, 3,  -2, 2,  -1, 1,   0, 0,   1,-1,   2,-2,   3,-3,
	-3, 2,  -2, 1,  -1, 1,   0, 0,   1,-1,   2,-1,   3,-2,
	-3, 1,  -2, 1,  -1, 0,   0, 0,   1, 0,   2,-1,   3,-1
};


void GaussSmooth(BYTE *pUnchImg, BYTE *pUnchSmthdImg, int nWidth, int nHeight, double sigma)
{
	int y;
	int x;
	int i;
	
	// 高斯滤波器的数组长度
	int nWindowSize;
	
	//  窗口长度的1/2
	int	nHalfLen;   
	
	// 一维高斯数据滤波器
	double *pdKernel ;
	
	// 高斯系数与图像数据的点乘
	double  dDotMul     ;
	
	// 高斯滤波系数的总和
	double  dWeightSum     ;          
  
	// 中间变量
	double * pdTmp ;
	
	// 分配内存
	pdTmp = new double[nWidth*nHeight];
	
	// 产生一维高斯数据滤波器
	MakeGauss(sigma, &pdKernel, &nWindowSize) ;
	
	// MakeGauss返回窗口的长度,利用此变量计算窗口的半长
	nHalfLen = nWindowSize / 2;
	
  // x方向进行滤波
	for(y=0; y<nHeight; y++)
	{
		for(x=0; x<nWidth; x++)
		{
			dDotMul		= 0;
			dWeightSum = 0;
			for(i=(-nHalfLen); i<=nHalfLen; i++)
			{
				// 判断是否在图像内部
				if( (i+x) >= 0  && (i+x) < nWidth )
				{
					dDotMul += (double)pUnchImg[y*nWidth + (i+x)] * pdKernel[nHalfLen+i];
					dWeightSum += pdKernel[nHalfLen+i];
				}
			}
			pdTmp[y*nWidth + x] = dDotMul/dWeightSum ;
		}
	}
	
	// y方向进行滤波
	for(x=0; x<nWidth; x++)
	{
		for(y=0; y<nHeight; y++)
		{
			dDotMul		= 0;
			dWeightSum = 0;
			for(i=(-nHalfLen); i<=nHalfLen; i++)
			{
				// 判断是否在图像内部
				if( (i+y) >= 0  && (i+y) < nHeight )
				{
					dDotMul += (double)pdTmp[(y+i)*nWidth + x] * pdKernel[nHalfLen+i];
					dWeightSum += pdKernel[nHalfLen+i];
				}
			}
			pUnchSmthdImg[y*nWidth + x] = (BYTE)(int)(dDotMul / dWeightSum);
		}
	}

	// 释放内存
	delete []pdKernel;
	pdKernel = NULL ;
	
	delete []pdTmp;
	pdTmp = NULL;
}

/*************************************************************************
 *
 * \函数名称:
 *   MakeGauss()
 *
 * \输入参数:
 *   double sigma									        - 高斯函数的标准差
 *   double **pdKernel										- 指向高斯数据数组的指针
 *   int *pnWindowSize										- 数据的长度
 *
 * \返回值:
 *   无
 *
 * \说明:
 *   这个函数可以生成一个一维的高斯函数的数字数据,理论上高斯数据的长度应
 *   该是无限长的,但是为了计算的简单和速度,实际的高斯数据只能是有限长的
 *   pnWindowSize就是数据长度
 *   
 *************************************************************************
 */
void MakeGauss(double sigma, double **pdKernel, int *pnWindowSize)
{
	// 循环控制变量
	int i   ;
	
	// 数组的中心点
	int nCenter;

	// 数组的某一点到中心点的距离
	double  dDis  ; 

	
	// 中间变量
	double  dValue; 
	double  dSum  ;
	dSum = 0 ; 
	
	// 数组长度,根据概率论的知识,选取[-3*sigma, 3*sigma]以内的数据。
	// 这些数据会覆盖绝大部分的滤波系数
	*pnWindowSize = (int)(1 + 2 * ceil(3 * sigma));
	
	// 中心
	nCenter = (*pnWindowSize) / 2;
	
	// 分配内存
	*pdKernel = new double[*pnWindowSize] ;
	
	for(i=0; i< (*pnWindowSize); i++)
	{
		dDis = (double)(i - nCenter);
		dValue = exp(-(1/2)*dDis*dDis/(sigma*sigma)) / (sqrt(2 * PI) * sigma );
		(*pdKernel)[i] = dValue ;
		dSum += dValue;
	}
	
	// 归一化
	for(i=0; i<(*pnWindowSize) ; i++)
	{
		(*pdKernel)[i] /= dSum;
	}
}


void getOrientMap(unsigned char* g_lpTemp, unsigned char* g_lpOrient, int IMGW, int IMGH, long  r)
{
	long  x, y, i, j;
	long  vx, vy, lvx, lvy;
	unsigned char   *lpSrc = NULL;
	unsigned char   *lpOri = NULL;
	long	angle, num;
	double  fAngle;

	for(y = 0; y < IMGH/2; y++)
	{
		for(x = 0; x < IMGW/2; x++)
		{
			lpOri = g_lpOrient + 2 * y * IMGW + 2 * x;
			lvx = 0;
			lvy = 0;
			num = 0;
			for(i = -r; i <= r; i++)	// 为提高速度,步长为
			{
				if(y+i<1 || y+i>=IMGH/2-1) continue;
				for(j = -r; j <= r; j++)	// 为提高速度,步长为
				{
					if(x+j<1 || x+j>=IMGW/2-1) continue;
					lpSrc = g_lpTemp + (y+i)*(IMGW/2) + x+j;
					//求x方向偏导
					vx = *(lpSrc + IMGW/2 + 1) - *(lpSrc + IMGW/2 - 1) +
						 *(lpSrc + 1)*2 - *(lpSrc - 1)*2 +
						 *(lpSrc - IMGW/2 + 1) - *(lpSrc - IMGW/2 - 1);
					//求y方向偏导
					vy = *(lpSrc + IMGW/2 - 1) - *(lpSrc - IMGW/2 - 1) +
						 *(lpSrc + IMGW/2)*2 - *(lpSrc - IMGW/2)*2 +
						 *(lpSrc + IMGW/2 + 1) - *(lpSrc - IMGW/2 + 1);

					lvx += vx * vy * 2;//sin(2sita)
					lvy += vx*vx - vy*vy;//cos(2sita)
					num++;
				}
			}

			if(num == 0) num = 1;

			// 求弧度
			fAngle = atan2(lvy, lvx);
			// 变换到(0 - 2*pi)
			if(fAngle < 0)	fAngle += 2*PI;
			
			// 求纹线角度
			fAngle = (fAngle*EPI*0.5 + 0.5);
			angle = (long)fAngle;

			// 因为采用sobel算子,所以角度偏转了度,所以要旋转求得的角度
			angle -= 135;
			// 角度变换到(-180)
			if(angle <= 0)	angle += 180;
			
			angle = 180-angle;
			// 最终纹线角度
			*lpOri = (unsigned char)angle;
			*(lpOri + 1) = (unsigned char)angle;
			*(lpOri + IMGW) = (unsigned char)angle;
			*(lpOri + IMGW + 1) = (unsigned char)angle;

		}
	}
}

void getGrads(unsigned char* g_lpTemp, unsigned char* g_lpDivide, int IMGW, int IMGH, long r)
{
	long  x, y, i, j;
	long  vx, vy, lvx, lvy;
	unsigned char   *lpSrc = NULL;
	unsigned char   *lpDiv = NULL;
	long	num;
	int gradSum;
	int grad;
	

	for(y = 0; y < IMGH/2; y++)
	{
		for(x = 0; x < IMGW/2; x++)
		{			
			lpDiv = g_lpDivide + 2*y*IMGW + 2*x;
			lvx = 0;
			lvy = 0;
			num = 0;
			gradSum = 0;
			for(i = -r; i <= r; i++)	// 为提高速度,步长为
			{
				if(y+i<1 || y+i>=IMGH/2-1) continue;
				for(j = -r; j <= r; j++)	// 为提高速度,步长为
				{
					if(x+j<1 || x+j>=IMGW/2-1) continue;
					lpSrc = g_lpTemp + (y+i)*(IMGW/2) + x+j;
					//求x方向偏导
					vx = *(lpSrc + IMGW/2 + 1) - *(lpSrc + IMGW/2 - 1) +
						 *(lpSrc + 1)*2 - *(lpSrc - 1)*2 +
						 *(lpSrc - IMGW/2 + 1) - *(lpSrc - IMGW/2 - 1);
					//求y方向偏导
					vy = *(lpSrc + IMGW/2 - 1) - *(lpSrc - IMGW/2 - 1) +
						 *(lpSrc + IMGW/2)*2 - *(lpSrc - IMGW/2)*2 +
						 *(lpSrc + IMGW/2 + 1) - *(lpSrc - IMGW/2 + 1);

					gradSum += (abs(vx)+abs(vy));		
					num++;
				}
			}

			if(num == 0)
				num = 1;
			// 求幅值,保存到g_lpDivide中,用于分割前景背景
			grad = gradSum/num;
			
			if(grad > 255)
				grad = 255;
			*lpDiv = (BYTE)grad;
			*(lpDiv + 1) = (BYTE)grad;
			*(lpDiv + IMGW) = (BYTE)grad;
			*(lpDiv + IMGW + 1) = (BYTE)grad;

	
		}
	}
}


void smooth(BYTE *lpInBuffer, BYTE *lpOutBuffer, int IMGW, int IMGH, int r, int d)
{
////////////////////////////////////////////////////////////////////////
//	lpInBuffer: [in] 要平滑的图像数据缓冲区
//	lpOutBuffer: [out] 平滑后的图像数据缓冲区
//	r: [in] 平滑滤波器半径
//	d: [in] 平滑滤波器步长
////////////////////////////////////////////////////////////////////////
	int	x, y, i, j;
	BYTE	*lpSrc;
	BYTE	*lpRst;
	int	sum, num;
	

	for(y = 0; y < IMGH; y++)
	{
		for(x = 0; x < IMGW; x++)
		{
			lpSrc = lpInBuffer + y*IMGW + x;
			lpRst = lpOutBuffer + y*IMGW + x;
			sum = 0; 
			num = 0;
			for(i = -r; i <= r; i+=d)
			{
				if(i+y<0 || i+y>=IMGH)
					continue;
				for(j = -r; j <= r; j+=d)
				{
					if(j+x<0 || j+x>=IMGW)
						continue;
					sum += *(lpSrc + i*IMGW + j);
					num++;
				}
			}
			*lpRst = (BYTE)(sum/num);
		}
	}


}


void zoomout(BYTE *g_lpOrgFinger, BYTE *g_lpTemp, int IMGW, int IMGH)
{
	int	x, y;
	BYTE	*lpSrc;
	BYTE	*lpRst;
	int	sum;
	int	SiteD8[8] = {IMGW-1, IMGW, IMGW+1, 1, -IMGW+1, -IMGW, -IMGW-1, -1};
	
	// 边缘部分
	for(y = 0; y < IMGH; y+=2)
	{
		lpSrc = g_lpOrgFinger + y*IMGW;
		lpRst = g_lpTemp + (y/2)*(IMGW/2);
		*lpRst = *lpSrc;
		lpSrc = g_lpOrgFinger + y*IMGW + IMGW - 1;
		lpRst = g_lpTemp + (y/2)*(IMGW/2) + (IMGW/2 - 1);
		*lpRst = *lpSrc;
	}
	for(x = 0; x < IMGW; x+=2)
	{
		lpSrc = g_lpOrgFinger + x;
		lpRst = g_lpTemp + x/2;
		*lpRst = *lpSrc;
		lpSrc = g_lpOrgFinger + (IMGH-1)*IMGW + x;
		lpRst = g_lpTemp + (IMGH/2-1)*(IMGW/2) + x/2;
		*lpRst = *lpSrc;
	}

	// 非边缘部分用高斯模板提取低频信息
	for(y = 2; y < IMGH-2; y+=2)
	{
		for(x = 2; x < IMGW-2; x+=2)
		{
			lpSrc = g_lpOrgFinger + y*IMGW + x;
			lpRst = g_lpTemp + (y/2)*(IMGW/2) + x/2;
			sum = *lpSrc*4 + *(lpSrc + SiteD8[0]) +
				  *(lpSrc + SiteD8[1])*2 + *(lpSrc + SiteD8[2]) +
				  *(lpSrc + SiteD8[3])*2 + *(lpSrc + SiteD8[4]) +
				  *(lpSrc + SiteD8[5])*2 + *(lpSrc + SiteD8[6]) +
				  *(lpSrc + SiteD8[7])*2;
			sum = sum>>4;
			*lpRst = (BYTE)sum;
		}
	}
	

}


void equalize(BYTE *lpDIBBits, BYTE *lpDataOut, int lWidth, int lHeight)
{
	
	// 指向源图像的指针
	BYTE*	lpSrc;
	BYTE*	lpRst;
	
	// 临时变量
	int	lTemp;
	// 循环变量
	int	i;
	int	j;
	
	// 灰度映射表
	BYTE	bMap[256];
	
	// 灰度映射表
	int	lCount[256];
	
	// 图像每行的字节数
	int	lLineBytes;
	
	// 计算图像每行的字节数
	//lLineBytes = WIDTHBYTES(lWidth * 8);
	lLineBytes = lWidth;
	
	// 重置计数为0
	for (i = 0; i < 256; i ++)
	{
		// 清零
		lCount[i] = 0;
	}
	
	// 计算各个灰度值的计数
	for (i = 0; i < lHeight; i ++)
	{
		for (j = 0; j < lWidth; j ++)
		{
			lpSrc = (unsigned char *)lpDIBBits + lLineBytes * i + j;
			
			// 计数加1
			lCount[*(lpSrc)]++;
		}
	}
	
	// 计算灰度映射表
	for (i = 0; i < 256; i++)
	{
		// 初始为0
		lTemp = 0;
		
		for (j = 0; j <= i ; j++)
		{
			lTemp += lCount[j];
		}
		
		// 计算对应的新灰度值
		bMap[i] = (BYTE) (lTemp * 255 / lHeight / lWidth);
	}
	// 每行
	for(i = 0; i < lHeight; i++)
	{		// 每列
		for(j = 0; j < lWidth; j++)
		{
			// 指向DIB第i行,第j个像素的指针
			lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;
			lpRst = (unsigned char*)lpDataOut + lLineBytes * (lHeight - 1 - i) + j;
			// 计算新的灰度值
			*lpRst = bMap[*lpRst];
		}
	}
	// 返回
	

}


int segment(BYTE *g_lpDivide, BYTE *g_lpTemp, int r, int threshold, int IMGW, int IMGH)
{
///////////////////////////////////////////////////////////////////////
//	r: [in] 对幅值图像高度平滑滤波的滤波器半径
//  threshold: [in] 分割的阈值
///////////////////////////////////////////////////////////////////////
	int	x, y;
	int  num = 0;

	// 对方向场幅值图像进行高度平滑滤波
	smooth(g_lpTemp, g_lpDivide, IMGW, IMGH, r, 2);
	
	// 图像边缘均设置为背景
	for(y = 0; y < IMGH; y++)
	{
		*(g_lpDivide + y*IMGW) = 255;
		*(g_lpDivide + y*IMGW + IMGW - 1) = 255;
	}
	for(x = 0; x < IMGW; x++)
	{
		*(g_lpDivide + x) = 255;
		*(g_lpDivide + (IMGH-1)*IMGW + x) = 255;
	}

	for(y = 1; y < IMGH-1; y++)
	{
		for(x = 1; x < IMGW-1; x++)
		{
			// 根据幅值与阈值大小判断是否为背景区域
			if(*(g_lpDivide + y*IMGW + x) < threshold)
			{
				*(g_lpDivide + y*IMGW + x) = 0;
			}
			else
			{
				*(g_lpDivide + y*IMGW + x) = 255;
				num++;
			}
		}
	}

	// 如果前景区域面积小于总面积的十分之一,则表示前景区域太小,返回错误
	if(num < IMGH * IMGW/10)
		return 1;
	else
		return 0;

}

//
//	clearEdge: 清除背景
//
void segment_clearEdge(BYTE *g_lpOrgFinger, BYTE *g_lpOrient, BYTE* g_lpDivide, int IMGW, int IMGH)
{
	int	x, y;
	int  temp;
	temp = 0;

	for(y = 0; y < IMGH; y++)
	{
		for(x = 0; x < IMGW; x++)
		{	
			// 如果是背景区域,则置该点为白点
			if(*(g_lpDivide + temp + x) == 0)
			{
				*(g_lpOrgFinger + temp + x) = 255;
				*(g_lpOrient + temp + x) = 255;
			}
		}
		temp += IMGW;
	}
}



int DDIndex(int angle)
{
/////////////////////////////////////////////////////////////////////////
//	angle: [in] 角度 (0 - 180)
/////////////////////////////////////////////////////////////////////////
	if(angle >= 173 || angle < 8)
	{
		return 0;
	}
	else
	{
		return ((angle-8)/15 + 1);
	}
}


void orientEnhance(BYTE *g_lpOrient, BYTE *g_lpOrgFinger, int IMGW, int IMGH)
{
	int x, y;
	int i;
	int d = 0;
	int sum = 0;
	// 纹线方向上进行平滑滤波的平滑滤波器
	int Hw[7] = {1, 1, 1, 1, 1, 1, 1};
	// 纹线方向的垂直方向上进行锐化滤波的锐化滤波器
	int Vw[7] = {-3, -1, 3, 9, 3, -1, -3};
	int hsum = 0;
	int vsum = 0;
	int temp = 0;
	BYTE  *lpSrc = NULL;
	BYTE  *lpDir = NULL;

	BYTE *g_lpTemp = new BYTE[IMGW * IMGH];

	// 纹线方向上进行平滑滤波
	temp = 0;
	for(y = 0; y < IMGH; y++)
	{
		for(x = 0; x < IMGW; x++)
		{
			lpDir = g_lpOrient + temp + x;
			lpSrc = g_lpOrgFinger + temp + x;
			// 纹线方向的索引
			d = DDIndex(*lpDir);
			sum = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -