Commit f7da1d93 authored by Richard Torenvliet's avatar Richard Torenvliet

Refactoring a bit

parent 3c33b0b3
...@@ -6,7 +6,9 @@ data/imm_face_db: data/imm_face_db.tar.gz ...@@ -6,7 +6,9 @@ data/imm_face_db: data/imm_face_db.tar.gz
tar -xvzf imm_face_db.tar.gz -C imm_face_db tar -xvzf imm_face_db.tar.gz -C imm_face_db
) )
train_model: data/pca_shape_model.npy data/pca_texture_model.npy train_model:train_shape
train_texture: data/pca_texture_model.npy
train_shape: data/pca_shape_model.npy
data/imm_face_db.tar.gz: data/imm_face_db.tar.gz:
(cd data; wget http://www.imm.dtu.dk/~aam/datasets/imm_face_db.tar.gz) (cd data; wget http://www.imm.dtu.dk/~aam/datasets/imm_face_db.tar.gz)
......
...@@ -84,16 +84,16 @@ def save_pca_model_texture(args): ...@@ -84,16 +84,16 @@ def save_pca_model_texture(args):
assert args.model_shape_file, '--model_texture_file needs to be provided to save the pca model' assert args.model_shape_file, '--model_texture_file needs to be provided to save the pca model'
assert args.model_texture_file, '--model_texture_file needs to be provided to save the pca model' assert args.model_texture_file, '--model_texture_file needs to be provided to save the pca model'
Vt, s, mean_shape, triangles = pca.load(args.model_shape_file) Vt, s, n_components, mean_shape, triangles = pca.load(args.model_shape_file)
textures = aam.build_texture_feature_vectors( textures = aam.build_texture_feature_vectors(
args.files, imm.get_imm_image_with_landmarks, mean_shape, triangles args.files, imm.get_imm_image_with_landmarks, mean_shape, triangles
) )
mean_texture = aam.get_mean(textures) mean_texture = aam.get_mean(textures)
_, s, Vt = pca.pca(textures, mean_texture) _, s, Vt, n_components = pca.pca(textures, mean_texture)
pca.save(Vt, s, mean_texture, triangles, args.model_texture_file) pca.save(Vt, s, n_components, mean_texture, triangles, args.model_texture_file)
logger.info('texture pca model saved in %s', args.model_texture_file) logger.info('texture pca model saved in %s', args.model_texture_file)
...@@ -123,12 +123,12 @@ def save_pca_model_shape(args): ...@@ -123,12 +123,12 @@ def save_pca_model_shape(args):
mean_values = aam.get_mean(points) mean_values = aam.get_mean(points)
_, s, Vt = pca.pca(points, mean_values) _, s, Vt, n_components = pca.pca(points, mean_values)
mean_xy = mean_values.reshape((-1, 2)) mean_xy = mean_values.reshape((-1, 2))
triangles = aam.get_triangles(mean_xy[:, 0], mean_xy[:, 1]) triangles = aam.get_triangles(mean_xy[:, 0], mean_xy[:, 1])
pca.save(Vt, s, mean_values, triangles, args.model_shape_file) pca.save(Vt, s, n_components, mean_values, triangles, args.model_shape_file)
logger.info('shape pca model saved in %s', args.model_shape_file + '_shape') logger.info('shape pca model saved in %s', args.model_shape_file + '_shape')
...@@ -142,8 +142,9 @@ def reconstruct_with_model(args): ...@@ -142,8 +142,9 @@ def reconstruct_with_model(args):
sys.argv[1:] = [] sys.argv[1:] = []
from view.reconstruct import ReconstructApp from view.reconstruct import ReconstructApp
Vt_shape, mean_values_shape, triangles = pca.load(args.model_shape_file)
Vt_texture, mean_values_texture, _ = pca.load(args.model_texture_file) Vt_shape, s, n_shape_components, mean_values_shape, triangles = pca.load(args.model_shape_file)
Vt_texture, s_texture, n_texture_components, mean_values_texture, _ = pca.load(args.model_texture_file)
app = ReconstructApp() app = ReconstructApp()
...@@ -152,7 +153,9 @@ def reconstruct_with_model(args): ...@@ -152,7 +153,9 @@ def reconstruct_with_model(args):
eigenv_shape=Vt_shape, eigenv_shape=Vt_shape,
eigenv_texture=Vt_texture, eigenv_texture=Vt_texture,
mean_values_shape=mean_values_shape, mean_values_shape=mean_values_shape,
n_shape_components=n_shape_components,
mean_values_texture=mean_values_texture, mean_values_texture=mean_values_texture,
n_texture_components=n_texture_components,
triangles=triangles triangles=triangles
) )
...@@ -165,19 +168,8 @@ def show_pca_model(args): ...@@ -165,19 +168,8 @@ def show_pca_model(args):
from utils.triangles import draw_shape, draw_texture from utils.triangles import draw_shape, draw_texture
Vt_shape, s, mean_values_shape, triangles = pca.load(args.model_shape_file) Vt_shape, s, n_shape_components, mean_values_shape, triangles = pca.load(args.model_shape_file)
Vt_texture, s_texture, mean_values_texture, _ = pca.load(args.model_texture_file) Vt_texture, s_texture, n_texture_components, mean_values_texture, _ = pca.load(args.model_texture_file)
# calculate n_components which captures 90 percent of the variance
total = s_texture.sum()
subtotal = 0.0
i = 0
while (subtotal * 100.0) / total <= 90.0:
subtotal += s_texture[i]
i += 1
n_components = i
image = np.full((480, 640, 3), fill_value=255, dtype=np.uint8) image = np.full((480, 640, 3), fill_value=255, dtype=np.uint8)
...@@ -195,7 +187,7 @@ def show_pca_model(args): ...@@ -195,7 +187,7 @@ def show_pca_model(args):
while True: while True:
draw_texture(input_image, image, Vt_texture, input_points, mean_values_shape, draw_texture(input_image, image, Vt_texture, input_points, mean_values_shape,
mean_values_texture, triangles) mean_values_texture, triangles, n_texture_components)
#draw_shape(image, mean_values_shape, triangles, multiply=False) #draw_shape(image, mean_values_shape, triangles, multiply=False)
cv2.imshow('input_image', input_image) cv2.imshow('input_image', input_image)
......
import numpy as np import numpy as np
def pca(data, mean_values): def pca(data, mean_values, variance_percentage=90):
""" """
Perform Singlar Value Decomposition Perform Singlar Value Decomposition
...@@ -14,10 +14,21 @@ def pca(data, mean_values): ...@@ -14,10 +14,21 @@ def pca(data, mean_values):
zero_mean = data - mean_values zero_mean = data - mean_values
U, s, Vt = np.linalg.svd(zero_mean, full_matrices=False) U, s, Vt = np.linalg.svd(zero_mean, full_matrices=False)
return U, s, Vt # calculate n_components which captures 90 percent of the variance
total = s.sum()
subtotal = 0.0
i = 0
while (subtotal * 100.0) / total <= variance_percentage:
subtotal += s[i]
i += 1
def reconstruct(feature_vector, Vt, mean_values, n_components=10): n_components = i
return U, s, Vt, n_components
def reconstruct(feature_vector, Vt, mean_values, n_components=None):
""" """
Reconstruct with U, s, Vt Reconstruct with U, s, Vt
...@@ -28,15 +39,18 @@ def reconstruct(feature_vector, Vt, mean_values, n_components=10): ...@@ -28,15 +39,18 @@ def reconstruct(feature_vector, Vt, mean_values, n_components=10):
Vt (numpy ndarray): Two dimensional array with dimensions Vt (numpy ndarray): Two dimensional array with dimensions
(n_features, n_features) (n_features, n_features)
mean_values (numpy ndarray): mean values of the features of the model, mean_values (numpy ndarray): mean values of the features of the model,
this should have dimensions (n_featurs, ) this should have dimensions (n_features, )
""" """
if n_components is None:
n_components = Vt.shape[1]
zm = feature_vector - mean_values zm = feature_vector - mean_values
yk = np.dot(Vt[:n_components], zm.T) yk = np.dot(Vt[:n_components], zm.T)
return np.dot(Vt[:n_components].T, yk) + mean_values return np.dot(Vt[:n_components].T, yk) + mean_values
def save(Vt, s, mean_values, triangles, filename): def save(Vt, s, n_components, mean_values, triangles, filename):
""" """
Store the U, s, Vt and mean of all the asf datafiles given by the asf Store the U, s, Vt and mean of all the asf datafiles given by the asf
files. files.
...@@ -52,7 +66,7 @@ def save(Vt, s, mean_values, triangles, filename): ...@@ -52,7 +66,7 @@ def save(Vt, s, mean_values, triangles, filename):
triangles = Vtm[2] triangles = Vtm[2]
""" """
saving = np.asarray([Vt, s, [mean_values], triangles]) saving = np.asarray([Vt, s, n_components, [mean_values], triangles])
np.save(filename, saving) np.save(filename, saving)
...@@ -77,10 +91,11 @@ def load(filename): ...@@ -77,10 +91,11 @@ def load(filename):
Vt = Vtm[0] Vt = Vtm[0]
s = Vtm[1] s = Vtm[1]
mean_values = Vtm[2][0] n_components = Vtm[2]
triangles = Vtm[3] mean_values = Vtm[3][0]
triangles = Vtm[4]
return Vt, s, mean_values, triangles return Vt, s, n_components, mean_values, triangles
def flatten_feature_vectors(data, dim=0): def flatten_feature_vectors(data, dim=0):
......
...@@ -67,7 +67,7 @@ def draw_shape(image, points, triangles, multiply=True): ...@@ -67,7 +67,7 @@ def draw_shape(image, points, triangles, multiply=True):
cv2.circle(image, tuple(p), 3, color=(0, 255, 100)) cv2.circle(image, tuple(p), 3, color=(0, 255, 100))
def draw_texture(src, dest, Vt, points2d_src, points2d_dst, texture, triangles): def draw_texture(src, dest, Vt, points2d_src, points2d_dst, texture, triangles, n_components):
# texture = np.asarray(texture, dtype=np.uint8).reshape((-1, 3)) # texture = np.asarray(texture, dtype=np.uint8).reshape((-1, 3))
texture = np.asarray(texture, np.uint8) texture = np.asarray(texture, np.uint8)
offset = 0 offset = 0
......
...@@ -20,6 +20,8 @@ from functools import partial ...@@ -20,6 +20,8 @@ from functools import partial
from math import cos, sin, pi from math import cos, sin, pi
import imm_points as imm import imm_points as imm
from utils.triangles import draw_texture
from utils.generate_head_texture import fill_triangle
#import IMMPoints, build_feature_vectors, \ #import IMMPoints, build_feature_vectors, \
# flatten_feature_vectors # flatten_feature_vectors
import pca import pca
...@@ -76,48 +78,53 @@ class ImageCanvas(Widget): ...@@ -76,48 +78,53 @@ class ImageCanvas(Widget):
self.canvas.ask_update() self.canvas.ask_update()
def build_texture(self, r_shape, r_texture, triangles): def build_texture(self, r_shape, r_texture, triangles):
self.texture.clear() return
#self.texture.clear()
image_width, image_height = self.get_rendered_size() #image_width, image_height = self.get_rendered_size()
bary_centric_range = np.linspace(0, 1, num=20) #bary_centric_range = np.linspace(0, 1, num=20)
texture = Texture.create(size=(image_width, image_height), colorfmt='bgr') #texture = Texture.create(size=(image_width, image_height), colorfmt='bgr')
buf = np.zeros((image_width, image_height, 3), dtype=np.uint8) #buf = np.zeros((image_width, image_height, 3), dtype=np.uint8)
for tri in triangles[:1]: #offset = 0
points = r_shape[tri]
pixels = r_texture[tri].reshape((-1, 3))
x = points[:, 0] * image_width + self.get_image_left(image_width) #for t, tri in enumerate(triangles):
y = (1.0 - points[:, 1]) * image_height + self.get_image_bottom(image_height) # src_p1, src_p2, src_p3 = r_shape[tri]
# x = r_shape[:, 0] * image_width + self.get_image_left(image_width)
# y = (1.0 - r_shape[:, 1]) * image_height + self.get_image_bottom(image_height)
p1 = [x[0], y[0]] # for t, tri in enumerate(triangles):
p2 = [x[1], y[1]] # offset += fill_triangle(
p3 = [x[2], y[2]] # r_texture, buf,
# src_p1[0], src_p1[1],
# src_p2[0], src_p2[1],
# src_p3[0], src_p3[1],
# dst_p1[0], dst_p1[1],
# dst_p2[0], dst_p2[1],
# dst_p3[0], dst_p3[1],
# offset,
# t
# )
L = np.zeros((3, 1)) # print offset
for s_i, s in enumerate(bary_centric_range): # #p1 = [x[0], y[0]]
for t_i, t in enumerate(bary_centric_range): # #p2 = [x[1], y[1]]
if s + t <= 1: # #p3 = [x[2], y[2]]
# build lambda's
L[0] = s
L[1] = t
L[2] = 1 - s - t
cart_x, cart_y, _ = aam.barycentric2cartesian(p1, p2, p3, L)
buf[s_i, t_i, :] = pixels[s_i * 20 + t_i, :]
#buf = b''.join(map(chr, buf)) ##buf = b''.join(map(chr, buf))
cv2.imshow('image', buf) #cv2.imshow('image', buf)
cv2.waitKey(0) #cv2.waitKey(0)
#texture.blit_buffer(buf, colorfmt='bgr', bufferfmt='ubyte') #texture.blit_buffer(buf, colorfmt='bgr', bufferfmt='ubyte')
#self.texture.add(Rectangle(texture=texture, pos=(0, 100), #self.texture.add(Rectangle(texture=texture, pos=(0, 100),
# size=(image_width, image_height))) # size=(image_width, image_height)))
self.canvas.add(self.texture) #self.canvas.add(self.texture)
self.canvas.ask_update() #self.canvas.ask_update()
def build_line_grid(self, r_shape, triangles): def build_line_grid(self, r_shape, triangles):
...@@ -175,28 +182,40 @@ class RootWidget(BoxLayout): ...@@ -175,28 +182,40 @@ class RootWidget(BoxLayout):
self.eigenv_shape = kwargs['eigenv_shape'] self.eigenv_shape = kwargs['eigenv_shape']
self.eigenv_texture = kwargs['eigenv_texture'] self.eigenv_texture = kwargs['eigenv_texture']
self.triangles = kwargs['triangles'] self.triangles = kwargs['triangles']
self.n_components = kwargs['args'].n_components self.n_shape_components = kwargs['args'].n_components
self.n_texture_components = kwargs['n_texture_components']
self.multipliers = np.ones(self.eigenv_shape.shape[1]) self.multipliers = np.ones(self.eigenv_shape.shape[1])
self.mean_values_shape_reshaped = np.copy(self.mean_values_shape).reshape((58, 2))
# slider index # slider index
self.index = 0 self.index = 0
self.filename = '' self.filename = ''
self.shape_list = aam.build_shape_feature_vectors(self.files, imm.get_imm_points, flattened=True)
# sliders
self.add_shape_sliders()
self.add_image_slider()
self.add_components_slider()
# ======= #
# event binders
self.ids['image_viewer'].bind(size=self.on_resize)
def add_components_slider(self):
n_components_slider = self.ids['n_shape_components']
n_components_slider.value = self.n_shape_components
n_components_slider.bind(value=self.update_n_components)
def add_image_slider(self):
image_slider = self.ids['image_slider'] image_slider = self.ids['image_slider']
image_slider.max = len(self.files) - 1 image_slider.max = len(self.files) - 1
image_slider.bind(value=self.update_image) image_slider.bind(value=self.update_image)
n_components_slider = self.ids['n_components'] def add_shape_sliders(self):
n_components_slider.value = self.n_components
n_components_slider.bind(value=self.update_n_components)
self.ids['image_viewer'].bind(size=self.on_resize)
box_layout = self.ids['eigenvalues'] box_layout = self.ids['eigenvalues']
self.shape_list = aam.build_shape_feature_vectors( for c in range(self.n_shape_components):
self.files, imm.get_imm_points, flattened=True)
for c in range(self.n_components):
slider = Slider(min=-10, max=10, value=0, id=str(c)) slider = Slider(min=-10, max=10, value=0, id=str(c))
box_layout.add_widget(slider) box_layout.add_widget(slider)
slider.bind(value=self.update_eigenvalues) slider.bind(value=self.update_eigenvalues)
...@@ -215,10 +234,26 @@ class RootWidget(BoxLayout): ...@@ -215,10 +234,26 @@ class RootWidget(BoxLayout):
r_shape = pca.reconstruct( r_shape = pca.reconstruct(
self.shape_list[self.index], Vt_shape, self.mean_values_shape, self.shape_list[self.index], Vt_shape, self.mean_values_shape,
n_components=self.n_components n_components=self.n_shape_components
).reshape((-1, 2)) ).reshape((-1, 2))
# image = cv2.imread(self.filename) #image = cv2.imread(self.filename)
#h, w = image.shape[0], image.shape[1]
#mean_values_shape = np.copy(self.mean_values_shape_reshaped)
#mean_values_shape[:, 0] = mean_values_shape[:, 0] * w
#mean_values_shape[:, 1] = mean_values_shape[:, 1] * h
#texture = aam.sample_from_triangles(
# image, r_shape, mean_values_shape, self.triangles
#)
#r_texture = pca.reconstruct(
# texture, self.eigenv_texture, self.mean_values_texture
#)
#r_texture = np.asarray(texture, np.uint8)
# pixels = aam.sample_from_triangles(image, r_shape, self.triangles) # pixels = aam.sample_from_triangles(image, r_shape, self.triangles)
# pixels = np.ndarray.flatten(pixels) # pixels = np.ndarray.flatten(pixels)
...@@ -230,12 +265,13 @@ class RootWidget(BoxLayout): ...@@ -230,12 +265,13 @@ class RootWidget(BoxLayout):
self.ids['image_viewer'].update_rect() self.ids['image_viewer'].update_rect()
self.ids['image_viewer'].update_image(self.filename) self.ids['image_viewer'].update_image(self.filename)
self.ids['image_viewer'].build_line_grid(r_shape, self.triangles) self.ids['image_viewer'].build_line_grid(r_shape, self.triangles)
#self.ids['image_viewer'].build_texture(r_shape, r_texture, self.triangles)
def on_resize(self, *args): def on_resize(self, *args):
self.update_image_viewer() self.update_image_viewer()
def update_n_components(self, slider, index): def update_n_components(self, slider, index):
self.n_components = int(index) self.n_shape_components = int(index)
self.update_image_viewer() self.update_image_viewer()
def update_image(self, slider, index): def update_image(self, slider, index):
...@@ -265,7 +301,9 @@ class ReconstructApp(App): ...@@ -265,7 +301,9 @@ class ReconstructApp(App):
eigenv_shape=self.eigenv_shape, eigenv_shape=self.eigenv_shape,
eigenv_texture=self.eigenv_texture, eigenv_texture=self.eigenv_texture,
mean_values_shape=self.mean_values_shape, mean_values_shape=self.mean_values_shape,
n_shape_components=self.n_shape_components,
mean_values_texture=self.mean_values_texture, mean_values_texture=self.mean_values_texture,
n_texture_components=self.n_texture_components,
triangles=self.triangles triangles=self.triangles
) )
......
...@@ -27,9 +27,9 @@ ...@@ -27,9 +27,9 @@
max: 100 max: 100
value: 0 value: 0
Label: Label:
text: "Using {} components".format(int(n_components.value)) text: "Using {} components".format(int(n_shape_components.value))
Slider: Slider:
id: n_components id: n_shape_components
min: 0 min: 0
max: 58 max: 58
value: 0 value: 0
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment