diff --git a/TODO b/TODO index b47e9f6..1145a38 100644 --- a/TODO +++ b/TODO @@ -1,4 +1,5 @@ ## GENERAL + * run_ai_on throws log line, for matching even if there are no faces, would be less noisy to not do that (or should say no faces?) * on viewer: - allow face to be used to create person, add to existing person, and allow 'ignore', mark as 'not a face', etc -> ignore/not a face/too young --> all need to go into DB so we can remember the 'override' when we re-ai-match diff --git a/ai.py b/ai.py index c893626..4e79732 100644 --- a/ai.py +++ b/ai.py @@ -105,3 +105,27 @@ def unmatched_faces(): face.img = str(face.img)[2:-1] return render_template("faces.html", faces=faces) + + +# this is called in Ajax, when we manually override a face that is currently unmatched load +# the original full image, find the current face's coords, grab pixels 10% larger and return +# it so we can show it in the dbox, and be able to pass it around for refimg creation (if needed) +@app.route("/get_face_from_image/", methods=["POST"]) +@login_required +def get_face_from_image(face_id): + face=Face.query.get(face_id) + f = Entry.query.join(File).join(FaceFileLink).filter(FaceFileLink.face_id==face_id).first() + tmp_locn=json.loads(face.locn) + x=tmp_locn[3]*0.95 + y=tmp_locn[0]*0.95 + x2=tmp_locn[1]*1.05 + y2=tmp_locn[2]*1.05 + + im = Image.open(f.FullPathOnFS()) + region = im.crop((x, y, x2, y2)) + img_bytearray = io.BytesIO() + region.save(img_bytearray, format='JPEG') + img_bytearray = img_bytearray.getvalue() + face_img = base64.b64encode(img_bytearray) + face_img = str(face_img)[2:-1] + return face_img diff --git a/internal/js/view_support.js b/internal/js/view_support.js index 9a6c7b0..f1fcbc0 100644 --- a/internal/js/view_support.js +++ b/internal/js/view_support.js @@ -204,8 +204,8 @@ $(document).ready( function() $.contextMenu({ selector: '#canvas', -// trigger: 'left', - trigger: 'none', + trigger: 'left', +// trigger: 'none', hideOnSecondTrigger: true, build: function($triggerElement, e) { @@ -226,16 +226,16 @@ $(document).ready( function() if( x >= fx && x <= fx+fw && y >= fy && y <= fy+fh ) { if( objs[current].faces[i].who ) - item_list['match']={ 'name': objs[current].faces[i].who, 'which_face': i } + item_list['match']={ 'name': objs[current].faces[i].who, 'which_face': i, 'id': objs[current].faces[i].id } else { - item_list['no_match_new_person']={ 'name': 'Add as reference image to NEW person', 'which_face': i } - item_list['no_match_new_refimg']={ 'name': 'Add as reference image to EXISTING person', 'which_face': i } - item_list['no_match_override_match']={ 'name': 'Manually match to existing person', 'which_face': i } - item_list['no_match_no_face']={ 'name': 'Mark as not a face', 'which_face': i } - item_list['no_match_too_young']={ 'name': 'Mark as face too young', 'which_face': i } - item_list['no_match_ignore']={ 'name': 'Ignore this face', 'which_face': i } - item_list['remove_override']={ 'name': 'Remove override for this face', 'which_face': i } + 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 } + item_list['remove_override']={ 'name': 'Remove override for this face', 'which_face': i, 'id': objs[current].faces[i].id } } delete item_list['not_a_face'] $('#canvas').prop('menu_item', item_list ) @@ -258,7 +258,13 @@ $(document).ready( function() function FaceDBox(key, item) { div ='

' - div+='Face #' + item[key]['which_face'] + div+='Face position #' + item[key]['which_face'] + div+='

' + $.ajax({ type: 'POST', data: null, url: '/get_face_from_image/'+item[key]['id'], + success: function(img_data) { + $('#face_img').html( '' ) + } + } ) div+='

' if ( key == 'no_match_new_person' ) { @@ -266,11 +272,18 @@ function FaceDBox(key, item) } if ( key == 'no_match_new_refimg' || key == 'no_match_override_match' ) { - div+='
search for existing person' + div+='
search for existing person:
' + div+= + ` +
+ +
+ ` } if ( key == 'no_match_no_face' || key == 'no_match_too_young' || key == 'no_match_ignore' ) { div+='
just track this against face#' + item[key]['which_face'] + div+='
face db id: ' + item[key]['id'] } $('#dbox-title').html(item[key]['name']) $('#dbox-content').html(div) diff --git a/tables.sql b/tables.sql index a1098d7..04520d4 100644 --- a/tables.sql +++ b/tables.sql @@ -92,6 +92,21 @@ create table FACE_REFIMG_LINK( FACE_ID integer, REFIMG_ID integer, FACE_DISTANCE constraint FK_FRL_FACE_ID foreign key (FACE_ID) references FACE(ID) on delete cascade, constraint FK_FRL_REFIMG_ID foreign key (REFIMG_ID) references REFIMG(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' ); + +create table FACE_NO_MATCH_OVERRIDE ( ID integer, FACE_ID integer, TYPE integer, + 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) ); +-- this could really suck, maybe we dont allow this??? +--create table FACE_MANUAL_OVERRIDE ( ID integer, FACE_ID integer, PERSON_ID integer, TYPE integer, constraint PK_FACE_MANUAL_OVERRIDE_ID primary key(ID) ); + create table PERSON_REFIMG_LINK ( PERSON_ID integer, REFIMG_ID integer, constraint PK_PRL primary key(PERSON_ID, REFIMG_ID), constraint FK_PRL_PERSON_ID foreign key (PERSON_ID) references PERSON(ID), diff --git a/templates/viewer.html b/templates/viewer.html index 442b806..4a65d12 100644 --- a/templates/viewer.html +++ b/templates/viewer.html @@ -40,6 +40,7 @@ e.faces=[] {% for face in objs[id].file_details.faces %} data = { + 'id': '{{face.id}}', 'x': '{{face.locn[3]}}', 'y': '{{face.locn[0]}}', 'w': '{{face.locn[1]-face.locn[3]}}', 'h':'{{face.locn[2]-face.locn[0]}}' }