Commit 2a5bfa69 authored by josh's avatar josh
Browse files

have been working on this project in another repo, updating to the new proj files

parent f65fca93
import numpy as np
from PIL import Image
from abc import ABC
from pathlib import Path
'''
HDR App database interface
'''
class HDRDatabaseInterface( ABC ):
def getImageList( self ) -> list:
'''
Should return a list of dictionaries containing:
- id : used to query database for more image information
- name: will be displayed in the UI
i.e.
[
{
"id" : id,
"name": name
}
]
'''
raise NotImplementedError( "getImageList: Method Not Implemented" )
def getSliceList( self, imageId: str, size: str ) -> list:
'''
Similar to getImageList
Should return a list of dictionaries containing information about sliced images:
- id : used to query database
- name: will be displayed in the UI
i.e.
[
{
"id" : id,
"name": name
}
]
'''
raise NotImplementedError( "getSliceList: Method Not Implemented" )
def getProcessedList( self, sliceId: str ) -> list:
'''
Should return a list of available processed images for given slice
i.e.
[
{
"id" : id,
"name": name
}
]
'''
raise NotImplementedError( "getProcessedList: Method Not Implemented" )
def getSliceSizes( self, imageId: str ) -> list:
'''
Should return a list of slice sizes for imageId
i.e.
[ "128", "256", "512" ]
'''
raise NotImplementedError( "getSliceSizes: Method Not Implemented" )
def getImageArray( self, imageId: str ) -> np.array:
'''
Returns an image as a numpy array
Only returns Original images, not slices or processed slices
'''
raise NotImplementedError( "getImageArray: Method Not Implemented" )
def getMSLabelArray( self, imageId: str ) -> np.array:
'''
'''
raise NotImplementedError( "getMSLabelArray: Method Not Implemented" )
def getProcessedSlices( self, id: str, size: int ) -> dict:
raise NotImplementedError( "getProcessedSlices: Method Not Implemented" )
class HDRFileDB( HDRDatabaseInterface ):
def __init__( self, dbLoc: str ):
'''
Location of info directory names
'''
self.UID = 0
self.IMG_TYPE = 1
self.NAME = 2
self.SL_SIZE = 4
self.X_PIX = 5
self.Y_PIX = 6
self.PROC_TYPE = 8
'''
Directory Names
'''
self.BASE_FOLDER = "Images"
self.SLICE_FOLDER = "Sliced"
self.PROCESSED_FOLDER = "Processed"
self.dbBasePath = Path( dbLoc ).resolve()
self.imagesPath = self.dbBasePath.joinpath( self.BASE_FOLDER )
'''
PUBLIC METHODS
'''
def getImageList( self ) -> list:
imageList = []
for imageDir in self.imagesPath.iterdir():
imageId = imageDir.name
displayName = "{}_{}".format( self._idName( imageId ), self._idUid( imageId ) )
imageList.append({
"id" : imageId,
"name": displayName
})
return imageList
def getSliceList( self, imageId: str, size: str ) -> list:
sliceList = []
slicedPath = self._idToBasePath( imageId ).joinpath( self.SLICE_FOLDER ).joinpath( size )
if slicedPath.is_dir():
for imageSlice in slicedPath.iterdir():
sliceId = imageSlice.name
displayName = "{}_{}_{}".format(
self._idName( sliceId ),
self._idXPix( sliceId ),
self._idYPix( sliceId )
)
sliceList.append({
"id" : sliceId,
"name": displayName
})
return sliceList
else:
return []
def getProcessedList( self, sliceId: str ) -> list:
processedList = []
slicedDir = [ p for p in self._idToBasePath( sliceId ).rglob( sliceId ) ][0]
processedDir = slicedDir.joinpath( "Processed" )
for processedImage in processedDir.iterdir():
processedId = processedImage.name
displayName = self._idParts( processedImage.name )[self.PROC_TYPE]
processedList.append({
"id" : processedId,
"name": displayName
})
return processedList
def getSliceSizes( self, imageId: str ) -> list:
nonEmptySliceDirs = []
for slDir in self._idToBasePath( imageId ).joinpath( self.SLICE_FOLDER ).iterdir():
slDirLen = len( [ f for f in slDir.iterdir() ] )
if slDirLen > 0:
nonEmptySliceDirs.append( slDir.name )
return nonEmptySliceDirs
def getImageArray( self, imageId: str ) -> np.array:
baseDir = self._idToBasePath( imageId )
imageFilePath = [ p for p in baseDir.rglob( "{}.*".format( imageId ) ) ][0]
return np.array( Image.open( imageFilePath ) )
def getMSLabelArray( self, sliceId: str ) -> np.array:
baseDir = self._idToBasePath( sliceId )
labelsIdentifier = "{}-{}-{}-Sliced-MeanShiftLabels-Processed.npy".format( self._idSliceSize( sliceId ),
self._idXPix( sliceId ),
self._idYPix( sliceId ) )
msLabelsPath = [ p for p in baseDir.rglob( "*{}".format( labelsIdentifier ) ) ][0]
return np.load( msLabelsPath )
'''
PRIVATE METHODS
'''
def _idParts( self, imageId: str ) -> list:
return imageId.split( "-" )
def _idImageType( self, imageId: str ) -> str:
return self._idParts( imageId )[-1]
def _idUid( self, imageId: str ) -> str:
return self._idParts( imageId )[self.UID]
def _idImageExt( self, imageId: str ) -> str:
return self._idParts( imageId )[self.IMG_TYPE]
def _idName( self, imageId: str ) -> str:
return self._idParts( imageId )[self.NAME]
def _idSliceSize( self, imageId: str ) -> str:
idParts = self._idParts( imageId )
if len( idParts ) > 3:
return idParts[self.SL_SIZE]
else:
return ""
def _idXPix( self, imageId: str ) -> str:
idParts = self._idParts( imageId )
if len( idParts ) > 3:
return idParts[self.X_PIX]
else:
return ""
def _idYPix( self, imageId: str ) -> str:
idParts = self._idParts( imageId )
if len( idParts ) > 3:
return idParts[self.Y_PIX]
else:
return ""
def _idToBasePath( self, imageId: str ) -> Path:
return self.imagesPath.joinpath( "{}-{}-{}-{}".format( self._idUid( imageId ),
self._idImageExt( imageId ),
self._idName( imageId ),
"Original" ) )
\ No newline at end of file
import webbrowser
import sys
import os
import shutil
from pathlib import Path
from flask import *
from appUtils import *
from HDRData import HDRFileDB
from werkzeug.utils import secure_filename
from PIL import Image
import numpy as np
import io
import base64
'''
Global Variables
'''
TEMP_LOC = Path.cwd().absolute().joinpath( "Temp" )
ALLOWED_EXTENSIONS = { "png", "jpg", "jpeg" }
'''
App Config
'''
app = Flask(__name__)
imageDB = None
app.config["STATIC_PATH"] = str( Path.cwd().joinpath( "static" ) )
'''
App Routes
'''
@app.route( "/" )
def index():
return render_template( "index.html" )
@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 )
@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",
imageId=imageId,
sliceSizes=sliceSizes )
@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",
imageId=imageId,
sliceSize=sliceSize,
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",
imageId=imageId,
sliceId=sliceId,
size=size,
refImages=processedImages )
'''
IMAGE UPLOAD ROUTES
'''
@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 )
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 )
tmpPath = TEMP_LOC.joinpath( filename.split( "." )[0] )
os.mkdir( tmpPath )
# LAUNCH PROCESSING - OUTPUT -> filenameTemp
file.save( os.path.join( str( tmpPath ), filename ) )
#os.system( "importAndProcessImage.py " )
# SAVE RESULTS TO DATABASE
#imageDB.saveImage( file, filename )
shutil.rmtree( tmpPath )
return render_template( "imageUpload.html" )
@app.route( "/save-mask", methods=["POST"] )
def saveMask():
imageId = request.values["imageId"]
sliceId = request.values["sliceId"]
sliceSize = request.values["sliceSize"]
maskBase64 = request.values["maskBase64"].split(',')[1]
im = Image.open( io.BytesIO( base64.b64decode( maskBase64 ) ) )
im = im.convert( "RGB" )
im.save( "test.jpg" )
return jsonify( "OK" )
'''
HELPER ROUTES
'''
@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 )
# convert numpy array to PIL Image
img = Image.fromarray( arr.astype( "uint8" ) )
# create file-object in memory
fileObject = io.BytesIO()
img.save( fileObject, "JPEG" )
# move to beginning of file so `send_file()` will read from start
fileObject.seek( 0 )
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( {
"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 )
if __name__ == "__main__":
if len( sys.argv ) == 2:
imageDB = HDRFileDB( sys.argv[1] )
webbrowser.open_new( "http://127.0.0.1:2000/" )
app.run( debug=True, port=2000 )
else:
print( "Must Provide Database Location" )
\ No newline at end of file
def fileTypeAllowed( filename, allowedExts ):
return '.' in filename and filename.rsplit('.', 1)[1].lower() in allowedExts
\ No newline at end of file
from flask import *
from flask_cors import CORS, cross_origin
from threading import Timer
import webbrowser
import pathlib
import os
import sys
import shutil
from pprint import pprint
from werkzeug.utils import secure_filename
'''
GLOBAL VARIABLES
'''
UPLOAD_FOLDER = "/home/josh/Desktop/working_dir"
ALLOWED_EXTENSIONS = {'txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'}
DB_LOC = None
OR_LOC = None
MS_LOC = None
SL_LOC = None
STATIC_LOC = None
ACTIVE_MEDIA = None
'''
APP CONFIG
'''
app = Flask( __name__ )
CORS( app )
app.config["UPLOAD_FOLDER"] = UPLOAD_FOLDER
@app.route( "/" )
def index():
return render_template( "index.html" )
'''
UPLOAD FOLDER
'''
# SOURCE - https://flask.palletsprojects.com/en/1.1.x/patterns/fileuploads/
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
@app.route("/demo-upload", methods=["GET", "POST"])
def upload_file():
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)
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 allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
return jsonify("Ok")
'''
DATABASE HELPER FUNCTIONS
'''
def getAssociatedFiles( imageName: str ) -> dict:
'''
Retreives all file names from the following directories:
- MS_LOC/imageName/128
- MS_LOC/imageName/256
- MS_LOC/imageName/512
- SL_LOC/imageName/128
- SL_LOC/imageName/256
- SL_LOC/imageName/512
'''
imageMSPath = MS_LOC.joinpath( imageName )
imageSLPath = SL_LOC.joinpath( imageName )
print( imageMSPath )
print( imageSLPath )
# Mean Shift Color Seg files
msColor128 = [ f.name for f in imageMSPath.joinpath( "128" ).iterdir() if "color" in f.name ]
msColor256 = [ f.name for f in imageMSPath.joinpath( "256" ).iterdir() if "color" in f.name ]
msColor512 = [ f.name for f in imageMSPath.joinpath( "512" ).iterdir() if "color" in f.name ]
# Mean Shift Image Label files
msLabel128 = [ f.name for f in imageMSPath.joinpath( "128" ).iterdir() if "labels" in f.name ]
msLabel256 = [ f.name for f in imageMSPath.joinpath( "256" ).iterdir() if "labels" in f.name ]
msLabel512 = [ f.name for f in imageMSPath.joinpath( "512" ).iterdir() if "labels" in f.name ]
# Slice files
s128 = [ f.name for f in imageSLPath.joinpath( "128" ).iterdir() ]
s256 = [ f.name for f in imageSLPath.joinpath( "256" ).iterdir() ]
s512 = [ f.name for f in imageSLPath.joinpath( "512" ).iterdir() ]
return {
"msColor128": msColor128,
"msColor256": msColor256,
"msColor512": msColor512,
"msLabel128": msLabel128,
"msLabel256": msLabel256,
"msLabel512": msLabel512,
"s128": s128,
"s256": s256,
"s512": s512
}
'''
DATABASE FUNCTIONALITY
'''
@app.route("/image-list", methods=["GET", "POST"])
def getDBImageList():
if request.method == "GET":
imageList = [ str( f.name ) for f in OR_LOC.iterdir() ]
return { "data": imageList }
@app.route("/copy-original-to-static", methods=["GET", "POST"])
def copyOriginalImageToStatic():
if request.method == "POST":
imgLoc = OR_LOC.joinpath( request.get_data().decode( "utf-8" ) )
print( imgLoc )
if imgLoc.is_file():
# Get all available processed images for image
associatedFiles = getAssociatedFiles( imgLoc.name.split( "." )[0] )
associatedFiles["mainImageName"] = imgLoc.name
associatedFiles["mainImageUrl"] = "static/activeMedia/{}".format( imgLoc.name )
pprint( associatedFiles )
# Clear images in active media
for f in ACTIVE_MEDIA.iterdir():
if f.is_file():
f.unlink()
# Copy image to active media
shutil.copy( imgLoc, ACTIVE_MEDIA.joinpath( imgLoc.name ) )
return jsonify( associatedFiles )
else:
return jsonify( "Not Found" )
@app.route("/copy-sliced-128-to-static", methods=["GET", "POST"])
def copySlicedImageToStatic():
if request.method == "POST":
requestedFile = request.get_data().decode( "utf-8" )
print( SL_LOC )
imgLoc = SL_LOC.joinpath( "GeoEye-0" ).joinpath( "128" ).joinpath( "{}".format( requestedFile ) )
print( imgLoc )
if imgLoc.is_file():
# Copy image to active media
shutil.copy( imgLoc, ACTIVE_MEDIA.joinpath( imgLoc.name ) )
return jsonify( "static/activeMedia/{}".format( imgLoc.name ) )
else:
return jsonify( "Not Found" )
def open_browser():
webbrowser.open_new( "http://127.0.0.1:2000/" )
if __name__ == "__main__":
if len( sys.argv ) == 2:
DB_LOC = pathlib.Path( sys.argv[1] ).absolute()
OR_LOC = DB_LOC.joinpath( "Original" )
MS_LOC = DB_LOC.joinpath( "MeanShift" )
SL_LOC = DB_LOC.joinpath( "Sliced" )
STATIC_LOC = pathlib.Path.cwd().absolute().joinpath( "static" )
ACTIVE_MEDIA = STATIC_LOC.joinpath( "activeMedia" )
'''
Run app
'''
Timer( 1, open_browser ).start()
app.run( debug=True, port=2000 )