|
|
|
@ -135,17 +135,17 @@ class fingerprint_app:
|
|
|
|
|
|
|
|
|
|
# Get mode and model parameters
|
|
|
|
|
if self.mode == 'p':
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.height_line = float(self.args.stl[1]) if len(
|
|
|
|
|
self.args.stl) > 1 else def_val.get("hl")
|
|
|
|
|
self.height_base = float(self.args.stl[2]) if len(
|
|
|
|
|
self.args.stl) > 2 else def_val.get("hb")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if len(self.args.stl) < 3:
|
|
|
|
|
log.print_message(
|
|
|
|
|
"Warning: Too few arguments, using some default values")
|
|
|
|
|
log.print_message("Base height:", self.height_base,
|
|
|
|
|
"mm, lines depth/height:", self.height_line, "mm")
|
|
|
|
|
"mm, lines depth/height:", self.height_line, "mm")
|
|
|
|
|
|
|
|
|
|
elif self.mode == 'c':
|
|
|
|
|
|
|
|
|
@ -157,13 +157,13 @@ class fingerprint_app:
|
|
|
|
|
self.args.stl) > 3 else def_val.get("crx")
|
|
|
|
|
self.curv_rate_y = float(self.args.stl[4]) if len(
|
|
|
|
|
self.args.stl) > 4 else def_val.get("cry")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if len(self.args.stl) < 5:
|
|
|
|
|
log.print_message(
|
|
|
|
|
"Warning: Too few arguments, using some default values")
|
|
|
|
|
log.print_message("Line height:", self.height_line, "mm, base height:", self.height_base,
|
|
|
|
|
"mm, x axis curvature:", self.curv_rate_x, ", y axis curvature:", self.curv_rate_y)
|
|
|
|
|
|
|
|
|
|
"mm, x axis curvature:", self.curv_rate_x, ", y axis curvature:", self.curv_rate_y)
|
|
|
|
|
|
|
|
|
|
elif self.mode == 'm':
|
|
|
|
|
|
|
|
|
|
self.height_line = float(self.args.stl[1]) if len(
|
|
|
|
@ -178,12 +178,12 @@ class fingerprint_app:
|
|
|
|
|
self.args.stl) > 5 else def_val.get("fz")
|
|
|
|
|
self.finger_name = str(self.args.stl[6]) if len(
|
|
|
|
|
self.args.stl) > 6 else def_val.get("f")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if len(self.args.stl) < 6:
|
|
|
|
|
log.print_message(
|
|
|
|
|
"Warning: Too few arguments, using some default values")
|
|
|
|
|
log.print_message("Line height:", self.height_line, "mm, iterations:", self.iter,
|
|
|
|
|
", finger position:", self.finger_x, self.finger_y, self.finger_z, "mm, finger model:", self.finger_name)
|
|
|
|
|
", finger position:", self.finger_x, self.finger_y, self.finger_z, "mm, finger model:", self.finger_name)
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
log.error_exit("Unrecognized generation mode")
|
|
|
|
@ -319,7 +319,8 @@ class fingerprint_app:
|
|
|
|
|
if self.height_line <= 0:
|
|
|
|
|
log.error_exit("Line height must be positive")
|
|
|
|
|
if self.iter < 0:
|
|
|
|
|
log.error_exit("Number of iterations must be positive orr zero")
|
|
|
|
|
log.error_exit(
|
|
|
|
|
"Number of iterations must be positive orr zero")
|
|
|
|
|
self.height_base = 0
|
|
|
|
|
|
|
|
|
|
# TODO: curved height base could be done here?
|
|
|
|
@ -359,8 +360,7 @@ class fingerprint_app:
|
|
|
|
|
|
|
|
|
|
# add parameters specific to the model creation process
|
|
|
|
|
if self.args.config:
|
|
|
|
|
param_list.append(self.config_file)
|
|
|
|
|
param_list.append(self.preset_name)
|
|
|
|
|
param_list.extend([self.config_file, self.preset_name])
|
|
|
|
|
else:
|
|
|
|
|
# add filters with their params
|
|
|
|
|
filter_list = []
|
|
|
|
@ -379,28 +379,18 @@ class fingerprint_app:
|
|
|
|
|
param_list.append(filter_string)
|
|
|
|
|
|
|
|
|
|
# these are the same for all types of models
|
|
|
|
|
param_list.append(str(self.height_line))
|
|
|
|
|
param_list.append(str(self.height_base))
|
|
|
|
|
param_list.extend([str(self.height_line), str(self.height_base)])
|
|
|
|
|
|
|
|
|
|
# add parameters specific to the model type
|
|
|
|
|
if self.mode == "c":
|
|
|
|
|
param_list.append(str(self.curv_rate_x))
|
|
|
|
|
param_list.append(str(self.curv_rate_y))
|
|
|
|
|
|
|
|
|
|
if self.mode == "m":
|
|
|
|
|
param_list.append(str(self.height_line))
|
|
|
|
|
param_list.append(str(self.iter))
|
|
|
|
|
param_list.append(str(self.finger_x))
|
|
|
|
|
param_list.append(str(self.finger_y))
|
|
|
|
|
param_list.append(str(self.finger_z))
|
|
|
|
|
param_list.append(str(self.finger_name))
|
|
|
|
|
param_list.extend([str(self.curv_rate_x), str(self.curv_rate_y)])
|
|
|
|
|
|
|
|
|
|
if self.mode == "p":
|
|
|
|
|
param_list.append("P")
|
|
|
|
|
elif self.mode == "c":
|
|
|
|
|
param_list.append("C")
|
|
|
|
|
elif self.mode == "m":
|
|
|
|
|
param_list.append("M")
|
|
|
|
|
param_list.extend(
|
|
|
|
|
[str(self.height_line), str(self.iter), str(self.finger_x),
|
|
|
|
|
str(self.finger_y), str(self.finger_z), str(self.finger_name)])
|
|
|
|
|
|
|
|
|
|
param_list.append(self.mode)
|
|
|
|
|
|
|
|
|
|
if self.args.mirror:
|
|
|
|
|
param_list.append("F")
|
|
|
|
@ -462,26 +452,21 @@ class fingerprint_app:
|
|
|
|
|
data = np.frombuffer(fig.canvas.tostring_rgb(), dtype=np.uint8)
|
|
|
|
|
data = data.reshape(fig.canvas.get_width_height()[::-1] + (3,))
|
|
|
|
|
plt.close()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# scale inscription layer to suitable height
|
|
|
|
|
data = (data/255)/10
|
|
|
|
|
|
|
|
|
|
# add the bottom array
|
|
|
|
|
OFFSET = 0.01
|
|
|
|
|
|
|
|
|
|
for i in range(self.height):
|
|
|
|
|
if self.mode == "p":
|
|
|
|
|
for j in range(self.width):
|
|
|
|
|
bottom_vert_arr[i][j][2] = data[i][j][0]
|
|
|
|
|
elif self.mode == "c":
|
|
|
|
|
# TODO: this is very badly written, fix it, why is teh offset needed at all?
|
|
|
|
|
# TODO: this sometimes generates invalid mesh, fix it
|
|
|
|
|
for j in range(self.width):
|
|
|
|
|
bottom_vert_arr[i][j][2] += data[i][j][0]
|
|
|
|
|
if (bottom_vert_arr[i][j][2] < (top_vert_arr[i][0][2])-OFFSET):
|
|
|
|
|
bottom_vert_arr[i][j][2] = top_vert_arr[i][0][2]-OFFSET
|
|
|
|
|
if (bottom_vert_arr[i][j][2] < (top_vert_arr[0][j][2])-OFFSET):
|
|
|
|
|
bottom_vert_arr[i][j][2] = top_vert_arr[0][j][2]-OFFSET
|
|
|
|
|
if (bottom_vert_arr[i][j][2] < (top_vert_arr[i][0][2])):
|
|
|
|
|
bottom_vert_arr[i][j][2] = top_vert_arr[i][0][2]
|
|
|
|
|
if (bottom_vert_arr[i][j][2] < (top_vert_arr[0][j][2])):
|
|
|
|
|
bottom_vert_arr[i][j][2] = top_vert_arr[0][j][2]
|
|
|
|
|
|
|
|
|
|
return bottom_vert_arr
|
|
|
|
|
|
|
|
|
@ -503,20 +488,20 @@ class fingerprint_app:
|
|
|
|
|
for i, face in enumerate(faces):
|
|
|
|
|
for j in range(3):
|
|
|
|
|
self.stl_model.vectors[i][j] = vertices[face[j], :]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Prints out generation progress
|
|
|
|
|
if i % 100 == 0:
|
|
|
|
|
percentage = round(i/len(faces) * 100, 2)
|
|
|
|
|
if percentage > c:
|
|
|
|
|
log.print_message("Creating model " + str(c) + "%")
|
|
|
|
|
c += 10
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
log.print_message("Model creation finished")
|
|
|
|
|
|
|
|
|
|
def create_faces(self, top_vert_arr, bottom_vert_arr):
|
|
|
|
|
'''Create faces for the model.
|
|
|
|
|
Iterate over all vertices, append to vector and create faces from indices.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
:param bottom_vert_arr: Bottom vertex array.
|
|
|
|
|
:param top_vert_arr: Top vertex array
|
|
|
|
|
'''
|
|
|
|
@ -524,57 +509,46 @@ class fingerprint_app:
|
|
|
|
|
count = 0
|
|
|
|
|
vertices = []
|
|
|
|
|
faces = []
|
|
|
|
|
max_width = self.width - 1
|
|
|
|
|
max_height = self.height - 1
|
|
|
|
|
|
|
|
|
|
# Front side faces
|
|
|
|
|
# Front side faces and vertices
|
|
|
|
|
for i in range(self.height - 1):
|
|
|
|
|
for j in range(self.width - 1):
|
|
|
|
|
|
|
|
|
|
vertices.append([top_vert_arr[i][j]])
|
|
|
|
|
vertices.append([top_vert_arr[i][j+1]])
|
|
|
|
|
vertices.append([top_vert_arr[i+1][j]])
|
|
|
|
|
vertices.append([top_vert_arr[i+1][j+1]])
|
|
|
|
|
vertices.extend([[top_vert_arr[i][j]], [top_vert_arr[i][j+1]],
|
|
|
|
|
[top_vert_arr[i+1][j]], [top_vert_arr[i+1][j+1]]])
|
|
|
|
|
count = self.append_faces(faces, count)
|
|
|
|
|
|
|
|
|
|
# Back side faces
|
|
|
|
|
# Back side faces and vertices
|
|
|
|
|
for i in range(self.height - 1):
|
|
|
|
|
for j in range(self.width - 1):
|
|
|
|
|
|
|
|
|
|
vertices.append([bottom_vert_arr[i][j]])
|
|
|
|
|
vertices.append([bottom_vert_arr[i+1][j]])
|
|
|
|
|
vertices.append([bottom_vert_arr[i][j+1]])
|
|
|
|
|
vertices.append([bottom_vert_arr[i+1][j+1]])
|
|
|
|
|
vertices.extend([[bottom_vert_arr[i][j]], [bottom_vert_arr[i+1][j]],
|
|
|
|
|
[bottom_vert_arr[i][j+1]], [bottom_vert_arr[i+1][j+1]]])
|
|
|
|
|
count = self.append_faces(faces, count)
|
|
|
|
|
|
|
|
|
|
# Horizontal side faces
|
|
|
|
|
|
|
|
|
|
# Horizontal side faces and vertices
|
|
|
|
|
for i in range(self.height - 1):
|
|
|
|
|
|
|
|
|
|
vertices.append([top_vert_arr[i][0]])
|
|
|
|
|
vertices.append([top_vert_arr[i+1][0]])
|
|
|
|
|
vertices.append([bottom_vert_arr[i][0]])
|
|
|
|
|
vertices.append([bottom_vert_arr[i+1][0]])
|
|
|
|
|
vertices.extend([[top_vert_arr[i][0]], [top_vert_arr[i+1][0]],
|
|
|
|
|
[bottom_vert_arr[i][0]], [bottom_vert_arr[i+1][0]]])
|
|
|
|
|
count = self.append_faces(faces, count)
|
|
|
|
|
max = self.width - 1
|
|
|
|
|
|
|
|
|
|
vertices.append([top_vert_arr[i+1][max]])
|
|
|
|
|
vertices.append([top_vert_arr[i][max]])
|
|
|
|
|
vertices.append([bottom_vert_arr[i+1][max]])
|
|
|
|
|
vertices.append([bottom_vert_arr[i][max]])
|
|
|
|
|
|
|
|
|
|
vertices.extend([[top_vert_arr[i+1][max_width]], [top_vert_arr[i][max_width]],
|
|
|
|
|
[bottom_vert_arr[i+1][max_width]], [bottom_vert_arr[i][max_width]]])
|
|
|
|
|
count = self.append_faces(faces, count)
|
|
|
|
|
|
|
|
|
|
# Vertical side faces
|
|
|
|
|
# Vertical side faces and vertices
|
|
|
|
|
for j in range(self.width - 1):
|
|
|
|
|
|
|
|
|
|
vertices.append([top_vert_arr[0][j+1]])
|
|
|
|
|
vertices.append([top_vert_arr[0][j]])
|
|
|
|
|
vertices.append([bottom_vert_arr[0][j+1]])
|
|
|
|
|
vertices.append([bottom_vert_arr[0][j]])
|
|
|
|
|
vertices.extend([[top_vert_arr[0][j+1]], [top_vert_arr[0][j]],
|
|
|
|
|
[bottom_vert_arr[0][j+1]], [bottom_vert_arr[0][j]]])
|
|
|
|
|
count = self.append_faces(faces, count)
|
|
|
|
|
max = self.height - 1
|
|
|
|
|
|
|
|
|
|
vertices.append([top_vert_arr[max][j]])
|
|
|
|
|
vertices.append([top_vert_arr[max][j+1]])
|
|
|
|
|
vertices.append([bottom_vert_arr[max][j]])
|
|
|
|
|
vertices.append([bottom_vert_arr[max][j+1]])
|
|
|
|
|
|
|
|
|
|
vertices.extend([[top_vert_arr[max_height][j]], [top_vert_arr[max_height][j+1]],
|
|
|
|
|
[bottom_vert_arr[max_height][j]], [bottom_vert_arr[max_height][j+1]]])
|
|
|
|
|
count = self.append_faces(faces, count)
|
|
|
|
|
|
|
|
|
|
return faces, vertices
|
|
|
|
@ -615,7 +589,7 @@ class fingerprint_app:
|
|
|
|
|
z = np.sqrt(1 - x**2) * self.curv_rate_x**2
|
|
|
|
|
z = np.tile(z, (self.height, 1))
|
|
|
|
|
z *= np.sqrt((1 - ((self.height - y) / self.height)**2)
|
|
|
|
|
* self.curv_rate_y**2)
|
|
|
|
|
* self.curv_rate_y**2)
|
|
|
|
|
z = z.reshape(-1, 1)
|
|
|
|
|
|
|
|
|
|
# Make a copy of z for the bottom side
|
|
|
|
@ -685,7 +659,7 @@ class fingerprint_app:
|
|
|
|
|
c = 0
|
|
|
|
|
for k, vertice in enumerate(vertices):
|
|
|
|
|
# Skip vertices under plane xy
|
|
|
|
|
# also skip vertices under the fingerprint image,
|
|
|
|
|
# also skip vertices under the fingerprint image,
|
|
|
|
|
# they are all unused
|
|
|
|
|
if vertice[2] < 0 or vertice[1] > self.height * px2mm:
|
|
|
|
|
continue
|
|
|
|
@ -698,7 +672,8 @@ class fingerprint_app:
|
|
|
|
|
# To the 2D image projection of vertice, add its value
|
|
|
|
|
point = find_nearest(vertice[0], vertice[1], self.img)
|
|
|
|
|
except IndexError:
|
|
|
|
|
log.error_exit("Fingerprint image is outside of the finger model")
|
|
|
|
|
log.error_exit(
|
|
|
|
|
"Fingerprint image is outside of the finger model")
|
|
|
|
|
|
|
|
|
|
vertices[k][2] += point
|
|
|
|
|
|
|
|
|
|