import os import shutil import uuid import logging from flask import Flask, redirect, url_for, request, flash, session from flask import render_template from flask import send_file logger = logging.getLogger(__name__) logging.basicConfig(level=logging.INFO) UPLOAD_FOLDER = '/app/images' OUT_FOLDER = '/app/anno' app = Flask(__name__) app.config['SEND_FILE_MAX_AGE_DEFAULT'] = 0 app.config["SECRET_KEY"] = '#thaistartsfirst!' app.config["IMAGES"] = UPLOAD_FOLDER app.config["OUT"] = OUT_FOLDER app.config["LABELS"] = [] app.config["HEAD"] = 0 app.config["SESSION_PERMANENT"] = False # Ensure the upload directory exists if not os.path.exists(UPLOAD_FOLDER): os.makedirs(UPLOAD_FOLDER) if not os.path.exists(OUT_FOLDER): os.makedirs(OUT_FOLDER) def get_anno_path(user_id): return os.path.join(OUT_FOLDER, f'{user_id}.csv') def get_images_directory(user_id): return os.path.join(UPLOAD_FOLDER, f'{user_id}') @app.route('/', methods=['GET', 'POST']) def index(): user_id = session.get('_id') # user_id = request.cookies.get('session') if user_id is None: user_id = uuid.uuid4() session['_id'] = user_id logger.info(user_id) anno_path = get_anno_path(user_id) with open(anno_path, 'w') as f: f.write("image,id,name,xMin,xMax,yMin,yMax\n") if request.method == 'POST': if 'file' not in request.files: flash('No files selected') return redirect('/') img_dir = get_images_directory(user_id) try: os.makedirs(img_dir) except FileExistsError: logger.info('user already has an active session') files = request.files.getlist("file") filenames = [] for f in files: f.save(os.path.join(img_dir, f.filename)) filenames.append(f.filename) app.config["FILES"] = filenames # logger.info(app.config["FILES"], app.config["HEAD"]) return redirect('/tagger', code=302) else: return render_template('index.html') @app.route('/tagger') def tagger(): if (app.config["HEAD"] == len(app.config["FILES"])): # done annotating the batch of images app.config["HEAD"] = 0 return redirect(url_for('final')) user_id = session.get('_id') img_dir = get_images_directory(user_id) # app.config["IMAGES"] + f'/{user_id}' image = app.config["FILES"][app.config["HEAD"]] labels = app.config["LABELS"] not_end = not(app.config["HEAD"] == len(app.config["FILES"]) - 1) return render_template('tagger.html', not_end=not_end, directory=img_dir, image=image, labels=labels, head=app.config["HEAD"] + 1, len=len(app.config["FILES"])) @app.route('/next') def next(): image = app.config["FILES"][app.config["HEAD"]] app.config["HEAD"] = app.config["HEAD"] + 1 user_id = session.get("_id") anno_path = get_anno_path(user_id) with open(anno_path, 'a+') as f: for label in app.config["LABELS"]: f.write(image + "," + label["id"] + "," + label["name"] + "," + str(round(float(label["xMin"]))) + "," + str(round(float(label["xMax"]))) + "," + str(round(float(label["yMin"]))) + "," + str(round(float(label["yMax"]))) + "\n") app.config["LABELS"] = [] return redirect(url_for('tagger')) @app.route("/final") def final(): return render_template('final.html') @app.route('/add/') def add(id): xMin = request.args.get("xMin") xMax = request.args.get("xMax") yMin = request.args.get("yMin") yMax = request.args.get("yMax") app.config["LABELS"].append({"id":id, "name":"", "xMin":xMin, "xMax":xMax, "yMin":yMin, "yMax":yMax}) return redirect(url_for('tagger')) @app.route('/remove/') def remove(id): index = int(id) - 1 del app.config["LABELS"][index] for label in app.config["LABELS"][index:]: label["id"] = str(int(label["id"]) - 1) return redirect(url_for('tagger')) @app.route('/label/') def label(id): name = request.args.get("name") app.config["LABELS"][int(id) - 1]["name"] = name return redirect(url_for('tagger')) @app.route('/image/') def images(f): user_id = session.get('_id') img_dir = get_images_directory(user_id) img_path = os.path.join(img_dir, f'{f}') return send_file(img_path) @app.route('/download') def download(): user_id = session.get('_id') anno_path = get_anno_path(user_id) img_dir = get_images_directory(user_id) shutil.copyfile(anno_path, f'{img_dir}/annotations_pascal_voc.csv') shutil.make_archive('final', 'zip', img_dir) return send_file('final.zip', mimetype='text/csv', download_name='final.zip', as_attachment=True) if __name__ == "__main__": app.run(debug="True")