implemented ai in our pa_job_manager, with refimgs, a job, and the whole deal

This commit is contained in:
2021-01-22 18:46:18 +11:00
parent 53d0f71b58
commit 605b26af89

View File

@@ -11,28 +11,37 @@
#
###
### SQLALCHEMY IMPORTS ###
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, Sequence, Float, ForeignKey, DateTime
from sqlalchemy import Column, Integer, String, Sequence, Float, ForeignKey, DateTime, LargeBinary
from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy.orm import relationship
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.orm import scoped_session
### SQLALCHEMY IMPORTS ###
### LOCAL FILE IMPORTS ###
from shared import DB_URL, PA_JOB_MANAGER_HOST, PA_JOB_MANAGER_PORT
from datetime import datetime, timedelta
import pytz
import time
import os
import glob
from PIL import Image
from PIL import Image, ImageOps
from pymediainfo import MediaInfo
import hashlib
import exifread
#import exifread
import base64
import numpy
import cv2
import socket
import threading
import io
import face_recognition
DEBUG=1
@@ -113,6 +122,43 @@ class Settings(Base):
def __repr__(self):
return "<id: {}, import_path: {}>".format(self.id, self.import_path )
class Person_Refimg_Link(Base):
__tablename__ = "person_refimg_link"
person_id = Column(Integer, ForeignKey('person.id'), unique=True, nullable=False, primary_key=True)
refimg_id = Column(Integer, ForeignKey('refimg.id'), unique=True, nullable=False, primary_key=True)
def __repr__(self):
return "<person_id: {}, refimg_id>".format(self.person_id, self.refimg_id)
class Person(Base):
__tablename__ = "person"
id = Column(Integer, Sequence('person_id_seq'), primary_key=True )
tag = Column(String(48), unique=False, nullable=False)
surname = Column(String(48), unique=False, nullable=False)
firstname = Column(String(48), unique=False, nullable=False)
refimg = relationship('Refimg', secondary=Person_Refimg_Link.__table__)
def __repr__(self):
return "<tag: {}, firstname: {}, surname: {}, refimg: {}>".format(self.tag,self.firstname, self.surname, self.refimg)
class Refimg(Base):
__tablename__ = "refimg"
id = Column(Integer, Sequence('refimg_id_seq'), primary_key=True )
fname = Column(String(256), unique=True, nullable=False)
encodings = Column(LargeBinary)
def __repr__(self):
return "<id: {}, fname: {}, encodings: {}>".format(self.id, self.fname, self.encodings )
class File_Person_Link(Base):
__tablename__ = "file_person_link"
file_id = Column(Integer, ForeignKey('file.eid'), unique=True, nullable=False, primary_key=True)
person_id = Column(Integer, ForeignKey('person.id'), unique=True, nullable=False, primary_key=True)
def __repr__(self):
return "<file_id: {}, person_id: {}>".format(self.file_id, self.person_id)
################################################################################
@@ -199,6 +245,13 @@ def ProcessImportDirs(parent_job=None):
session.commit()
if parent_job:
AddLogForJob(parent_job, "adding <a href='/job/{}'>job id={} {}</a> (wait for: {})".format( job2.id, job2.id, job2.name, job2.wait_for ) )
jex3=JobExtra( name="path", value=path )
job3=Job(start_time='now()', last_update='now()', name="processai", state="New", wait_for=job.id, pa_job_state="New" )
job3.extra.append(jex3)
session.add(job3)
session.commit()
if parent_job:
AddLogForJob(parent_job, "adding <a href='/job/{}'>job id={} {}</a> (wait for: {})".format( job3.id, job3.id, job3.name, job3.wait_for ) )
HandleJobs()
return
@@ -225,6 +278,8 @@ def RunJob(job):
JobNewImportDir(job)
elif job.name =="getfiledetails":
JobGetFileDetails(job)
elif job.name == "processai":
JobProcessAI(job)
else:
print("ERROR: Requested to process unknown job type: {}".format(job.name))
# okay, we finished a job, so check for any jobs that are dependant on this and run them...
@@ -414,6 +469,16 @@ def JobNewImportDir(job):
session.commit()
return
def JobProcessAI(job):
path=[jex.value for jex in job.extra if jex.name == "path"][0]
path='static/photos'
print('meeeee',path)
for e in FilesInDir( path ):
ProcessFilesInDir(job, e, ProcessAI, lambda a: True)
FinishJob(job, "Finished Processesing AI")
r = session.query(Refimg).get(1)
print(r)
def JobImportDir(job):
JobProgressState( job, "In Progress" )
settings = session.query(Settings).first()
@@ -527,6 +592,65 @@ def HashAndThumbDirHasNew(dir):
dir.last_hash_date = time.time()
return 1
def ProcessAI(job, e):
print('AING',e)
if e.type.name != 'Image':
return
people = session.query(Person).all()
for person in people:
generateKnownEncodings(person)
file = e.in_dir[0].path_prefix + '/' + e.name
im_orig = Image.open(file)
im = ImageOps.exif_transpose(im_orig)
unknown_encodings = generateUnknownEncodings(im)
for unknown_encoding in unknown_encodings:
for person in people:
lookForPersonInImage(person, unknown_encoding, e)
return
def lookForPersonInImage(person, unknown_encoding, e):
for refimg in person.refimg:
deserialized_bytes = numpy.frombuffer(refimg.encodings, dtype=numpy.float64)
#deserialized_x = numpy.reshape(deserialized_bytes, newshape=(2,2))
results = compareAI(deserialized_bytes, unknown_encoding)
if results[0]:
print(f'Found a match between: {person.tag} and {e.name}')
fpl = File_Person_Link(person_id=person.id, file_id=e.file_details[0].eid)
session.add(fpl)
return
def generateUnknownEncodings(im):
unknown_image = numpy.array(im)
face_locations = face_recognition.face_locations(unknown_image)
unknown_encodings = face_recognition.face_encodings(unknown_image, known_face_locations=face_locations)
# should save these to the db
# file.locations = face_locations
return unknown_encodings
def generateKnownEncodings(person):
for refimg in person.refimg:
img = face_recognition.load_image_file('reference_images/'+refimg.fname)
location = face_recognition.face_locations(img)
encodings = face_recognition.face_encodings(img, known_face_locations=location)
refimg.encodings = encodings[0].tobytes()
session.add(refimg)
session.commit()
def compareAI(known_encoding, unknown_encoding):
results = face_recognition.compare_faces([known_encoding], unknown_encoding, tolerance=0.55)
return results
def ProcessFilesInDir(job, e, file_func, go_into_dir_func):
if DEBUG==1:
print("DEBUG: files in dir - process: {} {}".format(e.name, e.in_dir[0].path_prefix))
@@ -602,18 +726,17 @@ def isImage(file):
def GenImageThumbnail(job, file):
thumbnail=None
AddLogForJob( job, "Generate Thumbnail from Image file: {}".format( file ), file )
f = open(file, 'rb')
try:
tags = exifread.process_file(f)
if '20210121_223307.jpg' in file:
print("Tag: img orientation={}".format( tags['Image Orientation']) )
print("Tag: GPS GPSLatitude={}".format( tags['GPS GPSLatitude']) )
thumbnail = base64.b64encode(tags['JPEGThumbnail'])
thumbnail = str(thumbnail)[2:-1]
im_orig = Image.open(file)
im = ImageOps.exif_transpose(im_orig)
im.thumbnail((256,256))
img_bytearray = io.BytesIO()
im.save(img_bytearray, format='JPEG')
img_bytearray = img_bytearray.getvalue()
thumbnail = base64.b64encode(img_bytearray)
except:
print('WARNING: NO EXIF TAGS?!?!?!?')
AddLogForJob(job, "WARNING: No EXIF TAF found for: {}".format(file))
f.close()
return thumbnail