From b935aa8ab805350cf019147481fce5fcfaf5d17a Mon Sep 17 00:00:00 2001
From: Damien De Paoli
Date: Mon, 13 Jun 2022 18:30:13 +1000
Subject: [PATCH] can now add/remove overrides (manual or no matchx3) in any
sequence of load/reload, or back-to-back and it all works
---
files.py | 6 +-
internal/js/view_support.js | 165 +++++++++++++++++++++++-------------
person.py | 54 ++++++++++--
tables.sql | 2 +-
templates/viewer.html | 26 ++++--
5 files changed, 179 insertions(+), 74 deletions(-)
diff --git a/files.py b/files.py
index e5d2a69..3c26b0c 100644
--- a/files.py
+++ b/files.py
@@ -32,7 +32,7 @@ from person import Refimg, Person, PersonRefimgLink
from settings import Settings, SettingsIPath, SettingsSPath, SettingsRBPath
from shared import SymlinkName
from dups import Duplicates
-from face import Face, FaceFileLink, FaceRefimgLink, FaceNoMatchOverride, FaceManualOverride
+from face import Face, FaceFileLink, FaceRefimgLink, FaceOverrideType, FaceNoMatchOverride, FaceManualOverride
# pylint: disable=no-member
@@ -737,6 +737,7 @@ def view(id):
face.no_match_override=fnmo
mo = FaceManualOverride.query.filter(FaceManualOverride.face_id==face.id).first()
if mo:
+ mo.type = FaceOverrideType.query.filter( FaceOverrideType.name== 'Manual match to existing person' ).first()
face.manual_override=mo
@@ -753,7 +754,8 @@ def view(id):
st.SetMessage( msg, "warning" )
return redirect("/")
else:
- return render_template("viewer.html", current=int(id), eids=eids, objs=objs, OPT=OPT )
+ NMO_data = FaceOverrideType.query.all()
+ return render_template("viewer.html", current=int(id), eids=eids, objs=objs, OPT=OPT, NMO_data=NMO_data )
##################################################################################
# /view/id -> grabs data from DB and views it (POST -> set state, redirect to GET)
diff --git a/internal/js/view_support.js b/internal/js/view_support.js
index a41da57..f854dd3 100644
--- a/internal/js/view_support.js
+++ b/internal/js/view_support.js
@@ -1,4 +1,3 @@
-// work out new width for canvas. depending on whether width > height of the
// image, then use the width of the image (with the specified gap) otherwise
// the height > width, so scale the new width based on height ratio of
// image to window
@@ -116,19 +115,20 @@ function DrawImg()
// this face has an override so diff colour
if( objs[current].faces[i].override )
- context.strokeStyle = 'blue'
- else
- context.strokeStyle = 'green'
-
- if( objs[current].faces[i].no_match_override)
- DrawLabelOnFace( objs[current].faces[i].no_match_override.type )
-
- if( objs[current].faces[i].who )
{
- str=objs[current].faces[i].who
- if( $('#distance').prop('checked') )
- str += "("+objs[current].faces[i].distance+")"
- DrawLabelOnFace( str )
+ context.strokeStyle = 'blue'
+ DrawLabelOnFace( objs[current].faces[i].override.who )
+ }
+ else
+ {
+ context.strokeStyle = 'green'
+ if( objs[current].faces[i].who )
+ {
+ str=objs[current].faces[i].who
+ if( $('#distance').prop('checked') )
+ str += "("+objs[current].faces[i].distance+")"
+ DrawLabelOnFace( str )
+ }
}
context.stroke();
}
@@ -230,7 +230,7 @@ $(document).ready( function()
{
if( objs[current].faces[i].override )
{
- item_list['remove_override']={ 'name': 'Remove override for this face', 'which_face': i, 'id': objs[current].faces[i].id }
+ item_list['remove_override_force_match']={ 'name': 'Remove override for this face', 'which_face': i, 'id': objs[current].faces[i].id }
}
else if( objs[current].faces[i].who )
{
@@ -241,10 +241,9 @@ $(document).ready( function()
{
item_list['no_match_new_person']={ 'name': 'Add as reference image to NEW person', 'which_face': i, 'id': objs[current].faces[i].id }
item_list['no_match_new_refimg']={ 'name': 'Add as reference image to EXISTING person', 'which_face': i, 'id': objs[current].faces[i].id }
- item_list['no_match_override_match']={ 'name': 'Manually match to existing person', 'which_face': i, 'id': objs[current].faces[i].id }
- item_list['no_match_no_face']={ 'name': 'Mark as not a face', 'which_face': i, 'id': objs[current].faces[i].id }
- item_list['no_match_too_young']={ 'name': 'Mark as face too young', 'which_face': i, 'id': objs[current].faces[i].id }
- item_list['no_match_ignore']={ 'name': 'Ignore this face', 'which_face': i, 'id': objs[current].faces[i].id }
+ for( var el in NMO ) {
+ item_list['NMO_'+el]={'type_id': NMO[el].type_id, 'name': 'Override: ' + NMO[el].name, 'which_face': i, 'id': objs[current].faces[i].id }
+ }
}
delete item_list['not_a_face']
$('#canvas').prop('menu_item', item_list )
@@ -264,17 +263,24 @@ $(document).ready( function()
} );
// quick wrapper function to make calling this ajax code simpler in SearchForPerson
-function OverrideForceMatch( person_id, face_id, face_pos )
+function OverrideForceMatch( person_id, face_id, face_pos, type_id )
{
+ // we have type_id passed in, so dig the NMO out, and use that below (its really just for name, but in case we change that in the DB)
+ for( el in NMO )
+ {
+ if( NMO[el].type_id == type_id )
+ {
+ fm_idx=el
+ break
+ }
+ }
ofm='&person_id='+person_id+'&face_id='+face_id
$.ajax({ type: 'POST', data: ofm, url: '/override_force_match', success: function(data) {
- // on success, remember the original data, apply override values, close the dbox, force face drawing boxes on and redraw the face with the new override
- if( objs[current].faces[face_pos].who )
- objs[current].faces[face_pos].old_who=objs[current].faces[face_pos].who
- objs[current].faces[face_pos].old_distance=objs[current].faces[face_pos].distance
- objs[current].faces[face_pos].who=data.person_tag
- objs[current].faces[face_pos].distance="N/A"
- objs[current].faces[face_pos].override=1
+ objs[current].faces[face_pos].override={}
+ objs[current].faces[face_pos].override.who=data.person_tag
+ objs[current].faces[face_pos].override.distance='N/A'
+ objs[current].faces[face_pos].override.type_id=NMO[fm_idx].id
+ objs[current].faces[face_pos].override.type_name=NMO[fm_idx].name
$('#dbox').modal('hide')
$('#faces').prop('checked',true)
@@ -286,7 +292,7 @@ function OverrideForceMatch( person_id, face_id, face_pos )
// 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, face_pos)
+function SearchForPerson(face_id, face_pos, type_id)
{
// make URI safe
who = encodeURIComponent( $('#stext').val() )
@@ -296,12 +302,8 @@ function SearchForPerson(face_id, face_pos)
content='Click one of the link(s) below to manually connect this face as once-off connection to the person:
'
for( var key in data ) {
var person = data[key];
- /*
- content+= ''+person.firstname+' '+person.surname+' ('+person.tag+') '
- */
content+= ''+person.firstname+' '+person.surname+' ('+person.tag+') '
+ +face_id+','+face_pos+','+type_id+')">'+person.firstname+' '+person.surname+' ('+person.tag+') '
}
$('#search_person_results').html( content )
}
@@ -309,16 +311,12 @@ function SearchForPerson(face_id, face_pos)
return false
}
-function RemoveOverride()
+function RemoveOverrideForceMatch(face_pos)
{
d='&face_id='+objs[current].faces[face_pos].id+'&person_tag='+objs[current].faces[face_pos].who+
'&file_eid='+current
- $.ajax({ type: 'POST', data: d, url: '/remove_override',
+ $.ajax({ type: 'POST', data: d, url: '/remove_override_force_match',
success: function(data) {
- if( objs[current].faces[face_pos].old_who )
- objs[current].faces[face_pos].who=objs[current].faces[face_pos].old_who
- else
- delete objs[current].faces[face_pos].who
delete objs[current].faces[face_pos].override
$('#dbox').modal('hide')
DrawImg()
@@ -328,6 +326,37 @@ function RemoveOverride()
return false
}
+function RemoveOverrideNoMatch(face_pos, type_id)
+{
+ d='&face_id='+objs[current].faces[face_pos].id+'&type_id='+type_id
+ $.ajax({ type: 'POST', data: d, url: '/remove_override_no_match',
+ success: function(data) {
+ delete objs[current].faces[face_pos].override
+ $('#dbox').modal('hide')
+ DrawImg()
+ return false
+ }
+ } )
+ return false
+}
+
+function AddNoMatchOverride(type_id, face_id, face_pos, type_id)
+{
+ d='&type_id='+type_id+'&face_id='+face_id
+ $.ajax({ type: 'POST', data: d, url: '/add_no_match_override',
+ success: function(data) {
+ objs[current].faces[face_pos].override={}
+ objs[current].faces[face_pos].override.who=NMO[type_id].name
+ objs[current].faces[face_pos].override.distance='N/A'
+ objs[current].faces[face_pos].override.type_id=type_id
+ objs[current].faces[face_pos].override.type_name=NMO[type_id].name
+ $('#dbox').modal('hide')
+ $('#faces').prop('checked',true)
+ DrawImg()
+ }
+ } )
+}
+
// 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
@@ -344,42 +373,60 @@ function FaceDBox(key, item)
}
} )
div+='
'
- if ( key == 'remove_override' )
+ if ( key == 'remove_override_force_match' )
{
- div+='
remove this override (force match to: ' + objs[current].faces[face_pos].who + ')'
+ if( objs[current].faces[face_pos].override.type_name == 'Manual match to existing person' )
+ div+='
remove this override (force match to: ' + objs[current].faces[face_pos].override.who + ')