Commit 71eee9a5 authored by Richard Torenvliet's avatar Richard Torenvliet

Made the shape_components sliders work with the multipliers in the backend,...

Made the shape_components sliders work with the multipliers in the backend, able to change the face now
parent be1ae552
...@@ -10,6 +10,7 @@ import cv2 ...@@ -10,6 +10,7 @@ import cv2
# local imports # local imports
import pca import pca
import aam import aam
import numpy as np
# import imm # import imm
from reconstruction import reconstruction from reconstruction import reconstruction
...@@ -200,7 +201,7 @@ def show_reconstruction(args): ...@@ -200,7 +201,7 @@ def show_reconstruction(args):
texture_model = pca.PCAModel(args.model_texture_file) texture_model = pca.PCAModel(args.model_texture_file)
input_points = dataset_module.IMMPoints( input_points = dataset_module.IMMPoints(
filename='data/imm_face_db/40-3m.asf' filename='data/imm_face_db/01-1m.asf'
) )
input_image = input_points.get_image() input_image = input_points.get_image()
...@@ -210,41 +211,49 @@ def show_reconstruction(args): ...@@ -210,41 +211,49 @@ def show_reconstruction(args):
n_components = 58 n_components = 58
count = 0 count = 0
shape_eigenvalues_multiplier = np.ones(15, dtype=np.float32)
while True: while True:
input_image_copy = input_image.copy() input_image_copy = input_image.copy()
input_points_copy = copy.deepcopy(input_points) input_points_copy = copy.deepcopy(input_points)
output_points = dataset_module.IMMPoints(
points_list=input_points.get_points()
)
# scale by scaling the Vt matrix
shape_Vt = shape_model.Vt
shape_Vt = reconstruction.scale_eigenvalues(
shape_Vt, shape_eigenvalues_multiplier
)
# recontruct the shape
reconstruction.reconstruct_shape( reconstruction.reconstruct_shape(
input_image_copy, input_points_copy, shape_model, output_points,
shape_model,
shape_Vt=shape_Vt, # overwrite by scaled Vt
n_components=n_components - count n_components=n_components - count
) )
# use the new shape ane mean points to reconstruct
reconstruction.reconstruct_texture( reconstruction.reconstruct_texture(
input_image_copy, # src image input_image_copy, # src image
input_image_copy, # dst image input_image_copy, # dst image
texture_model, texture_model,
input_points_copy, # shape points input input_points_copy, # shape points input
mean_points # shape points mean mean_points, # shape points mean
output_points
) )
input_points_copy.get_scaled_points(input_image.shape) output_points.get_scaled_points(input_image.shape)
input_points_copy.draw_triangles(image=input_image_copy, show_points=False) output_points.draw_triangles(image=input_image_copy, show_points=False)
dst = reconstruction.get_texture( dst = reconstruction.get_texture(
mean_points, texture_model.mean_values mean_points, texture_model.mean_values
) )
cv2.imshow('original', input_image) #count += 2
cv2.imshow('reconstructed', input_image_copy) shape_eigenvalues_multiplier[0] += 0.1
cv2.imshow('main face', dst)
k = cv2.waitKey(0) & 0xFF
if k == 27:
break
count += 2
cv2.destroyAllWindows() cv2.destroyAllWindows()
......
...@@ -73,18 +73,26 @@ def draw_shape(image, points, triangles, multiply=True): ...@@ -73,18 +73,26 @@ def draw_shape(image, points, triangles, multiply=True):
def get_texture(Points, flattened_texture): def get_texture(Points, flattened_texture):
offset_x, offset_y, w_slice, h_slice = Points.get_bounding_box() offset_x, offset_y, w_slice, h_slice = Points.get_bounding_box()
# Make a rectangle image from the flattened texture array # Make a rectangle image from the flattened texture array
return np.asarray(flattened_texture, np.uint8).reshape((h_slice, w_slice, 3)) return np.asarray(flattened_texture, np.uint8).reshape((h_slice, w_slice, 3))
def reconstruct_shape(image, points, shape_model, n_components=None): def scale_eigenvalues(Vt, multiplier_array):
multipliers = np.ones(Vt.shape[1], dtype=np.float32)
multipliers[:len(multiplier_array)] = multiplier_array
Vt = np.dot(np.diag(multipliers), Vt)
return Vt
def reconstruct_shape(points, shape_model, shape_Vt=None, n_components=None):
input_points = points.get_points() input_points = points.get_points()
mean_points = shape_model.mean_values mean_points = shape_model.mean_values
shape_Vt = shape_Vt if shape_Vt is not None else shape_model.Vt
reconstructed = pca.reconstruct( reconstructed = pca.reconstruct(
input_points, input_points,
shape_model.Vt, shape_Vt,
mean_points, mean_points,
n_components=n_components n_components=n_components
) )
...@@ -92,7 +100,8 @@ def reconstruct_shape(image, points, shape_model, n_components=None): ...@@ -92,7 +100,8 @@ def reconstruct_shape(image, points, shape_model, n_components=None):
points.normalized_flattened_points_list = reconstructed points.normalized_flattened_points_list = reconstructed
def reconstruct_texture(src_image, dst_image, texture_model, src_points, dst_points): def reconstruct_texture(src_image, dst_image, texture_model,
src_points, dst_points, output_points):
""" """
Recontruct texture given the src and dst image Recontruct texture given the src and dst image
...@@ -124,6 +133,7 @@ def reconstruct_texture(src_image, dst_image, texture_model, src_points, dst_poi ...@@ -124,6 +133,7 @@ def reconstruct_texture(src_image, dst_image, texture_model, src_points, dst_poi
points2d_src = src_points.get_scaled_points(src_image.shape) points2d_src = src_points.get_scaled_points(src_image.shape)
points2d_dst = dst_points.get_scaled_points(dst_image.shape) points2d_dst = dst_points.get_scaled_points(dst_image.shape)
points2d_output = output_points.get_scaled_points(src_image.shape)
# get the texture from the rectangles. # get the texture from the rectangles.
aam.sample_from_triangles( aam.sample_from_triangles(
...@@ -154,16 +164,13 @@ def reconstruct_texture(src_image, dst_image, texture_model, src_points, dst_poi ...@@ -154,16 +164,13 @@ def reconstruct_texture(src_image, dst_image, texture_model, src_points, dst_poi
points2d_dst[:, 0] -= offset_x points2d_dst[:, 0] -= offset_x
points2d_dst[:, 1] -= offset_y points2d_dst[:, 1] -= offset_y
for tri in triangles: points2d_src = points2d_src * 1.1
src_p1, src_p2, src_p3 = points2d_src[tri]
dst_p1, dst_p2, dst_p3 = points2d_dst[tri] # get the texture from the rectangles.
aam.sample_from_triangles(
fill_triangle_src_dst( r_texture,
r_texture, dst_image, points2d_dst, # turn src and dst around
dst_p1[0], dst_p1[1], points2d_output, # turn src and dst around
dst_p2[0], dst_p2[1], triangles,
dst_p3[0], dst_p3[1], dst_image
src_p1[0], src_p1[1],
src_p2[0], src_p2[1],
src_p3[0], src_p3[1]
) )
...@@ -61,7 +61,11 @@ class ImageWebSocketHandler(websocket.WebSocketHandler): ...@@ -61,7 +61,11 @@ class ImageWebSocketHandler(websocket.WebSocketHandler):
image_index = message['reconstruction_index'] image_index = message['reconstruction_index']
image_as_background = message.get('background_image', True) image_as_background = message.get('background_image', True)
shape_components = message.get('shape_components', 58) shape_components = message.get('shape_components', 58)
print message shape_eigenvalues_multiplier = message.get('shape_eigenvalues')
shape_eigenvalues_multiplier = np.asarray(
shape_eigenvalues_multiplier, dtype=np.float32
)
logger.info('using %s shape_components', shape_components) logger.info('using %s shape_components', shape_components)
...@@ -80,8 +84,20 @@ class ImageWebSocketHandler(websocket.WebSocketHandler): ...@@ -80,8 +84,20 @@ class ImageWebSocketHandler(websocket.WebSocketHandler):
else: else:
dst_image = input_image dst_image = input_image
output_points = imm.IMMPoints(
points_list=input_points.get_points()
)
shape_Vt = self.shape_model.Vt
shape_Vt = reconstruction.scale_eigenvalues(
shape_Vt, shape_eigenvalues_multiplier
)
# recontruct the shape
reconstruction.reconstruct_shape( reconstruction.reconstruct_shape(
input_image, input_points, self.shape_model, output_points,
self.shape_model,
shape_Vt=shape_Vt, # overwrite by scaled Vt
n_components=shape_components n_components=shape_components
) )
...@@ -90,10 +106,11 @@ class ImageWebSocketHandler(websocket.WebSocketHandler): ...@@ -90,10 +106,11 @@ class ImageWebSocketHandler(websocket.WebSocketHandler):
dst_image, # dst image dst_image, # dst image
self.texture_model, self.texture_model,
input_points, # shape points input input_points, # shape points input
mean_points # shape points mean mean_points, # shape points mean
output_points
) )
input_points.draw_triangles(show_points=False) output_points.draw_triangles(image=dst_image, show_points=False)
_, reconstructed = cv2.imencode('.jpg', dst_image) _, reconstructed = cv2.imencode('.jpg', dst_image)
reconstructed = base64.b64encode(reconstructed) reconstructed = base64.b64encode(reconstructed)
...@@ -112,12 +129,15 @@ class ImageWebSocketHandler(websocket.WebSocketHandler): ...@@ -112,12 +129,15 @@ class ImageWebSocketHandler(websocket.WebSocketHandler):
for m in message.keys(): for m in message.keys():
try: try:
handler = getattr(self, self.handlers[m]) handler = getattr(self, self.handlers[m])
handler(message[m])
except (AttributeError, KeyError) as e: except (AttributeError, KeyError) as e:
msg = 'no handler for {}'.format(m) msg = 'no handler for {}'.format(m)
print(msg, e) print(msg, e)
self.__return_error(msg) self.__return_error(msg)
except Exception as e:
handler(message[m]) msg = 'no handler for {}'.format(m)
print(msg, e)
self.__return_error(msg)
def on_close(self): def on_close(self):
print("WebSocket closed") print("WebSocket closed")
......
...@@ -20,25 +20,10 @@ const ThreeComponent = Ember.Component.extend({ ...@@ -20,25 +20,10 @@ const ThreeComponent = Ember.Component.extend({
var renderer = new THREE.WebGLRenderer(); var renderer = new THREE.WebGLRenderer();
// the sidebar 'dat-gui' controls
var reconstructionControls = {
index: 0,
shape_components: 58,
background_image: true,
};
for(var i = 0; i < 15; i++) {
reconstructionControls['shape_eigen_value_' + i] = 0.0;
}
var shapeEigenValueSliders = {};
this.set('scene', scene); this.set('scene', scene);
this.set('camera', camera); this.set('camera', camera);
this.set('renderer', renderer); this.set('renderer', renderer);
this.set('gui', gui); this.set('gui', gui);
this.set('controls', reconstructionControls);
this.set('shapeEigenValueSliders', shapeEigenValueSliders);
this.get('store').findAll('face').then((faces) => { this.get('store').findAll('face').then((faces) => {
this.set('faces', faces); this.set('faces', faces);
...@@ -66,20 +51,19 @@ const ThreeComponent = Ember.Component.extend({ ...@@ -66,20 +51,19 @@ const ThreeComponent = Ember.Component.extend({
addSliders() { addSliders() {
var self = this; var self = this;
var gui = this.get('gui'); var gui = this.get('gui');
var reconstructionControls = this.get('controls');
var shapeEigenValueSliders = this.get('shapeEigenValueSliders'); // the sidebar 'dat-gui' controls
var reconstructionControls = {
index: 0,
shape_components: 58,
background_image: true
};
var length = this.get('faces').get('length'); var length = this.get('faces').get('length');
var index = gui.add(reconstructionControls, 'index', 0, length - 1); var index = gui.add(reconstructionControls, 'index', 0, length - 1);
var shape_components = gui.add(reconstructionControls, 'shape_components', 0, 58); var shapeComponents = gui.add(reconstructionControls, 'shape_components', 0, 58);
var background = gui.add(reconstructionControls, 'background_image'); var background = gui.add(reconstructionControls, 'background_image');
var shapeEigenValueControls = gui.addFolder('shape_eigen_values');
for(var i = 0; i < 15; i++) {
shapeEigenValueControls.add(reconstructionControls, 'shape_eigen_value_' + i, 0.0, 10.0);
}
// on index change // on index change
index.onChange(function(newValue) { index.onChange(function(newValue) {
...@@ -92,13 +76,35 @@ const ThreeComponent = Ember.Component.extend({ ...@@ -92,13 +76,35 @@ const ThreeComponent = Ember.Component.extend({
self.sendAction('updateBackground', newValue); self.sendAction('updateBackground', newValue);
}); });
shape_components.onChange(function(newValue) { shapeComponents.onChange(function(newValue) {
self.sendAction('updateShapeComponents', newValue); self.sendAction('updateShapeComponents', newValue);
}); });
reconstructionControls.onChange(function(newValue) { var shapeEigenValueControls = gui.addFolder('shape_eigen_values');
console.log(newValue);
/**
* ShapeSlider callback function
*/
var handleShapeSlidersCb = function(value) {
var sliderObject = this;
// slider index is the last character of the slider property string.
var sliderCharacterIndex = sliderObject.property.length - 1;
var sliderIndex = parseInt(sliderObject.property[sliderCharacterIndex]);
self.sendAction('updateShapeEigenValues', sliderIndex, value);
};
var shapeEigenValues = this.get('shape_eigenvalues');
shapeEigenValues.forEach(function(value, index) {
reconstructionControls['shape_eigen_value_' + index] = value;
var slider = shapeEigenValueControls.add(reconstructionControls, 'shape_eigen_value_' + index, 0.0, 10.0);
slider.onChange(handleShapeSlidersCb);
}); });
console.log(gui.__controllers);
} }
}); });
......
...@@ -11,9 +11,10 @@ export default Ember.Controller.extend({ ...@@ -11,9 +11,10 @@ export default Ember.Controller.extend({
image_index: 0, image_index: 0,
background_image: true, background_image: true,
shape_components: null, shape_components: 58,
n_images: null, n_images: null,
reconstructed: null, reconstructed: null,
shape_eigenvalues: [],
socketRef: null, socketRef: null,
...@@ -25,6 +26,16 @@ export default Ember.Controller.extend({ ...@@ -25,6 +26,16 @@ export default Ember.Controller.extend({
socket.on('close', this.closeHandler, this); socket.on('close', this.closeHandler, this);
this.set('socketRef', socket); this.set('socketRef', socket);
this.initShapeEigenValues(15);
},
initShapeEigenValues(amountOfEigenValues) {
var shapeEigenValues = this.get('shape_eigenvalues');
shapeEigenValues.length = amountOfEigenValues;
shapeEigenValues.fill(1.0);
this.set('shape_eigenvalues', shapeEigenValues);
}, },
willDestroyElement() { willDestroyElement() {
...@@ -66,7 +77,9 @@ export default Ember.Controller.extend({ ...@@ -66,7 +77,9 @@ export default Ember.Controller.extend({
}, },
getReconstruction: Ember.observer( getReconstruction: Ember.observer(
'image_index', 'background_image', 'shape_components', function() { 'image_index', 'background_image',
'shape_components', 'shape_eigenvalues', function() {
console.log('updating');
this.send('getReconstruction'); this.send('getReconstruction');
}), }),
...@@ -94,11 +107,11 @@ export default Ember.Controller.extend({ ...@@ -94,11 +107,11 @@ export default Ember.Controller.extend({
reconstruction: { reconstruction: {
reconstruction_index: this.get('image_index'), reconstruction_index: this.get('image_index'),
background_image: this.get('background_image'), background_image: this.get('background_image'),
shape_components: this.get('shape_components') shape_components: this.get('shape_components'),
shape_eigenvalues: this.get('shape_eigenvalues')
} }
})
} );
));
}, },
// connects components together // connects components together
...@@ -114,6 +127,19 @@ export default Ember.Controller.extend({ ...@@ -114,6 +127,19 @@ export default Ember.Controller.extend({
updateShapeComponents(components) { updateShapeComponents(components) {
console.log('shape_components', components); console.log('shape_components', components);
this.set('shape_components', components); this.set('shape_components', components);
},
updateShapeEigenValues(eigenValueIndex, value) {
console.log('shape_eigenvalues', value);
var eigenValues = this.get('shape_eigenvalues');
eigenValues[eigenValueIndex] = value;
this.set('shape_eigenvalues', eigenValues);
this.send('getReconstruction');
},
resetShapeEigenValues(gui) {
this.initShapeEigenValues(15);
} }
} }
}); });
...@@ -28,9 +28,12 @@ ...@@ -28,9 +28,12 @@
<div class="col col-12 px2"> <div class="col col-12 px2">
{{three-js-reconstruction {{three-js-reconstruction
shape_eigenvalues=shape_eigenvalues
updateIndex=(action 'updateIndexComponentConnector') updateIndex=(action 'updateIndexComponentConnector')
updateBackground=(action 'updateBackgroundComponentConnector') updateBackground=(action 'updateBackgroundComponentConnector')
updateShapeComponents=(action 'updateShapeComponents') updateShapeComponents=(action 'updateShapeComponents')
updateShapeEigenValues=(action 'updateShapeEigenValues')
resetShapeEigenValues=(action 'resetShapeEigenValues')
}} }}
</div> </div>
</div> </div>
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