summaryrefslogtreecommitdiff
path: root/old/server/app/main
diff options
context:
space:
mode:
Diffstat (limited to 'old/server/app/main')
-rw-r--r--old/server/app/main/__init__.py5
-rw-r--r--old/server/app/main/errors.py32
-rw-r--r--old/server/app/main/forms.py60
-rw-r--r--old/server/app/main/img_proc_config.py20
-rw-r--r--old/server/app/main/paths.py19
-rw-r--r--old/server/app/main/tasks.py374
-rw-r--r--old/server/app/main/utils.py37
-rw-r--r--old/server/app/main/views.py300
8 files changed, 847 insertions, 0 deletions
diff --git a/old/server/app/main/__init__.py b/old/server/app/main/__init__.py
new file mode 100644
index 00000000..a21e2754
--- /dev/null
+++ b/old/server/app/main/__init__.py
@@ -0,0 +1,5 @@
+from flask import Blueprint
+
+main = Blueprint('main', __name__)
+
+from . import views, errors, tasks, utils \ No newline at end of file
diff --git a/old/server/app/main/errors.py b/old/server/app/main/errors.py
new file mode 100644
index 00000000..60b5f227
--- /dev/null
+++ b/old/server/app/main/errors.py
@@ -0,0 +1,32 @@
+from flask import render_template, request, jsonify
+from . import main
+
+
+@main.app_errorhandler(403)
+def forbidden(e):
+ if request.accept_mimetypes.accept_json and \
+ not request.accept_mimetypes.accept_html:
+ response = jsonify({'error': 'forbidden'})
+ response.status_code = 403
+ return response
+ return render_template('403.html'), 403
+
+
+@main.app_errorhandler(404)
+def page_not_found(e):
+ if request.accept_mimetypes.accept_json and \
+ not request.accept_mimetypes.accept_html:
+ response = jsonify({'error': 'not found'})
+ response.status_code = 404
+ return response
+ return render_template('404.html'), 404
+
+
+@main.app_errorhandler(500)
+def internal_server_error(e):
+ if request.accept_mimetypes.accept_json and \
+ not request.accept_mimetypes.accept_html:
+ response = jsonify({'error': 'internal server error'})
+ response.status_code = 500
+ return response
+ return render_template('500.html'), 500
diff --git a/old/server/app/main/forms.py b/old/server/app/main/forms.py
new file mode 100644
index 00000000..bc1399ad
--- /dev/null
+++ b/old/server/app/main/forms.py
@@ -0,0 +1,60 @@
+from flask.ext.wtf import Form
+from wtforms import StringField, TextAreaField, BooleanField, SelectField,\
+ SubmitField
+from wtforms.validators import Required, Length, Email, Regexp
+from wtforms import ValidationError
+from flask.ext.pagedown.fields import PageDownField
+from ..models import Role, User
+
+
+class NameForm(Form):
+ name = StringField('What is your name?', validators=[Required()])
+ submit = SubmitField('Submit')
+
+
+class EditProfileForm(Form):
+ name = StringField('Real name', validators=[Length(0, 64)])
+ location = StringField('Location', validators=[Length(0, 64)])
+ about_me = TextAreaField('About me')
+ submit = SubmitField('Submit')
+
+
+class EditProfileAdminForm(Form):
+ email = StringField('Email', validators=[Required(), Length(1, 64),
+ Email()])
+ username = StringField('Username', validators=[
+ Required(), Length(1, 64), Regexp('^[A-Za-z][A-Za-z0-9_.]*$', 0,
+ 'Usernames must have only letters, '
+ 'numbers, dots or underscores')])
+ confirmed = BooleanField('Confirmed')
+ role = SelectField('Role', coerce=int)
+ name = StringField('Real name', validators=[Length(0, 64)])
+ location = StringField('Location', validators=[Length(0, 64)])
+ about_me = TextAreaField('About me')
+ submit = SubmitField('Submit')
+
+ def __init__(self, user, *args, **kwargs):
+ super(EditProfileAdminForm, self).__init__(*args, **kwargs)
+ self.role.choices = [(role.id, role.name)
+ for role in Role.query.order_by(Role.name).all()]
+ self.user = user
+
+ def validate_email(self, field):
+ if field.data != self.user.email and \
+ User.query.filter_by(email=field.data).first():
+ raise ValidationError('Email already registered.')
+
+ def validate_username(self, field):
+ if field.data != self.user.username and \
+ User.query.filter_by(username=field.data).first():
+ raise ValidationError('Username already in use.')
+
+
+class PostForm(Form):
+ body = PageDownField("What's on your mind?", validators=[Required()])
+ submit = SubmitField('Submit')
+
+
+class CommentForm(Form):
+ body = StringField('Enter your comment', validators=[Required()])
+ submit = SubmitField('Submit')
diff --git a/old/server/app/main/img_proc_config.py b/old/server/app/main/img_proc_config.py
new file mode 100644
index 00000000..db124978
--- /dev/null
+++ b/old/server/app/main/img_proc_config.py
@@ -0,0 +1,20 @@
+# paths for image processors
+import os
+from os.path import join
+
+class ImgProcConfig:
+
+ def __init__(self):
+ dir_models = '/data_store/apps/dulldream/dnn_models'
+
+ # mask rcnn
+ self.mask_rcnn_class_config = '/dulldream/src/config/coco_meta.json'
+ self.mask_rcnn_model = join(dir_models,'tf/mask_rcnn_coco.h5')
+
+ # p2p
+ self.p2p_ckpts_dir = join(dir_models,'p2p/coco2014_person')
+ self.p2p_epoch = 'latest'
+
+ # p2p objects only
+ self.p2p_bg_ckpts_dir = join(dir_models,'p2p/coco2014_objects')
+ self.p2p_bg_epoch = 'latest'
diff --git a/old/server/app/main/paths.py b/old/server/app/main/paths.py
new file mode 100644
index 00000000..69c21627
--- /dev/null
+++ b/old/server/app/main/paths.py
@@ -0,0 +1,19 @@
+from flask import current_app as app
+
+def get_paths(agree):
+ if agree:
+ return (
+ app.config['UPLOADS'],
+ app.config['RENDERS'],
+ app.config['JSON_DIR'],
+ app.config['UPLOADS_URI'],
+ app.config['RENDERS_URI'],
+ )
+ else:
+ return (
+ app.config['UPLOADS_PRIVATE'],
+ app.config['RENDERS_PRIVATE'],
+ app.config['JSON_PRIVATE_DIR'],
+ app.config['UPLOADS_PRIVATE_URI'],
+ app.config['RENDERS_PRIVATE_URI'],
+ )
diff --git a/old/server/app/main/tasks.py b/old/server/app/main/tasks.py
new file mode 100644
index 00000000..970e6988
--- /dev/null
+++ b/old/server/app/main/tasks.py
@@ -0,0 +1,374 @@
+import os
+import sys
+import time
+import datetime
+import json
+from PIL import Image, ImageFilter
+import cv2 as cv
+import numpy as np
+from . import main, utils
+from .. import basemodels
+from flask import current_app as app
+from .paths import get_paths
+celery = basemodels.celery
+from celery.utils.log import get_task_logger
+celery_logger = get_task_logger(__name__)
+import imutils
+
+
+# init image processors
+sys.path.append('/dulldream/src/')
+from .img_proc_config import ImgProcConfig
+from image_processors.mask_rcnn import MaskRCNN
+from image_processors.pix2pix import Pix2Pix
+from utils import imx
+from utils import fiox
+
+
+# initialize image processor
+img_proc_config = ImgProcConfig()
+p2p = Pix2Pix(img_proc_config.p2p_ckpts_dir,epoch=img_proc_config.p2p_epoch)
+p2p_objects = Pix2Pix(img_proc_config.p2p_bg_ckpts_dir,epoch=img_proc_config.p2p_epoch)
+
+mask_rcnn = MaskRCNN(img_proc_config.mask_rcnn_class_config,
+ model_path=img_proc_config.mask_rcnn_model)
+
+
+@celery.task(bind=True)
+def task_dull(self, uuid_name, agree, mask_rcnn_result):
+ """Process image and update during"""
+ celery_logger.debug('process_image_task, uuid: {}'.format(uuid_name))
+
+ upload_dir, render_dir, json_dir, upload_uri, render_uri = get_paths(agree)
+
+ files = []
+ im = Image.open(os.path.join(upload_dir, uuid_name + '.jpg')).convert('RGB')
+ #im_np = cv.cvtColor(imx.ensure_np(im),cv.COLOR_RGB2BGR)
+ im_np = imx.ensure_np(im)
+ im_np = im_np[:,:,::-1]
+ im = im.resize((256,256))
+ im_np_256 = imutils.resize(im_np,width=256)
+
+ # Add original
+ fpath = os.path.join(render_dir, uuid_name + '_orig.jpg')
+ im.save(fpath, 'JPEG', quality=95)
+ files.append({
+ 'title': 'Original',
+ 'fn': render_uri + uuid_name + '_orig.jpg'
+ })
+
+ if mask_rcnn_result['valid']:
+ # -----------------------------------------------
+ # Segment image (processed in views)
+ # seems to be an error with async celery processor?
+ # -----------------------------------------------
+
+ # parse mrcnn data
+ im_mask = cv.imread(mask_rcnn_result['fp_im_mask'])
+ seg_mask = cv.imread(mask_rcnn_result['fp_seg_mask'])
+ #score = mask_rcnn_result['score']
+ #name = mask_rcnn_result['name']
+ #color = mask_rcnn_result['color']
+ files.append({
+ 'title': 'Semantic Segmentation',
+ 'fn': render_uri + uuid_name + '_seg_mask.jpg'
+ })
+ files.append({
+ 'title': 'Semantic Segmentation Isolate',
+ 'fn': render_uri + uuid_name + '_im_mask.jpg'
+ })
+
+
+ # -----------------------------------------------
+ # run rag generator
+ # -----------------------------------------------
+
+ self.update_state(
+ state = 'PROCESSING',
+ meta = {
+ 'percent': 0.50,
+ 'message': 'Applying Region Adjacency Graph',
+ 'uuid': uuid_name
+ })
+
+ # save the regions adjancency graph
+ im_rag = imx.create_rag_mean(im_mask,compactness=30,n_segments=128)
+ fpath = os.path.join(render_dir, uuid_name + '_rgraph.jpg')
+ imx.save_np_as_pil(fpath,im_rag,quality=95)
+ files.append({
+ 'title': 'Region Adjacency Graph',
+ 'fn': render_uri + uuid_name + '_rgraph.jpg'
+ })
+
+
+ # -----------------------------------------------
+ # generate p2p fake
+ # -----------------------------------------------
+
+ self.update_state(
+ state = 'PROCESSING',
+ meta = {
+ 'percent': 0.75,
+ 'message': 'Running generative adversarial network...',
+ 'uuid': uuid_name
+ })
+
+
+ # convert segmentation to mask
+ seg_mask_gray = cv.cvtColor(seg_mask,cv.COLOR_BGR2GRAY)
+ seg_mask_gray[seg_mask_gray > 1] = 255
+
+ # find best P2P fit
+ ims_p2p = []
+ match_amts = []
+ iters = 15
+ for i in range(0,iters):
+ im_p2p = p2p.create_p2p(im_rag)
+ ims_p2p.append(im_p2p)
+ im_p2p_mask = cv.cvtColor(im_p2p,cv.COLOR_RGB2GRAY)
+ im_p2p_mask[im_p2p_mask > 1] = 255
+ # find where masks intersect
+ matches = np.bitwise_and(im_p2p_mask,seg_mask_gray)
+ amt = len(np.where(matches == 255)[0])
+ match_amts.append(amt)
+ self.update_state(
+ state = 'PROCESSING',
+ meta = {
+ 'percent': 0.75,
+ 'message': 'Generating ({}/{})'.format(i,iters),
+ 'uuid': uuid_name
+ })
+
+ best_idx = np.argmax(match_amts)
+ im_p2p = ims_p2p[best_idx]
+
+ fpath = os.path.join(render_dir, uuid_name + '_gan.jpg')
+ imx.save_np_as_pil(fpath,im_p2p,quality=95)
+ files.append({
+ 'title': 'Generative Adversarial Network',
+ 'fn': render_uri + uuid_name + '_gan.jpg'
+ })
+
+
+ # -----------------------------------------------
+ # generate p2p fake
+ # -----------------------------------------------
+
+ # announce to user
+ self.update_state(
+ state = 'PROCESSING',
+ meta = {
+ 'percent': 0.90,
+ 'message': 'Compositing images...',
+ 'uuid': uuid_name
+ })
+
+
+ # apply masked cloning
+ im_p2p_gray = cv.cvtColor(im_p2p,cv.COLOR_BGR2GRAY)
+ im_clone_mask = np.zeros_like(im_p2p_gray,dtype=np.uint8)
+ im_clone_mask[im_p2p_gray > 1] = 255
+
+
+ # apply smoothed copy+paste clone
+ im_blur_mask = np.zeros(im_np_256.shape[:2],dtype=np.float64)
+ im_blur_mask[im_p2p_gray > 1] = 1.0
+ im_blur_mask = np.array([im_blur_mask,im_blur_mask,im_blur_mask]).transpose((1,2,0))
+
+ # erode mask to remove black border
+ kernel = np.ones((3,3),np.uint8)
+ im_blur_mask = cv.erode(im_blur_mask,kernel,iterations = 3)
+
+ # feather mask
+ feather_amt = (3,3)
+ im_blur_mask = (cv.GaussianBlur(im_blur_mask,feather_amt, 0) > 0) * 1.0 #?
+ im_blur_mask = cv.GaussianBlur(im_blur_mask,feather_amt, 0)
+ im_blur_mask = np.clip(im_blur_mask,0.0,1.0)
+
+ # mask p2p fg --> photo bg
+ im_dull = im_np_256.astype(np.float64) * (1.0 - im_blur_mask) + im_p2p.astype(np.float64) * im_blur_mask
+ im_dull = im_dull.astype(np.uint8)
+
+
+ else:
+ print('No person. Apply background P2P')
+ celery_logger.debug('No person. Apply background P2P, uuid: {}'.format(uuid_name))
+ im_bg_blur = cv.GaussianBlur(im_np_256,(31,31),0)
+ im_bg_rag = imx.create_rag_mean(im_bg_blur,compactness=30,n_segments=64)
+
+ # apply gan
+ im_dull = p2p_objects.create_p2p(im_bg_rag)
+
+ # resize back to full 512px
+ im_dull_512 = imutils.resize(im_dull,width=512)
+
+ # save dulldream image
+ fpath = os.path.join(render_dir, uuid_name + '_dull.jpg')
+ imx.save_np_as_pil(fpath,im_dull_512,quality=95)
+ files.append({
+ 'title': 'Your DullDream',
+ 'fn': render_uri + uuid_name + '_dull.jpg'
+ })
+
+
+ # -----------------------------------------------
+ # Write data to disk
+ # -----------------------------------------------
+
+ data = {
+ 'uuid': uuid_name,
+ 'date': str(datetime.datetime.now()),
+ 'files': files
+ }
+
+ json_path = os.path.join(json_dir, uuid_name + '.json')
+ with open(json_path, 'w') as json_file:
+ json.dump(data, json_file)
+
+ return {
+ 'percent': 100,
+ 'state': 'complete',
+ 'uuid': uuid_name
+ }
+
+
+
+
+@celery.task(bind=True)
+def blur_task(self, uuid_name, agree, extra):
+ """Process image and update during"""
+ celery_logger.debug('process_image_task, uuid: {}'.format(uuid_name))
+
+ upload_dir, render_dir, json_dir, upload_uri, render_uri = get_paths(agree)
+
+ files = []
+
+ im = Image.open(os.path.join(upload_dir, uuid_name + '.jpg')).convert('RGB')
+ im = im.resize((256,256))
+ files.append({
+ 'title': 'Original image',
+ 'fn': upload_uri + uuid_name + '.jpg'
+ })
+
+ self.update_state(
+ state = 'PROCESSING',
+ meta = {
+ 'percent': 0.25,
+ 'message': 'Applying blur',
+ 'uuid': uuid_name
+ })
+
+ im_np = utils.ensure_np(im)
+ im_blur = cv.blur(im_np, (5,5), 1.0)
+ im_blur_pil = utils.ensure_pil(im_blur)
+
+ fn = uuid_name + '_blur.jpg'
+ fpath = os.path.join(render_dir, fn)
+ im_blur_pil.save(fpath, 'JPEG', quality=95)
+
+ files.append({
+ 'title': 'Blurred image',
+ 'fn': render_uri + uuid_name + '_blur.jpg'
+ })
+
+ time.sleep(3)
+
+ self.update_state(
+ state = 'PROCESSING',
+ meta = {
+ 'percent': 0.50,
+ 'message': 'Sleeping for some reason',
+ 'uuid': uuid_name
+ })
+ time.sleep(2)
+
+ self.update_state(
+ state = 'PROCESSING',
+ meta = {
+ 'percent': 0.75,
+ 'message': 'Sleeping some more',
+ 'uuid': uuid_name
+ })
+ time.sleep(2)
+
+ data = {
+ 'uuid': uuid_name,
+ 'date': str(datetime.datetime.now()),
+ 'files': files
+ }
+
+ json_path = os.path.join(json_dir, uuid_name + '.json')
+ with open(json_path, 'w') as json_file:
+ json.dump(data, json_file)
+
+ celery_logger.debug('ok')
+
+ return {
+ 'percent': 100,
+ 'state': 'complete',
+ 'uuid': uuid_name,
+ }
+
+@celery.task(bind=True)
+def sleep_task(self, uuid_name):
+ celery_logger.debug('sleep_task'.format(uuid_name))
+ msgs = [
+ {'msg':'Uploaded OK','time':.1},
+ {'msg':'Segmenting Image...','time':2},
+ {'msg':'Found: Person, Horse','time':1},
+ {'msg':'Creating Pix2Pix','time':2}
+ ]
+ for i,m in enumerate(msgs):
+ percent = int(float(i)/float(len(msgs))*100.0)
+ self.update_state(
+ state = 'PROCESSING',
+ meta = {
+ 'percent': percent,
+ 'message': m['msg'],
+ 'uuid': uuid_name
+ })
+ celery_logger.debug(m['msg'])
+ time.sleep(m['time'])
+
+ return {
+ 'percent': 100,
+ 'state': 'complete',
+ 'uuid': uuid_name
+ }
+
+def make_task_json():
+ dropdown = {}
+ for k,v in task_lookup.items():
+ if 'active' not in v or v['active'] is not False:
+ is_default = 'default' in v and v['default'] is True
+ task = {
+ 'name': k,
+ 'title': v['title'],
+ 'selected': is_default,
+ }
+ dropdown[k] = task
+ return json.dumps(dropdown)
+
+# Add all valid tasks to this lookup.
+# Set 'active': False to disable a task
+# Set 'default': True to define the default task
+
+task_lookup = {
+ 'sleep': {
+ 'title': 'Sleep Test',
+ 'task': sleep_task,
+ 'active': False
+ },
+ 'blur': {
+ 'title': 'Blur',
+ 'task': blur_task,
+ 'active': False
+ },
+ 'task_dull': {
+ 'title': 'DullDream V2',
+ 'task': task_dull,
+ 'active': True,
+ 'default': True
+ }
+}
+
diff --git a/old/server/app/main/utils.py b/old/server/app/main/utils.py
new file mode 100644
index 00000000..62d9c95f
--- /dev/null
+++ b/old/server/app/main/utils.py
@@ -0,0 +1,37 @@
+from flask import current_app as app
+from PIL import Image
+import numpy as np
+import cv2 as cv
+import os
+from os.path import join
+
+def ensure_pil(im):
+ try:
+ im.verify()
+ return im
+ except:
+ return Image.fromarray(im.astype('uint8'), 'RGB')
+
+def ensure_np(im):
+ if type(im) == np.ndarray:
+ return im
+ return np.asarray(im, np.uint8)
+
+def get_recent_uploads(limit=10):
+ d_uploads = app.config['UPLOADS']
+ d_renders = app.config['RENDERS']
+
+ # list all files in uploads dir
+ filenames = [s for s in os.listdir(d_uploads)
+ if os.path.isfile(os.path.join(d_uploads, s))]
+ # sort uploaded files by date
+ filenames.sort(key=lambda s: os.path.getmtime(os.path.join(d_uploads, s)),reverse=True)
+ basenames = [os.path.splitext(os.path.basename(f))[0] for f in filenames]
+ basenames = basenames[:limit]
+ filenames = [f for f in basenames if os.path.isfile(join(d_renders,'{}_dull.jpg'.format(f)))]
+
+ # create list for uploads and renders
+ uploads = [join('/img/uploads',f) for f in filenames]
+ renders = [join('/img/renders','{}_dull'.format(f)) for f in filenames]
+ urls = [join('/d',f) for f in basenames]
+ return uploads, renders, urls
diff --git a/old/server/app/main/views.py b/old/server/app/main/views.py
new file mode 100644
index 00000000..11a8ca53
--- /dev/null
+++ b/old/server/app/main/views.py
@@ -0,0 +1,300 @@
+import os
+import uuid
+import json
+from flask import render_template, redirect, url_for, send_from_directory
+from flask import request, make_response, jsonify
+from . import main, utils
+from .tasks import task_lookup, make_task_json
+from PIL import Image, ImageOps
+import cv2 as cv
+
+from .paths import get_paths
+
+from flask import current_app as app
+from werkzeug.utils import secure_filename
+import imutils
+
+# ------------------------------------------------------------
+# Temp: run mask rcnn outside celery
+# ------------------------------------------------------------
+
+# init image processors
+import sys
+from .img_proc_config import ImgProcConfig
+sys.path.append('/dulldream/src/')
+from image_processors.mask_rcnn import MaskRCNN
+from utils import imx
+from utils import fiox
+
+img_proc_congif = ImgProcConfig()
+mask_rcnn = MaskRCNN(img_proc_congif.mask_rcnn_class_config,
+ model_path=img_proc_congif.mask_rcnn_model)
+
+# ------------------------------------------------------------
+# Tasks
+# ------------------------------------------------------------
+
+@main.route('/status/<task_name>/<task_id>')
+def task_status(task_name, task_id):
+ """Return celery image processing status"""
+ if task_name in task_lookup:
+ task = task_lookup[task_name]['task'].AsyncResult(task_id)
+ else:
+ return jsonify({
+ 'state': 'error',
+ 'percent': 100,
+ 'message': 'Unknown task'
+ })
+
+ app.logger.info('task state: {}'.format(task.state))
+ if task.state == 'PENDING':
+ response = {
+ 'state': task.state,
+ 'percent': 0,
+ 'message': 'Pending...'
+ }
+ elif task.state != 'FAILURE':
+ response = {
+ 'state': task.state,
+ 'percent': task.info.get('percent', 0),
+ 'uuid': task.info.get('uuid', 0),
+ 'message': task.info.get('message', '')
+ }
+ if 'result' in task.info:
+ response['result'] = task.info['result']
+ else:
+ # something went wrong in the background job
+ response = {
+ 'state': task.state,
+ 'percent': 100,
+ 'message': str(task.info), # this is the exception raised
+ }
+ return jsonify(response)
+
+# ------------------------------------------------------------
+# POST Routes
+# ------------------------------------------------------------
+
+@main.route('/upload/sleep', methods=['GET', 'POST'])
+def sleep_test():
+ async_task = task_lookup['sleep']['task'].apply_async(args=['sleep_test'])
+ task_url = url_for('main.task_status', task_name='sleep', task_id=async_task.id)
+ return jsonify({
+ 'result': True,
+ 'task_url': task_url,
+ })
+
+@main.route('/upload', methods=['POST'])
+def upload():
+
+ style = request.form['style']
+ print('style',style)
+ if style in task_lookup:
+ task = task_lookup[style]['task']
+ print('task',task)
+ else:
+ return jsonify({
+ 'result': False,
+ 'error': 'Unknown task',
+ })
+
+ file = request.files['user_image']
+ agree = bool(request.form['agree'])
+ ext = request.form['ext']
+ if ext is None:
+ ext = request.files['ext']
+
+ uuid_name = str(uuid.uuid4())
+
+ app.logger.info('[+] style: {}'.format(style))
+ app.logger.info('[+] ext: {}'.format(ext))
+ app.logger.info('[+] uuid_name: {}'.format(uuid_name))
+ app.logger.info('[+] agreed: {}'.format(agree))
+
+ # convert PNG to JPG
+ print('[+] Resizing image')
+
+ # LOL MaskRCNN needs to be run outside of the Celery Task
+ im = Image.open(file.stream).convert('RGB')
+ im = ImageOps.fit(im,(512,512))
+ if agree:
+ upload_folder = app.config['UPLOADS']
+ else:
+ upload_folder = app.config['UPLOADS_PRIVATE']
+
+ fpath = os.path.join(upload_folder, uuid_name + '.jpg')
+
+ # Save image to disk
+ print('[+] Save image to {}'.format(fpath))
+ im.save(fpath, 'JPEG', quality=100)
+ im_pil_256 = im.resize((256,256))
+
+ print('[+] ensure_np...')
+ im_np = imx.ensure_np(im_pil_256)
+ #print('[+] resize np...')
+ #im_np = imutils.resize(im_np,width=256)
+
+ upload_dir, render_dir, json_dir, upload_uri, render_uri = get_paths(agree)
+
+ print('[+] Run mrcnn...')
+ try:
+ result = mask_rcnn.create_segmentations(im_np,concat=True)
+ except:
+ print('[-] Error. Could not run mask_rcnn')
+ result = []
+
+ if len(result) > 0:
+ result = result[0]
+
+ # save data, then pass to celery task
+ print('[+] Save masks')
+ seg_mask = result['seg_mask']
+ fpath_seg_mask = os.path.join(render_dir, uuid_name + '_seg_mask.jpg')
+ #cv.imwrite(fpath_seg_mask,cv.cvtColor(seg_mask,cv.COLOR_BGR2RGB))
+ #seg_mask = seg_mask[:,:,::-1]
+ seg_mask_pil = imx.ensure_pil(seg_mask)
+ seg_mask_pil.save(fpath_seg_mask, 'JPEG', quality=100)
+
+ im_mask = result['im_mask']
+ fpath_im_mask = os.path.join(render_dir, uuid_name + '_im_mask.jpg')
+ #im_mask = im_mask[:,:,::-1]
+ im_mask_pil = imx.ensure_pil(im_mask)
+ im_mask_pil.save(fpath_im_mask, 'JPEG',quality=100)
+ #cv.imwrite(fpath_im_mask,cv.cvtColor(im_mask,cv.COLOR_BGR2RGB))
+
+ celery_result = {
+ 'score':str(result['score']),
+ 'name':str(result['name']),
+ 'class_index':str(result['class_index']),
+ 'color':str(result['color']),
+ 'fp_im_mask':fpath_im_mask,
+ 'fp_seg_mask':fpath_seg_mask,
+ 'valid':True
+ }
+ else:
+ print('[-] no reults. process background only')
+ celery_result = {
+ 'score':None,
+ 'name':None,
+ 'class_index':None,
+ 'color':None,
+ 'fp_im_mask':None,
+ 'fp_seg_mask':None,
+ 'valid':False
+ }
+
+ print('[+] Start celery')
+ async_task = task.apply_async(args=[uuid_name, agree, celery_result])
+ task_url = url_for('main.task_status', task_name=style, task_id=async_task.id)
+
+ return jsonify({
+ 'result': True,
+ 'task_url': task_url,
+ 'uuid': uuid_name
+ })
+
+
+
+# ----------------------------------------------------
+# Fileserver, temp solution
+# ----------------------------------------------------
+
+@main.route('/img/<string:imtype>/<string:uuid_name>')
+def get_image(imtype,uuid_name):
+ """Return image files from render or uploads"""
+ if imtype == 'uploads':
+ d = app.config['UPLOADS']
+ suffix = ''
+ elif imtype == 'renders':
+ d = app.config['RENDERS']
+ suffix = ''
+ elif imtype == 'fcn':
+ d = app.config['RENDERS']
+ suffix = '_fcn8'
+
+ fname = uuid_name + suffix + '.jpg'
+ fpath = os.path.join(d, fname)
+
+ if os.path.isfile(fpath):
+ return send_from_directory(d,fname)
+ else:
+ return send_from_directory('static', 'img/404.jpg')
+
+# ----------------------------------------------------
+# Deleting images
+# ----------------------------------------------------
+
+def destroy_data(uuid_name, is_public):
+ uri_base = app.config['URI_BASE']
+ upload_dir, render_dir, json_dir, upload_uri, render_uri = get_paths(is_public)
+
+ json_path = os.path.join(json_dir, uuid_name + '.json')
+ with open(json_path) as json_file:
+ data = json.load(json_file)
+ for f in data['files']:
+ path = os.path.join(uri_base, f['fn'][1:])
+ if os.path.exists(path):
+ os.remove(path)
+ os.remove(json_path)
+
+@main.route('/d/<uuid_name>/destroy', strict_slashes=False) # public
+def route_public_destroy(uuid_name):
+ destroy_data(uuid_name, True)
+ return redirect("/", code=302)
+
+@main.route('/p/<uuid_name>/destroy', strict_slashes=False) # private
+def route_private_destroy(uuid_name):
+ destroy_data(uuid_name, False)
+ return redirect("/", code=302)
+
+# ----------------------------------------------------
+# Static routes
+# ----------------------------------------------------
+
+# Most of the pages are served with the single page app in index.html:
+
+task_json = make_task_json()
+
+@main.route('/', strict_slashes=False)
+def index():
+ return render_template('index.html', task_json=task_json)
+
+@main.route('/about', strict_slashes=False)
+def about():
+ return render_template('index.html', task_json=task_json)
+
+@main.route('/d/<uuid_name>', strict_slashes=False) # public
+def route_public(uuid_name):
+ return render_template('index.html', task_json=task_json)
+
+@main.route('/p/<uuid_name>', strict_slashes=False) # private
+def route_private(uuid_name):
+ return render_template('index.html', task_json=task_json)
+
+@main.route('/privacy', strict_slashes=False)
+def privacy():
+ return render_template('index.html', task_json=task_json)
+
+# Some of the pages have their own static file:
+
+@main.route('/gallery', strict_slashes = False)
+def gallery():
+ app.logger.info('access gallery')
+ uploads, renders, urls = utils.get_recent_uploads(limit=50)
+ uuids = [os.path.splitext(os.path.basename(f))[0] for f in uploads]
+ images = [{'upload':u,'render':r, 'url':url} for u,r,url in zip(uploads,renders,urls)]
+ return render_template('gallery.html',images=images)
+
+@main.route('/zkm', strict_slashes=False)
+def zkm():
+ app.logger.info('access ZkM')
+ return render_template('zkm.html')
+
+@main.route('/celery', strict_slashes=False)
+def celery_route():
+ return render_template('celery.html')
+
+@main.route('/projector', strict_slashes=False)
+def projector():
+ uploads, renders,urls = utils.get_recent_uploads()
+ return render_template('projector.html', uploads=uploads, renders=renders)