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

📄 preprocess.cpp

📁 指纹算法引擎(内含指纹预处理和比对算法)本程序是由VC++编程的
💻 CPP
📖 第 1 页 / 共 2 页
字号:
			hsum = 0;
			for(i = 0; i < 7; i++)
			{
				if(y+g_DDSite[d][i][1] < 0 || y+g_DDSite[d][i][1] >= IMGH ||
				   x+g_DDSite[d][i][0] < 0 || x+g_DDSite[d][i][0] >= IMGW)
				{
					continue;
				}
				sum += Hw[i]*(*(lpSrc + g_DDSite[d][i][1]*IMGW + g_DDSite[d][i][0]));
				hsum += Hw[i];
			}
			if(hsum != 0)
			{
				*(g_lpTemp + temp + x) = (BYTE)(sum/hsum);
			}
			else
			{
				*(g_lpTemp + temp + x) = 255;
			}
		}
		temp += IMGW;
	}

	// 纹线方向的垂直方向上进行锐化滤波
	temp = 0;
	for(y = 0; y < IMGH; y++)
	{
		for(x = 0; x < IMGW; x++)
		{
			lpDir = g_lpOrient + temp + x;
			lpSrc = g_lpTemp + temp + x;
			
			// 纹线方向的垂直方向的索引
			d = (DDIndex(*lpDir)+6) % 12;

			sum = 0;
			vsum = 0;
			for(i = 0; i < 7; i++)
			{
				if(y+g_DDSite[d][i][1] < 0 || y+g_DDSite[d][i][1] >= IMGH ||
				   x+g_DDSite[d][i][0] < 0 || x+g_DDSite[d][i][0] >= IMGW)
				{
					continue;
				}
				sum += Vw[i]*(*(lpSrc + g_DDSite[d][i][1]*IMGW + g_DDSite[d][i][0]));
				vsum += Vw[i];
			}
			if(vsum > 0)
			{
				sum /= vsum;
				if(sum > 255)
				{
					*(g_lpOrgFinger + temp + x) = 255;
				}
				else if(sum < 0)
				{
					*(g_lpOrgFinger + temp + x) = 0;
				}
				else
				{
					*(g_lpOrgFinger + temp + x) = (BYTE)sum;
				}
			}
			else
			{
				*(g_lpOrgFinger + temp + x) = 255;
			}
		}
		temp += IMGW;
	}

}


int binary(BYTE *g_lpOrgFinger, BYTE *g_lpTemp, BYTE *g_lpOrient, int IMGW, int IMGH)
{
	int x, y;
	int i;
	int d = 0;
	int sum = 0;
	// 纹线方向上的7个点的权值
	int Hw[7] = {2, 2, 3, 4, 3, 2, 2};
	// 纹线方向的垂直方向上的7个点的权值
	int Vw[7] = {1, 1, 1, 1, 1, 1, 1};
	int hsum = 0;	// 纹线方向上的7个点的加权和
	int vsum = 0;	// 纹线方向的垂直方向上的7个点的加权和
	int Hv = 0;		// 纹线方向上的7个点的加权平均值
	int Vv = 0;		// 纹线方向的垂直方向上的7个点的加权平均值
	int temp = 0;
	BYTE  *lpSrc = NULL;	// 指纹图像像素点指针
	BYTE  *lpDir = NULL;	// 纹线方向指针

	temp = 0;
	for(y = 0; y < IMGH; y++)
	{
		for(x = 0; x < IMGW; x++)
		{
			lpDir = g_lpOrient + temp + x;
			lpSrc = g_lpOrgFinger + temp + x;
			
			// 如果该点非常黑,则在临时缓冲区内置该点为黑点,值为0
			if(*lpSrc < 4)
			{
				*(g_lpTemp + temp + x) = 0;
				continue;
			}
			// 计算方向索引(量化为12个方向)
			d = DDIndex(*lpDir);
			
			// 计算当前点在纹线方向上的加权平均值
			sum = 0;
			hsum = 0;
			for(i = 0; i < 7; i++)
			{
				// 坐标是否越界
				if(y+g_DDSite[d][i][1] < 0 || y+g_DDSite[d][i][1] >= IMGH ||
				   x+g_DDSite[d][i][0] < 0 || x+g_DDSite[d][i][0] >= IMGW)
				{
					continue;
				}
				sum += Hw[i]*(*(lpSrc + g_DDSite[d][i][1]*IMGW + g_DDSite[d][i][0]));
				hsum += Hw[i];
			}
			if(hsum != 0)
			{
				Hv = sum/hsum;
			}
			else
			{
				Hv = 255;
			}

			// 纹线方向的垂直方向的索引
			d = (d+6)%12;

			// 计算当前点在纹线方向的垂直方向上的加权平均值
			sum = 0;
			vsum = 0;
			for(i = 0; i < 7; i++)
			{
				if(y+g_DDSite[d][i][1] < 0 || y+g_DDSite[d][i][1] >= IMGH ||
				   x+g_DDSite[d][i][0] < 0 || x+g_DDSite[d][i][0] >= IMGW)
				{
					continue;
				}
				sum += Vw[i]*(*(lpSrc + g_DDSite[d][i][1]*IMGW + g_DDSite[d][i][0]));
				vsum += Vw[i];
			}
			if(vsum != 0)
			{
				Vv = sum/vsum;
			}
			else
			{
				Vv = 255;
			}

			
			if(Hv < Vv)
			{
				// 纹线方向上加权平均值较小则置当前点为黑点
				*(g_lpTemp + temp + x) = 0;
			}
			else
			{
				// 纹线方向上加权平均值较大则置当前点为白点
				*(g_lpTemp + temp + x) = 255;
			}
		}
		temp += IMGW;
	}

	// 将临时缓冲区内数据拷贝到原始图像数据缓冲区
	//memcpy((void *)g_lpOrgFinger, (void *)g_lpTemp, IMGSIZE);
	

	return 0;

}

//
//	binary: 对二值化指纹图像进行去噪声
//
void binaryClear(BYTE *g_lpOrgFinger, BYTE *g_lpTemp, BYTE *g_lpDivide, int IMGW, int IMGH)
{
	int x, y, i;
	int num = 0;
	bool   bWorking;
	int temp;
	BYTE  *lpSrc = NULL;
	bWorking = true;
	int  n = 0;
	// 某点周围8个点的地址偏移
	int	SiteD8[8] = {IMGW-1, IMGW, IMGW+1, 1, -IMGW+1, -IMGW, -IMGW-1, -1};
	
	// 初始化临时缓冲区
	memset((void *)g_lpTemp, 0xFF, IMGW * IMGH);

	// 循环处理直到处理完毕或者处理次数超过8
	while(bWorking && n < 8)
	{
		bWorking = false;
		n++;
		temp = IMGW;
		for(y = 1; y < IMGH-1; y++)
		{
			for(x = 1; x < IMGW-1; x++)
			{
				// 背景的点不处理
				if(*(g_lpDivide + temp + x) == 0)
				{
					continue;
				}
				// 统计当前点周围与它相同类型点的个数
				num = 0;
				lpSrc = g_lpOrgFinger + temp + x;
				for(i = 0; i < 8; i++)
				{
					if(*(lpSrc+SiteD8[i]) == *lpSrc)
					{
						num++;
					}
				}
				// 相同点个数小于二则改变当前点类型
				if(num < 2)
				{
					*(g_lpTemp+temp+x) = 255 - *lpSrc;
					bWorking = true;
				}
				else
				{
					*(g_lpTemp+temp+x) = *lpSrc;
				}

			}
			temp += IMGW;
		}
		// 将处理结果拷贝到原始图像缓冲区
		//memcpy((void *)g_lpOrgFinger, (void *)g_lpTemp, IMGSIZE);
	}

}

int imageThin(BYTE *lpBits, BYTE *g_lpTemp, int Width, int Height)
{
/////////////////////////////////////////////////////////////////
//	lpBits: [in, out] 要细化的图像数据缓冲区 
//	Width: [in] 要细化的图像宽度
//	Height: [in] 要细化的图像高度
/////////////////////////////////////////////////////////////////
	BYTE  erasetable[256]={
			0,0,1,1,0,0,1,1,             1,1,0,1,1,1,0,1,
			1,1,0,0,1,1,1,1,             0,0,0,0,0,0,0,1,
			0,0,1,1,0,0,1,1,             1,1,0,1,1,1,0,1,
			1,1,0,0,1,1,1,1,             0,0,0,0,0,0,0,1,
			1,1,0,0,1,1,0,0,             0,0,0,0,0,0,0,0,
			0,0,0,0,0,0,0,0,             0,0,0,0,0,0,0,0,
			1,1,0,0,1,1,0,0,             1,1,0,1,1,1,0,1,
			0,0,0,0,0,0,0,0,             0,0,0,0,0,0,0,0,
			0,0,1,1,0,0,1,1,             1,1,0,1,1,1,0,1,
			1,1,0,0,1,1,1,1,             0,0,0,0,0,0,0,1,
			0,0,1,1,0,0,1,1,             1,1,0,1,1,1,0,1,
			1,1,0,0,1,1,1,1,             0,0,0,0,0,0,0,0,
			1,1,0,0,1,1,0,0,             0,0,0,0,0,0,0,0,
			1,1,0,0,1,1,1,1,             0,0,0,0,0,0,0,0,
			1,1,0,0,1,1,0,0,             1,1,0,1,1,1,0,0,
			1,1,0,0,1,1,1,0,             1,1,0,0,1,0,0,0
	};
	int		x,y;
	int      num;
	BOOL        Finished;
	BYTE       nw,n,ne,w,e,sw,s,se;
	BYTE       *lpPtr = NULL;
	BYTE       *lpTempPtr = NULL;	

	memcpy((void *)g_lpTemp, (void *)lpBits, Width*Height);
	
	//结束标志置成假
	Finished=FALSE;
	while(!Finished){ //还没有结束
              //结束标志置成假
            Finished=TRUE;
       //先进行水平方向的细化
              for (y=1;y<Height-1;y++)
			  { //注意为防止越界,y的范围从1到高度-2
                     //lpPtr指向原图数据,lpTempPtr指向新图数据

                     lpPtr=(BYTE *)lpBits+y*Width;
                     lpTempPtr=(BYTE *)g_lpTemp+y*Width;

                     x=1; //注意为防止越界,x的范围从1到宽度-2

                     while(x<Width-1)
					 {
                            if(*(lpPtr+x)==0)
							{ //是黑点才做处理
                                   w = *(lpPtr+x-1);  //左邻点
                                   e = *(lpPtr+x+1);  //右邻点

                                   if( (w==255)|| (e==255)){ 

									//如果左右两个邻居中至少有一个是白点才处理

                                          nw=*(lpPtr+x+Width-1); //左上邻点

                                          n=*(lpPtr+x+Width); //上邻点

                                          ne=*(lpPtr+x+Width+1); //右上邻点

                                          sw=*(lpPtr+x-Width-1); //左下邻点

                                          s=*(lpPtr+x-Width); //下邻点

                                          se=*(lpPtr+x-Width+1); //右下邻点

                                          //计算索引

                            num=nw/255+n/255*2+ne/255*4+w/255*8+e/255*16+
								sw/255*32+s/255*64+se/255*128;

                                          if(erasetable[num]==1){ //经查表,可以删除

												//在原图缓冲区中将该黑点删除

                                                 *(lpPtr+x)=255; 

													//结果图中该黑点也删除

                                                 *(lpTempPtr+x)=255; 

                                                 Finished=FALSE; //有改动,结束标志置成假

                                                 x++; //水平方向跳过一个象素

                                          }

                                   }

                            }

                            x++; //扫描下一个象素

                     }

              }

       //再进行垂直方向的细化

              for (x=1;x<Width-1;x++){ //注意为防止越界,x的范围从1到宽度-2

                     y=1; //注意为防止越界,y的范围从1到高度-2

                     while(y<Height-1){

                            lpPtr=lpBits+y*Width;

                            lpTempPtr=g_lpTemp+y*Width;

                            if(*(lpPtr+x)==0){ //是黑点才做处理

                                   n=*(lpPtr+x+Width);

                                   s=*(lpPtr+x-Width);

                                   if( (n==255)|| (s==255)){

//如果上下两个邻居中至少有一个是白点才处理

                                          nw=*(lpPtr+x+Width-1);

                                          ne=*(lpPtr+x+Width+1);

                                          w=*(lpPtr+x-1);

                                          e=*(lpPtr+x+1);

                                          sw=*(lpPtr+x-Width-1);

                                          se=*(lpPtr+x-Width+1);

                                          //计算索引

										num=nw/255+n/255*2+ne/255*4+w/255*8+e/255*16+

											sw/255*32+s/255*64+se/255*128;

                                          if(erasetable[num]==1){ //经查表,可以删除

//在原图缓冲区中将该黑点删除

                                                 *(lpPtr+x)=255; 

//结果图中该黑点也删除

                                                 *(lpTempPtr+x)=255; 

                                                 Finished=FALSE; //有改动,结束标志置成假

                                                 y++;//垂直方向跳过一个象素

                                          }

                                   }

                            }

                            y++; //扫描下一个象素

                     }

              } 

	}
	
	//memcpy((void *)lpBits, (void *)g_lpTemp, Width*Height);

	return 0;
}


int  GetNext(BYTE *lpNow, BYTE *lpLast, BYTE **lppNext, int IMGW, int IMGH)
{
/////////////////////////////////////////////////////////////////////////////
//	lpNow : [in] 当前点的地址
//	lpLast : [in] 前驱点的地址
//	lppNext : [out] 下一个点的地址的指针
/////////////////////////////////////////////////////////////////////////////
	int  i;
	BYTE   *lpSrc = NULL;
	int  n;
	BYTE   *Temp[8];	// 某点周围8个点的地址
	int	SiteD8[8] = {IMGW-1, IMGW, IMGW+1, 1, -IMGW+1, -IMGW, -IMGW-1, -1};

	*lppNext = NULL;
	
	// 找到当前点周围的是黑点并且不是前驱点的黑点,保存到数组
	n = 0;
	for(i = 0; i < 8; i++)
	{
		lpSrc = lpNow + SiteD8[i];
		if(*lpSrc == 0 && lpSrc != lpLast)
		{
			Temp[n] = lpSrc;
			n++;
		}
	}
	
	if(n == 0)	// 没有找到其他黑点则表示没有后继点
	{
		*lppNext = NULL;
		return 1;
	}
	else if(n == 1) // 找到了一个,则其为后继点
	{
		*lppNext = Temp[0];
		return 0;
	}
	else // 找到多个点则返回错误
	{
		*lppNext = NULL;
		return 1;
	}
	
	return 0;
}

bool   IsFork(BYTE *lpNow, int IMGW, int IMGH)
{
/////////////////////////////////////////////////////////////////////////////
//	lpNow : [in] 当前点的地址
/////////////////////////////////////////////////////////////////////////////
	int i, sum;
	// 某点周围8个点的地址偏移
	int	SiteD8[8] = {IMGW-1, IMGW, IMGW+1, 1, -IMGW+1, -IMGW, -IMGW-1, -1};
	
	// 8个点所有相邻两个点的差的绝对值的和如果为6*255则为叉点
	sum = 0;
	for(i = 0; i < 8; i++)
	{
		sum += abs(*(lpNow + SiteD8[(i+1)%8]) - *(lpNow + SiteD8[i]));
	}
	if(sum == 255*6)
	{
		return true;
	}
	else
	{
		return false;
	}
}

//
//	thinClear: 清除细化图像中短棒和毛刺
//
int  thinClear(BYTE *g_lpOrgFinger, int  len, int IMGW, int IMGH)
{
/////////////////////////////////////////////////////////////////
//	len: [in] 短棒和毛刺的最大长度
/////////////////////////////////////////////////////////////////
	int	x, y;
	int  i, n, num;
	int  temp;
	BYTE   *Line[25];
	BYTE   *lpNow = NULL;
	BYTE   *lpLast = NULL;
	BYTE   *lpNext = NULL;
	BYTE   *tempPtr[8];
	int	SiteD8[8] = {IMGW-1, IMGW, IMGW+1, 1, -IMGW+1, -IMGW, -IMGW-1, -1};

	temp = 0;
	for(y = 0; y < IMGH; y++)
	{
		for(x = 0; x < IMGW; x++)
		{
			lpNow = g_lpOrgFinger + temp + x;
			if(*lpNow != 0)
			{
				continue;
			}
			Line[0] = lpNow;
			// 统计当前点的周围黑点个数
			n = 0;
			for(i = 0; i < 8; i++)
			{
				lpNext = lpNow + SiteD8[i];
				if(*lpNext == 0)
				{
					tempPtr[n] = lpNext;
					n++;
				}
			}
			// 黑点个数为零,表示当前点是孤点,置为白色
			if(n == 0)
			{
				*lpNow = 255;
				continue;
			}
			// 黑点个数为1,表示为端点
			else if(n == 1)
			{
				num = 0;
				lpLast = lpNow;
				lpNow = tempPtr[0];
				// 沿纹线跟踪len个点
				for(i = 0; i < len; i++)
				{
					// 如果遇到叉点则跳出循环
					if(IsFork(lpNow, IMGW, IMGH))
					{
						break;
					}
					num++;
					Line[num] = lpNow;
					if(GetNext(lpNow, lpLast, &lpNext, IMGW, IMGH) == 0)
					{
						lpLast = lpNow;
						lpNow = lpNext;
					}
					else // 如果遇到异常跳出循环
					{
						break;
					}

				}
				
				// 纹线较短,表示为短棒或者是毛刺
				if(num < len)
				{
					for(i = 0; i <= num; i++)
					{
						*Line[i] = 255;
					}
				}

			}
		}
		temp += IMGW;
	}

	return 0;
}

⌨️ 快捷键说明

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