You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
229 lines
7.4 KiB
Python
229 lines
7.4 KiB
Python
#
|
|
#
|
|
# DEPENDENCIES
|
|
import os
|
|
from flask import Flask, url_for, render_template, flash, request, redirect
|
|
from werkzeug.utils import secure_filename
|
|
import json
|
|
import mariadb
|
|
import sys
|
|
from PIL import Image
|
|
|
|
#
|
|
#
|
|
# GLOBAL VARIABLES
|
|
UPLOAD_FOLDER = os.path.join(os.getcwd(), 'static/uploads/annotation-compass/')
|
|
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif'}
|
|
#
|
|
#
|
|
# FUNCTIONS
|
|
|
|
def connection():
|
|
''' Open a connection to the mariaDB database '''
|
|
try:
|
|
conn = mariadb.connect(
|
|
user="guardian_of_the_labels",
|
|
password="soup_of_the_labels",
|
|
host="localhost",
|
|
port=3306,
|
|
database='collecting_labels',
|
|
autocommit=True
|
|
)
|
|
except mariadb.Error as e:
|
|
print(f'Error connecting to MariaDB Platflorm: {e}')
|
|
sys.exit(1)
|
|
|
|
return conn
|
|
|
|
|
|
def make_link_list(names, base_url):
|
|
''' Generate a list of link from the files in a folder '''
|
|
link_list = ''
|
|
for name in names:
|
|
if allowed_file(name, ALLOWED_EXTENSIONS):
|
|
link = f'<a href="{base_url}/{name}/">{name}</a><br/>'
|
|
link_list = link_list + link
|
|
return link_list
|
|
|
|
|
|
def allowed_file(filename, extensions):
|
|
''' Check if the file extension is in the allowed extensions array '''
|
|
return '.' in filename and \
|
|
filename.rsplit('.', 1)[1].lower() in extensions
|
|
|
|
|
|
def temp_fix_date(timestamp):
|
|
''' JS Date to mySQL Date '''
|
|
from datetime import datetime
|
|
from time import strftime
|
|
date = datetime.fromtimestamp(timestamp / 1000.0)
|
|
return date.strftime('%Y-%m-%d %H:%M:%S')
|
|
|
|
|
|
def add_label(cursor, label):
|
|
''' Insert a new label in the database '''
|
|
x = label['position']['x']
|
|
y = label['position']['y']
|
|
width = label['size']['width']
|
|
height = label['size']['height']
|
|
text = label['text']
|
|
timestamp = temp_fix_date(label['timestamp'])
|
|
user_id = str(label['userID'])
|
|
image = label['image']
|
|
|
|
try:
|
|
cursor.execute(f'INSERT INTO labels (x,y,width,height,text,timestamp,userID,image) VALUES (?, ?, ?, ?, ?, ?, ?, ?)', (x, y, width, height, text, timestamp, user_id, image ))
|
|
print(f'Insert label#{cursor.lastrowid} from user {user_id} on {image} at {timestamp}.')
|
|
except mariadb.Error as e:
|
|
print(f"Error error error in MariaDB Platform: {e}")
|
|
return {"message":"oh no", "error":e}
|
|
|
|
|
|
def get_labels(cursor, filename):
|
|
''' List the labels for a specific image from the database '''
|
|
try:
|
|
cursor.execute(f"SELECT * FROM labels WHERE image = '{filename}'")
|
|
db_labels = cursor.fetchall()
|
|
labels = []
|
|
for (index, x, y, width, height, text, timestamp, user_id, image) in db_labels:
|
|
label = {
|
|
'position': {
|
|
'x': x,
|
|
'y': y
|
|
},
|
|
'size': {
|
|
'width': width,
|
|
'height': height
|
|
},
|
|
'text': text,
|
|
'timestamp': timestamp,
|
|
'userID': user_id,
|
|
'image': image
|
|
}
|
|
labels.append(label)
|
|
return labels
|
|
except mariadb.Error as e:
|
|
print(f"Error error error in MariaDB Platform: {e}")
|
|
return {"message":"oh no", "error":e}
|
|
|
|
|
|
def add_image_description(filename, description):
|
|
''' Set description for an image during upload '''
|
|
image_description_output = {}
|
|
with open(os.path.join(os.getcwd(), "projects/annotation-compass/descriptions.json"), "r") as f:
|
|
image_description_input = json.loads(f.read())
|
|
image_description_output = image_description_input
|
|
image_description_output[filename] = {
|
|
'description': description
|
|
}
|
|
|
|
with open(os.path.join(os.getcwd(), "projects/annotation-compass/descriptions.json"), "w") as f:
|
|
f.write(json.dumps(image_description_output))
|
|
|
|
|
|
|
|
|
|
def get_image_description(filename):
|
|
''' Get the description of an uploaded image '''
|
|
with open(os.path.join(os.getcwd(), "projects/annotation-compass/descriptions.json"), "r") as f:
|
|
descriptions = json.loads(f.read())
|
|
return descriptions[filename]['description']
|
|
|
|
|
|
def thumbnail(image):
|
|
try:
|
|
img = Image.open(image)
|
|
img.thumbnail((128,128))
|
|
name = image.rsplit('.', 1)[0]
|
|
ext = image.rsplit('.', 1)[1]
|
|
img.save(f'{name}_thumb.{ext}')
|
|
except IOError:
|
|
pass
|
|
|
|
|
|
# TODO: clean up this dai
|
|
# /generic-labels/ → /si16/annotation-compass/ (GET, POST)
|
|
def upload_file(request):
|
|
''' Upload a new image in the Annotation Compass '''
|
|
# check if the post request has the file part
|
|
if 'file' not in request.files:
|
|
flash('No file part')
|
|
return redirect(request.url)
|
|
file = request.files['file']
|
|
# If the user does not select a file, the browser submits an
|
|
# empty file without a filename.
|
|
if file.filename == '':
|
|
flash('No selected file')
|
|
return redirect(request.url)
|
|
if file and allowed_file(file.filename, ALLOWED_EXTENSIONS):
|
|
filename = secure_filename(file.filename)
|
|
file.save(os.path.join(UPLOAD_FOLDER, filename))
|
|
thumbnail(os.path.join(UPLOAD_FOLDER, filename))
|
|
description = request.form['description']
|
|
add_image_description(filename, description)
|
|
|
|
|
|
def list_images():
|
|
''' List the images in the Annotation Compass. '''
|
|
files = os.listdir(UPLOAD_FOLDER)
|
|
files.sort()
|
|
|
|
not_thumbs = filter(lambda file: '_thumb.' not in file, files)
|
|
|
|
images = []
|
|
for image in not_thumbs:
|
|
if allowed_file(image, ALLOWED_EXTENSIONS):
|
|
name = image.rsplit('.', 1)[0]
|
|
ext = image.rsplit('.', 1)[1]
|
|
img = image
|
|
thumb = f'{name}_thumb.{ext}'
|
|
images.append((img, thumb))
|
|
return images
|
|
|
|
# links = make_link_list(images, 'annotate/' )
|
|
|
|
# TODO: transform this in a template
|
|
# return f'''
|
|
# <!doctype html>
|
|
# <title>Collecting Labels</title>
|
|
# {links}
|
|
# <h2>Upload new File</h2>
|
|
# <form method=post enctype=multipart/form-data>
|
|
# <input type=file name=file>
|
|
# <input type=submit value=Upload>
|
|
# <textarea name=description ></textarea>
|
|
# </form>
|
|
# '''
|
|
|
|
# /generic-labels/annotate/<image>/ → /si16/annotation-compass/annotate/<image>/
|
|
# def annotate_image(image=None):
|
|
# ''' Open the Annotation Compass on a specific image '''
|
|
# description = ''
|
|
# try:
|
|
# description = get_image_description(image)
|
|
# except:
|
|
# print("There is no description")
|
|
# return render_template('annotate_image.html', image=image, description=description)
|
|
|
|
|
|
# /generic-labels/add-label/ → /si16/annotation-compass/add-label
|
|
# in the URL there is no reference to the image because the info is in the json body of the label itself
|
|
def insert_label(request):
|
|
''' Insert a new label in the database '''
|
|
connect = connection()
|
|
cursor = connect.cursor()
|
|
add_label(cursor, request.json)
|
|
connect.close()
|
|
return {"response": "ok"}
|
|
|
|
# /generic-labels/get-labels/ → /si16/annotation-compass/get-labels/<image>/
|
|
# TODO: adapt the old url with the query
|
|
# OLD: /get-labels/?image=<image>
|
|
# NEW: /get-labels/<image>/
|
|
|
|
def get_labels_list(image = None):
|
|
connect = connection()
|
|
cursor = connect.cursor()
|
|
labels = get_labels(cursor, image)
|
|
connect.close()
|
|
return {"response": "ok", "labels": labels } |