📄 imagemanip.c
字号:
FvsInt_t peak_pos[BLOCK_L]; /* 顶点 */ FvsInt_t peak_cnt; /* 顶点数目 */ FvsFloat_t peak_freq; /* 顶点频率 */ FvsFloat_t Xsig[BLOCK_L]; /* x signature */ FvsFloat_t pmin, pmax; memset(out, 0, size); memset(freq, 0, size); /* 1 - 图像分块 BLOCK_W x BLOCK_W - (16 x 16) */ for (y = BLOCK_L2; y < h-BLOCK_L2; y++) for (x = BLOCK_L2; x < w-BLOCK_L2; x++) { /* 2 - 脊线方向的窗口 l x w (32 x 16) */ dir = orientation[(x+BLOCK_W2) + (y+BLOCK_W2)*w]; cosdir = -sin(dir); sindir = cos(dir); /* 3 - 计算 x-signature X[0], X[1], ... X[l-1] */ for (k = 0; k < BLOCK_L; k++) { Xsig[k] = 0.0; for (d = 0; d < BLOCK_W; d++) { u = (FvsInt_t)(x + (d-BLOCK_W2)*cosdir + (k-BLOCK_L2)*sindir); v = (FvsInt_t)(y + (d-BLOCK_W2)*sindir - (k-BLOCK_L2)*cosdir); /* clipping */ if (u<0) u = 0; else if (u>w-1) u = w-1; if (v<0) v = 0; else if (v>h-1) v = h-1; Xsig[k] += p[u + (v*pitchi)]; } Xsig[k] /= BLOCK_W; } /* 计算 T(i,j) */ /* 寻找 x signature 中的顶点 */ peak_cnt = 0; pmax = pmin = Xsig[0]; for (k = 1; k < BLOCK_L; k++) { if (pmin>Xsig[k]) pmin = Xsig[k]; if (pmax<Xsig[k]) pmax = Xsig[k]; } if ((pmax - pmin)>64.0) { for (k = 1; k < BLOCK_L-1; k++) if ((Xsig[k-1] < Xsig[k]) && (Xsig[k] >= Xsig[k+1])) { peak_pos[peak_cnt++] = k; } } /* 计算均值 */ peak_freq = 0.0; if (peak_cnt>=2) { for (k = 0; k < peak_cnt-1; k++) peak_freq += peak_pos[k+1]-peak_pos[k]; peak_freq /= peak_cnt-1; } /* 4 - 验证频率范围 [1/25-1/3] */ /* 可以扩大到 [1/30-1/2] */ if (peak_freq > 30.0) out[x+y*w] = 0.0; else if (peak_freq < 2.0) out[x+y*w] = 0.0; else out[x+y*w] = 1.0/peak_freq; } /* 5 - 未知点 */ for (y = BLOCK_L2; y < h-BLOCK_L2; y++) for (x = BLOCK_L2; x < w-BLOCK_L2; x++) { if (out[x+y*w]<EPSILON) { if (out[x+(y-1)*w]>EPSILON) { out[x+(y*w)] = out[x+(y-1)*w]; } else { if (out[x-1+(y*w)]>EPSILON) out[x+(y*w)] = out[x-1+(y*w)]; } } } /* 6 - 频率插值 */ for (y = BLOCK_L2; y < h-BLOCK_L2; y++) for (x = BLOCK_L2; x < w-BLOCK_L2; x++) { k = x + y*w; peak_freq = 0.0; for ( v = -LPSIZE; v <= LPSIZE; v++) for ( u = -LPSIZE; u <= LPSIZE; u++) peak_freq += out[(x+u)+(y+v)*w]; freq[k] = peak_freq*LPFACTOR; } free(out); } return nRet;}/****************************************************************************** * 功能:获取指纹图像的有效区域,以进行进一步的处理。 * 如果某个区域不可用用,则掩码置为0,包括如下区域: * 边界,背景点,图像质量很差的区域。 * 有效区域的掩码置为255。 * 参数:image 指纹图像 * direction 脊线方向 * frequency 脊线频率 * mask 输出的掩码 * 返回:错误编号******************************************************************************/FvsError_t FingerprintGetMask(const FvsImage_t image, const FvsFloatField_t direction, const FvsFloatField_t frequency, FvsImage_t mask){ FvsError_t nRet = FvsOK; FvsFloat_t freqmin = 1.0 / 25; FvsFloat_t freqmax = 1.0 / 3; /* 输入图像的宽度高度 */ FvsInt_t w = ImageGetWidth (image); FvsInt_t h = ImageGetHeight(image); FvsByte_t* out; FvsInt_t pitchout; FvsInt_t pos, posout, x, y; FvsFloat_t* freq = FloatFieldGetBuffer(frequency); if (freq==NULL) return FvsMemory; /* 需要做改进:检查 */ nRet = ImageSetSize(mask, w, h); if (nRet==FvsOK) nRet = ImageClear(mask); out = ImageGetBuffer(mask); if (out==NULL) return FvsMemory; if (nRet==FvsOK) { pitchout = ImageGetPitch(mask); for (y = 0; y < h; y++) for (x = 0; x < w; x++) { pos = x + y * w; posout = x + y * pitchout; out[posout] = 0; if (freq[pos] >= freqmin && freq[pos] <= freqmax) { out[posout] = 255; } } /* 补洞 */ for (y = 0; y < 4; y++) (void)ImageDilate(mask); /* 去除边界 */ for (y = 0; y < 12; y++) (void)ImageErode(mask); } return nRet;}/* 细化算法 */#undef P#define P(x,y) ((x)+(y)*pitch)#define REMOVE_P { p[P(x,y)]=0x80; changed = FvsTrue; }/******************************************************************************** 邻域点定义如下:** 9 2 3** 8 1 4** 7 5 6******************************************************************************//* 宏定义 */#define P1 p[P(x ,y )]#define P2 p[P(x ,y-1)]#define P3 p[P(x+1,y-1)]#define P4 p[P(x+1,y )]#define P5 p[P(x+1,y+1)]#define P6 p[P(x ,y+1)]#define P7 p[P(x-1,y+1)]#define P8 p[P(x-1,y )]#define P9 p[P(x-1,y-1)]FvsError_t ImageRemoveSpurs(FvsImage_t image){ FvsInt_t w = ImageGetWidth(image); FvsInt_t h = ImageGetHeight(image); FvsInt_t pitch = ImageGetPitch(image); FvsByte_t* p = ImageGetBuffer(image); FvsInt_t x, y, n, t, c; c = 0; do { n = 0; for (y=1; y<h-1; y++) for (x=1; x<w-1; x++) { if( p[P(x,y)]==0xFF) { t=0; if (P3==0 && P2!=0 && P4==0) t++; if (P5==0 && P4!=0 && P6==0) t++; if (P7==0 && P6!=0 && P8==0) t++; if (P9==0 && P8!=0 && P2==0) t++; if (P3!=0 && P4==0) t++; if (P5!=0 && P6==0) t++; if (P7!=0 && P8==0) t++; if (P9!=0 && P2==0) t++; if (t==1) { p[P(x,y)] = 0x80; n++; } } } for (y=1; y<h-1; y++) for (x=1; x<w-1; x++) { if( p[P(x,y)]==0x80) p[P(x,y)] = 0; } } while (n>0 && ++c < 5); return FvsOK;}/* a) 验证其有2-6个邻点 */#define STEP_A n = 0; /* 邻点个数 */ \ if (P2!=0) n++; if (P3!=0) n++; if (P4!=0) n++; if (P5!=0) n++; \ if (P6!=0) n++; if (P7!=0) n++; if (P8!=0) n++; if (P9!=0) n++; \ if (n>=2 && n<=6)/* b) 统计由0变1的个数 */#define STEP_B t = 0; /* 变化的数目 */ \ if (P9==0 && P2!=0) t++; if (P2==0 && P3!=0) t++; \ if (P3==0 && P4!=0) t++; if (P4==0 && P5!=0) t++; \ if (P5==0 && P6!=0) t++; if (P6==0 && P7!=0) t++; \ if (P7==0 && P8!=0) t++; if (P8==0 && P9!=0) t++; \ if (t==1)/****************************************************************************** * 功能:细化指纹图像 * 图像必须是二值化过的(只包含0x00或oxFF) * 该算法基于领域的判断,决定某个象素该移去还是保留 * 参数:image 指纹图像 * 返回:错误编号******************************************************************************/ FvsError_t ImageThinConnectivity(FvsImage_t image){ FvsInt_t w = ImageGetWidth(image); FvsInt_t h = ImageGetHeight(image); FvsInt_t pitch = ImageGetPitch(image); FvsByte_t* p = ImageGetBuffer(image); FvsInt_t x, y, n, t; FvsBool_t changed = FvsTrue; if (p==NULL) return FvsMemory; if (ImageGetFlag(image)!=FvsImageBinarized) return FvsBadParameter; while (changed==FvsTrue) { changed = FvsFalse; for (y=1; y<h-1; y++) for (x=1; x<w-1; x++) { if (p[P(x,y)]==0xFF) { STEP_A { STEP_B { /* c) 2*4*6=0 (2,4 ,or 6 为0) d) 4*6*8=0 */ if (P2*P4*P6==0 && P4*P6*P8==0) REMOVE_P; } } } } for (y=1; y<h-1; y++) for (x=1; x<w-1; x++) if (p[P(x,y)]==0x80) p[P(x,y)] = 0; for (y=1; y<h-1; y++) for (x=1; x<w-1; x++) { if (p[P(x,y)]==0xFF) { STEP_A { STEP_B { /* c) 2*6*8=0 d) 2*4*8=0 */ if (P2*P6*P8==0 && P2*P4*P8==0) REMOVE_P; } } } } for (y=1; y<h-1; y++) for (x=1; x<w-1; x++) if (p[P(x,y)]==0x80) p[P(x,y)] = 0; } ImageRemoveSpurs(image); return ImageSetFlag(image, FvsImageThinned);} /* 重新定义 REMOVE_P */#undef REMOVE_P#define REMOVE_P { p[P(x,y)]=0x00; changed = FvsTrue; }/****************************************************************************** * 功能:细化指纹图像,使用“Hit and Miss”结构元素。 * 图像必须是二值化过的(只包含0x00或oxFF) * 该算法的缺点是产生很多伪造的线条(伪特征), * 必须由另外的算法来消除,后处理非常必要。 * 参数:image 指纹图像 * 返回:错误编号******************************************************************************/FvsError_t ImageThinHitMiss(FvsImage_t image){ FvsInt_t w = ImageGetWidth(image); FvsInt_t h = ImageGetHeight(image); FvsInt_t pitch = ImageGetPitch(image); FvsByte_t* p = ImageGetBuffer(image); /* // // 0 0 0 0 0 // 1 1 1 0 // 1 1 1 1 // */ FvsInt_t x,y, t; FvsBool_t changed = FvsTrue; if (p==NULL) return FvsMemory; if (ImageGetFlag(image)!=FvsImageBinarized) return FvsBadParameter; while (changed==FvsTrue) { changed = FvsFalse; for (y=1; y<h-1; y++) for (x=1; x<w-1; x++) { if (p[P(x,y)]==0xFF) { /* // 0 0 0 0 1 1 1 1 1 0 // 1 0 1 1 1 1 1 0 // 1 1 1 0 1 0 0 0 1 0 */ if (p[P(x-1,y-1)]==0 && p[P(x,y-1)]==0 && p[P(x+1,y-1)]==0 && p[P(x-1,y+1)]!=0 && p[P(x,y+1)]!=0 && p[P(x+1,y+1)]!=0) REMOVE_P; if (p[P(x-1,y-1)]!=0 && p[P(x,y-1)]!=0 && p[P(x+1,y-1)]!=0 && p[P(x-1,y+1)]==0 && p[P(x,y+1)]==0 && p[P(x+1,y+1)]==0) REMOVE_P; if (p[P(x-1,y-1)]==0 && p[P(x-1,y)]==0 && p[P(x-1,y+1)]==0 && p[P(x+1,y-1)]!=0 && p[P(x+1,y)]!=0 && p[P(x+1,y+1)]!=0) REMOVE_P; if (p[P(x-1,y-1)]!=0 && p[P(x-1,y)]!=0 && p[P(x-1,y+1)]!=0 && p[P(x+1,y-1)]==0 && p[P(x+1,y)]==0 && p[P(x+1,y+1)]==0) REMOVE_P; /* // 0 0 0 0 1 1 // 1 1 0 0 1 1 0 1 1 1 1 0 // 1 1 0 0 0 0 */ if (p[P(x,y-1)]==0 && p[P(x+1,y-1)]==0 && p[P(x+1,y)]==0 && p[P(x-1,y)]!=0 && p[P(x,y+1)]!=0) REMOVE_P; if (p[P(x-1,y-1)]==0 && p[P(x,y-1)]==0 && p[P(x-1,y)]==0 && p[P(x+1,y)]!=0 && p[P(x,y+1)]!=0) REMOVE_P; if (p[P(x-1,y+1)]==0 && p[P(x-1,y)]==0 && p[P(x,y+1)]==0 && p[P(x+1,y)]!=0 && p[P(x,y-1)]!=0) REMOVE_P; if (p[P(x+1,y+1)]==0 && p[P(x+1,y)]==0 && p[P(x,y+1)]==0 && p[P(x-1,y)]!=0 && p[P(x,y-1)]!=0) REMOVE_P; } } } ImageRemoveSpurs(image); return ImageSetFlag(image, FvsImageThinned);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -