import cv2
import numpy as np
import random
FG_SHAPE_NONE = 0
FG_SHAPE_THUMB = 1
FG_SHAPE_INDEX = 2
FG_SHAPE_MIDDLE = 3
FG_SHAPE_RING = 4
FG_SHAPE_LITTLE = 5
FG_CLASS_NONE = 0
FG_CLASS_ARCH = 1
FG_CLASS_TENTED_ARCH = 2
FG_CLASS_LEFT_LOOP = 3
FG_CLASS_RIGHT_LOOP = 4
FG_CLASS_WHORL = 5
FG_CLASS_TWIN_LOOP = 6
FG_MODE_RUN = 0
FG_MODE_DEBUG = 1
FG_CACHE_DEG = 36
FG_CACHE_FREQ = 20
FG_GABOR_FILTER_SIZE = 10
class FinGe():
def __init__(self):
self.minF = 1.0 / 15
self.maxF = 1.0 / 5
self.nCore = 0
self.nDelta = 0
self.mode = 0
def set_mode(self,mode):
self.mode = mode
def set_shape(self,left,right,top,bottom,middle):
# 这一步产生了轮廓图和密度图
self.sL = left
self.sR = right
self.sT = top
self.sB = bottom
self.sM = middle
self.size = (self.sT + self.sM + self.sB,self.sL + self.sR)
self.size_cv = (self.sL + self.sR,self.sT + self.sM + self.sB)
self.generate_shape()
def generate_shape(self):
self.shape = np.zeros(self.size, dtype=np.float64) # 轮廓图
cv2.ellipse(self.shape, (self.sL, self.sT), (self.sL, self.sT), 0, 180, 270, 1, -1)
cv2.ellipse(self.shape, (self.sL - 1, self.sT), (self.sR, self.sT), 0, 270, 360, 1, -1)
cv2.ellipse(self.shape, (self.sL, self.sT + self.sM - 1), (self.sL, self.sB), 0, 90, 180, 1, -1)
cv2.ellipse(self.shape, (self.sL - 1, self.sT + self.sM - 1), (self.sR, self.sB), 0, 0, 90, 1, -1)
cv2.rectangle(self.shape, (0, self.sT), (self.sL + self.sR, self.sT + self.sM), 1, -1)
if self.mode == FG_MODE_DEBUG: # FG_MODE_DEBUG
self.show_shape()
print("Step 1: Generate shape")
# input("Press any key to go to Step 2 ...")
self.generate_density()
def show_shape(self):
cv2.imshow("Finger shape", self.shape)
cv2.waitKey(0)
def generate_density(self):
resolution = [5, 6, 7]
padding = 10
random.seed()
self.density = np.zeros(self.size, dtype=np.float64)
self.density_steps = np.zeros((self.size[0] + padding * 2,self.size[1] * 3 + padding * 4), dtype=np.float64)
print("self.density_steps:",self.density_steps.shape)
print("Step 2: Density map (Frequency map)")
for i in range(3):
# 用zoom产生噪声
zoom_img = np.random.uniform(self.minF, self.maxF, (resolution[i], resolution[i])).astype(np.float64)
zoom_img = cv2.resize(zoom_img, self.size_cv, interpolation=cv2.INTER_CUBIC)
self.density += zoom_img / 3.0
self.density_steps[
padding:padding + self.size[0], i * self.size[1] + (i + 1) * padding:(i+1) * self.size[1] + (i + 1) * padding
] = zoom_img.copy()
if self.mode == FG_MODE_DEBUG: # FG_MODE_DEBUG
cv2.imshow("Density", self.density_steps)
print("Density layer", i + 1)
cv2.waitKey(0)
if self.mode == FG_MODE_DEBUG: # FG_MODE_DEBUG
self.show_density()
def show_density(self):
cv2.imshow("Density", self.density)
cv2.waitKey(0)
def set_points(self, nCore, cores, nDelta, deltas):
self.nCore = nCore
self.nDelta = nDelta
self.cores = cores.copy()
self.deltas = deltas.copy()
self.generate_orientation()
# 生成方向图
def generate_orientation(self):
self.orientation = np.zeros(self.size, dtype=np.float64)
for i in range(self.size[1]):
for j in range(self.size[0]):
theta = 0
for k in range(self.nCore):
z = (self.cores[k][0]-i, self.cores[k][1]-j)
theta += np.arctan2(z[1], z[0])
for k in range(self.nDelta):
z = (self.deltas[k][0] - i, self.deltas[k][1] - j)
theta -= np.arctan2(z[1], z[0])
theta *= 0.5
self.orientation[j, i] = theta
self.orientation = cv2.blur(self.orientation, (5, 5))
self.orientation_display = np.zeros(self.size, dtype=np.float64)
for i in range(5, self.size[1], 10):
for j in range(5, self.size[0], 10):
center = (i, j)
theta = self.orientation[j, i]
p1 = (int(i - 4.5 * np.cos(theta)), int(j - 4.5 * np.sin(theta)))
p2 = (int(i + 4.5 * np.cos(theta)), int(j + 4.5 * np.sin(theta)))
cv2.line(self.orientation_display, p1, p2, 1)
self.orientation_display = self.orientation_display * self.shape
self.orientation_display = cv2.merge([self.orientation_display, self.orientation_display, self.orientation_display])
for k in range(self.nCore):
cv2.circle(self.orientation_display, (int(self.cores[k][0]),int(self.cores[k][1])), 5, (0, 0, 255), 1)
for k in range(self.nDelta):
cv2.circle(self.orientation_display, (int(self.deltas[k][0]),int(self.deltas[k][1])), 5, (0, 255, 0), 1)
if self.mode == FG_MODE_DEBUG: # FG_MODE_DEBUG
self.show_orientation()
# input("Press any key to go to step 4")
self.generate_ridge()
def show_orientation(self):
cv2.imshow("Orientation", self.orientation_display)
cv2.waitKey(0)
def generate_ridge(self):
gb_cache = np.empty((FG_CACHE_DEG * FG_CACHE_FREQ,), dtype=object)
for i in range(FG_CACHE_DEG):
for j in range(FG_CACHE_FREQ):
theta = self.index_to_val(i, 0, 2 * np.pi, FG_CACHE_DEG) + np.pi / 2.0
F = self.index_to_val(j, self.minF, self.maxF, FG_CACHE_FREQ)
sigma = np.sqrt(-9.0 / (8.0 * F * F * np.log(0.001)))
gb_cache[self.FG_CACHE_INDEX(i, j)] = cv2.getGaborKernel(
(2 * FG_GABOR_FILTER_SIZE, 2 * FG_GABOR_FILTER_SIZE), sigma, theta, 1.0 / F, 1, 0)
finger = np.zeros(self.size, dtype=np.float64)
cv2.randu(finger,0,1)
finger = np.where(finger < 0.001, 1, 0).astype(np.float64)
if self.mode == FG_MODE_DEBUG: # FG_MODE_DEBUG
cv2.imshow("Master Fingerprint", finger)
cv2.waitKey(0)
b = FG_GABOR_FILTER_SIZE
while True:
layer = np.zeros(finger.shape, dtype=np.float64)
for i in range(self.size[0]):
for j in range(self.size[1]):
theta = self.orientation[i, j]
theta = theta + 2 * np.pi if theta < 0 else theta
F = self.density[i, j]
index = self.FG_CACHE_INDEX(self.val_to_index(theta, 0, 2 * np.pi, FG_CACHE_DEG),
self.val_to_index(F, self.minF, self.maxF, FG_CACHE_FREQ))
fil_rec = (max(b - i, 0), max(b - j, 0), min(min(2 * b, finger.shape[0] + b - i), b + i),
min(min(2 * b, finger.shape[1] + b - j), b + j))
# print("fil_rec",fil_rec)
fng_rec = (max(i - b, 0), max(j - b, 0), fil_rec[2], fil_rec[3])
# print("fng_rec",fng_rec)
t = np.sum(gb_cache[index][fil_rec[0]:fil_rec[0]+fil_rec[2],fil_rec[1]:fil_rec[1]+fil_rec[3]]*
finger[fng_rec[0]:fng_rec[0]+fng_rec[2],fng_rec[1]:fng_rec[1]+fng_rec[3]])
if t < 0:
t = 0
if t > 0:
t = 1
layer[i,j] = t
if np.abs(np.count_nonzero(finger) - np.count_nonzero(layer)) / (self.size[0] * self.size[1]) > 0.001:
finger = layer
if self.mode == FG_MODE_DEBUG:
cv2.imshow("Master Fingerprint", finger)
cv2.waitKey(0)
else:
break
self.master_fng = finger * self.shape
def sh