static FvsError_t OverlayDirection(FvsImage_t image, const FvsFloatField_t field) { FvsError_t nRet = FvsOK; FvsInt_t w = ImageGetWidth (image); FvsInt_t h = ImageGetHeight(image); FvsInt_t pitch, dirp; FvsFloat_t theta, c, s; FvsByte_t* p; FvsFloat_t* orientation; FvsInt_t x, y, size, i, j, l; size = 8; (void)ImageLuminosity(image, 168); pitch = ImageGetPitch (image); p = ImageGetBuffer(image); orientation = FloatFieldGetBuffer(field); dirp = FloatFieldGetPitch(field); if (p == NULL || orientation == NULL) return FvsMemory; for (y = size; y < h - size; y += size - 2) for (x = size; x < w - size; x += size - 2) { theta = orientation[x + y * dirp]; c = cos(theta); s = sin(theta); for (l = 0; l < size; l++) { i = (FvsInt_t)(x + size / 2 - l * s); j = (FvsInt_t)(y + size / 2 + l * c); p[i + j * pitch] = 0; } } return nRet; }
/* 从RGB888图像数据构造image对象 */ static FvsError_t rgb24_to_image(FvsByte_t *rgb24_buf, FvsImage_t image) { FvsByte_t pal[256]; FvsByte_t* pDest = NULL; FvsInt_t nMax; FvsByte_t r,g,b; FvsInt_t i; /* default palette */ for (i = 0; i < 256; i++) pal[i] = (FvsByte_t)i; pDest = ImageGetBuffer(image); if (pDest==NULL) return FvsMemory; nMax = ImageGetWidth(image) * ImageGetHeight(image) * 3; for (i = 0; i < nMax; i += 3) { r = *rgb24_buf++; g = *rgb24_buf++; b = *rgb24_buf++; *pDest++ = pal[((r+(g<<1)+b)>>2)&0xFF]; } return FvsOK; }
void ProThread::run() { QPixmap tempPic; QString tname; FvsImage_t mask; FvsImage_t image; FvsImage_t directionimage; FvsMinutiaSet_t minutia = minutiaSet; FvsFloatField_t direction; FvsFloatField_t frequency; FvsByte_t bmfh[14]; BITMAPINFOHEADER bmih; RGBQUAD rgbq[256]; char *orifilename = bmpfilename.toLatin1().data(); char *fname; mask = ImageCreate(); image = ImageCreate(); directionimage = ImageCreate(); direction = FloatFieldCreate(); frequency = FloatFieldCreate(); if(FvsOK != FvsImageImport(image, orifilename, bmfh, &bmih, rgbq)) { QMessageBox::information(NULL, "Error", "BMP file error!"); return; } tempPic.load(orifilename); originLabel->setPixmap(tempPic); FvsInt_t w = ImageGetWidth (image); FvsInt_t h = ImageGetHeight(image); ImageSetSize(directionimage, w, h); ImageSoftenMean(image, 3); ImageNormalize(image, 100, 10000); FingerprintGetDirection(image, direction, 7, 8); FingerprintGetFrequency1(image, direction, frequency); FingerprintGetMask(image, direction, frequency, mask); ImageEnhanceGabor(image, direction, frequency, mask, radius); OverlayDirection(directionimage, direction); //saving file.... if(genPic) { tname = bmpfilename + "_dir.bmp"; fname = tname.toLatin1().data(); FvsImageExport(directionimage, fname, bmfh, &bmih, rgbq); tempPic.load(fname); directionLabel->setPixmap(tempPic); tname = bmpfilename + "_mask.bmp"; fname = tname.toLatin1().data(); FvsImageExport(mask, fname, bmfh, &bmih, rgbq); tempPic.load(fname); maskLabel->setPixmap(tempPic); tname = bmpfilename + "_enh.bmp"; fname = tname.toLatin1().data(); FvsImageExport(image, fname, bmfh, &bmih, rgbq); tempPic.load(fname); enhanceLabel->setPixmap(tempPic); } ImageBinarize(image, (FvsByte_t)0x80); if(genPic) { tname = bmpfilename + "_bin.bmp"; fname = tname.toLatin1().data(); FvsImageExport(image, fname, bmfh, &bmih, rgbq); tempPic.load(fname); binarizeLabel->setPixmap(tempPic); } ImageThinHitMiss(image); if(genPic) { tname = bmpfilename + "_thin.bmp"; fname = tname.toLatin1().data(); FvsImageExport(image, fname, bmfh, &bmih, rgbq); tempPic.load(fname); thinningLabel->setPixmap(tempPic); } MinutiaSetExtract(minutia, image, direction, mask); if(genPic) { ImageClear(image); MinutiaSetDraw(minutia, image); tname = bmpfilename + "_minu.bmp"; fname = tname.toLatin1().data(); FvsImageExport(image, fname, bmfh, &bmih, rgbq); tempPic.load(fname); minutiaLabel->setPixmap(tempPic); } //QMessageBox::information(NULL,"Done","Complete!"); }
/** * 函数描述: * 将指纹对象image保存到指纹数据库中, * 可用的ID而且没有重复指纹保存成功后返回该指纹的ID号 * 参数: * rgb24_buf : 24bit RGB图像缓冲区 * width : 图像宽度 * height : 图像高度 * id : 该指纹保存的ID * 返回值: * 验证通过则返回FvsOK,否则放回FvsError_t错误码。 **/ FvsError_t fp_store(FvsByte_t *rgb24_buf, FvsInt_t width, FvsInt_t height, FvsInt_t *id) { FvsError_t err; FvsInt_t goodness; FvsInt_t i; FvsImage_t image, mask; FvsMinutiaSet_t exist_minutias, new_minutias; DP("Store width : %d, height : %d.\n", width, height); image = ImageCreate(); if (FvsOK != (err = ImageSetSize(image, width, height))) { return err; } if (FvsOK != (err = rgb24_to_image(rgb24_buf, image))) { ImageDestroy(image); return err; } /* process source image */ mask = ImageCreate(); err = ImageSetSize(mask, ImageGetWidth(image), ImageGetHeight(image)); if (FvsOK != err) { return err; } new_minutias = MinutiaSetCreate(MAXMINUTIA); exist_minutias = MinutiaSetCreate(MAXMINUTIA); if (FvsOK != (err = img_to_minutias(image,mask,new_minutias))) { ImageDestroy(image); ImageDestroy(mask); MinutiaSetDestroy(new_minutias); MinutiaSetDestroy(exist_minutias); return err; } /* 暂时跳过指纹重复检测 */ #if 0 /* 保存指纹之前检查是否有指纹重复 */ for (i = 0; i < MAX_FINGER_NO ; i++) { if (fdb_id_is_used(i) != ID_USED){ continue; } if (FvsOK != (err = fdb_load_minutias(i, exist_minutias))) { return err; } err = MatchingCompareMinutiaSets(new_minutias, exist_minutias, &goodness); if (FvsOK != err) { return err; } if (FP_THRESHOLD >= goodness) { break; } } if (MAX_FINGER_NO == i) { return FvsNoID; } #endif if (FvsOK != (err = fdb_alloc_id(id)) ){ ImageDestroy(image); ImageDestroy(mask); MinutiaSetDestroy(new_minutias); MinutiaSetDestroy(exist_minutias); return err; } fdb_id_set(*id); err = fdb_store_minutias(*id, new_minutias); ImageDestroy(image); ImageDestroy(mask); MinutiaSetDestroy(new_minutias); MinutiaSetDestroy(exist_minutias); #if 0 /* 存储之后立即读出来验证 */ new_minutias = MinutiaSetCreate(MAXMINUTIA); err = fdb_load_minutias(*id, new_minutias); if (err == FvsOK) { DP("\tLoad after store minutias ok.\n"); } else { DP("\tLoad after store minutias fail. return %d.\n", err); } MinutiaSetDestroy(new_minutias); #endif return err; }
/** * 函数描述: * 将指纹对象image进行验证, * 通过则返回匹配指纹的ID号和指纹匹配度 * 参数: * rgb24_buf : 24bit RGB图像缓冲区 * width : 图像宽度 * height : 图像高度 * id : 与image匹配指纹的ID * goodness : 指纹匹配值 * 返回值: * 验证通过则返回FvsOK,否则放回FvsError_t错误码。 **/ FvsError_t fp_auth(FvsByte_t *rgb24_buf, FvsInt_t width, FvsInt_t height, FvsInt_t *id, FvsInt_t *goodness) { FvsError_t err; FvsInt_t score; /* 最佳匹配使用变量 */ FvsInt_t max_score, max_id; FvsInt_t i; FvsImage_t image, mask; FvsMinutiaSet_t exist_minutias, new_minutias; image = ImageCreate(); if (FvsOK != (err = ImageSetSize(image, width, height))) { return err; } if (FvsOK != (err = rgb24_to_image(rgb24_buf, image))) { return err; } new_minutias = MinutiaSetCreate(MAXMINUTIA); exist_minutias = MinutiaSetCreate(MAXMINUTIA); /* process source image */ mask = ImageCreate(); err = ImageSetSize(mask, ImageGetWidth(image), ImageGetHeight(image)); if (FvsOK != err) { return err; } if (FvsOK != (err = img_to_minutias(image,mask,new_minutias))) { return err; } /* 在算法没有对指纹进行分类之前,先使用遍历方法查找指纹特征向量 */ max_score = 0; max_id = -1; for (i = 0; i < MAX_FINGER_NO; i++) { if (fdb_id_is_used(i)) { continue; } DP("---> Load index : %d minutia set...\n", i); if (FvsOK != (err = fdb_load_minutias(i, exist_minutias))) { goto exit_auth; } DP("----> Matching index : %d ...\n", i); err = MatchingCompareMinutiaSets(new_minutias, exist_minutias, &score); if (FvsOK != err) { return err; } DP("----> Match to index : %d score is : %d.\n", i, score); #ifdef FVS_BEST_MATCH /* 最佳匹配 */ if (score >= FP_THRESHOLD) { if (score > max_score) { max_score = score; max_id = i; } } #else /* 首次匹配 */ if (score >= FP_THRESHOLD) { *id = i; *goodness = score; goto exit_auth; } #endif } #ifdef FVS_BEST_MATCH *id = max_id; *goodness = max_score; #endif exit_auth: ImageDestroy(image); ImageDestroy(mask); MinutiaSetDestroy(new_minutias); MinutiaSetDestroy(exist_minutias); return err; }