📄 preprocess.cpp
字号:
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 + -