renamed AI_Model to AIModel for consistency, added it as a functioning drop-down select on settings page, added face_distance to db and code, put face_distance model_used into all classes ready for use
This commit is contained in:
33
TODO
33
TODO
@@ -1,26 +1,37 @@
|
||||
## GENERAL
|
||||
|
||||
* face locations:
|
||||
* Face matching:
|
||||
- upgrade to face distance per face per file
|
||||
- so we dont get 2 x same face in one file, and if it could match say Cam and Mich for 1 face, take the higher match, not the first one to be over the threshold
|
||||
- allow for threshold/settings to be tweaked from the GUI?
|
||||
---> at least settings for default value (back to 0.6 / 0.5?)
|
||||
---> with override table to do per file / per face?
|
||||
- face locations:
|
||||
START FORM SCRATCH so all images have face_locn data
|
||||
right now GenThumb is in shared, and does width, height as well --> in person.py BUT need this for pa_job_manager
|
||||
-- show face locns in viewer.html [DONE]
|
||||
* how hard would bootstrap 5 be, and use form-switch instead of 'badge'
|
||||
- algo:
|
||||
for each face (even known) in image
|
||||
foreach refimg
|
||||
get face_distance
|
||||
sort by face_distance
|
||||
for each face
|
||||
connect lowest score with that face (for this file)
|
||||
this means this face is no longer 'free' for a match
|
||||
if (sorted) face distance > 0.55 stop as no further 'matches'
|
||||
- use cnn model (check ftst.py) for ref images, and potentially as a setting to check images without a face?
|
||||
- or always?
|
||||
-- would CUDA be useful here? (which is faster say an old 730 or the AMD cpu?)
|
||||
|
||||
* allow for threshold/settings to be tweaked from the GUI
|
||||
- it would be good to then say, just run the scanner against this image or maybe this DIR, to see how it IDs ppl
|
||||
---> settings for default value
|
||||
---> override table to do per file combos?
|
||||
|
||||
* refimg
|
||||
- remove AI menu from top-level -> make a sub-of Person, and just have Match or AI
|
||||
|
||||
* viewer:
|
||||
can we make it preload next/prev images, and only reload the image div when we jump? to make arrow-based nav much faster
|
||||
|
||||
* remove dirs after the duplicate cleanup removes all its content
|
||||
* fix up logging in general
|
||||
|
||||
* could look to remove the hand fixing of json.loads of array data --> seems you can make your own datatype in the ORM, and it can do the conversion every time you use it
|
||||
- https://stackoverflow.com/questions/28143557/sqlalchemy-convert-column-value-back-and-forth-between-internal-and-database-fo
|
||||
|
||||
* fix up logging in general
|
||||
* comment your code
|
||||
* more OO goodness :)
|
||||
|
||||
|
||||
4
face.py
4
face.py
@@ -2,7 +2,6 @@ from main import db, app, ma
|
||||
from sqlalchemy import Sequence
|
||||
from sqlalchemy.exc import SQLAlchemyError
|
||||
|
||||
|
||||
class Face(db.Model):
|
||||
__tablename__ = "face"
|
||||
id = db.Column(db.Integer, db.Sequence('face_id_seq'), primary_key=True )
|
||||
@@ -17,6 +16,7 @@ class FaceFileLink(db.Model):
|
||||
__tablename__ = "face_file_link"
|
||||
face_id = db.Column(db.Integer, db.ForeignKey("face.id"), primary_key=True )
|
||||
file_eid = db.Column(db.Integer, db.ForeignKey("file.eid"), primary_key=True )
|
||||
model_used = db.Column(db.Integer, db.ForeignKey("ai_model.id"), primary_key=True )
|
||||
|
||||
def __repr__(self):
|
||||
return f"<face_id: {self.face_id}, file_eid={self.file_eid}"
|
||||
@@ -25,6 +25,8 @@ class FaceRefimgLink(db.Model):
|
||||
__tablename__ = "face_refimg_link"
|
||||
face_id = db.Column(db.Integer, db.ForeignKey("face.id"), primary_key=True )
|
||||
refimg_id = db.Column(db.Integer, db.ForeignKey("refimg.id"), primary_key=True )
|
||||
model_used = db.Column(db.Integer, db.ForeignKey("ai_model.id"), primary_key=True )
|
||||
face_distance = db.Column(db.Integer)
|
||||
|
||||
def __repr__(self):
|
||||
return f"<face_id: {self.face_id}, refimg_id={self.refimg_id}"
|
||||
|
||||
@@ -227,6 +227,14 @@ class Refimg(Base):
|
||||
def __repr__(self):
|
||||
return f"<id: {self.id}, fname: {self.fname}, created_on: {self.created_on}>"
|
||||
|
||||
class AIModel(Base):
|
||||
__tablename__ = "ai_model"
|
||||
id = Column(Integer, primary_key=True )
|
||||
name = Column(String)
|
||||
|
||||
def __repr__(self):
|
||||
return f"<id: {self.id}, name: {self.name}>"
|
||||
|
||||
class Face(Base):
|
||||
__tablename__ = "face"
|
||||
id = Column(Integer, Sequence('face_id_seq'), primary_key=True )
|
||||
@@ -240,6 +248,7 @@ class FaceFileLink(Base):
|
||||
__tablename__ = "face_file_link"
|
||||
face_id = Column(Integer, ForeignKey("face.id"), primary_key=True )
|
||||
file_eid = Column(Integer, ForeignKey("file.eid"), primary_key=True )
|
||||
model_used = Column(Integer, ForeignKey("ai_model.id") )
|
||||
|
||||
def __repr__(self):
|
||||
return f"<face_id: {self.face_id}, file_eid={self.file_eid}"
|
||||
@@ -248,6 +257,8 @@ class FaceRefimgLink(Base):
|
||||
__tablename__ = "face_refimg_link"
|
||||
face_id = Column(Integer, ForeignKey("face.id"), primary_key=True )
|
||||
refimg_id = Column(Integer, ForeignKey("refimg.id"), primary_key=True )
|
||||
model_used = Column(Integer, ForeignKey("ai_model.id") )
|
||||
face_distance = Column(Integer)
|
||||
|
||||
def __repr__(self):
|
||||
return f"<face_id: {self.face_id}, refimg_id={self.refimg_id}"
|
||||
|
||||
@@ -12,7 +12,7 @@ from flask_login import login_required, current_user
|
||||
################################################################################
|
||||
# Class describing AI_MODEL in the database, and via sqlalchemy, connected to the DB as well
|
||||
################################################################################
|
||||
class AI_Model(db.Model):
|
||||
class AIModel(db.Model):
|
||||
__tablename__ = "ai_model"
|
||||
id = db.Column(db.Integer, primary_key=True )
|
||||
name = db.Column(db.String)
|
||||
@@ -20,6 +20,7 @@ class AI_Model(db.Model):
|
||||
def __repr__(self):
|
||||
return f"<id: {self.id}, name: {self.name}>"
|
||||
|
||||
|
||||
################################################################################
|
||||
# Class describing Settings in the database, and via sqlalchemy, connected to the DB as well
|
||||
################################################################################
|
||||
@@ -53,7 +54,7 @@ class SettingsForm(FlaskForm):
|
||||
import_path = StringField('Path(s) to import from:', [validators.DataRequired()])
|
||||
storage_path = StringField('Path to store sorted images to:', [validators.DataRequired()])
|
||||
recycle_bin_path = StringField('Path to temporarily store deleted images in:', [validators.DataRequired()])
|
||||
default_model = SelectField( 'default_model', choices=[(c.id, c.name) for c in AI_Model.query.order_by('id')] )
|
||||
default_model = SelectField( 'default_model', choices=[(c.id, c.name) for c in AIModel.query.order_by('id')] )
|
||||
default_threshold = StringField('Face Distance threshold (below is a match):', [validators.DataRequired()])
|
||||
submit = SubmitField('Save' )
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ create table FACE_FILE_LINK( FACE_ID integer, FILE_EID integer, MODEL_USED integ
|
||||
constraint FK_FFL_FILE_EID foreign key (FILE_EID) references FILE(EID),
|
||||
constraint FK_FFL_MODEL_USED foreign key (MODEL_USED) references AI_MODEL(ID) );
|
||||
|
||||
create table FACE_REFIMG_LINK( FACE_ID integer, REFIMG_ID integer, MODEL_USED integer,
|
||||
create table FACE_REFIMG_LINK( FACE_ID integer, REFIMG_ID integer, MODEL_USED integer, FACE_DISTANCE integer,
|
||||
constraint PK_FRL_FACE_ID_REFIMG_ID primary key(FACE_ID, REFIMG_ID),
|
||||
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),
|
||||
|
||||
Reference in New Issue
Block a user