Files
photoassistant/face.py

130 lines
6.3 KiB
Python

""" file containing all classes to handle Face (and associated tables) from the database """
from main import db
from shared import PA
################################################################################
class Face(PA,db.Model):
"""Class describing a Face in the database
Attributes:
id (int): database id of row in Face table / primary key
face (bytes): the binary version of numpy array so we dont need to recalc it
face_top (int): top-most pixel of face
face_right (int): right-most pixel of face
face_bottom (int): bottom-most pixel of face
face_left (int): left-most pixel of face
w (int) : width of face in pixels
h (int) : height of face in pixels
refimg_lnk (FaceRefimgLink): face_refimg_link data - viewOnly / just for convenience in viewer
facefile_lnk (FaceFileLink): face_file_link data - viewOnly / just for convenience in viewer
refimg (Refimg): link to the refimg used for this face (used in viewer). Set when there is a matched face, or None if no match
"""
__tablename__ = "face"
id = db.Column(db.Integer, db.Sequence("face_id_seq"), primary_key=True )
face = db.Column( db.LargeBinary )
face_top = db.Column( db.Integer )
face_right = db.Column( db.Integer )
face_bottom = db.Column( db.Integer )
face_left = db.Column( db.Integer )
w = db.Column( db.Integer )
h = db.Column( db.Integer )
refimg_lnk = db.relationship("FaceRefimgLink", uselist=False, viewonly=True )
facefile_lnk = db.relationship("FaceFileLink", uselist=False, viewonly=True )
refimg =db.relationship("Refimg", secondary="face_refimg_link", uselist=False)
fnmo = db.relationship("FaceNoMatchOverride", back_populates="face")
ffmo = db.relationship("FaceForceMatchOverride", back_populates="face")
################################################################################
class FaceFileLink(PA, db.Model):
"""Class describing a Face_File_Link in the database
NOTE: this data model is not perfect, each face in the same file is always found
with the same model - so really should have ModelFileLink or something, in the long run
this might even be better as ScanDetailsFileLink and ScanDetails
Attributes:
face_id (int): face id of row in Face table / foreign key - part primary key
file_eid (int): entry id of a row in File table / foreign key - part primary key
model_used(int): id of a row in AI_model table used to find the face / foreign key - part primary key
"""
__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 )
################################################################################
class FaceRefimgLink(PA, db.Model):
"""Class describing a Face_Regimg_Link in the database
connects / implies a face has matched a refimg and we keep the distance too
distance is mainly for debugging for now and shown in viewer
Attributes:
face_id (int): face id of row in Face table / foreign key - part primary key
refimg_id (int): face id of row in Face table / foreign key - part primary key
face_distance (float): distance value (how similar matched Face was)
"""
__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 )
face_distance = db.Column(db.Float)
################################################################################
class FaceOverrideType(PA, db.Model):
"""Class describing a Face_Override_Type in the database
when a face has an override, it will be a simple list of different types
eg (forced match, no match, not a face, etc)
Attributes:
id (int): database id of row in FaceOverrideType table / part primary key
name (str): name of the type of face override
"""
__tablename__ = "face_override_type"
id = db.Column(db.Integer, db.Sequence("face_override_type_id_seq"), primary_key=True )
name = db.Column( db.String )
################################################################################
class FaceNoMatchOverride(PA, db.Model):
"""Class describing a Face_No_Match_Override in the database
used when a face does not match for some reason (type and face id connected)
Attributes:
id (int): database id of row in Face_No_Match_Override table / part primary key
face_id (int): face id of row in Face table / foreign key - part primary key
type_id (int): id of row in Face_Override_Type table / foreign key
type (FaceOverrideType): convenience field for face override type for this face
"""
__tablename__ = "face_no_match_override"
id = db.Column(db.Integer, db.Sequence("face_override_id_seq"), primary_key=True )
face_id = db.Column(db.Integer, db.ForeignKey("face.id"), primary_key=True )
type_id = db.Column(db.Integer, db.ForeignKey("face_override_type.id"))
type = db.relationship("FaceOverrideType")
face = db.relationship("Face", back_populates="fnmo")
################################################################################
class FaceForceMatchOverride(PA, db.Model):
"""Class describing a Face_Force_Match_Override in the database
used when a face is forced to match for some reason (who and face id connected)
Attributes:
id (int): database id of row in Face_Force_Match_Override table / part primary key
face_id (int): face id of row in Face table / foreign key - part primary key
person_id (int): person id of row in Person table / foreign key - part primary key
person (Person): convenience field for Person with forced match
"""
__tablename__ = "face_force_match_override"
id = db.Column(db.Integer, db.Sequence("face_override_id_seq"), primary_key=True )
face_id = db.Column(db.Integer, db.ForeignKey("face.id"), primary_key=True )
person_id = db.Column(db.Integer, db.ForeignKey("person.id"), primary_key=True )
person = db.relationship("Person")
face = db.relationship("Face", back_populates="ffmo")