refactored inputs and outputs

This commit is contained in:
Abubakar Abid 2019-02-17 19:06:08 -08:00
parent 8fa0bf1cca
commit 1a9f82a8d8
5 changed files with 166 additions and 150 deletions

View File

@ -2,14 +2,11 @@
<project version="4">
<component name="ChangeListManager">
<list default="true" id="fd73cd66-e80f-470e-a2ec-e220d3b6b864" name="Default Changelist" comment="">
<change afterPath="$PROJECT_DIR$/Usage.ipynb" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.gitignore" beforeDir="false" afterPath="$PROJECT_DIR$/.gitignore" afterDir="false" />
<change afterPath="$PROJECT_DIR$/outputs.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.ipynb_checkpoints/Emotion Detector-checkpoint.ipynb" beforeDir="false" afterPath="$PROJECT_DIR$/.ipynb_checkpoints/Emotion Detector-checkpoint.ipynb" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Emotion Detector.ipynb" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/Test Notebook.ipynb" beforeDir="false" afterPath="$PROJECT_DIR$/Test Notebook.ipynb" afterDir="false" />
<change beforePath="$PROJECT_DIR$/gradio.py" beforeDir="false" afterPath="$PROJECT_DIR$/gradio.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/js/class-output.js" beforeDir="false" afterPath="$PROJECT_DIR$/js/class-output.js" afterDir="false" />
<change beforePath="$PROJECT_DIR$/inputs.py" beforeDir="false" afterPath="$PROJECT_DIR$/inputs.py" afterDir="false" />
</list>
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
<option name="SHOW_DIALOG" value="false" />
@ -79,48 +76,33 @@
<counts>
<entry key="gitignore" value="1" />
<entry key="ipynb" value="1" />
<entry key="py" value="5" />
<entry key="py" value="6" />
</counts>
</usages-collector>
<usages-collector id="statistics.file.types.open">
<counts>
<entry key="IPNB" value="1" />
<entry key="PLAIN_TEXT" value="1" />
<entry key="Python" value="5" />
<entry key="Python" value="6" />
</counts>
</usages-collector>
<usages-collector id="statistics.file.extensions.edit">
<counts>
<entry key="dummy" value="10" />
<entry key="gitignore" value="2" />
<entry key="py" value="1804" />
<entry key="py" value="2014" />
</counts>
</usages-collector>
<usages-collector id="statistics.file.types.edit">
<counts>
<entry key="PLAIN_TEXT" value="12" />
<entry key="Python" value="1804" />
<entry key="Python" value="2014" />
</counts>
</usages-collector>
</session>
</component>
<component name="FileEditorManager">
<leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/index.html">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="3850">
<caret line="154" selection-start-line="154" selection-end-line="154" />
<folding>
<element signature="n#style#0;n#nav#0;n#body#0;n#html#0;n#!!top" expanded="true" />
<element signature="n#style#0;n#a#0;n#nav#0;n#body#0;n#html#0;n#!!top" expanded="true" />
<element signature="n#style#0;n#li#0;n#ul#1;n#div#0;n#nav#0;n#body#0;n#html#0;n#!!top" expanded="true" />
<element signature="n#style#0;n#p#0;n#div#0;n#section#0;n#main#0;n#body#0;n#html#0;n#!!top" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/../khateebi/quickstart.py">
<provider selected="true" editor-type-id="text-editor">
@ -163,8 +145,20 @@
<file pinned="false" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/gradio.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="366">
<caret line="200" column="36" lean-forward="true" selection-start-line="200" selection-start-column="36" selection-end-line="200" selection-end-column="36" />
<state relative-caret-position="491">
<caret line="20" column="60" selection-start-line="20" selection-start-column="60" selection-end-line="20" selection-end-column="60" />
<folding>
<element signature="e#0#14#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/inputs.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="275">
<caret line="11" selection-start-line="11" selection-end-line="11" />
<folding>
<element signature="e#0#35#0" expanded="true" />
</folding>
@ -172,6 +166,15 @@
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/outputs.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="175">
<caret line="7" selection-start-line="6" selection-end-line="7" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/.gitignore">
<provider selected="true" editor-type-id="text-editor">
@ -197,11 +200,6 @@
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/inputs.py">
<provider selected="true" editor-type-id="text-editor" />
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/preprocessing_utils.py">
<provider selected="true" editor-type-id="text-editor">
@ -222,7 +220,6 @@
</component>
<component name="FindInProjectRecents">
<findStrings>
<find>mouseX</find>
<find>titl</find>
<find>predict</find>
<find>help</find>
@ -252,6 +249,7 @@
<find>server</find>
<find>zip</find>
<find>resize_</find>
<find>base</find>
</findStrings>
<replaceStrings>
<replace>400</replace>
@ -287,10 +285,11 @@
<option value="$PROJECT_DIR$/templates/server.py" />
<option value="$PROJECT_DIR$/server.py" />
<option value="$PROJECT_DIR$/preprocessing_utils.py" />
<option value="$PROJECT_DIR$/inputs.py" />
<option value="$PROJECT_DIR$/networking.py" />
<option value="$PROJECT_DIR$/.gitignore" />
<option value="$PROJECT_DIR$/gradio.py" />
<option value="$PROJECT_DIR$/outputs.py" />
<option value="$PROJECT_DIR$/inputs.py" />
</list>
</option>
</component>
@ -507,9 +506,6 @@
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/inputs.py">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$PROJECT_DIR$/networking.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="450">
@ -531,15 +527,32 @@
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/gradio.py">
<entry file="file://$PROJECT_DIR$/outputs.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="366">
<caret line="200" column="36" lean-forward="true" selection-start-line="200" selection-start-column="36" selection-end-line="200" selection-end-column="36" />
<state relative-caret-position="175">
<caret line="7" selection-start-line="6" selection-end-line="7" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/inputs.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="275">
<caret line="11" selection-start-line="11" selection-end-line="11" />
<folding>
<element signature="e#0#35#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/gradio.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="491">
<caret line="20" column="60" selection-start-line="20" selection-start-column="60" selection-end-line="20" selection-end-column="60" />
<folding>
<element signature="e#0#14#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</component>
</project>

