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:
2022-06-10 16:53:13 +10:00
parent b0779c2704
commit 8c78d9e633
3 changed files with 107 additions and 3 deletions

24
face.py
View File

@@ -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) );

View File

@@ -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' )
{

View File

@@ -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>&nbsp;{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"