Commit b6cef93a authored by Richard Torenvliet's avatar Richard Torenvliet

Updated app to use a RESTFul api endpoint for getting the images

parent 62fabe5c
...@@ -63,5 +63,8 @@ test: ...@@ -63,5 +63,8 @@ test:
test_modules: test_modules:
python -m py.test -f src/*/*_test.py python -m py.test -f src/*/*_test.py
run: server:
python server.py (cd src/; python -m tornado.autoreload server.py)
ember:
(cd viewer; ember server);
import json
import base64
from glob import glob
from tornado import websocket, web, ioloop
BASE = 'viewer/app'
FILES_DIR = 'data/'
FACE_DB = '{}{}'.format(FILES_DIR, 'imm_face_db')
class SocketHandler(websocket.WebSocketHandler):
def __init__(self, *args, **kwargs):
self.images = glob('{}/*.jpg'.format(FACE_DB))
websocket.WebSocketHandler.__init__(self, *args, **kwargs)
def check_origin(self, origin):
return True
def open(self):
print("WebSocket opened")
self.write_message(json.dumps({'n_images': len(self.images)}))
def on_message(self, message):
message = json.loads(message)
image_index = message['image_index']
filename = self.images[image_index]
image = None
with open(filename, "rb") as f:
image = base64.b64encode(f.read())
self.write_message(json.dumps({'image': image}))
def on_close(self):
print("WebSocket closed")
#class ApiHandler(web.RequestHandler):
# def __init__(self, *args, **kwargs):
# self.images = glob('{}/*.jpg'.format(FACE_DB))
# websocket.RequestHandler.__init__(self, *args, **kwargs)
#
# @web.asynchronous
# def get(self, *args):
# self.finish()
#
# if self.get_argument('images'):
# self.get_images()
#
# #id = self.get_argument("id")
# #value = self.get_argument("value")
# #data = {"id": id, "value" : value}
# #data = json.dumps(data)
#
# #self.write_message(data)
#
# @web.asynchronous
# def post(self):
# pass
app = web.Application([
(r'/reconstruction', SocketHandler),
])
if __name__ == '__main__':
app.listen(8888)
ioloop.IOLoop.instance().start()
...@@ -246,6 +246,7 @@ def show_reconstruction(args): ...@@ -246,6 +246,7 @@ def show_reconstruction(args):
cv2.destroyAllWindows() cv2.destroyAllWindows()
def main(): def main():
"""main""" """main"""
parser = add_parser_options() parser = add_parser_options()
......
def reconstruct(model_shape_file, model_texture_file, image, asf_file):
#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'
Vt_shape, s, n_shape_components, mean_value_points, triangles = pca.load(args.model_shape_file)
Vt_texture, s_texture, n_texture_components, mean_values_texture, _ = pca.load(args.model_texture_file)
InputPoints = imm.IMMPoints(filename=asf_file)
input_image = InputPoints.get_image()
MeanPoints = imm.IMMPoints(points_list=mean_value_points)
MeanPoints.get_scaled_points(input_image.shape)
while True:
utils.reconstruct_texture(
input_image, # src image
input_image, # dst image
Vt_texture, # Vt
InputPoints, # shape points input
MeanPoints, # shape points mean
mean_values_texture, # mean texture
triangles, # triangles
n_texture_components # learned n_texture_components
)
dst = utils.get_texture(MeanPoints, mean_values_texture)
cv2.imshow('original', InputPoints.get_image())
cv2.imshow('reconstructed', input_image)
cv2.imshow('main face', dst)
k = cv2.waitKey(0) & 0xFF
if k == 27:
break
cv2.destroyAllWindows()
import json
import base64
from glob import glob
from tornado import websocket, web, ioloop
import imm_points as imm
BASE = '../viewer/app'
FILES_DIR = '../data/'
FACE_DB = '{}{}'.format(FILES_DIR, 'imm_face_db')
class ImageWebSocketHandler(websocket.WebSocketHandler):
handlers = {
'filename': 'handle_return_image',
'reconstruction_index': 'handle_return_reconstruction'
}
def __init__(self, *args, **kwargs):
self.images = glob('{}/*.jpg'.format(FACE_DB))
self.asf = glob('{}/*.asf'.format(FACE_DB))
websocket.WebSocketHandler.__init__(self, *args, **kwargs)
def __get_base64_image(self, filename):
image = None
with open(filename, "rb") as f:
image = base64.b64encode(f.read())
return image
def check_origin(self, origin):
return True
def open(self):
print("WebSocket opened")
#self.write_message(
# json.dumps({
# 'n_images': len(self.images),
# 'image': self.__get_base64_image(self.images[0])
# }
#))
#self.write_message(json.dumps({'n_images': len(self.images)}))
def __return_error(self, message):
self.write_message(json.dumps(
{'error': message}
))
def handle_return_reconstruction(self, message):
image_index = message['reconstruction_index']
filename = self.images[image_index]
image = self.__get_base64_image(filename)
self.write_message(json.dumps({'reconstructed': image}))
def handle_return_image(self, message):
filename = message['filename']
#filename = self.images[image_index]
image = self.__get_base64_image(filename)
self.write_message(json.dumps({'image': image}))
def on_message(self, message):
message = json.loads(message)
for m in message.keys():
try:
handler = getattr(self, self.handlers[m])
except (AttributeError, KeyError) as e:
msg = 'no handler for {}'.format(m)
print(msg, e)
self.__return_error(msg)
handler(message)
def on_close(self):
print("WebSocket closed")
class ApiHandler(web.RequestHandler):
def __init__(self, *args, **kwargs):
self.images = glob('{}/*.jpg'.format(FACE_DB))
self.asf_files = glob('{}/*.asf'.format(FACE_DB))
web.RequestHandler.__init__(self, *args, **kwargs)
def set_default_headers(self):
self.set_header("Access-Control-Allow-Origin", "*")
self.set_header("Access-Control-Allow-Headers", "x-requested-with")
self.set_header('Access-Control-Allow-Methods', 'POST, GET, OPTIONS')
self.set_header("Content-Type", 'application/vnd.api+json')
class FaceHandler(ApiHandler):
@web.asynchronous
def get(self, *args):
data = []
for id, filename in enumerate(self.asf_files):
Points = imm.IMMPoints(filename)
data.append({
'type': 'faces',
'id': id,
'attributes': {
'filename': filename,
'shape': Points.get_scaled_points(shape=(480, 640)).tolist()
}
})
result = {
'data': data
}
self.write(json.dumps(result))
self.finish()
app = web.Application([
(r'/reconstruction[\/0-9]?', ImageWebSocketHandler),
(r'/api/v1/faces[\/0-9]?', FaceHandler),
])
if __name__ == '__main__':
app.listen(8888)
ioloop.IOLoop.instance().start()
import JSONAPIAdapter from 'ember-data/adapters/json-api';
export default JSONAPIAdapter.extend({
host: 'http://localhost:8888',
namespace: 'api/v1'
});
import Ember from 'ember';
import THREE from 'npm:three';
import dat from 'npm:dat-gui';
export default Ember.Component.extend({
store: Ember.inject.service(),
willRender() {
if (this.scene) {
return;
}
var scene = new THREE.Scene();
var gui = new dat.GUI();
var camera = new THREE.PerspectiveCamera(
75, window.innerWidth / window.innerHeight, 0.1, 1000
);
scene.add(camera);
var renderer = new THREE.WebGLRenderer();
this.set('scene', scene);
this.set('camera', camera);
this.set('renderer', renderer);
this.set('gui', gui);
},
/**
* Wait for elements to be inserted, else we can not find
* the threejs container.
* TODO: try to not use appendChild
*/
loadGui: Ember.on('didInsertElement', function() {
//var container = document.getElementById('threejs-container');
//container.appendChild(this.get('renderer').domElement);
this.addSliders();
}),
addSliders() {
var self = this;
var gui = this.get('gui');
var obj = {
name: "Image filename",
index: 0
};
var components = {
name: "Components",
components: 0
};
var imagesSlider = gui.add(obj, "index").min(0).max(
this.n_images - 1).step(1);
gui.add(components, "components").min(0).max(this.n_images - 1).step(1);
imagesSlider.onChange(function(newValue) {
self.set('image_index', newValue);
});
}
});
...@@ -7,7 +7,14 @@ export default Ember.Controller.extend({ ...@@ -7,7 +7,14 @@ export default Ember.Controller.extend({
websockets: inject.service(), websockets: inject.service(),
socketRef: null, socketRef: null,
image: null, image: null,
n_images: 0, reconstructed: null,
n_images: null,
n_components: null,
image_index: 0,
imageIndexChanged: Ember.observer('image_index', function() {
this.send('getImage');
}),
init() { init() {
const socket = get(this, 'websockets').socketFor('ws://localhost:8888/reconstruction'); const socket = get(this, 'websockets').socketFor('ws://localhost:8888/reconstruction');
...@@ -17,6 +24,15 @@ export default Ember.Controller.extend({ ...@@ -17,6 +24,15 @@ 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.get('store').findAll('face').
then(function(faces) {
var face = faces.objectAt(0);
this.send('getImage', face);
}, function(reason) {
console.log('fail');
console.log(reason);
});
}, },
willDestroyElement() { willDestroyElement() {
...@@ -31,18 +47,33 @@ export default Ember.Controller.extend({ ...@@ -31,18 +47,33 @@ export default Ember.Controller.extend({
}, },
openHandler(event) { openHandler(event) {
//var message = JSON.parse(event.data);
//this.set('n_images', message.n_images);
console.log(event); console.log(event);
console.log(event.data.n_images);
console.log(`On open event has been called: ${event}`); console.log(`On open event has been called: ${event}`);
}, },
messageHandler(event) { messageHandler(event) {
//var message = JSON.parse(event.data); var message = JSON.parse(event.data);
//this.set('image', message.image);
if (message.n_images) {
this.set('n_images', message.n_images);
}
if (message.image) {
this.set('image', message.image);
}
//console.log(`Message: ${'received image'}`); if (message.reconstructed) {
this.set('reconstructed', message.reconstructed);
}
if (message.error) {
console.log(message.error);
}
//this.get('store').createRecord('face', {
// filename: 'Derp',
// shape: [1, 2, 3, 4, 5]
//});
}, },
closeHandler(event) { closeHandler(event) {
...@@ -50,11 +81,22 @@ export default Ember.Controller.extend({ ...@@ -50,11 +81,22 @@ export default Ember.Controller.extend({
}, },
actions: { actions: {
get_image() { getImage(faceModel) {
var filename = faceModel.get('filename');
const socket = this.get('socketRef'); const socket = this.get('socketRef');
console.log(socket);
socket.send( socket.send(
JSON.stringify({image_index: 1} JSON.stringify({filename: filename})
)); );
}, },
getReconstruction() {
const socket = this.get('socketRef');
socket.send(
JSON.stringify({reconstruction_index: this.get('image_index')}
));
}
} }
}); });
...@@ -12,14 +12,21 @@ ...@@ -12,14 +12,21 @@
<link rel="stylesheet" href="assets/vendor.css"> <link rel="stylesheet" href="assets/vendor.css">
<link rel="stylesheet" href="assets/viewer.css"> <link rel="stylesheet" href="assets/viewer.css">
<link href="https://npmcdn.com/basscss@7.1.1/css/basscss.min.css"
rel="stylesheet">
{{content-for "head-footer"}} {{content-for "head-footer"}}
</head> </head>
<body> <body>
{{content-for "body"}} <div class="clearfix">
{{content-for "body"}}
</div>
<script src="assets/vendor.js"></script> <script src="assets/vendor.js"></script>
<script src="assets/viewer.js"></script> <script src="assets/viewer.js"></script>
{{content-for "body-footer"}} <div class="clearfix">
{{content-for "body-footer"}}
</div>
</body> </body>
</html> </html>
import Model from 'ember-data/model';
import attr from 'ember-data/attr';
import { hasMany } from 'ember-data/relationships';
export default Model.extend({
type: attr('string'),
maxComponents: attr('int'),
nEigenvalues: attr('int'),
faces: hasMany('face')
});
import Model from 'ember-data/model';
import attr from 'ember-data/attr';
import { belongsTo } from 'ember-data/relationships';
export default Model.extend({
filename: attr('string'),
shape: attr(),
faceModel: belongsTo('face-model')
});
import Ember from 'ember';
export default Ember.Route.extend({
});
canvas { width: 100%; height: 100% }
<h1>Reconstruction</h1> <h1>Reconstruction</h1>
<h3><button {{action "get_image"}}>{{title}}</button></h3>
<h2>{{n_images}}</h2>
{{#if image }} <div class="container">
<img src='data:image/jpg;base64,{{image}}' alt='missing image'> <div class="clearfix">
{{/if}} <div class="col col-6">
{{#if image }}
<img src='data:image/jpg;base64,{{image}}' alt='missing image'>
{{/if}}
</div>
<div class="col col-6">
{{#if reconstructed }}
<img src='data:image/jpg;base64,{{reconstructed}}' alt='missing image'>
{{/if}}
</div>
</div>
<div class="col col-12 px2">
{{#if n_images }}
{{
three-js-reconstruction
n_images=n_images
image_index=image_index
n_components=n_components
}}
{{/if}}
</div>
</div>
<div class="clearfix">
<div class="mx-auto col-2">
<button class="btn btn-primary" {{action "getReconstruction"}}>
Show reconstruction
</button>
</div>
</div>
...@@ -7,6 +7,7 @@ module.exports = function(defaults) { ...@@ -7,6 +7,7 @@ module.exports = function(defaults) {
// Add options here // Add options here
}); });
// bower compoenents
app.import('bower_components/basscss/modules/align/index.css'); app.import('bower_components/basscss/modules/align/index.css');
app.import('bower_components/basscss/modules/border/index.css'); app.import('bower_components/basscss/modules/border/index.css');
app.import('bower_components/basscss/modules/flexbox/index.css'); app.import('bower_components/basscss/modules/flexbox/index.css');
...@@ -19,6 +20,9 @@ module.exports = function(defaults) { ...@@ -19,6 +20,9 @@ module.exports = function(defaults) {
app.import('bower_components/basscss/modules/type-scale/index.css'); app.import('bower_components/basscss/modules/type-scale/index.css');
app.import('bower_components/basscss/modules/typography/index.css'); app.import('bower_components/basscss/modules/typography/index.css');
// npm modules
//app.import('node_modules/basscss-responsive-margin/css/responsive-margin.css');
// Use `app.import` to add additional libraries to the generated // Use `app.import` to add additional libraries to the generated
// output files. // output files.
// //
......
...@@ -19,11 +19,14 @@ ...@@ -19,11 +19,14 @@
"author": "", "author": "",
"license": "MIT", "license": "MIT",
"devDependencies": { "devDependencies": {
"basscss-responsive-margin": "^1.1.0",
"broccoli-asset-rev": "^2.4.2", "broccoli-asset-rev": "^2.4.2",
"ember-ajax": "^2.0.1", "ember-ajax": "^2.0.1",
"ember-browserify": "1.1.10",
"ember-cli": "2.6.2", "ember-cli": "2.6.2",
"ember-cli-app-version": "^1.0.0", "ember-cli-app-version": "^1.0.0",
"ember-cli-babel": "^5.1.6", "ember-cli-babel": "^5.1.6",
"ember-cli-cors": "0.0.2",
"ember-cli-dependency-checker": "^1.2.0", "ember-cli-dependency-checker": "^1.2.0",
"ember-cli-htmlbars": "^1.0.3", "ember-cli-htmlbars": "^1.0.3",
"ember-cli-htmlbars-inline-precompile": "^0.3.1", "ember-cli-htmlbars-inline-precompile": "^0.3.1",
...@@ -41,6 +44,6 @@ ...@@ -41,6 +44,6 @@
"ember-welcome-page": "^1.0.1", "ember-welcome-page": "^1.0.1",
"loader.js": "^4.0.1", "loader.js": "^4.0.1",
"mock-socket": "3.0.1", "mock-socket": "3.0.1",
"three": "0.78.0" "three": "^0.78.0"
} }
} }
import { moduleForComponent, test } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';
moduleForComponent('three-js-reconstruction', 'Integration | Component | three js reconstruction', {
integration: true
});
test('it renders', function(assert) {
// Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.on('myAction', function(val) { ... });
this.render(hbs`{{three-js-reconstruction}}`);
assert.equal(this.$().text().trim(), '');
// Template block usage:
this.render(hbs`
{{#three-js-reconstruction}}
template block text
{{/three-js-reconstruction}}
`);
assert.equal(this.$().text().trim(), 'template block text');
});
import { moduleForModel, test } from 'ember-qunit';
moduleForModel('face-model', 'Unit | Model | face model', {
// Specify the other units that are required for this test.
needs: []
});
test('it exists', function(assert) {
let model = this.subject();
// let store = this.store();
assert.ok(!!model);
});
import { moduleForModel, test } from 'ember-qunit';
moduleForModel('face', 'Unit | Model | face', {
// Specify the other units that are required for this test.
needs: []
});
test('it exists', function(assert) {
let model = this.subject();
// let store = this.store();
assert.ok(!!model);
});
import { moduleFor, test } from 'ember-qunit';
moduleFor('route:faces', 'Unit | Route | faces', {
// Specify the other units that are required for this test.
// needs: ['controller:foo']
});
test('it exists', function(assert) {
let route = this.subject();
assert.ok(route);
});
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