从 Python 3 中的指纹特征提取器中提取细节终止点和分叉值

问题描述 投票:0回答:1

我最近尝试了 Utkarsh-Deshmukh 的新指纹特征提取器库(https://github.com/Utkarsh-Deshmukh/Fingerprint-Feature-Extraction),它的工作原理就像奇迹一样。问题是我需要从库中提取终止点和分叉值。我使用 github 链接中包含的代码来获取特征分叉和终止:

import fingerprint_feature_extractor

img = cv2.imread('image_path', 0)
FeaturesTerminations, FeaturesBifurcations = fingerprint_feature_extractor.extract_minutiae_features(img, showResult=True, spuriousMinutiaeThresh=10)

我尝试使用

print()
命令查看 FeaturesBifurcations 内部的内容,但我无法理解输出的含义。

print() command on FeaturesBifurcations

我需要的是如下所示的值,其中第一列和第二列表示 xy 坐标,第三列表示方向,第四列表示类型:

minutiaes bifurcations (marked with 1 in the last column) and terminations (marked with 0 in the last column) values extracted from fingerprint

我尝试阅读库中的类,我想我可以获得这些值(库中明确说明了特征位置、方向和类型),但我不知道如何提取这些值。这是指纹特征提取器库中的内容:

import cv2
import numpy as np
import skimage.morphology
from skimage.morphology import convex_hull_image, erosion
from skimage.morphology import square
import math

class MinutiaeFeature(object):
  def __init__(self, locX, locY, Orientation, Type):
    self.locX = locX;
    self.locY = locY;
    self.Orientation = Orientation;
    self.Type = Type;

class FingerprintFeatureExtractor(object):
  def __init__(self):
    self._mask = []
    self._skel = []
    self.minutiaeTerm = []
    self.minutiaeBif = []

  def __skeletonize(self, img):
    img = np.uint8(img > 128)
    self._skel = skimage.morphology.skeletonize(img)
    self._skel = np.uint8(self._skel) * 255
    self._mask = img * 255

  def __computeAngle(self, block, minutiaeType):
    angle = []
    (blkRows, blkCols) = np.shape(block);
    CenterX, CenterY = (blkRows - 1) / 2, (blkCols - 1) / 2
    if (minutiaeType.lower() == 'termination'):
        sumVal = 0;
        for i in range(blkRows):
            for j in range(blkCols):
                if ((i == 0 or i == blkRows - 1 or j == 0 or j == blkCols - 1) and block[i][j] != 0):
                    angle.append(-math.degrees(math.atan2(i - CenterY, j - CenterX)))
                    sumVal += 1
                    if (sumVal > 1):
                        angle.append(float('nan'))
        return (angle)

    elif (minutiaeType.lower() == 'bifurcation'):
        (blkRows, blkCols) = np.shape(block);
        CenterX, CenterY = (blkRows - 1) / 2, (blkCols - 1) / 2
        angle = []
        sumVal = 0;
        for i in range(blkRows):
            for j in range(blkCols):
                if ((i == 0 or i == blkRows - 1 or j == 0 or j == blkCols - 1) and block[i][j] != 0):
                    angle.append(-math.degrees(math.atan2(i - CenterY, j - CenterX)))
                    sumVal += 1
        if (sumVal != 3):
            angle.append(float('nan'))
        return (angle)

  def __getTerminationBifurcation(self):
    self._skel = self._skel == 255;
    (rows, cols) = self._skel.shape;
    self.minutiaeTerm = np.zeros(self._skel.shape);
    self.minutiaeBif = np.zeros(self._skel.shape);

    for i in range(1, rows - 1):
        for j in range(1, cols - 1):
            if (self._skel[i][j] == 1):
                block = self._skel[i - 1:i + 2, j - 1:j + 2];
                block_val = np.sum(block);
                if (block_val == 2):
                    self.minutiaeTerm[i, j] = 1;
                elif (block_val == 4):
                    self.minutiaeBif[i, j] = 1;

    self._mask = convex_hull_image(self._mask > 0)
    self._mask = erosion(self._mask, square(5))  # Structuing element for mask erosion = square(5)
    self.minutiaeTerm = np.uint8(self._mask) * self.minutiaeTerm

  def __removeSpuriousMinutiae(self, minutiaeList, img, thresh):
    img = img * 0;
    SpuriousMin = [];
    numPoints = len(minutiaeList);
    D = np.zeros((numPoints, numPoints))
    for i in range(1,numPoints):
        for j in range(0, i):
            (X1,Y1) = minutiaeList[i]['centroid']
            (X2,Y2) = minutiaeList[j]['centroid']

            dist = np.sqrt((X2-X1)**2 + (Y2-Y1)**2);
            D[i][j] = dist
            if(dist < thresh):
                SpuriousMin.append(i)
                SpuriousMin.append(j)

    SpuriousMin = np.unique(SpuriousMin)
    for i in range(0,numPoints):
        if(not i in SpuriousMin):
            (X,Y) = np.int16(minutiaeList[i]['centroid']);
            img[X,Y] = 1;

    img = np.uint8(img);
    return(img)

  def __cleanMinutiae(self, img):
    self.minutiaeTerm = skimage.measure.label(self.minutiaeTerm, connectivity=2);
    RP = skimage.measure.regionprops(self.minutiaeTerm)
    self.minutiaeTerm = self.__removeSpuriousMinutiae(RP, np.uint8(img), 10);

  def __performFeatureExtraction(self):
    FeaturesTerm = []
    self.minutiaeTerm = skimage.measure.label(self.minutiaeTerm, connectivity=2);
    RP = skimage.measure.regionprops(np.uint8(self.minutiaeTerm))

    WindowSize = 2  # --> For Termination, the block size must can be 3x3, or 5x5. Hence the window selected is 1 or 2
    FeaturesTerm = []
    for num, i in enumerate(RP):
        print(num)
        (row, col) = np.int16(np.round(i['Centroid']))
        block = self._skel[row - WindowSize:row + WindowSize + 1, col - WindowSize:col + WindowSize + 1]
        angle = self.__computeAngle(block, 'Termination')
        if(len(angle) == 1):
            FeaturesTerm.append(MinutiaeFeature(row, col, angle, 'Termination'))

    FeaturesBif = []
    self.minutiaeBif = skimage.measure.label(self.minutiaeBif, connectivity=2);
    RP = skimage.measure.regionprops(np.uint8(self.minutiaeBif))
    WindowSize = 1  # --> For Bifurcation, the block size must be 3x3. Hence the window selected is 1
    for i in RP:
        (row, col) = np.int16(np.round(i['Centroid']))
        block = self._skel[row - WindowSize:row + WindowSize + 1, col - WindowSize:col + WindowSize + 1]
        angle = self.__computeAngle(block, 'Bifurcation')
        if(len(angle) == 3):
            FeaturesBif.append(MinutiaeFeature(row, col, angle, 'Bifurcation'))
    return (FeaturesTerm, FeaturesBif)

  def extractMinutiaeFeatures(self, img):
    self.__skeletonize(img)

    self.__getTerminationBifurcation()

    self.__cleanMinutiae(img)

    FeaturesTerm, FeaturesBif = self.__performFeatureExtraction()
    return(FeaturesTerm, FeaturesBif)

  def showResults(self):
    BifLabel = skimage.measure.label(self.minutiaeBif, connectivity=2);
    TermLabel = skimage.measure.label(self.minutiaeTerm, connectivity=2);

    minutiaeBif = TermLabel * 0;
    minutiaeTerm = BifLabel * 0;

    (rows, cols) = self._skel.shape
    DispImg = np.zeros((rows, cols, 3), np.uint8)
    DispImg[:, :, 0] = 255*self._skel;
    DispImg[:, :, 1] = 255*self._skel;
    DispImg[:, :, 2] = 255*self._skel;

    RP = skimage.measure.regionprops(BifLabel)
    for idx, i in enumerate(RP):
        (row, col) = np.int16(np.round(i['Centroid']))
        minutiaeBif[row, col] = 1;
        (rr, cc) = skimage.draw.circle_perimeter(row, col, 3);
        skimage.draw.set_color(DispImg, (rr, cc), (255, 0, 0));

    RP = skimage.measure.regionprops(TermLabel)
    for idx, i in enumerate(RP):
        (row, col) = np.int16(np.round(i['Centroid']))
        minutiaeTerm[row, col] = 1;
        (rr, cc) = skimage.draw.circle_perimeter(row, col, 3);
        skimage.draw.set_color(DispImg, (rr, cc), (0, 0, 255));

    cv2.imshow('a', DispImg);
    cv2.waitKey(0)

def extract_minutiae_features(img, showResult=False):
  feature_extractor = FingerprintFeatureExtractor()
  FeaturesTerm, FeaturesBif = feature_extractor.extractMinutiaeFeatures(img)

  if(showResult):
      feature_extractor.showResults()

  return(FeaturesTerm, FeaturesBif)

有没有办法从这个库中提取位置、方向和类型浮点(和/或整数)值?或者有没有办法或库将这些列表绘制为笛卡尔或极坐标?

python python-3.x feature-extraction fingerprint
1个回答
0
投票

基本上这就是提取坐标的方式

只需循环 FeaturesTerminations 和 FeaturesBifurcations ,然后提取点

   for idx, curr_minutiae in enumerate(FeaturesTerminations):
    row, col, Orientation, Type = curr_minutiae.locX, curr_minutiae.locY, 
    curr_minutiae.Orientation, curr_minutiae.Type
© www.soinside.com 2019 - 2024. All rights reserved.