Commit 534604c7 authored by josh's avatar josh
Browse files

started create model page

parent 36ba04bd
......@@ -16,18 +16,18 @@ import base64
from celery import Celery
def make_celery( app ):
def make_celery(app):
celery = Celery(
app.import_name,
backend=app.config['result_backend'],
broker=app.config['broker_url']
)
celery.conf.update( app.config )
)
celery.conf.update(app.config)
class ContextTask( celery.Task ):
class ContextTask(celery.Task):
def __call__(self, *args, **kwargs):
with app.app_context():
return self.run( *args, **kwargs )
return self.run(*args, **kwargs)
celery.Task = ContextTask
return celery
......@@ -35,30 +35,30 @@ def make_celery( app ):
'''
Global Variables
'''
TEMP_LOC = Path.cwd().absolute().joinpath( "Temp" )
TEMP_LOC = Path.cwd().absolute().joinpath("Temp")
ALLOWED_EXTENSIONS = { "png", "jpg", "jpeg" }
'''
App Config
'''
app = Flask( __name__ )
imageDB = HDRFileDB( "../ImageDatabase" )
app = Flask(__name__)
imageDB = HDRFileDB("../ImageDatabase")
app.config["STATIC_PATH"] = str( Path.cwd().joinpath( "static" ) )
app.config["STATIC_PATH"] = str(Path.cwd().joinpath("static"))
app.config["broker_url"] = 'redis://localhost:6379'
app.config["result_backend"] = 'redis://localhost:6379'
celery = make_celery( app )
celery = make_celery(app)
'''
Celery Tasks
'''
@celery.task( name="app.importAndProcessImage" )
def importAndProcessImage( imagePath ):
imageDB.importAndProcessImage( imagePath )
@celery.task(name="app.importAndProcessImage")
def importAndProcessImage(imagePath):
imageDB.importAndProcessImage(imagePath)
return "OK"
......@@ -66,104 +66,110 @@ def importAndProcessImage( imagePath ):
App Routes
'''
@app.route( "/" )
@app.route("/")
def index():
return render_template( "index.html" )
return render_template("index.html")
@app.route( "/image-select" )
@app.route("/image-select")
def imageSelect():
'''
Displays a list of images available in the database to view further
'''
imageList = imageDB.getImageList()
return render_template( "imageSelect.html", imageList=imageList )
return render_template("imageSelect.html", imageList=imageList)
@app.route( "/image-size-select/<string:imageId>" )
def imageSizeSelect( imageId ):
@app.route("/image-size-select/<string:imageId>")
def imageSizeSelect(imageId):
'''
Displays the selected image from the database along with
a selection of available slice sizes.
'''
sliceSizes = imageDB.getSliceSizes( imageId )
return render_template( "imageSizeSelect.html",
sliceSizes = imageDB.getSliceSizes(imageId)
return render_template("imageSizeSelect.html",
imageId=imageId,
sliceSizes=sliceSizes )
sliceSizes=sliceSizes)
@app.route( "/image-slice-content/<string:imageId>/<int:sliceSize>" )
def imageSliceContent( imageId, sliceSize ):
@app.route("/image-slice-content/<string:imageId>/<int:sliceSize>")
def imageSliceContent(imageId, sliceSize):
'''
Main Image viewing area with available slices
'''
sliceList = imageDB.getSliceList( imageId, str( sliceSize ) )
return render_template( "imageSliceContent.html",
sliceList = imageDB.getSliceList(imageId, str(sliceSize))
return render_template("imageSliceContent.html",
imageId=imageId,
sliceSize=sliceSize,
sliceList=sliceList )
sliceList=sliceList)
@app.route( "/create-mask/<string:imageId>/<string:sliceId>/<int:size>" )
def createMask( imageId, sliceId, size ):
processedImages = imageDB.getProcessedList( sliceId )
return render_template( "createMask.html",
@app.route("/create-mask/<string:imageId>/<string:sliceId>/<int:size>")
def createMask(imageId, sliceId, size):
processedImages = imageDB.getProcessedList(sliceId)
return render_template("createMask.html",
imageId=imageId,
sliceId=sliceId,
size=size,
refImages=processedImages )
refImages=processedImages)
@app.route("/create-model/<string:imageId>/<int:size>")
def createModel(imageId, size):
print(imageId, size)
return render_template("createModel.html")
'''
IMAGE UPLOAD ROUTES
'''
@app.route( "/image-upload", methods=[ "POST", "GET" ] )
@app.route("/image-upload", methods=[ "POST", "GET" ])
def uploadImage():
if request.method == "POST":
# check if the post request has the file part
if "file" not in request.files:
flash( "No file part" )
return redirect( request.url )
flash("No file part")
return redirect(request.url)
file = request.files["file"]
# if user does not select file, browser also
# submit an empty part without filename
if file.filename == "":
flash( "No selected file" )
return redirect( request.url )
if file and fileTypeAllowed( file.filename, ALLOWED_EXTENSIONS ):
filename = secure_filename( file.filename )
tmpDir = TEMP_LOC.joinpath( filename.split( "." )[0] )
flash("No selected file")
return redirect(request.url)
if file and fileTypeAllowed(file.filename, ALLOWED_EXTENSIONS):
filename = secure_filename(file.filename)
tmpDir = TEMP_LOC.joinpath(filename.split(".")[0])
# Add id to folder name to avoid collisions
ids = [int( f.name.split( "-" )[0] ) for f in TEMP_LOC.iterdir() ]
ids = [int(f.name.split("-")[0]) for f in TEMP_LOC.iterdir() ]
uId = 0
if len( ids ) != 0:
uId = max( ids ) + 1
if len(ids) != 0:
uId = max(ids) + 1
# Save image to temporary dir
tmpDir = tmpDir.parent.joinpath( "{}-{}".format( uId, tmpDir.name ) )
os.mkdir( tmpDir )
file.save( os.path.join( str( tmpDir ), filename ) )
tmpDir = tmpDir.parent.joinpath("{}-{}".format(uId, tmpDir.name))
os.mkdir(tmpDir)
file.save(os.path.join(str(tmpDir), filename))
# Launch import and process
result = importAndProcessImage.delay( str( tmpDir.joinpath( filename ).resolve() ) )
result = importAndProcessImage.delay(str(tmpDir.joinpath(filename).resolve()))
return render_template( "imageUpload.html" )
return render_template("imageUpload.html")
@app.route( "/save-mask", methods=["POST"] )
@app.route("/save-mask", methods=["POST"])
def saveMask():
imageId = request.values["imageId"]
sliceId = request.values["sliceId"]
maskName = request.values["maskName"]
maskBase64 = request.values["maskBase64"].split(',')[1]
maskImage = Image.open( io.BytesIO( base64.b64decode( maskBase64 ) ) )
maskImage = maskImage.convert( "RGB" )
maskImage = Image.open(io.BytesIO(base64.b64decode(maskBase64)))
maskImage = maskImage.convert("RGB")
imageDB.saveMask( sliceId, maskImage, maskName=maskName )
imageDB.saveMask(sliceId, maskImage, maskName=maskName)
return jsonify( "OK" )
return jsonify("OK")
'''
......@@ -171,40 +177,40 @@ HELPER ROUTES
'''
@app.route( "/download-image/<string:imageId>", methods=["POST", "GET"] )
def downloadImage( imageId ):
@app.route("/download-image/<string:imageId>", methods=["POST", "GET"])
def downloadImage(imageId):
'''
Creates and sends a file object for given file
'''
arr = imageDB.getImageArray( imageId )
arr = imageDB.getImageArray(imageId)
# convert numpy array to PIL Image
img = Image.fromarray( arr.astype( "uint8" ) )
img = Image.fromarray(arr.astype("uint8"))
# create file-object in memory
fileObject = io.BytesIO()
img.save( fileObject, "JPEG" )
img.save(fileObject, "JPEG")
# move to beginning of file so `send_file()` will read from start
fileObject.seek( 0 )
fileObject.seek(0)
return send_file( fileObject, mimetype="image/jpg" )
return send_file(fileObject, mimetype="image/jpg")
# TODO : FIGURE OUT WHY THE INDEXING IS BACKWARDS
@app.route( "/get-homogeneous-pixels/<string:sliceId>/<int:pX>/<int:pY>", methods=["GET"] )
def getHomogeneousPixels( sliceId, pX, pY ):
labelImageArray = imageDB.getMSLabelArray( sliceId )
equalIndices = np.where( labelImageArray == labelImageArray[pX, pY] )
return jsonify( {
@app.route("/get-homogeneous-pixels/<string:sliceId>/<int:pX>/<int:pY>", methods=["GET"])
def getHomogeneousPixels(sliceId, pX, pY):
labelImageArray = imageDB.getMSLabelArray(sliceId)
equalIndices = np.where(labelImageArray == labelImageArray[pX, pY])
return jsonify({
"x": equalIndices[1].tolist(),
"y": equalIndices[0].tolist()
})
@app.route( "/processed-images/<string:sliceId>", methods=["GET", "POST"] )
def getProcessedImages( sliceId ):
processedList = imageDB.getProcessedList( sliceId )
return jsonify( processedList )
@app.route("/processed-images/<string:sliceId>", methods=["GET", "POST"])
def getProcessedImages(sliceId):
processedList = imageDB.getProcessedList(sliceId)
return jsonify(processedList )
if __name__ == "__main__":
webbrowser.open_new( "http://127.0.0.1:2000/" )
app.run( debug=True, port=2000 )
\ No newline at end of file
webbrowser.open_new("http://127.0.0.1:2000/")
app.run(debug=True, port=2000)
\ No newline at end of file
.main-section-container {
width: 100%;
height: 100%;
display: grid;
grid-template-columns: 1fr 50% 1fr;
grid-template-rows: 1fr 80% 1fr;
grid-template-areas:
". . ."
". input-container ."
". . .";
}
.model-input-container {
grid-area: input-container;
background-color: brown;
display: grid;
grid-template-columns: 1fr 45% 45% 1fr;
grid-template-rows: 1fr 80% 1fr;
grid-template-areas:
". . . ."
". name-send sample-select ."
". . . .";
}
.model-name-send-container {
grid-area: name-send;
background-color:cadetblue;
}
.model-sample-select {
grid-area: sample-select;
background-color: chocolate;
}
ul {
list-style: none;
padding: 0;
margin: 0;
}
\ No newline at end of file
......@@ -44,7 +44,7 @@
}
.slice-menu-container select {
width: 30%;
width: 25%;
height: 30px;
}
......@@ -54,8 +54,21 @@
text-decoration: none;
}
.slice-menu-container #mask-create-containter {
width: 30%;
.slice-menu-container #mask-create-container {
width: 20%;
height: 30px;
background-color: white;
display: flex;
justify-content: space-around;
align-items: center;
border-radius: 5px;
}
.slice-menu-container #model-create-container {
width: 20%;
height: 30px;
background-color: white;
......
......@@ -4,22 +4,22 @@
* Starts slice content update process for event an onchange
* event for id: #slice-sizes
*/
function sliceSelectChange( imageId, sizeSelected ) {
function sliceSelectChange(imageId, sizeSelected) {
var sliceId = $( "#slice-sizes" ).find(":selected").val();
var sliceId = $("#slice-sizes").find(":selected").val();
var maskCreateLink = $( "#mask-create-link" );
var maskCreateLink = $("#mask-create-link");
// TEMPORARY FOR REFERENCE PHOTO
maskCreateLink.prop( "href", `/create-mask/${imageId}/${sliceId}/${sizeSelected}` );
maskCreateLink.prop("href", `/create-mask/${imageId}/${sliceId}/${sizeSelected}`);
$.get( `/processed-images/${sliceId}`, function( data ) {
$.get(`/processed-images/${sliceId}`, function(data) {
/* SET UP SLICE IMAGE SECTION */
setNewSliceImage( sliceId );
setNewSliceImage(sliceId);
/* SET UP PROCESSED IMAGE SECTION */
clearProcessedSection();
fillProcessedSelection( data );
fillProcessedSelection(data);
});
}
......@@ -27,10 +27,10 @@ function sliceSelectChange( imageId, sizeSelected ) {
* Download new image to display in slice section, reload the
* slice image controller
*/
function setNewSliceImage( sliceId ) {
var sliceImage = $( "#slice-image" );
sliceImage.attr( "src", `/download-image/${sliceId}` );
sliceImage.load( function() {
function setNewSliceImage(sliceId) {
var sliceImage = $("#slice-image");
sliceImage.attr("src", `/download-image/${sliceId}`);
sliceImage.load(function() {
/* FROM: 'canvasControllers.js' */
setNewSliceController();
});
......@@ -41,18 +41,18 @@ function setNewSliceImage( sliceId ) {
function clearProcessedSection() {
// Clear processed image selection
var processed = $( "#processed-images" );
var processed = $("#processed-images");
processed.empty();
// Clear processed image canvas
if ( PROCESSED_CONTROLLER != null ) {
$( "#processed-image" ).prop( "src", "" );
if (PROCESSED_CONTROLLER != null) {
$("#processed-image").prop("src", "");
PROCESSED_CONTROLLER.updateImage();
PROCESSED_CONTROLLER = undefined;
}
// Clear mask canvas
if ( MASK_CONTROLLER != null ) {
if (MASK_CONTROLLER != null) {
MASK_CONTROLLER.clear();
MASK_CONTROLLER = undefined;
}
......@@ -62,20 +62,20 @@ function clearProcessedSection() {
* Get list of available processed images for selected slice
* then fill process selection
*/
function fillProcessedSelection( data ) {
var processed = $( "#processed-images" );
function fillProcessedSelection(data) {
var processed = $("#processed-images");
// Create new selection dropdown
var option = document.createElement( "option" );
var option = document.createElement("option");
option.value = "";
option.text = "-- Select Processed Image --";
processed.append( option );
processed.append(option);
for ( var i = 0; i < data.length; i++ ) {
option = document.createElement( "option" );
for (var i = 0; i < data.length; i++) {
option = document.createElement("option");
option.value = data[i]["id"];
option.text = data[i]["name"];
processed.append( option );
processed.append(option);
}
}
......@@ -83,15 +83,15 @@ function fillProcessedSelection( data ) {
* Handles event onchange for id: #processed-images
*/
function processedSelectChange() {
var processedId = $( "#processed-images" ).find( ":selected" ).val();
var processedId = $("#processed-images").find(":selected").val();
var sliceImage = $( "#processed-image" );
sliceImage.attr( "src", `/download-image/${processedId}` );
sliceImage.load( function() {
var sliceImage = $("#processed-image");
sliceImage.attr("src", `/download-image/${processedId}`);
sliceImage.load(function() {
setNewProcessedController();
// Sync processed controller and slice controller
syncControllers( slice=true, processed=true, mask=false );
syncControllers(slice=true, processed=true, mask=false);
});
}
......@@ -99,11 +99,11 @@ function processedSelectChange() {
// ==================== MASK CANVAS
function loadMaskCanvas() {
var processedImageCanvas = $( "#processed-image-canvas" );
var processedImageCanvas = $("#processed-image-canvas");
var offset = processedImageCanvas.offset();
// Show mask canvas
var maskCanvas = $( "#mask-create-canvas" );
var maskCanvas = $("#mask-create-canvas");
maskCanvas.css({
"display": "block",
"position": "absolute",
......@@ -114,11 +114,17 @@ function loadMaskCanvas() {
// Create mask creator canvas
setNewMaskController();
syncControllers( slice=true, processed=true, mask=true );
syncControllers(slice=true, processed=true, mask=true);
}
window.addEventListener( "load", ( event ) => {
// ==================== CREATEM MODEL BUTTON
function createModel(imageId, sliceSize) {
var modelName = prompt("Give Model a Name:", "");
}
window.addEventListener("load", (event) => {
/* MAIN CONTROLLER */
setNewMainController();
......
{% extends "base.html" %}
{% block head %}
<link rel="stylesheet" href="{{ url_for( 'static', filename='css/createModel.css' ) }}">
{% block imageViewHead %}
{% endblock %}
{% endblock %}
{% block body %}
<script src="{{ url_for( 'static', filename='js/createModel.js' ) }}"></script>
<div class="main-section-container">
<div class="model-input-container">
<div class="model-name-send-container">
<ul>
<li>
<label for="name">Name:</label>
<input type="text" id="name" name="user_name">
</li>
<li class="button">
<button type="submit">Save Model</button>
</li>
</ul>
</div>
<div class="model-sample-select">
</div>
</div>
</div>
{% endblock %}
\ No newline at end of file
......@@ -12,7 +12,7 @@
<div class="slice-menu-container">
<select name="slice-sizes" id="slice-sizes" onchange="sliceSelectChange( '{{imageId}}', '{{sliceSize}}' )">
<select name="slice-sizes" id="slice-sizes" onchange="sliceSelectChange('{{imageId}}', '{{sliceSize}}')">
<option value="">-- Select Slice --</option>
{% for sliceInfo in sliceList %}
<option value="{{sliceInfo.id}}">{{sliceInfo.name}}</option>
......@@ -23,7 +23,9 @@
<option value="">-- Select Processed Image --</option>
</select>
<div id="mask-create-containter"><a href="" id="mask-create-link">Create Mask</a></div>
<div id="mask-create-container"><a href="" id="mask-create-link">Create Mask</a></div>
<div id="model-create-container"><a href="/create-model/{{imageId}}/{{sliceSize}}" id="model-create-link">Create Model</a></div>
</div>
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment