From 76f36c6c5dafe754b066903b1ee8ecdd1b92dcab Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Sun, 16 Dec 2018 20:01:23 +0100 Subject: faceSearch client --- site/assets/css/applets.css | 45 +++++++++++++++++++++++++++++++++++++++++++++ site/assets/css/css.css | 16 ++++++++++++---- 2 files changed, 57 insertions(+), 4 deletions(-) (limited to 'site/assets/css') diff --git a/site/assets/css/applets.css b/site/assets/css/applets.css index fc71ecc4..2b531908 100644 --- a/site/assets/css/applets.css +++ b/site/assets/css/applets.css @@ -1,7 +1,52 @@ .applet { margin-bottom: 40px; + transition: opacity 0.2s cubic-bezier(0,0,1,1); + opacity: 0; } .applet.map { width: 100vw; height: 50vh; +} +.applet.loaded { + opacity: 1; +} + +.row { + display: flex; + flex-direction: row; + justify-content: flex-start; +} + +.query h2 { + margin-top: 0; padding-top: 0; +} +.cta { + padding-left: 20px; +} +.uploadContainer > div { + position: relative; + width: 300px; + height: 300px; + display: flex; + align-items: center; + justify-content: center; + background: #333; + border: 3px dashed #fff; + border-radius: 10px; + opacity: 0.3; + transition: opacity 0.2s cubic-bezier(0,0,1,1); +} +.uploadContainer.active, +.desktop .uploadContainer > div:hover { + opacity: 1; +} +.uploadContainer input { + position: absolute; + top: 0; left: 0; + width: 100%; height: 100%; + opacity: 0; + cursor: pointer; +} +.uploadContainer img { + max-width: 40px; } \ No newline at end of file diff --git a/site/assets/css/css.css b/site/assets/css/css.css index b6742cdc..4f2d7c6e 100644 --- a/site/assets/css/css.css +++ b/site/assets/css/css.css @@ -131,23 +131,31 @@ h1 { padding: 0; transition: color 0.2s cubic-bezier(0,0,1,1); } -h2, h3 { +h2 { + color: #ddd; + font-weight: 300; + font-size: 18pt; + margin: 20px 0 10px; + padding: 0; + transition: color 0.2s cubic-bezier(0,0,1,1); +} +h3 { margin: 0 0 20px 0; padding: 0; font-size: 11pt; font-weight: 500; transition: color 0.2s cubic-bezier(0,0,1,1); } -.content h2 a { +.content h3 a { color: #888; text-decoration: none; } -.desktop .content h2 a:hover { +.desktop .content h3 a:hover { color: #fff; text-decoration: underline; } -th, .gray, h2, h3 { +th, .gray, h3 { font-family: 'Roboto Mono', monospace; font-weight: 400; text-transform: uppercase; -- cgit v1.2.3-70-g09d2 From f968f0e4bcc6e195eb293c4e2b965e8879075d8b Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Sun, 16 Dec 2018 22:35:49 +0100 Subject: ok --- client/index.js | 8 ++++++-- client/tables.js | 2 +- site/assets/css/applets.css | 7 ++++++- webpack.config.prod.js | 2 +- 4 files changed, 14 insertions(+), 5 deletions(-) (limited to 'site/assets/css') diff --git a/client/index.js b/client/index.js index 90fc22e1..2beb5526 100644 --- a/client/index.js +++ b/client/index.js @@ -69,7 +69,8 @@ function runApplets() { dataset = null url = opt } else if (opt.indexOf('assets') === 0) { - url = 'https://nyc3.digitaloceanspaces.com/megapixels/v1' + window.location.pathname + opt + let pathname = window.location.pathname.replace('index.html', '') + url = 'https://nyc3.digitaloceanspaces.com/megapixels/v1' + pathname + opt dataset = null // console.log(url) } else { @@ -80,7 +81,10 @@ function runApplets() { if (!dataset && !url) { const path = window.location.pathname.split('/').filter(s => !!s) if (path.length) { - dataset = path[path.length - 1] + dataset = path.pop() + if (dataset === 'index.html') { + dataset = path.pop() + } // console.log('dataset from path:', dataset) } else { console.log('couldnt determine citations dataset') diff --git a/client/tables.js b/client/tables.js index b2b3d39c..2a2699f9 100644 --- a/client/tables.js +++ b/client/tables.js @@ -68,7 +68,7 @@ export default function append(el, payload) { table.setData(data) el.classList.add('loaded') } catch (e) { - console.error("error parsing json:", payload.url) + console.error("error making json:", payload.url) console.error(e) // console.log(text) } diff --git a/site/assets/css/applets.css b/site/assets/css/applets.css index 2b531908..54508f44 100644 --- a/site/assets/css/applets.css +++ b/site/assets/css/applets.css @@ -22,6 +22,11 @@ } .cta { padding-left: 20px; + font-size: 11pt; +} +.cta ol { + margin: 0; + padding: 0 0 20px 20px; } .uploadContainer > div { position: relative; @@ -49,4 +54,4 @@ } .uploadContainer img { max-width: 40px; -} \ No newline at end of file +} diff --git a/webpack.config.prod.js b/webpack.config.prod.js index 69bc63ec..b9d3f411 100644 --- a/webpack.config.prod.js +++ b/webpack.config.prod.js @@ -10,7 +10,7 @@ module.exports = { main: './client/index.js', }, output: { - path: path.resolve(__dirname, 'dist'), + path: path.resolve(__dirname, 'site/assets/js/dist'), filename: 'index.js', }, plugins: [ -- cgit v1.2.3-70-g09d2 From d7df4ee5b9e24a9cdf2bf4d1bc2e73e97352afdc Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 17 Dec 2018 01:02:40 +0100 Subject: searches execute --- client/actions.js | 6 +----- client/faceSearch/faceSearch.result.js | 35 ++++++++++++++++++++++++++++++---- megapixels/app/models/sql_factory.py | 5 +++-- megapixels/app/server/api.py | 9 +++++---- site/assets/css/applets.css | 17 +++++++++++++++++ 5 files changed, 57 insertions(+), 15 deletions(-) (limited to 'site/assets/css') diff --git a/client/actions.js b/client/actions.js index 37b4eb2e..bb011838 100644 --- a/client/actions.js +++ b/client/actions.js @@ -1,9 +1,5 @@ import * as faceSearch from './faceSearch/faceSearch.actions' -// import * as review from './review/review.actions' -// import * as metadata from './metadata/metadata.actions' export { - // search, - // review, - // metadata, + faceSearch } diff --git a/client/faceSearch/faceSearch.result.js b/client/faceSearch/faceSearch.result.js index 844a5a70..2b223a46 100644 --- a/client/faceSearch/faceSearch.result.js +++ b/client/faceSearch/faceSearch.result.js @@ -1,17 +1,44 @@ import React, { Component } from 'react' import { bindActionCreators } from 'redux' import { connect } from 'react-redux' +import { courtesyS } from '../util' import * as actions from './faceSearch.actions' class FaceSearchResult extends Component { - componentDidMount() { - } - render() { + const { dataset } = this.props.payload + const { distances, results } = this.props.result + if (!results) { + return ( +
+ ) + } + if (!this.props.result.results.length) { + return ( +
No results
+ ) + } + const els = results.map((result, i) => { + const distance = distances[i] + const { uuid } = result.uuid + const { fullname, gender, description, images } = result.identity + return ( +
+ + {fullname} {'('}{gender}{')'}
+ {description}
+ {courtesyS(images, 'image')}
+ {distance} +
+ ) + }) + return (
- Result here +
+ {els} +
) } diff --git a/megapixels/app/models/sql_factory.py b/megapixels/app/models/sql_factory.py index 0f7e73a0..9a44941b 100644 --- a/megapixels/app/models/sql_factory.py +++ b/megapixels/app/models/sql_factory.py @@ -83,8 +83,8 @@ class SqlDataset: def get_identity(self, id): table = self.get_table('identity_meta') - identity = table.query.filter(table.image_id >= id).order_by(table.image_id.asc()).first().toJSON() - print(identity) + # id += 1 + identity = table.query.filter(table.image_id <= id).order_by(table.image_id.desc()).first().toJSON() return { 'uuid': self.select('uuids', id), 'identity': identity, @@ -100,6 +100,7 @@ class SqlDataset: # for obj in session.query(table).filter_by(id=id): print(table) obj = session.query(table).filter(table.id == id).first() + session.close() return obj.toJSON() def get_table(self, type): diff --git a/megapixels/app/server/api.py b/megapixels/app/server/api.py index 36563910..2f78ecd3 100644 --- a/megapixels/app/server/api.py +++ b/megapixels/app/server/api.py @@ -70,7 +70,7 @@ def upload(name): query = np.array([ vec ]).astype('float32') # query FAISS! - distances, indexes = faiss_dataset.search(query, 5) + distances, indexes = faiss_dataset.search(query, 10) if len(indexes) == 0: print("weird, no results!") @@ -85,6 +85,7 @@ def upload(name): return [] lookup = {} + ids = [i+1 for i in indexes] for _d, _i in zip(distances, indexes): lookup[_i+1] = _d @@ -97,13 +98,13 @@ def upload(name): query = { 'timing': time.time() - start, } - results = [ dataset.get_identity(index) for index in indexes ] + results = [ dataset.get_identity(id) for id in ids ] print(results) return jsonify({ 'results': results, - # 'distances': distances.tolist(), - # 'indexes': indexes.tolist(), + 'distances': distances.tolist(), + 'indexes': indexes.tolist(), }) @api.route('/dataset//name', methods=['GET']) diff --git a/site/assets/css/applets.css b/site/assets/css/applets.css index 54508f44..a01703d5 100644 --- a/site/assets/css/applets.css +++ b/site/assets/css/applets.css @@ -17,6 +17,23 @@ justify-content: flex-start; } +.results { + display: flex; + flex-direction: row; + flex-wrap: wrap; +} +.results > div { + width: 200px; + margin-left: 20px; + margin-bottom: 40px; + font-size: 8pt; +} +.results > div img { + margin-bottom: 4px; +} +.results > div:nth-child(3n+1) { + margin-left: 0; +} .query h2 { margin-top: 0; padding-top: 0; } -- cgit v1.2.3-70-g09d2 From a2d4ad0499e4ee4f3f528b2ed7bc162d61026d09 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 17 Dec 2018 01:13:32 +0100 Subject: build --- client/faceSearch/faceSearch.result.js | 14 +++++++++++++- megapixels/app/server/api.py | 14 ++++++++++---- site/assets/css/applets.css | 3 +++ 3 files changed, 26 insertions(+), 5 deletions(-) (limited to 'site/assets/css') diff --git a/client/faceSearch/faceSearch.result.js b/client/faceSearch/faceSearch.result.js index 2b223a46..1882def0 100644 --- a/client/faceSearch/faceSearch.result.js +++ b/client/faceSearch/faceSearch.result.js @@ -5,10 +5,22 @@ import { courtesyS } from '../util' import * as actions from './faceSearch.actions' +const errors = { + 'bbox': "Sorry, we couldn't find a face in that image. Please choose an image where the face is large and clear.", + 'nomatch': "We didn't find a match.", + 'default': "There was an error!", +} + class FaceSearchResult extends Component { render() { const { dataset } = this.props.payload - const { distances, results } = this.props.result + const { distances, results, error } = this.props.result + if (error) { + let errorMessage = errors[error.message] || errors.default + return ( +
{errorMessage}
+ ) + } if (!results) { return (
diff --git a/megapixels/app/server/api.py b/megapixels/app/server/api.py index 2f78ecd3..bc60118c 100644 --- a/megapixels/app/server/api.py +++ b/megapixels/app/server/api.py @@ -58,6 +58,10 @@ def upload(name): # get detection as BBox object bboxes = detector.detect(im_np, largest=True) + if not len(bboxes): + return jsonify({ + 'error': 'bbox' + }) bbox = bboxes[0] dim = im_np.shape[:2][::-1] bbox = bbox.to_dim(dim) # convert back to real dimensions @@ -73,16 +77,18 @@ def upload(name): distances, indexes = faiss_dataset.search(query, 10) if len(indexes) == 0: - print("weird, no results!") - return [] + return jsonify({ + 'error': 'nomatch' + }) # get the results for this single query... distances = distances[0] indexes = indexes[0] if len(indexes) == 0: - print("no results!") - return [] + return jsonify({ + 'error': 'nomatch' + }) lookup = {} ids = [i+1 for i in indexes] diff --git a/site/assets/css/applets.css b/site/assets/css/applets.css index a01703d5..ecba518c 100644 --- a/site/assets/css/applets.css +++ b/site/assets/css/applets.css @@ -30,6 +30,9 @@ } .results > div img { margin-bottom: 4px; + width: 200px; + height: 200px; + background: rgba(255,255,255,0.05); } .results > div:nth-child(3n+1) { margin-left: 0; -- cgit v1.2.3-70-g09d2