From 7eb2b4509802388f2fe980a3477dad006cf81016 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 17 Dec 2018 17:47:37 +0100 Subject: fix map --- site/assets/css/css.css | 1 + 1 file changed, 1 insertion(+) (limited to 'site') diff --git a/site/assets/css/css.css b/site/assets/css/css.css index 4f2d7c6e..003ac4a3 100644 --- a/site/assets/css/css.css +++ b/site/assets/css/css.css @@ -27,6 +27,7 @@ header { left: 0; width: 100%; height: 70px; + z-index: 1; background: #1e1e1e; display: flex; flex-direction: row; -- cgit v1.2.3-70-g09d2 From 1c82f7ec6a603978322e16470547731e92e947c6 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 17 Dec 2018 20:15:41 +0100 Subject: adding verbiage and timing --- client/faceSearch/faceSearch.result.js | 52 +++++++++++++++++++++++----- megapixels/app/models/sql_factory.py | 2 +- megapixels/app/server/api.py | 62 ++++++++++++++++++++-------------- megapixels/app/site/parser.py | 2 +- site/assets/css/applets.css | 5 +++ site/public/test/index.html | 16 ++++----- site/public/test/style/index.html | 10 ++++-- 7 files changed, 104 insertions(+), 45 deletions(-) (limited to 'site') diff --git a/client/faceSearch/faceSearch.result.js b/client/faceSearch/faceSearch.result.js index 1882def0..bc7831d9 100644 --- a/client/faceSearch/faceSearch.result.js +++ b/client/faceSearch/faceSearch.result.js @@ -4,31 +4,59 @@ import { connect } from 'react-redux' import { courtesyS } from '../util' import * as actions from './faceSearch.actions' +import { Loader } from '../common' 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!", + bbox: ( +
+

No face found

+ {"Sorry, we didn't detect a face in that image. "} + {"Please choose an image where the face is large and clear."} +
+ ), + nomatch: ( +
+

{"You're clear"}

+ {"No images in this dataset match your face. We show only matches above 70% probability."} +
+ ), + error: ( +
+

{"No matches found"}

+ {"Sorry, an error occured."} +
+ ), } class FaceSearchResult extends Component { render() { const { dataset } = this.props.payload - const { distances, results, error } = this.props.result + const { query, distances, results, loading, error } = this.props.result + if (loading) { + return ( +
+
+
+

Searching...

+
+
+ ) + } if (error) { - let errorMessage = errors[error.message] || errors.default + console.log(error) + let errorMessage = errors[error] || errors.error return (
{errorMessage}
) } if (!results) { return ( -
+
{errors.nomatch}
) } if (!this.props.result.results.length) { return ( -
No results
+
{errors.nomatch}
) } const els = results.map((result, i) => { @@ -48,7 +76,15 @@ class FaceSearchResult extends Component { return (
-
+
+

Did we find you?

+ {'These faces matched images in the '} + {dataset} + {' dataset with over 70% probability.'} +
+ Query took {query.timing.toFixed(2)} seconds +
+
{els}
diff --git a/megapixels/app/models/sql_factory.py b/megapixels/app/models/sql_factory.py index 9a44941b..02b722df 100644 --- a/megapixels/app/models/sql_factory.py +++ b/megapixels/app/models/sql_factory.py @@ -98,7 +98,7 @@ class SqlDataset: return None session = Session() # for obj in session.query(table).filter_by(id=id): - print(table) + # print(table) obj = session.query(table).filter(table.id == id).first() session.close() return obj.toJSON() diff --git a/megapixels/app/server/api.py b/megapixels/app/server/api.py index bc60118c..b3447eb1 100644 --- a/megapixels/app/server/api.py +++ b/megapixels/app/server/api.py @@ -15,24 +15,32 @@ from app.utils.im_utils import pil2np sanitize_re = re.compile('[\W]+') valid_exts = ['.gif', '.jpg', '.jpeg', '.png'] +LIMIT = 9 +THRESHOLD = 0.3 + api = Blueprint('api', __name__) faiss_datasets = load_faiss_databases() @api.route('/') def index(): + """List the datasets and their fields""" return jsonify({ 'datasets': list_datasets() }) + @api.route('/dataset/') def show(name): + """Show the data that a dataset will return""" dataset = get_dataset(name) if dataset: return jsonify(dataset.describe()) else: return jsonify({ 'status': 404 }) + @api.route('/dataset//face/', methods=['POST']) def upload(name): + """Query an image against FAISS and return the matching identities""" start = time.time() dataset = get_dataset(name) if name not in faiss_datasets: @@ -52,31 +60,39 @@ def upload(name): im = Image.open(file.stream).convert('RGB') im_np = pil2np(im) - + # Face detection detector = face_detector.DetectorDLIBHOG() # get detection as BBox object bboxes = detector.detect(im_np, largest=True) - if not len(bboxes): + if not bboxes or not len(bboxes): return jsonify({ 'error': 'bbox' }) bbox = bboxes[0] + if not bbox: + return jsonify({ + 'error': 'bbox' + }) + dim = im_np.shape[:2][::-1] bbox = bbox.to_dim(dim) # convert back to real dimensions + print("got bbox") + if not bbox: + return jsonify({ + 'error': 'bbox' + }) - # face recognition/vector + # extract 128-D vector recognition = face_recognition.RecognitionDLIB(gpu=-1) vec = recognition.vec(im_np, bbox) - - # print(vec) query = np.array([ vec ]).astype('float32') - # query FAISS! - distances, indexes = faiss_dataset.search(query, 10) + # query FAISS + distances, indexes = faiss_dataset.search(query, LIMIT) - if len(indexes) == 0: + if len(indexes) == 0 or len(indexes[0]) == 0: return jsonify({ 'error': 'nomatch' }) @@ -85,36 +101,32 @@ def upload(name): distances = distances[0] indexes = indexes[0] - if len(indexes) == 0: - return jsonify({ - 'error': 'nomatch' - }) - - lookup = {} - ids = [i+1 for i in indexes] + dists = [] + ids = [] for _d, _i in zip(distances, indexes): - lookup[_i+1] = _d + if _d <= THRESHOLD: + dists.append(round(float(_d), 2)) + ids.append(_i+1) - print(distances) - print(indexes) + results = [ dataset.get_identity(_i) for _i in ids ] - # with the result we have an ID - # query the sql dataset for the UUID etc here + print(distances) + print(ids) query = { - 'timing': time.time() - start, + 'timing': round(time.time() - start, 3), } - results = [ dataset.get_identity(id) for id in ids ] - print(results) return jsonify({ + 'query': query, 'results': results, - 'distances': distances.tolist(), - 'indexes': indexes.tolist(), + 'distances': dists, }) + @api.route('/dataset//name', methods=['GET']) def name_lookup(dataset): + """Find a name in the dataset""" start = time.time() dataset = get_dataset(name) diff --git a/megapixels/app/site/parser.py b/megapixels/app/site/parser.py index ecfae0cb..b3d3a8c2 100644 --- a/megapixels/app/site/parser.py +++ b/megapixels/app/site/parser.py @@ -64,7 +64,7 @@ def format_applet(section, s3_path): else: command = payload[0] opt = None - if command == 'python': + if command == 'python' or command == 'javascript' or command == 'code': return format_section([ section ], s3_path) applet['command'] = command diff --git a/site/assets/css/applets.css b/site/assets/css/applets.css index ecba518c..edd5b709 100644 --- a/site/assets/css/applets.css +++ b/site/assets/css/applets.css @@ -18,6 +18,8 @@ } .results { + margin-top: 10px; + padding-bottom: 10px; display: flex; flex-direction: row; flex-wrap: wrap; @@ -27,6 +29,9 @@ margin-left: 20px; margin-bottom: 40px; font-size: 8pt; + background: #000; + padding: 5px; + font-weight: 500; } .results > div img { margin-bottom: 4px; diff --git a/site/public/test/index.html b/site/public/test/index.html index b4d16036..41f8eda5 100644 --- a/site/public/test/index.html +++ b/site/public/test/index.html @@ -30,14 +30,14 @@

Megapixels UI Tests

diff --git a/site/public/test/style/index.html b/site/public/test/style/index.html index 6d99a236..ab13a589 100644 --- a/site/public/test/style/index.html +++ b/site/public/test/style/index.html @@ -54,10 +54,16 @@
Person 3. Let me tell you about Person 3.  This person has a very long description with text which wraps like crazy
Person 3. Let me tell you about Person 3. This person has a very long description with text which wraps like crazy

est, qui dolorem ipsum, quia dolor sit amet consectetur adipisci[ng] velit, sed quia non-numquam [do] eius modi tempora inci[di]dunt, ut labore et dolore magnam aliquam quaerat voluptatem.

ThisĀ image is extremely wide and the text beneath it will wrap but thats fine because it can also contain <a href="https://example.com/">hyperlinks</a>! Yes, you read that right—hyperlinks! Lorem ipsum dolor sit amet ad volotesque sic hoc ad nauseam
ThisĀ image is extremely wide and the text beneath it will wrap but that's fine because it can also contain hyperlinks! Yes, you read that right—hyperlinks! Lorem ipsum dolor sit amet ad volotesque sic hoc ad nauseam

Inline code has back-ticks around it.

-
s = "Python syntax highlighting"
+
var s = "JavaScript syntax highlighting";
+alert(s);
+
+
s = "Python syntax highlighting"
 print(s)
 
-
tag."]}'>

Horizontal rule

+
Generic code block. Note that code blocks that are not so marked will not appear.
+But let's throw in a <b>tag</b>.
+
+

Horizontal rule


Citations below here

-- cgit v1.2.3-70-g09d2 From 7b8e6f9a7d3eb36b72b53d5e754b9c7916b98ed7 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Tue, 18 Dec 2018 01:03:10 +0100 Subject: namesearchg --- client/actions.js | 4 +- client/applet.js | 5 +- client/faceSearch/faceSearch.container.js | 2 +- client/faceSearch/faceSearch.result.js | 16 +++++- client/index.js | 1 - client/nameSearch/index.js | 5 ++ client/nameSearch/nameSearch.actions.js | 52 ++++++++++++++++++ client/nameSearch/nameSearch.container.js | 24 +++++++++ client/nameSearch/nameSearch.query.js | 48 +++++++++++++++++ client/nameSearch/nameSearch.reducer.js | 32 +++++++++++ client/nameSearch/nameSearch.result.js | 88 +++++++++++++++++++++++++++++++ client/store.js | 8 +-- client/tables.js | 4 ++ client/types.js | 3 ++ megapixels/app/models/sql_factory.py | 14 +++++ megapixels/app/server/api.py | 41 +++++++------- megapixels/app/settings/app_cfg.py | 2 +- site/assets/css/applets.css | 24 +++++++-- 18 files changed, 339 insertions(+), 34 deletions(-) create mode 100644 client/nameSearch/index.js create mode 100644 client/nameSearch/nameSearch.actions.js create mode 100644 client/nameSearch/nameSearch.container.js create mode 100644 client/nameSearch/nameSearch.query.js create mode 100644 client/nameSearch/nameSearch.reducer.js create mode 100644 client/nameSearch/nameSearch.result.js (limited to 'site') diff --git a/client/actions.js b/client/actions.js index bb011838..2be8229d 100644 --- a/client/actions.js +++ b/client/actions.js @@ -1,5 +1,7 @@ import * as faceSearch from './faceSearch/faceSearch.actions' +import * as nameSearch from './nameSearch/nameSearch.actions' export { - faceSearch + faceSearch, + nameSearch, } diff --git a/client/applet.js b/client/applet.js index 4d2a8e6c..80d40657 100644 --- a/client/applet.js +++ b/client/applet.js @@ -1,13 +1,16 @@ import React, { Component } from 'react' import { Container as FaceSearchContainer } from './faceSearch' +import { Container as NameSearchContainer } from './nameSearch' export default class Applet extends Component { render() { - console.log(this.props) + // console.log(this.props) switch (this.props.payload.cmd) { case 'face_search': return + case 'name_search': + return default: return
{'Megapixels'}
} diff --git a/client/faceSearch/faceSearch.container.js b/client/faceSearch/faceSearch.container.js index f96961db..94c6eb9f 100644 --- a/client/faceSearch/faceSearch.container.js +++ b/client/faceSearch/faceSearch.container.js @@ -10,7 +10,7 @@ import FaceSearchResult from './faceSearch.result' class FaceSearchContainer extends Component { render() { const { payload } = this.props - console.log(payload) + // console.log(payload) return (
diff --git a/client/faceSearch/faceSearch.result.js b/client/faceSearch/faceSearch.result.js index d63f3265..936bc8d2 100644 --- a/client/faceSearch/faceSearch.result.js +++ b/client/faceSearch/faceSearch.result.js @@ -32,6 +32,7 @@ class FaceSearchResult extends Component { render() { const { dataset } = this.props.payload const { query, distances, results, loading, error } = this.props.result + console.log(this.props.result) if (loading) { return (
@@ -43,7 +44,7 @@ class FaceSearchResult extends Component { ) } if (error) { - console.log(error) + // console.log(error) let errorMessage = errors[error] || errors.error return (
{errorMessage}
@@ -60,10 +61,21 @@ class FaceSearchResult extends Component { const els = results.map((result, i) => { const distance = distances[i] const { uuid } = result.uuid + const { x, y, w, h } = result.roi const { fullname, gender, description, images } = result.identity + const bbox = { + left: (100 * x) + '%', + top: (100 * y) + '%', + width: (100 * w) + '%', + height: (100 * h) + '%', + } + // console.log(bbox) return (
- +
+ +
+
{fullname} {'('}{gender}{')'}
{description}
{courtesyS(images, 'image')}{' in dataset'}
diff --git a/client/index.js b/client/index.js index 2beb5526..93341a77 100644 --- a/client/index.js +++ b/client/index.js @@ -38,7 +38,6 @@ function appendApplets(applets) { el.classList.add('loaded') break default: - console.log('react', el, payload) appendReactApplet(el, payload) el.classList.add('loaded') break diff --git a/client/nameSearch/index.js b/client/nameSearch/index.js new file mode 100644 index 00000000..8c6475e4 --- /dev/null +++ b/client/nameSearch/index.js @@ -0,0 +1,5 @@ +import Container from './nameSearch.container' + +export { + Container, +} diff --git a/client/nameSearch/nameSearch.actions.js b/client/nameSearch/nameSearch.actions.js new file mode 100644 index 00000000..290ee38d --- /dev/null +++ b/client/nameSearch/nameSearch.actions.js @@ -0,0 +1,52 @@ +// import fetchJsonp from 'fetch-jsonp' +import * as types from '../types' +// import { hashPath } from '../util' +import { post } from '../util' +// import querystring from 'query-string' + +// urls + +const url = { + search: (dataset, q) => process.env.API_HOST + '/api/dataset/' + dataset + '/name?q=' + encodeURIComponent(q), +} +export const publicUrl = { +} + +// standard loading events + +const loading = (tag, offset) => ({ + type: types.nameSearch.loading, + tag, + offset +}) +const loaded = (tag, data, offset = 0) => ({ + type: types.nameSearch.loaded, + tag, + data, + offset +}) +const error = (tag, err) => ({ + type: types.nameSearch.error, + tag, + err +}) + +// search UI functions + +export const updateOptions = opt => dispatch => { + dispatch({ type: types.nameSearch.update_options, opt }) +} + +// API functions + +export const search = (payload, q) => dispatch => { + const tag = 'result' + const fd = new FormData() + fd.append('q', q) + dispatch(loading(tag)) + post(url.search(payload.dataset, q), fd) + .then(data => { + dispatch(loaded(tag, data)) + }) + .catch(err => dispatch(error(tag, err))) +} diff --git a/client/nameSearch/nameSearch.container.js b/client/nameSearch/nameSearch.container.js new file mode 100644 index 00000000..b0de0c3a --- /dev/null +++ b/client/nameSearch/nameSearch.container.js @@ -0,0 +1,24 @@ +import React, { Component } from 'react' +import { bindActionCreators } from 'redux' +import { connect } from 'react-redux' + +import * as actions from './nameSearch.actions' + +import NameSearchQuery from './nameSearch.query' +import NameSearchResult from './nameSearch.result' + +class NameSearchContainer extends Component { + render() { + const { payload } = this.props + // console.log(payload) + return ( +
+ + +
+ ) + } +} + + +export default NameSearchContainer diff --git a/client/nameSearch/nameSearch.query.js b/client/nameSearch/nameSearch.query.js new file mode 100644 index 00000000..b82e324b --- /dev/null +++ b/client/nameSearch/nameSearch.query.js @@ -0,0 +1,48 @@ +import React, { Component } from 'react' +import { bindActionCreators } from 'redux' +import { connect } from 'react-redux' + +import * as actions from './nameSearch.actions' + +class NameSearchQuery extends Component { + state = { + value: null + } + + handleInput(value) { + this.setState({ q: value }) + if (value.length > 2) { + this.props.actions.search(this.props.payload, value) + } + } + + render() { + return ( +
+

Find Your Name

+

Searching {13456} identities

+

+ {'Enter your name to see if you were included in this dataset..'} +

+ this.handleInput(e.target.value)} + /> +
+ ) + } +} + +const mapStateToProps = state => ({ + result: state.nameSearch.result, + options: state.nameSearch.options, +}) + +const mapDispatchToProps = dispatch => ({ + actions: bindActionCreators({ ...actions }, dispatch), +}) + +export default connect(mapStateToProps, mapDispatchToProps)(NameSearchQuery) diff --git a/client/nameSearch/nameSearch.reducer.js b/client/nameSearch/nameSearch.reducer.js new file mode 100644 index 00000000..101c93ea --- /dev/null +++ b/client/nameSearch/nameSearch.reducer.js @@ -0,0 +1,32 @@ +import * as types from '../types' + +const initialState = () => ({ + query: {}, + result: {}, + loading: false, +}) + +export default function nameSearchReducer(state = initialState(), action) { + switch (action.type) { + case types.nameSearch.loading: + return { + ...state, + [action.tag]: { loading: true }, + } + + case types.nameSearch.loaded: + return { + ...state, + [action.tag]: action.data, + } + + case types.nameSearch.error: + return { + ...state, + [action.tag]: { error: action.err }, + } + + default: + return state + } +} diff --git a/client/nameSearch/nameSearch.result.js b/client/nameSearch/nameSearch.result.js new file mode 100644 index 00000000..9e20228c --- /dev/null +++ b/client/nameSearch/nameSearch.result.js @@ -0,0 +1,88 @@ +import React, { Component } from 'react' +import { bindActionCreators } from 'redux' +import { connect } from 'react-redux' +import { courtesyS } from '../util' + +import * as actions from './nameSearch.actions' +import { Loader } from '../common' + +const errors = { + nomatch: ( +
+

Name not found

+ {"No names matched your query."} +
+ ), + error: ( +
+

{"No matches found"}

+
+ ), +} + +class NameSearchResult extends Component { + render() { + const { dataset } = this.props.payload + const { query, results, loading, error } = this.props.result + console.log(this.props.result) + if (loading) { + return ( +
+
+ +
+
+ ) + } + if (error) { + console.log(error) + let errorMessage = errors[error] || errors.error + return ( +
{errorMessage}
+ ) + } + if (!results) { + return
+ } + if (!results.length) { + return ( +
{errors.nomatch}
+ ) + } + const els = results.map((result, i) => { + const { uuid } = result.uuid + const { fullname, gender, description, images } = result.identity + return ( +
+ + {fullname} {'('}{gender}{')'}
+ {description}
+ {courtesyS(images, 'image')}{' in dataset'}
+
+ ) + }) + + return ( +
+
+ {'Search took '}{Math.round(query.timing * 1000) + ' ms'} +
+
+ {els} +
+
+ ) + } +} + +const mapStateToProps = state => ({ + query: state.nameSearch.query, + result: state.nameSearch.result, + options: state.nameSearch.options, +}) + +const mapDispatchToProps = dispatch => ({ + actions: bindActionCreators({ ...actions }, dispatch), +}) + +export default connect(mapStateToProps, mapDispatchToProps)(NameSearchResult) diff --git a/client/store.js b/client/store.js index 03f983a5..13612f2d 100644 --- a/client/store.js +++ b/client/store.js @@ -1,16 +1,12 @@ import { applyMiddleware, compose, combineReducers, createStore } from 'redux' import thunk from 'redux-thunk' -// import metadataReducer from './metadata/metadata.reducer' import faceSearchReducer from './faceSearch/faceSearch.reducer' -// import reviewReducer from './review/review.reducer' +import nameSearchReducer from './nameSearch/nameSearch.reducer' const rootReducer = combineReducers({ - auth: (state = {}) => state, - // auth: (state = login()) => state, - // metadata: metadataReducer, faceSearch: faceSearchReducer, - // review: reviewReducer, + nameSearch: nameSearchReducer, }) function configureStore(initialState = {}) { diff --git a/client/tables.js b/client/tables.js index 2a2699f9..b4c13887 100644 --- a/client/tables.js +++ b/client/tables.js @@ -74,4 +74,8 @@ export default function append(el, payload) { } }) } + + if (fields.length > 1 && fields[1].indexOf('filter')) { + const filter = fields[1].split(' ') + } } diff --git a/client/types.js b/client/types.js index d295d0d1..fb1fbe30 100644 --- a/client/types.js +++ b/client/types.js @@ -10,5 +10,8 @@ export const faceSearch = tagAsType('faceSearch', [ 'loading', 'loaded', 'error', 'update_options', ]) +export const nameSearch = tagAsType('nameSearch', [ + 'loading', 'loaded', 'error', 'update_options', +]) export const init = '@@INIT' diff --git a/megapixels/app/models/sql_factory.py b/megapixels/app/models/sql_factory.py index 414ef3a6..da95b539 100644 --- a/megapixels/app/models/sql_factory.py +++ b/megapixels/app/models/sql_factory.py @@ -97,6 +97,20 @@ class SqlDataset: 'pose': self.select('pose', id), } + def search_name(self, q): + table = self.get_table('identity_meta') + uuid_table = self.get_table('uuids') + + identity = table.query.filter(table.fullname.like(q)).order_by(table.fullname.desc()).limit(30) + identities = [] + for row in identity: + uuid = uuid_table.query.filter(uuid_table.id == row.image_id).first() + identities.append({ + 'uuid': uuid.toJSON(), + 'identity': row.toJSON(), + }) + return identities + def select(self, table, id): table = self.get_table(table) if not table: diff --git a/megapixels/app/server/api.py b/megapixels/app/server/api.py index 8ff06611..33cf45df 100644 --- a/megapixels/app/server/api.py +++ b/megapixels/app/server/api.py @@ -28,26 +28,26 @@ def index(): return jsonify({ 'datasets': list_datasets() }) -@api.route('/dataset/') -def show(name): +@api.route('/dataset/') +def show(dataset_name): """Show the data that a dataset will return""" - dataset = get_dataset(name) + dataset = get_dataset(dataset_name) if dataset: return jsonify(dataset.describe()) else: return jsonify({ 'status': 404 }) -@api.route('/dataset//face/', methods=['POST']) -def upload(name): +@api.route('/dataset//face', methods=['POST']) +def upload(dataset_name): """Query an image against FAISS and return the matching identities""" start = time.time() - dataset = get_dataset(name) - if name not in faiss_datasets: + dataset = get_dataset(dataset_name) + if dataset_name not in faiss_datasets: return jsonify({ 'error': 'invalid dataset' }) - faiss_dataset = faiss_datasets[name] + faiss_dataset = faiss_datasets[dataset_name] file = request.files['query_img'] fn = file.filename if fn.endswith('blob'): @@ -106,17 +106,21 @@ def upload(name): for _d, _i in zip(distances, indexes): if _d <= THRESHOLD: dists.append(round(float(_d), 2)) - ids.append(_i) + ids.append(_i+1) results = [ dataset.get_identity(int(_i)) for _i in ids ] # print(distances) # print(ids) + # 'bbox': str(bboxes[0]), + # 'bbox_dim': str(bbox), + print(bboxes[0]) + print(bbox) + query = { - 'bbox': bboxes[0], - 'bbox_dim': bbox, 'timing': round(time.time() - start, 3), + 'bbox': str(bbox), } # print(results) return jsonify({ @@ -126,20 +130,21 @@ def upload(name): }) -@api.route('/dataset//name', methods=['GET']) -def name_lookup(dataset): +@api.route('/dataset//name', methods=['GET','POST']) +def name_lookup(dataset_name): """Find a name in the dataset""" start = time.time() - dataset = get_dataset(name) + dataset = get_dataset(dataset_name) - # we have a query from the request query string... - # use this to do a like* query on the identities_meta table + q = request.args.get('q') + print(q) query = { + 'q': q, 'timing': time.time() - start, } - results = [] - + results = dataset.search_name(q + '%') if q else None + # print(results) return jsonify({ 'query': query, diff --git a/megapixels/app/settings/app_cfg.py b/megapixels/app/settings/app_cfg.py index d7752739..55fed166 100644 --- a/megapixels/app/settings/app_cfg.py +++ b/megapixels/app/settings/app_cfg.py @@ -89,7 +89,7 @@ CKPT_ZERO_PADDING = 9 HASH_TREE_DEPTH = 3 HASH_BRANCH_SIZE = 3 -DLIB_FACEREC_JITTERS = 25 # number of face recognition jitters +DLIB_FACEREC_JITTERS = 5 # number of face recognition jitters DLIB_FACEREC_PADDING = 0.25 # default dlib POSE_MINMAX_YAW = (-25,25) diff --git a/site/assets/css/applets.css b/site/assets/css/applets.css index edd5b709..315d72e0 100644 --- a/site/assets/css/applets.css +++ b/site/assets/css/applets.css @@ -16,7 +16,15 @@ flex-direction: row; justify-content: flex-start; } - +.q { + width: 100%; + padding: 5px; + font-size: 14pt; +} +.timing { + font-size: 9pt; + padding-top: 10px; +} .results { margin-top: 10px; padding-bottom: 10px; @@ -34,9 +42,10 @@ font-weight: 500; } .results > div img { + display: block; margin-bottom: 4px; - width: 200px; - height: 200px; + width: 190px; + height: 190px; background: rgba(255,255,255,0.05); } .results > div:nth-child(3n+1) { @@ -45,6 +54,15 @@ .query h2 { margin-top: 0; padding-top: 0; } +.img { + position: relative; +} +.img .bbox { + position: absolute; + color: rgba(255,0,0,1); + background: rgba(255,0,0,0.05); + border: 1px solid; +} .cta { padding-left: 20px; font-size: 11pt; -- cgit v1.2.3-70-g09d2