|
|
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 |
|
|
|
|
|
|
|
|
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') |
|
|
|
|
|
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 |
|
|
|
|
|
return redirect('/tagger', code=302) |
|
|
else: |
|
|
return render_template('index.html') |
|
|
|
|
|
|
|
|
@app.route('/tagger') |
|
|
def tagger(): |
|
|
if (app.config["HEAD"] == len(app.config["FILES"])): |
|
|
|
|
|
app.config["HEAD"] = 0 |
|
|
return redirect(url_for('final')) |
|
|
user_id = session.get('_id') |
|
|
img_dir = get_images_directory(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/<id>') |
|
|
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/<id>') |
|
|
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/<id>') |
|
|
def label(id): |
|
|
name = request.args.get("name") |
|
|
app.config["LABELS"][int(id) - 1]["name"] = name |
|
|
return redirect(url_for('tagger')) |
|
|
|
|
|
@app.route('/image/<f>') |
|
|
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") |
|
|
|