Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
SULI 2021
AI4HDR_GUI
Commits
534604c7
Commit
534604c7
authored
Feb 02, 2021
by
josh
Browse files
started create model page
parent
36ba04bd
Changes
7
Hide whitespace changes
Inline
Side-by-side
app.py
View file @
534604c7
...
...
@@ -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
static/css/createModel.css
0 → 100644
View file @
534604c7
.main-section-container
{
width
:
100%
;
height
:
100%
;
display
:
grid
;
grid-template-columns
:
1
fr
50%
1
fr
;
grid-template-rows
:
1
fr
80%
1
fr
;
grid-template-areas
:
". . ."
". input-container ."
". . ."
;
}
.model-input-container
{
grid-area
:
input-container
;
background-color
:
brown
;
display
:
grid
;
grid-template-columns
:
1
fr
45%
45%
1
fr
;
grid-template-rows
:
1
fr
80%
1
fr
;
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
static/css/imageSliceContent.css
View file @
534604c7
...
...
@@ -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
;
...
...
static/js/createModel.js
0 → 100644
View file @
534604c7
static/js/imageSliceContent.js
View file @
534604c7
...
...
@@ -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
();
...
...
templates/createModel.html
0 → 100644
View file @
534604c7
{% 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
templates/imageSliceContent.html
View file @
534604c7
...
...
@@ -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>
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment