File size: 6,748 Bytes
9bbf7fe 2f83e6d d806786 9bbf7fe 4a33e04 9bbf7fe 2f83e6d a190092 2a4e18c a190092 9bbf7fe a190092 9bbf7fe 43bd8fd 9bbf7fe a190092 2a4e18c a190092 2a4e18c a190092 9bbf7fe 7a43999 9bbf7fe 7a43999 9bbf7fe 2f83e6d 7a43999 43bd8fd 9bbf7fe 7a43999 9bbf7fe 7a43999 a190092 2f83e6d 9bbf7fe 7a43999 9bbf7fe e8b9871 9bbf7fe 43bd8fd 9bbf7fe 43bd8fd 7a43999 9bbf7fe 7a43999 9bbf7fe 43bd8fd 9bbf7fe 01f7b8a 9bbf7fe 01f7b8a 9bbf7fe 43bd8fd 9bbf7fe 01f7b8a 9bbf7fe 01f7b8a 9bbf7fe d806786 9bbf7fe d806786 9bbf7fe 01f7b8a 9bbf7fe 7a43999 ccf3267 9bbf7fe 01f7b8a 9bbf7fe 7a43999 43bd8fd 4a33e04 7a43999 4a33e04 9bbf7fe 4a33e04 9bbf7fe 01f7b8a 9bbf7fe d806786 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 |
import os
import shutil
import uuid
import logging
import json
from flask import Flask, redirect, url_for, request, flash, session, after_this_request
from flask import render_template
from flask import send_file
logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO)
UPLOAD_FOLDER = './images'
OUT_FOLDER = './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["CATEGORIES"] = {} # []
app.config["HEAD"] = 0
app.config["SESSION_PERMANENT"] = False
# Ensure the upload directory exists
#if not os.path.exists(os.path.join(os.getcwd(), UPLOAD_FOLDER)):
if not os.path.exists(UPLOAD_FOLDER):
os.makedirs(UPLOAD_FOLDER)
#if not os.path.exists(os.path.join(os.getcwd(), OUT_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,category,name,xMin,yMin,xMax,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')
# app.config["IMAGES"] + f'/{user_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 + "," +
str(label["category"]) + "," +
label["name"] + "," +
str(round(float(label["xMin"]))) + "," +
str(round(float(label["yMin"]))) + "," +
str(round(float(label["xMax"]))) + "," +
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": "", "category": "", "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").lower()
app.config["LABELS"][int(id) - 1]["name"] = name
category = app.config["CATEGORIES"].get(name, None)
if category is None:
# add to category
category = len(app.config["CATEGORIES"])
app.config["CATEGORIES"][name] = category
app.config["LABELS"][int(id) - 1]["category"] = category
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)
data = {}
with open(anno_path, 'r') as f:
for line in f.readlines():
elems = line.strip().split(',')
file_name = data.get(elems[0], None)
if file_name is None:
data[elems[0]] = {'bbox': [], 'categories': [], 'names': []}
data[elems[0]]['categories'].append(int(elems[1]))
data[elems[0]]['names'].append(elems[2])
data[elems[0]]['bbox'].append([int(elems[i]) for i in range(3, len(elems))])
img_dataset = []
for file_name, obj in data.items():
img_dataset.append(
{
'file_name': file_name,
'objects': obj
}
)
with open(f'{img_dir}/metadata.jsonl', 'w') as f:
for item in img_dataset:
f.write(json.dumps(item) + "\n")
#shutil.copyfile(anno_path, f'{img_dir}/annotations_pascal_voc.csv')
download_zip = os.path.join(img_dir, 'final')
print(download_zip)
shutil.make_archive('final', 'zip', img_dir)
# shutil.make_archive(base_name=download_zip,
# format='zip',
# base_dir=img_dir)
@after_this_request
def remove_directory(response):
try:
shutil.rmtree(img_dir)
os.remove(anno_path)
except Exception as e:
print(f"Error deleting directory {img_dir}: {e}")
return response
return send_file('final.zip',
mimetype='text/csv',
download_name='annotated_data.zip',
as_attachment=True)
if __name__ == "__main__":
app.run(debug="True")
|