View File

@ -43,14 +43,14 @@
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Model available locally at: http://localhost:6002/\n",
"Model available locally at: http://localhost:6002/templates/tmp_html.html\n",
"Model available publicly for 8 hours at: http://57d2bd20.ngrok.io/templates/tmp_html.html\n"
]
}

114
gradio.py
View File

@ -1,16 +1,11 @@
from abc import ABC, abstractmethod
import base64
import asyncio
import websockets
import nest_asyncio
from PIL import Image
from io import BytesIO
import numpy as np
import os
import webbrowser
from bs4 import BeautifulSoup
import inputs
import outputs
import networking
import preprocessing_utils
nest_asyncio.apply()
@ -18,105 +13,6 @@ LOCALHOST_IP = '127.0.0.1'
SOCKET_PORT = 5680
class AbstractInput(ABC):
"""
An abstract class for defining the methods that all gradio inputs should have.
"""
def __init__(self):
super().__init__()
@abstractmethod
def _get_template_path(self):
"""
All interfaces should define a method that returns the path to its template.
"""
pass
@abstractmethod
def _pre_process(self):
"""
All interfaces should define a method that returns the path to its template.
"""
pass
class AbstractOutput(ABC):
"""
An abstract class for defining the methods that all gradio inputs should have.
"""
def __init__(self):
"""
"""
super().__init__()
@abstractmethod
def _get_template_path(self):
"""
All interfaces should define a method that returns the path to its template.
"""
pass
@abstractmethod
def _post_process(self):
"""
All interfaces should define a method that returns the path to its template.
"""
pass
class Sketchpad(AbstractInput):
def _get_template_path(self):
return 'templates/sketchpad_input.html'
def _pre_process(self, imgstring):
"""
"""
content = imgstring.split(';')[1]
image_encoded = content.split(',')[1]
body = base64.decodebytes(image_encoded.encode('utf-8'))
im = Image.open(BytesIO(base64.b64decode(image_encoded))).convert('L')
im = preprocessing_utils.resize_and_crop(im, (28, 28))
array = np.array(im).flatten().reshape(1, 28, 28, 1)
return array
class Webcam(AbstractInput):
def _get_template_path(self):
return 'templates/webcam_input.html'
def _pre_process(self, imgstring):
"""
"""
content = imgstring.split(';')[1]
image_encoded = content.split(',')[1]
body = base64.decodebytes(image_encoded.encode('utf-8'))
im = Image.open(BytesIO(base64.b64decode(image_encoded))).convert('L')
im = preprocessing_utils.resize_and_crop(im, (48, 48))
array = np.array(im).flatten().reshape(1,48,48,1)
return array
class Class(AbstractOutput):
def _get_template_path(self):
return 'templates/class_output.html'
def _post_process(self, prediction):
"""
"""
return prediction
registry = {
'webcam':Webcam,
'sketchpad' :Sketchpad,
'class' :Class,
}
class Interface():
"""
"""
@ -128,8 +24,8 @@ class Interface():
:param model_obj: the model object, such as a sklearn classifier or keras model.
:param model_params: additional model parameters.
"""
self.input_interface = registry[input]()
self.output_interface = registry[output]()
self.input_interface = inputs.registry[input]()
self.output_interface = outputs.registry[output]()
self.model_type = model_type
self.model_obj = model_obj
self.preprocessing_fn = preprocessing_fn
@ -203,7 +99,7 @@ class Interface():
webbrowser.get(chrome_path).open(path_to_server + path_to_template)
start_server = websockets.serve(self.communicate, LOCALHOST_IP, SOCKET_PORT)
print("Model available locally at: {}".format(path_to_server))
print("Model available locally at: {}".format(path_to_server + path_to_template))
if share_link:
ngrok_url = networking.setup_ngrok(server_port)

View File

@ -0,0 +1,66 @@
from abc import ABC, abstractmethod
import base64
from PIL import Image
from io import BytesIO
import numpy as np
import preprocessing_utils
class AbstractInput(ABC):
"""
An abstract class for defining the methods that all gradio inputs should have.
When this is subclassed, it is automatically added to the registry
"""
def __init__(self):
super().__init__()
@abstractmethod
def _get_template_path(self):
"""
All interfaces should define a method that returns the path to its template.
"""
pass
@abstractmethod
def _pre_process(self):
"""
All interfaces should define a method that returns the path to its template.
"""
pass
class Sketchpad(AbstractInput):
def _get_template_path(self):
return 'templates/sketchpad_input.html'
def _pre_process(self, imgstring):
"""
"""
content = imgstring.split(';')[1]
image_encoded = content.split(',')[1]
body = base64.decodebytes(image_encoded.encode('utf-8'))
im = Image.open(BytesIO(base64.b64decode(image_encoded))).convert('L')
im = preprocessing_utils.resize_and_crop(im, (28, 28))
array = np.array(im).flatten().reshape(1, 28, 28, 1)
return array
class Webcam(AbstractInput):
def _get_template_path(self):
return 'templates/webcam_input.html'
def _pre_process(self, imgstring):
"""
"""
content = imgstring.split(';')[1]
image_encoded = content.split(',')[1]
body = base64.decodebytes(image_encoded.encode('utf-8'))
im = Image.open(BytesIO(base64.b64decode(image_encoded))).convert('L')
im = preprocessing_utils.resize_and_crop(im, (48, 48))
array = np.array(im).flatten().reshape(1, 48, 48, 1)
return array
registry = {cls.__name__.lower(): cls for cls in AbstractInput.__subclasses__()}

41
outputs.py Normal file
View File

@ -0,0 +1,41 @@
from abc import ABC, abstractmethod
class AbstractOutput(ABC):
"""
An abstract class for defining the methods that all gradio inputs should have.
When this is subclassed, it is automatically added to the registry
"""
def __init__(self):
"""
"""
super().__init__()
@abstractmethod
def _get_template_path(self):
"""
All interfaces should define a method that returns the path to its template.
"""
pass
@abstractmethod
def _post_process(self):
"""
All interfaces should define a method that returns the path to its template.
"""
pass
class Class(AbstractOutput):
def _get_template_path(self):
return 'templates/class_output.html'
def _post_process(self, prediction):
"""
"""
return prediction
registry = {cls.__name__.lower(): cls for cls in AbstractOutput.__subclasses__()}