progress towards allowing overrides. dbox can now allow finding a person and clicking them to post to back-end.. More work to make this real, for now it goes through the routes but does not update the DB, see bottom of face.py for next steps
This commit is contained in:
24
face.py
24
face.py
@@ -2,6 +2,7 @@ from main import db, app, ma
|
||||
from sqlalchemy import Sequence
|
||||
from sqlalchemy.exc import SQLAlchemyError
|
||||
|
||||
|
||||
# DEL ME SOON
|
||||
from flask_login import login_required
|
||||
from flask import render_template
|
||||
@@ -61,3 +62,26 @@ class FaceRefimgLink(db.Model):
|
||||
|
||||
def __repr__(self):
|
||||
return f"<face_id: {self.face_id}, refimg_id={self.refimg_id}, face_distance: {self.face_distance}"
|
||||
|
||||
|
||||
### DDP: todo next, make these into sqlachemy classes, THEN person.py add the override in ORM, THEN draw override in blue/not green in DrawImg
|
||||
### THEN find_person needs to call appropriate override func (OR pass in type?) and get it to be smarter - that sounds okay actually
|
||||
# create table FACE_OVERRIDE_TYPE ( ID integer, NAME varchar unique, constraint PK_FACE_OVERRIDE_TYPE_ID primary key(ID) );
|
||||
#create sequence FACE_OVERRIDE_TYPE_ID_SEQ;
|
||||
#create sequence FACE_OVERRIDE_ID_SEQ;
|
||||
#create table FACE_OVERRIDE_TYPE ( ID integer, NAME varchar unique, constraint PK_FACE_OVERRIDE_TYPE_ID primary key(ID) );
|
||||
#insert into FACE_OVERRIDE_TYPE values ( (select nextval('FACE_OVERRIDE_TYPE_ID_SEQ')), 'Not a face' );
|
||||
#insert into FACE_OVERRIDE_TYPE values ( (select nextval('FACE_OVERRIDE_TYPE_ID_SEQ')), 'Too young' );
|
||||
#insert into FACE_OVERRIDE_TYPE values ( (select nextval('FACE_OVERRIDE_TYPE_ID_SEQ')), 'Ignore face' );
|
||||
#insert into FACE_OVERRIDE_TYPE values ( (select nextval('FACE_OVERRIDE_TYPE_ID_SEQ')), 'Manual match' );
|
||||
#
|
||||
#-- keep non-redundant FACE because, when we rebuild data we may have a null FACE_ID, but still want to connect to this override
|
||||
#-- from a previous AI pass... (would happen if we delete a file and then reimport/scan it), OR, more likely we change (say) a threshold, etc.
|
||||
#-- any reordering of faces, generates new face_ids... (but if the face data was the same, then this override should stand)
|
||||
#create table FACE_NO_MATCH_OVERRIDE ( ID integer, FACE_ID integer, TYPE integer, FACE bytea,
|
||||
# constraint FK_FNMO_FACE_ID foreign key (FACE_ID) references FACE(ID),
|
||||
# constraint FK_FNMO_TYPE foreign key (TYPE) references FACE_OVERRIDE_TYPE(ID),
|
||||
# constraint PK_FNMO_ID primary key(ID) );
|
||||
#
|
||||
#-- manual match goes to person not refimg, so on search, etc. we deal with this anomaly (via sql not ORM)
|
||||
#create table FACE_MANUAL_OVERRIDE ( ID integer, FACE_ID integer, PERSON_ID integer, TYPE integer, constraint PK_FACE_MANUAL_OVERRIDE_ID primary key(ID) );
|
||||
|
||||
@@ -257,7 +257,44 @@ $(document).ready( function()
|
||||
} )
|
||||
} );
|
||||
|
||||
// quick wrapper function to make calling this ajax code simpler in SearchForPerson
|
||||
function OverrideForceMatch( person, face )
|
||||
{
|
||||
ofm='&person_id='+person+'&face_id='+face
|
||||
// on success, close the dbox, force face drawing on and redraw the face with the new override
|
||||
$.ajax({ type: 'POST', data: ofm, url: '/override_force_match', success: function(data) {
|
||||
$('#dbox').modal('hide');
|
||||
$('#faces').prop('checked',true);
|
||||
DrawImg();
|
||||
}
|
||||
} )
|
||||
}
|
||||
|
||||
// function to facilitate adding a face match override to this "found" person
|
||||
// uses Ajax to the f/e to get any person matching #stext's content (via any name/tag)
|
||||
// and displays results in #search_person_results
|
||||
function SearchForPerson(face_id)
|
||||
{
|
||||
// make URI safe
|
||||
who = encodeURIComponent( $('#stext').val() )
|
||||
// call ajax to find ppl
|
||||
$.ajax({ type: 'POST', data: null, url: '/find_persons/'+ who,
|
||||
success: function(data) {
|
||||
content='Click one of the link(s) below to manually connect this face as once-off connection to the person:<br><br>'
|
||||
for( var key in data ) {
|
||||
var person = data[key];
|
||||
content+= '<a onClick="OverrideForceMatch('+person.id+','+face_id+')">'+person.firstname+' '+person.surname+'('+person.tag+')</a><br>'
|
||||
}
|
||||
$('#search_person_results').html( content )
|
||||
}
|
||||
} )
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
// function that is called when we click on a face in the viewer and we want to
|
||||
// potentially override the non-match / match... it shows the face, and then
|
||||
// based on which menu item got us here, shows appropriate text to do next action
|
||||
function FaceDBox(key, item)
|
||||
{
|
||||
div ='<p>'
|
||||
@@ -279,9 +316,12 @@ function FaceDBox(key, item)
|
||||
div+=
|
||||
`
|
||||
<div class="input-group mb-3"><input type="text" class="form-control" id="stext" placeholder="tag/name">
|
||||
<button class="btn btn-outline-success" type="button" onClick="console.log('search for: ' + $('#stext').val());return false">Search</button>
|
||||
<button class="btn btn-outline-success" type="button" onClick="SearchForPerson(`
|
||||
div+= item[key]['id']
|
||||
div+=`)">Search</button>
|
||||
</div>
|
||||
`
|
||||
<div id="search_person_results">
|
||||
</div>`
|
||||
}
|
||||
if ( key == 'wrong_person' )
|
||||
{
|
||||
|
||||
42
person.py
42
person.py
@@ -9,7 +9,7 @@ from status import st, Status
|
||||
from flask_login import login_required, current_user
|
||||
from werkzeug.utils import secure_filename
|
||||
from shared import GenFace, GenThumb
|
||||
from face import FaceRefimgLink
|
||||
from face import Face, FaceRefimgLink
|
||||
import os
|
||||
import json
|
||||
import time
|
||||
@@ -225,3 +225,43 @@ def add_refimg():
|
||||
except Exception as e:
|
||||
st.SetMessage( f"<b>Failed to modify Refimg:</b> {e}", "danger" )
|
||||
return redirect( url_for( 'person', id=person.id) )
|
||||
|
||||
################################################################################
|
||||
# /find_persons/<who> -> POST (an arbitrary string to find a person (via
|
||||
# name/tag match)
|
||||
################################################################################
|
||||
@app.route("/find_persons/<who>", methods=["POST"])
|
||||
@login_required
|
||||
def find_persons(who):
|
||||
resp={}
|
||||
people = Person.query.filter( Person.tag.ilike(f'%{who}%') | Person.firstname.ilike(f'%{who}%') | Person.surname.ilike(f'%{who}%') ).all();
|
||||
|
||||
for p in people:
|
||||
resp[p.id]={}
|
||||
resp[p.id]['id']=p.id
|
||||
resp[p.id]['tag']=p.tag
|
||||
resp[p.id]['firstname']=p.firstname
|
||||
resp[p.id]['surname']=p.surname
|
||||
|
||||
print( resp )
|
||||
return resp
|
||||
|
||||
################################################################################
|
||||
# /override_force_match -> POST
|
||||
################################################################################
|
||||
@app.route("/override_force_match", methods=["POST"])
|
||||
@login_required
|
||||
def override_force_match():
|
||||
person_id = request.form['person_id']
|
||||
face_id = request.form['face_id']
|
||||
p = Person.query.get(person_id);
|
||||
if not p:
|
||||
raise Exception("could not find person to add override too!")
|
||||
f = Face.query.get(face_id);
|
||||
if not f:
|
||||
raise Exception("could not find face to add override for!")
|
||||
|
||||
print( f"Being asked to force an override match for face_id {face_id}, for person: {p.tag} -- doing nothing for now" )
|
||||
st.SetMessage( f"Being asked to force an override match for face_id {face_id}, for person: {p.tag} -- doing nothing for now" )
|
||||
# might need to do something smarter here (reload to old view is good though & happens now, not sure why (last url)?)
|
||||
return "ok"
|
||||
|
||||
Reference in New Issue
Block a user