diff --git a/TODO b/TODO index 10c886d..f3b329d 100644 --- a/TODO +++ b/TODO @@ -3,8 +3,6 @@ * move all unsorted photos/* -> import/ - * add an option on the person menu to run_ai_on all photos (or at least import/storage) - * per file you could select an unknown face and add it as a ref img to an existing person, or make a new person and attach? * when search, have a way to hide deleted files diff --git a/ai.py b/ai.py index 3fb3fad..c1c8b45 100644 --- a/ai.py +++ b/ai.py @@ -5,9 +5,14 @@ from main import db, app, ma from sqlalchemy import Sequence from sqlalchemy.exc import SQLAlchemyError from status import st, Status -from files import Entry, File +from path import Path, PathType +from files import Entry, Dir, File, PathDirLink from person import Refimg, Person, PersonRefimgLink from flask_login import login_required, current_user +from PIL import Image +import io +import base64 +import json from job import Job, JobExtra, Joblog, NewJob from face import Face, FaceFileLink, FaceRefimgLink @@ -52,3 +57,59 @@ def run_ai_on(): job=NewJob( "run_ai_on", 0, None, jex ) st.SetMessage( f"Created Job #{job.id} to Look for face(s) in selected file(s)") return render_template("base.html") + +@app.route("/run_ai_on_import") +@login_required +def run_ai_on_import(): + jex=[] + jex.append( JobExtra( name=f"person", value="all" ) ) + paths=Path.query.join(PathType).filter(PathType.name=='Import').all() + path_cnt=0 + for p in paths: + d = Dir.query.join(PathDirLink).filter(PathDirLink.path_id==p.id).filter(Dir.rel_path=='').first() + jex.append( JobExtra( name=f"eid-{path_cnt}", value=f"{d.eid}" ) ) + path_cnt+=1 + print(jex) + job=NewJob( "run_ai_on", 0, None, jex ) + st.SetMessage( f"Created Job #{job.id} to Look for face(s) in import path(s)") + return render_template("base.html") + +@app.route("/run_ai_on_storage") +@login_required +def run_ai_on_storage(): + jex=[] + jex.append( JobExtra( name=f"person", value="all" ) ) + paths=Path.query.join(PathType).filter(PathType.name=='Storage').all() + path_cnt=0 + for p in paths: + d = Dir.query.join(PathDirLink).filter(PathDirLink.path_id==p.id).filter(Dir.rel_path=='').first() + jex.append( JobExtra( name=f"eid-{path_cnt}", value=f"{d.eid}" ) ) + path_cnt+=1 + print(jex) + job=NewJob( "run_ai_on", 0, None, jex ) + st.SetMessage( f"Created Job #{job.id} to Look for face(s) in storage path(s)") + return render_template("base.html") + +@app.route("/unmatched_faces") +@login_required +def unmatched_faces(): + faces=Face.query.join(FaceFileLink).join(FaceRefimgLink, isouter=True).filter(FaceRefimgLink.refimg_id==None).limit(10).all() + imgs={} + for face in faces: + face.locn=json.loads("["+face.locn+"]") + f = Entry.query.join(File).join(FaceFileLink).filter(FaceFileLink.face_id==face.id).first() + face.file_eid=f.id + face.url=f.FullPathOnFS() + x=face.locn[0][3]*0.95 + y=face.locn[0][0]*0.95 + x2=face.locn[0][1]*1.05 + y2=face.locn[0][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 render_template("faces.html", faces=faces) diff --git a/internal/js/face.js b/internal/js/face.js new file mode 100644 index 0000000..fca55f6 --- /dev/null +++ b/internal/js/face.js @@ -0,0 +1,29 @@ +// Define this once and before it will be called, hence at the top of this file +function DrawRefimg(fig, img, canvas, orig_face ) +{ + // FIXME: should get this from shared.py, not sure why this doesnt work at present + thumbsize=256 + + context=canvas.getContext('2d') + // another call to this func will occur on load, so skip this one + if( img.width == 0 ) + return + + // only set canvas.width once we have valid img dimensions + canvas.width=img.width/2 + + // actually draw the pixel images to the canvas at the right size + context.drawImage(img, 0, 0, img.width/(img.height/canvas.height), canvas.height); + fig.width(canvas.width) + + // draw rectangle on face + context.beginPath(); + new_x=(orig_face.x/orig_face.orig_w)*img.width/(img.height/canvas.height) + new_y=(orig_face.y/orig_face.orig_h)*thumbsize/(img.height/canvas.height) + new_w=(orig_face.w/orig_face.orig_w)*img.width/(img.height/canvas.height) + new_h=(orig_face.h/orig_face.orig_h)*thumbsize/(img.height/canvas.height) + context.rect(new_x, new_y, new_w, new_h) + context.lineWidth = 2; + context.strokeStyle = 'green'; + context.stroke(); +} diff --git a/templates/base.html b/templates/base.html index a7a235c..cffd212 100644 --- a/templates/base.html +++ b/templates/base.html @@ -74,7 +74,10 @@