mirror of
https://github.com/gradio-app/gradio.git
synced 2025-03-13 11:57:29 +08:00
Merge branch 'master' of https://github.com/gradio-app/gradio-UI
This commit is contained in:
commit
b000f86261
@ -2,6 +2,8 @@
|
||||
|
||||
# Gradio UI
|
||||
|
||||

|
||||
|
||||
At Gradio, we often try to understand what inputs that a model is particularly sensitive to. To help facilitate this, we've developed and open-sourced `gradio`, a python library that allows you to easily create input and output interfaces over trained models to make it easy for you to "play around" with your model in your browser by dragging-and-dropping in your own images (or pasting your own text, recording your own voice, etc.) and seeing what the model outputs. We are working on making creating a shareable, public link to your model so you can share the interface with others (e.g. your client, your advisor, or your dad), who can use the model without writing any code.
|
||||
|
||||
Gradio is useful for:
|
||||
@ -54,7 +56,7 @@ label = gradio.outputs.Label(num_top_classes=3)
|
||||
gr.Interface(classify_image, imagein, label).launch();
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
You can supply your own model instead of the pretrained model above, as well as use different kinds of models or functions. Changing the `input` and `output` parameters in the `Interface` face object allow you to create different interfaces, depending on the needs of your model. Take a look at the python notebooks for more examples. The currently supported interfaces are as follows:
|
||||
@ -82,7 +84,7 @@ label = Label(num_top_classes=4)
|
||||
gradio.Interface(predict, sketchpad, label).launch();
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
#### Human DNA Variant Effect Prediction (Input: Textbox, Output: Label)
|
||||
|
||||
@ -90,7 +92,7 @@ gradio.Interface(predict, sketchpad, label).launch();
|
||||
gradio.Interface(predict, 'textbox', 'label').launch()
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
### Contributing:
|
||||
If you would like to contribute and your contribution is small, you can directly open a pull request (PR). If you would like to contribute a larger feature, we recommend first creating an issue with a proposed design for discussion. Please see our contributing guidelines for more info.
|
||||
|
@ -332,9 +332,9 @@ class ImageIn(AbstractInput):
|
||||
im = np.array(im).flatten()
|
||||
im = im * self.scale + self.shift
|
||||
if self.num_channels is None:
|
||||
array = im.reshape(1, self.image_width, self.image_height)
|
||||
array = im.reshape(self.image_width, self.image_height)
|
||||
else:
|
||||
array = im.reshape(1, self.image_width, self.image_height, \
|
||||
array = im.reshape(self.image_width, self.image_height, \
|
||||
self.num_channels)
|
||||
return array
|
||||
|
||||
|
@ -180,7 +180,7 @@ class Interface:
|
||||
return
|
||||
raise RuntimeError("Validation did not pass")
|
||||
|
||||
def launch(self, inline=None, inbrowser=None, share=True, validate=True):
|
||||
def launch(self, inline=None, inbrowser=None, share=False, validate=True):
|
||||
"""
|
||||
Standard method shared by interfaces that creates the interface and sets up a websocket to communicate with it.
|
||||
:param inline: boolean. If True, then a gradio interface is created inline (e.g. in jupyter or colab notebook)
|
||||
@ -212,7 +212,6 @@ class Interface:
|
||||
server_port, httpd = networking.start_simple_server(self, output_directory, self.server_name)
|
||||
path_to_local_server = "http://{}:{}/".format(self.server_name, server_port)
|
||||
networking.build_template(output_directory)
|
||||
networking.set_config(self.get_config_file(), output_directory)
|
||||
|
||||
self.status = "RUNNING"
|
||||
self.simple_server = httpd
|
||||
@ -243,6 +242,7 @@ class Interface:
|
||||
if share:
|
||||
try:
|
||||
share_url = networking.setup_tunnel(server_port)
|
||||
print(share_url)
|
||||
except RuntimeError:
|
||||
share_url = None
|
||||
if self.verbose:
|
||||
@ -288,5 +288,8 @@ class Interface:
|
||||
else:
|
||||
display(IFrame(path_to_local_server, width=1000, height=500))
|
||||
|
||||
config = self.get_config_file()
|
||||
config["share_url"] = share_url
|
||||
networking.set_config(config, output_directory)
|
||||
|
||||
return httpd, path_to_local_server, share_url
|
||||
|
@ -139,7 +139,7 @@ def serve_files_in_background(interface, port, directory_to_serve=None, server_n
|
||||
int(self.headers["Content-Length"]))
|
||||
msg = json.loads(data_string)
|
||||
raw_input = msg["data"]
|
||||
output = {"action": "output", "data": interface.process(raw_input)}
|
||||
output = {"data": interface.process(raw_input)}
|
||||
if interface.saliency is not None:
|
||||
saliency = interface.saliency(raw_input, prediction)
|
||||
output['saliency'] = saliency.tolist()
|
||||
@ -179,81 +179,6 @@ def serve_files_in_background(interface, port, directory_to_serve=None, server_n
|
||||
f.write(json.dumps(output))
|
||||
f.write("\n")
|
||||
|
||||
# TODO(abidlabs): clean this up
|
||||
elif self.path == "/api/auto/rotation":
|
||||
from gradio import validation_data, preprocessing_utils
|
||||
import numpy as np
|
||||
|
||||
self._set_headers()
|
||||
data_string = self.rfile.read(
|
||||
int(self.headers["Content-Length"]))
|
||||
msg = json.loads(data_string)
|
||||
img_orig = preprocessing_utils.decode_base64_to_image(
|
||||
msg["data"])
|
||||
img_orig = img_orig.convert('RGB')
|
||||
img_orig = img_orig.resize((224, 224))
|
||||
|
||||
flag_dir = os.path.join(directory_to_serve, FLAGGING_DIRECTORY)
|
||||
os.makedirs(flag_dir, exist_ok=True)
|
||||
|
||||
for deg in range(-180, 180+45, 45):
|
||||
img = img_orig.rotate(deg)
|
||||
img_array = np.array(img) / 127.5 - 1
|
||||
prediction = interface.predict(
|
||||
np.expand_dims(img_array, axis=0))
|
||||
processed_output = interface.output_interface.postprocess(
|
||||
prediction)
|
||||
output = {'input': interface.input_interface.save_to_file(flag_dir, img),
|
||||
'output': interface.output_interface.rebuild_flagged(
|
||||
flag_dir, {'data': {'output': processed_output}}),
|
||||
'message': 'rotation by {} degrees'.format(
|
||||
deg)}
|
||||
|
||||
with open(os.path.join(flag_dir, FLAGGING_FILENAME), 'a+') as f:
|
||||
f.write(json.dumps(output))
|
||||
f.write("\n")
|
||||
|
||||
# Prepare return json dictionary.
|
||||
self.wfile.write(json.dumps({}).encode())
|
||||
|
||||
elif self.path == "/api/auto/lighting":
|
||||
from gradio import validation_data, preprocessing_utils
|
||||
import numpy as np
|
||||
from PIL import ImageEnhance
|
||||
|
||||
self._set_headers()
|
||||
data_string = self.rfile.read(
|
||||
int(self.headers["Content-Length"]))
|
||||
msg = json.loads(data_string)
|
||||
img_orig = preprocessing_utils.decode_base64_to_image(
|
||||
msg["data"])
|
||||
img_orig = img_orig.convert('RGB')
|
||||
img_orig = img_orig.resize((224, 224))
|
||||
enhancer = ImageEnhance.Brightness(img_orig)
|
||||
|
||||
flag_dir = os.path.join(directory_to_serve, FLAGGING_DIRECTORY)
|
||||
os.makedirs(flag_dir, exist_ok=True)
|
||||
|
||||
for i in range(9):
|
||||
img = enhancer.enhance(i/4)
|
||||
img_array = np.array(img) / 127.5 - 1
|
||||
prediction = interface.predict(
|
||||
np.expand_dims(img_array, axis=0))
|
||||
processed_output = interface.output_interface.postprocess(
|
||||
prediction)
|
||||
output = {'input': interface.input_interface.save_to_file(flag_dir, img),
|
||||
'output': interface.output_interface.rebuild_flagged(
|
||||
flag_dir, {'data': {'output': processed_output}}),
|
||||
'message': 'brighting adjustment by a factor '
|
||||
'of {}'.format(i)}
|
||||
|
||||
with open(os.path.join(flag_dir, FLAGGING_FILENAME), 'a+') as f:
|
||||
f.write(json.dumps(output))
|
||||
f.write("\n")
|
||||
|
||||
# Prepare return json dictionary.
|
||||
self.wfile.write(json.dumps({}).encode())
|
||||
|
||||
else:
|
||||
self.send_error(404, 'Path not found: {}'.format(self.path))
|
||||
|
||||
|
@ -9,6 +9,7 @@ import numpy as np
|
||||
import json
|
||||
from gradio import preprocessing_utils
|
||||
import datetime
|
||||
import operator
|
||||
|
||||
# Where to find the static resources associated with each template.
|
||||
BASE_OUTPUT_INTERFACE_JS_PATH = 'static/js/interfaces/output/{}.js'
|
||||
@ -41,14 +42,6 @@ class AbstractOutput(ABC):
|
||||
"""
|
||||
return {}
|
||||
|
||||
@abstractmethod
|
||||
def rebuild_flagged(self, inp):
|
||||
"""
|
||||
All interfaces should define a method that rebuilds the flagged output when it's passed back (i.e. rebuilds image from base64)
|
||||
"""
|
||||
pass
|
||||
|
||||
import operator
|
||||
class Label(AbstractOutput):
|
||||
def __init__(self, num_top_classes=None, label=None):
|
||||
self.num_top_classes = num_top_classes
|
||||
@ -90,6 +83,17 @@ class Label(AbstractOutput):
|
||||
return json.loads(msg)
|
||||
|
||||
|
||||
class KeyValues(AbstractOutput):
|
||||
def __init__(self, label=None):
|
||||
super().__init__(label)
|
||||
|
||||
@classmethod
|
||||
def get_shortcut_implementations(cls):
|
||||
return {
|
||||
"key_values": {},
|
||||
}
|
||||
|
||||
|
||||
class Textbox(AbstractOutput):
|
||||
def __init__(self, lines=None, placeholder=None, label=None):
|
||||
self.lines = lines
|
||||
|
13
build/lib/gradio/static/css/interfaces/output/key_values.css
Normal file
13
build/lib/gradio/static/css/interfaces/output/key_values.css
Normal file
@ -0,0 +1,13 @@
|
||||
.key_values th {
|
||||
text-align: left;
|
||||
}
|
||||
.key_values tr {
|
||||
padding: 4px;
|
||||
}
|
||||
.key_values {
|
||||
font-family: monospace;
|
||||
font-size: 16px;
|
||||
}
|
||||
.key_values tbody tr:nth-child(odd) {
|
||||
background-color: white;
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
.key_values {
|
||||
width: 100%;
|
||||
}
|
@ -21,28 +21,15 @@ nav img {
|
||||
margin-right: auto;
|
||||
height: 32px;
|
||||
}
|
||||
#share_row {
|
||||
justify-content: center;
|
||||
#share {
|
||||
text-align: center;
|
||||
margin-bottom: 10px;
|
||||
font-size: 14px;
|
||||
}
|
||||
#share_form {
|
||||
flex-grow: 1;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
#share_row button, #share_row input[type=text] {
|
||||
padding: 6px 4px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
#share_row input[type=text] {
|
||||
background-color: #F6F6F6;
|
||||
}
|
||||
#share_email {
|
||||
flex-grow: 1;
|
||||
max-width: 400px;
|
||||
}
|
||||
#share_row, #share_complete, #share_form {
|
||||
display: none;
|
||||
#share-copy {
|
||||
background-color: whitesmoke;
|
||||
padding: 4px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.panels {
|
||||
display: flex;
|
||||
|
@ -12,14 +12,14 @@ function gradio(config, fn, target) {
|
||||
</div>
|
||||
<div class="panel output_panel">
|
||||
<div class="loading interface invisible">
|
||||
<img class="loading_in_progress" src="../static/img/logo_loading.gif">
|
||||
<img class="loading_failed" src="../static/img/logo_error.png">
|
||||
<img class="loading_in_progress" src="static/img/logo_loading.gif">
|
||||
<img class="loading_failed" src="static/img/logo_error.png">
|
||||
</div>
|
||||
<div class="output_interfaces">
|
||||
</div>
|
||||
</div>
|
||||
</div>`);
|
||||
io_master = Object.create(io_master_template);
|
||||
let io_master = Object.create(io_master_template);
|
||||
io_master.fn = fn
|
||||
io_master.target = target;
|
||||
io_master.config = config;
|
||||
@ -41,6 +41,7 @@ function gradio(config, fn, target) {
|
||||
"csv" : {},
|
||||
"image" : image_output,
|
||||
"label" : label_output,
|
||||
"keyvalues" : key_values,
|
||||
"textbox" : textbox_output
|
||||
}
|
||||
let id_to_interface_map = {}
|
||||
|
@ -92,7 +92,7 @@ const image_input = {
|
||||
var io = this;
|
||||
if (this.state == "IMAGE_LOADED") {
|
||||
resizeImage.call(this, this.image_data, 300, 300, function(image_data) {
|
||||
this.io_master.input(io.id, image_data);
|
||||
io.io_master.input(io.id, image_data);
|
||||
})
|
||||
}
|
||||
},
|
||||
|
@ -1,19 +1,12 @@
|
||||
const webcam = {
|
||||
html: `
|
||||
<div class="webcam_box"></div>
|
||||
<button class="take_photo">
|
||||
<span class="camera_on">Click here to take a photo!</span>
|
||||
<span class="snapped">Snapped!</span>
|
||||
</button>
|
||||
`,
|
||||
init: function(opts) {
|
||||
var io = this;
|
||||
// this.target.find(".webcam_box").width(this.target.find(".webcam_box").width);
|
||||
let w = this.target.find(".webcam_box").width();
|
||||
let h = this.target.find(".webcam_box").height();
|
||||
if (this.io_master.config.live) {
|
||||
this.target.find(".take_photo").hide();
|
||||
}
|
||||
let RATIO = 4/3;
|
||||
let dim = Math.min(h, w / RATIO);
|
||||
Webcam.set({
|
||||
@ -24,48 +17,19 @@ const webcam = {
|
||||
dest_height: dim,
|
||||
})
|
||||
Webcam.attach(this.target.find(".webcam_box")[0]);
|
||||
window.setTimeout(function() {
|
||||
io.state = "CAMERA_ON";
|
||||
}, 1000);
|
||||
this.target.find(".webcam_box, .take_photo").click(function() {
|
||||
if (io.state != "CAMERA_ON" || config.live) {
|
||||
return;
|
||||
}
|
||||
Webcam.snap(function(image_data) {
|
||||
io.image_data = image_data;
|
||||
});
|
||||
|
||||
io.state = "SNAPPED";
|
||||
Webcam.freeze();
|
||||
io.target.find(".webcam_box video").hide();
|
||||
io.target.find(".camera_on").hide();
|
||||
io.target.find(".snapped").show();
|
||||
|
||||
})
|
||||
},
|
||||
submit: function() {
|
||||
var io = this;
|
||||
if (this.io_master.config.live) {
|
||||
if (this.state == "CAMERA_ON") {
|
||||
Webcam.snap(function(image_data) {
|
||||
this.io_master.input(io.id, image_data);
|
||||
});
|
||||
} else {
|
||||
window.setTimeout(function() {
|
||||
io.submit();
|
||||
}, 500);
|
||||
}
|
||||
} else if (this.state == "SNAPPED") {
|
||||
this.io_master.input(this.id, this.image_data);
|
||||
}
|
||||
Webcam.freeze();
|
||||
Webcam.snap(function(image_data) {
|
||||
io.io_master.input(io.id, image_data);
|
||||
});
|
||||
this.state = "SNAPPED";
|
||||
},
|
||||
clear: function() {
|
||||
if (this.state == "SNAPPED") {
|
||||
this.state = "CAMERA_ON";
|
||||
this.target.find(".camera_on").show();
|
||||
this.target.find(".snapped").hide();
|
||||
Webcam.unfreeze();
|
||||
this.target.find(".webcam_box video").show();
|
||||
}
|
||||
},
|
||||
state: "NOT_STARTED",
|
||||
|
25
build/lib/gradio/static/js/interfaces/output/key_values.js
Normal file
25
build/lib/gradio/static/js/interfaces/output/key_values.js
Normal file
@ -0,0 +1,25 @@
|
||||
const key_values = {
|
||||
html: `
|
||||
<table class="key_values">
|
||||
<thead>
|
||||
<th>Property</th>
|
||||
<th>Value</th>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
`,
|
||||
init: function(opts) {},
|
||||
output: function(data) {
|
||||
let html = ""
|
||||
for (let row of data) {
|
||||
html += `<tr>
|
||||
<td>${row[0]}</td>
|
||||
<td>${row[1]}</td>
|
||||
</tr>`;
|
||||
}
|
||||
this.target.find("tbody").html(html);
|
||||
},
|
||||
clear: function() {
|
||||
this.target.find("tbody").empty();
|
||||
}
|
||||
}
|
@ -18,6 +18,7 @@
|
||||
<link rel="stylesheet" href="../static/css/interfaces/input/microphone.css">
|
||||
<link rel="stylesheet" href="../static/css/interfaces/output/image.css">
|
||||
<link rel="stylesheet" href="../static/css/interfaces/output/label.css">
|
||||
<link rel="stylesheet" href="../static/css/interfaces/output/key_values.css">
|
||||
<link rel="stylesheet" href="../static/css/interfaces/output/textbox.css">
|
||||
<link rel="stylesheet" href="../static/css/loading.css"/>
|
||||
<!-- TUI EDITOR -->
|
||||
@ -29,17 +30,9 @@
|
||||
<nav>
|
||||
<a href="https://gradio.app"><img src="../static/img/logo_inline.png" /></a>
|
||||
</nav>
|
||||
<div id="share_row">
|
||||
<button id="share" class="primary">Share this Interface</button>
|
||||
<div id="share_form">
|
||||
<input type="text" id="share_name" placeholder="sender name (you)"></input>
|
||||
<input type="text" id="share_email" placeholder="emails (comma-separated if multiple)"></input>
|
||||
<button class="primary" id="send_link">Send Link</button>
|
||||
</div>
|
||||
<div id="share_complete">
|
||||
<span id="share_message"></span>
|
||||
<button class="secondary" id="share_more"></button>
|
||||
</div>
|
||||
<div id="share" class="invisible">
|
||||
Live at <a id="share-link"></a>.
|
||||
<button id="share-copy">Copy Link</button>
|
||||
</div>
|
||||
<div id="interface_target"></div>
|
||||
<script src="../static/js/vendor/jquery.min.js"></script>
|
||||
@ -74,8 +67,8 @@
|
||||
<script src="../static/js/vendor/p5.dom.min.js"></script>
|
||||
<script src="../static/js/interfaces/output/image.js"></script>
|
||||
<script src="../static/js/interfaces/output/label.js"></script>
|
||||
<script src="../static/js/interfaces/output/key_values.js"></script>
|
||||
<script src="../static/js/interfaces/output/textbox.js"></script>
|
||||
<script src="../static/js/share.js"></script>
|
||||
<script src="../static/js/gradio.js"></script>
|
||||
<script>
|
||||
$.getJSON("static/config.json", function(config) {
|
||||
@ -89,7 +82,23 @@
|
||||
});
|
||||
});
|
||||
}, "#interface_target");
|
||||
if (config["share_url"]) {
|
||||
let share_url = config["share_url"];
|
||||
$("#share").removeClass("invisible");
|
||||
$("#share-link").text(share_url).attr("href", share_url);
|
||||
$("#share-copy").click(function() {
|
||||
copyToClipboard(share_url);
|
||||
})
|
||||
}
|
||||
});
|
||||
const copyToClipboard = str => {
|
||||
const el = document.createElement('textarea');
|
||||
el.value = str;
|
||||
document.body.appendChild(el);
|
||||
el.select();
|
||||
document.execCommand('copy');
|
||||
document.body.removeChild(el);
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,14 +1,21 @@
|
||||
import gradio as gr
|
||||
from time import sleep
|
||||
|
||||
def answer_question(text1, text2):
|
||||
return text1, text2, {"plagiarism": 0.62, "original": 0.38}
|
||||
sleep(2)
|
||||
return text1[::-1], [
|
||||
("Value 1", 12.3),
|
||||
("Section", "DF3"),
|
||||
("Confidence", 100),
|
||||
]
|
||||
|
||||
|
||||
gr.Interface(answer_question,
|
||||
[
|
||||
gr.inputs.Microphone(label="speech"),
|
||||
gr.inputs.Dropdown(["Deepspeech", "Sphynx", "Wav2Text"], label="model"),
|
||||
gr.inputs.Textbox(label="text 1", lines=4),
|
||||
gr.inputs.Textbox(label="text 2", lines=4),
|
||||
], [
|
||||
gr.outputs.Textbox(label="text 1", lines=8),
|
||||
gr.outputs.Textbox(label="out", lines=8),
|
||||
"key_values"
|
||||
]
|
||||
).launch()
|
||||
).launch(share=True)
|
||||
|
@ -4,16 +4,17 @@ from time import time
|
||||
|
||||
def flip(image):
|
||||
start = time()
|
||||
return np.flipud(image), time() - start
|
||||
return image, {
|
||||
"1": 0.2,
|
||||
"2": 0.8
|
||||
}
|
||||
|
||||
def flip2(image):
|
||||
start = time()
|
||||
return np.fliplr(image), time() - start
|
||||
|
||||
|
||||
gr.Interface([flip, flip2],
|
||||
"imagein",
|
||||
[
|
||||
"image",
|
||||
gr.outputs.Textbox(lines=1)
|
||||
gr.Interface(flip,
|
||||
"image",
|
||||
["image", "label"
|
||||
]).launch()
|
@ -4,4 +4,4 @@ import numpy as np
|
||||
def snap(image):
|
||||
return np.flipud(image)
|
||||
|
||||
gr.Interface(snap, "webcam", "image", live=True, show_input=False).launch()
|
||||
gr.Interface(snap, "webcam", "image").launch()
|
@ -31,6 +31,7 @@ gradio/static/css/interfaces/input/slider.css
|
||||
gradio/static/css/interfaces/input/textbox.css
|
||||
gradio/static/css/interfaces/input/webcam.css
|
||||
gradio/static/css/interfaces/output/image.css
|
||||
gradio/static/css/interfaces/output/key_values.css
|
||||
gradio/static/css/interfaces/output/label.css
|
||||
gradio/static/css/interfaces/output/textbox.css
|
||||
gradio/static/css/vendor/tui-color-picker.css
|
||||
@ -51,7 +52,6 @@ gradio/static/img/vendor/icon-c.svg
|
||||
gradio/static/img/vendor/icon-d.svg
|
||||
gradio/static/js/all_io.js
|
||||
gradio/static/js/gradio.js
|
||||
gradio/static/js/share.js
|
||||
gradio/static/js/utils.js
|
||||
gradio/static/js/interfaces/input/checkbox.js
|
||||
gradio/static/js/interfaces/input/checkbox_group.js
|
||||
@ -65,6 +65,7 @@ gradio/static/js/interfaces/input/slider.js
|
||||
gradio/static/js/interfaces/input/textbox.js
|
||||
gradio/static/js/interfaces/input/webcam.js
|
||||
gradio/static/js/interfaces/output/image.js
|
||||
gradio/static/js/interfaces/output/key_values.js
|
||||
gradio/static/js/interfaces/output/label.js
|
||||
gradio/static/js/interfaces/output/textbox.js
|
||||
gradio/static/js/vendor/FileSaver.min.js
|
||||
|
@ -332,9 +332,9 @@ class ImageIn(AbstractInput):
|
||||
im = np.array(im).flatten()
|
||||
im = im * self.scale + self.shift
|
||||
if self.num_channels is None:
|
||||
array = im.reshape(1, self.image_width, self.image_height)
|
||||
array = im.reshape(self.image_width, self.image_height)
|
||||
else:
|
||||
array = im.reshape(1, self.image_width, self.image_height, \
|
||||
array = im.reshape(self.image_width, self.image_height, \
|
||||
self.num_channels)
|
||||
return array
|
||||
|
||||
|
@ -179,7 +179,7 @@ class Interface:
|
||||
return
|
||||
raise RuntimeError("Validation did not pass")
|
||||
|
||||
def launch(self, inline=None, inbrowser=None, share=True, validate=True):
|
||||
def launch(self, inline=None, inbrowser=None, share=False, validate=True):
|
||||
"""
|
||||
Standard method shared by interfaces that creates the interface and sets up a websocket to communicate with it.
|
||||
:param inline: boolean. If True, then a gradio interface is created inline (e.g. in jupyter or colab notebook)
|
||||
@ -212,7 +212,6 @@ class Interface:
|
||||
server_port, httpd = networking.start_simple_server(self, output_directory, self.server_name)
|
||||
path_to_local_server = "http://{}:{}/".format(self.server_name, server_port)
|
||||
networking.build_template(output_directory)
|
||||
networking.set_config(self.get_config_file(), output_directory)
|
||||
|
||||
self.status = "RUNNING"
|
||||
self.simple_server = httpd
|
||||
@ -243,6 +242,7 @@ class Interface:
|
||||
if share:
|
||||
try:
|
||||
share_url = networking.setup_tunnel(server_port)
|
||||
print(share_url)
|
||||
except RuntimeError:
|
||||
share_url = None
|
||||
if self.verbose:
|
||||
@ -288,5 +288,8 @@ class Interface:
|
||||
else:
|
||||
display(IFrame(path_to_local_server, width=1000, height=500))
|
||||
|
||||
config = self.get_config_file()
|
||||
config["share_url"] = share_url
|
||||
networking.set_config(config, output_directory)
|
||||
|
||||
return httpd, path_to_local_server, share_url
|
||||
|
@ -139,7 +139,7 @@ def serve_files_in_background(interface, port, directory_to_serve=None, server_n
|
||||
int(self.headers["Content-Length"]))
|
||||
msg = json.loads(data_string)
|
||||
raw_input = msg["data"]
|
||||
output = {"action": "output", "data": interface.process(raw_input)}
|
||||
output = {"data": interface.process(raw_input)}
|
||||
if interface.saliency is not None:
|
||||
saliency = interface.saliency(raw_input, prediction)
|
||||
output['saliency'] = saliency.tolist()
|
||||
@ -179,81 +179,6 @@ def serve_files_in_background(interface, port, directory_to_serve=None, server_n
|
||||
f.write(json.dumps(output))
|
||||
f.write("\n")
|
||||
|
||||
# TODO(abidlabs): clean this up
|
||||
elif self.path == "/api/auto/rotation":
|
||||
from gradio import validation_data, preprocessing_utils
|
||||
import numpy as np
|
||||
|
||||
self._set_headers()
|
||||
data_string = self.rfile.read(
|
||||
int(self.headers["Content-Length"]))
|
||||
msg = json.loads(data_string)
|
||||
img_orig = preprocessing_utils.decode_base64_to_image(
|
||||
msg["data"])
|
||||
img_orig = img_orig.convert('RGB')
|
||||
img_orig = img_orig.resize((224, 224))
|
||||
|
||||
flag_dir = os.path.join(directory_to_serve, FLAGGING_DIRECTORY)
|
||||
os.makedirs(flag_dir, exist_ok=True)
|
||||
|
||||
for deg in range(-180, 180+45, 45):
|
||||
img = img_orig.rotate(deg)
|
||||
img_array = np.array(img) / 127.5 - 1
|
||||
prediction = interface.predict(
|
||||
np.expand_dims(img_array, axis=0))
|
||||
processed_output = interface.output_interface.postprocess(
|
||||
prediction)
|
||||
output = {'input': interface.input_interface.save_to_file(flag_dir, img),
|
||||
'output': interface.output_interface.rebuild_flagged(
|
||||
flag_dir, {'data': {'output': processed_output}}),
|
||||
'message': 'rotation by {} degrees'.format(
|
||||
deg)}
|
||||
|
||||
with open(os.path.join(flag_dir, FLAGGING_FILENAME), 'a+') as f:
|
||||
f.write(json.dumps(output))
|
||||
f.write("\n")
|
||||
|
||||
# Prepare return json dictionary.
|
||||
self.wfile.write(json.dumps({}).encode())
|
||||
|
||||
elif self.path == "/api/auto/lighting":
|
||||
from gradio import validation_data, preprocessing_utils
|
||||
import numpy as np
|
||||
from PIL import ImageEnhance
|
||||
|
||||
self._set_headers()
|
||||
data_string = self.rfile.read(
|
||||
int(self.headers["Content-Length"]))
|
||||
msg = json.loads(data_string)
|
||||
img_orig = preprocessing_utils.decode_base64_to_image(
|
||||
msg["data"])
|
||||
img_orig = img_orig.convert('RGB')
|
||||
img_orig = img_orig.resize((224, 224))
|
||||
enhancer = ImageEnhance.Brightness(img_orig)
|
||||
|
||||
flag_dir = os.path.join(directory_to_serve, FLAGGING_DIRECTORY)
|
||||
os.makedirs(flag_dir, exist_ok=True)
|
||||
|
||||
for i in range(9):
|
||||
img = enhancer.enhance(i/4)
|
||||
img_array = np.array(img) / 127.5 - 1
|
||||
prediction = interface.predict(
|
||||
np.expand_dims(img_array, axis=0))
|
||||
processed_output = interface.output_interface.postprocess(
|
||||
prediction)
|
||||
output = {'input': interface.input_interface.save_to_file(flag_dir, img),
|
||||
'output': interface.output_interface.rebuild_flagged(
|
||||
flag_dir, {'data': {'output': processed_output}}),
|
||||
'message': 'brighting adjustment by a factor '
|
||||
'of {}'.format(i)}
|
||||
|
||||
with open(os.path.join(flag_dir, FLAGGING_FILENAME), 'a+') as f:
|
||||
f.write(json.dumps(output))
|
||||
f.write("\n")
|
||||
|
||||
# Prepare return json dictionary.
|
||||
self.wfile.write(json.dumps({}).encode())
|
||||
|
||||
else:
|
||||
self.send_error(404, 'Path not found: {}'.format(self.path))
|
||||
|
||||
|
@ -9,6 +9,7 @@ import numpy as np
|
||||
import json
|
||||
from gradio import preprocessing_utils
|
||||
import datetime
|
||||
import operator
|
||||
|
||||
# Where to find the static resources associated with each template.
|
||||
BASE_OUTPUT_INTERFACE_JS_PATH = 'static/js/interfaces/output/{}.js'
|
||||
@ -41,14 +42,6 @@ class AbstractOutput(ABC):
|
||||
"""
|
||||
return {}
|
||||
|
||||
@abstractmethod
|
||||
def rebuild_flagged(self, inp):
|
||||
"""
|
||||
All interfaces should define a method that rebuilds the flagged output when it's passed back (i.e. rebuilds image from base64)
|
||||
"""
|
||||
pass
|
||||
|
||||
import operator
|
||||
class Label(AbstractOutput):
|
||||
def __init__(self, num_top_classes=None, label=None):
|
||||
self.num_top_classes = num_top_classes
|
||||
@ -90,6 +83,17 @@ class Label(AbstractOutput):
|
||||
return json.loads(msg)
|
||||
|
||||
|
||||
class KeyValues(AbstractOutput):
|
||||
def __init__(self, label=None):
|
||||
super().__init__(label)
|
||||
|
||||
@classmethod
|
||||
def get_shortcut_implementations(cls):
|
||||
return {
|
||||
"key_values": {},
|
||||
}
|
||||
|
||||
|
||||
class Textbox(AbstractOutput):
|
||||
def __init__(self, lines=None, placeholder=None, label=None):
|
||||
self.lines = lines
|
||||
|
13
gradio/static/css/interfaces/output/key_values.css
Normal file
13
gradio/static/css/interfaces/output/key_values.css
Normal file
@ -0,0 +1,13 @@
|
||||
.key_values th {
|
||||
text-align: left;
|
||||
}
|
||||
.key_values tr {
|
||||
padding: 4px;
|
||||
}
|
||||
.key_values {
|
||||
font-family: monospace;
|
||||
font-size: 16px;
|
||||
}
|
||||
.key_values tbody tr:nth-child(odd) {
|
||||
background-color: white;
|
||||
}
|
@ -21,28 +21,15 @@ nav img {
|
||||
margin-right: auto;
|
||||
height: 32px;
|
||||
}
|
||||
#share_row {
|
||||
justify-content: center;
|
||||
#share {
|
||||
text-align: center;
|
||||
margin-bottom: 10px;
|
||||
font-size: 14px;
|
||||
}
|
||||
#share_form {
|
||||
flex-grow: 1;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
#share_row button, #share_row input[type=text] {
|
||||
padding: 6px 4px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
#share_row input[type=text] {
|
||||
background-color: #F6F6F6;
|
||||
}
|
||||
#share_email {
|
||||
flex-grow: 1;
|
||||
max-width: 400px;
|
||||
}
|
||||
#share_row, #share_complete, #share_form {
|
||||
display: none;
|
||||
#share-copy {
|
||||
background-color: whitesmoke;
|
||||
padding: 4px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.panels {
|
||||
display: flex;
|
||||
|
@ -12,14 +12,14 @@ function gradio(config, fn, target) {
|
||||
</div>
|
||||
<div class="panel output_panel">
|
||||
<div class="loading interface invisible">
|
||||
<img class="loading_in_progress" src="../static/img/logo_loading.gif">
|
||||
<img class="loading_failed" src="../static/img/logo_error.png">
|
||||
<img class="loading_in_progress" src="static/img/logo_loading.gif">
|
||||
<img class="loading_failed" src="static/img/logo_error.png">
|
||||
</div>
|
||||
<div class="output_interfaces">
|
||||
</div>
|
||||
</div>
|
||||
</div>`);
|
||||
io_master = Object.create(io_master_template);
|
||||
let io_master = Object.create(io_master_template);
|
||||
io_master.fn = fn
|
||||
io_master.target = target;
|
||||
io_master.config = config;
|
||||
@ -41,6 +41,7 @@ function gradio(config, fn, target) {
|
||||
"csv" : {},
|
||||
"image" : image_output,
|
||||
"label" : label_output,
|
||||
"keyvalues" : key_values,
|
||||
"textbox" : textbox_output
|
||||
}
|
||||
let id_to_interface_map = {}
|
||||
|
@ -92,7 +92,7 @@ const image_input = {
|
||||
var io = this;
|
||||
if (this.state == "IMAGE_LOADED") {
|
||||
resizeImage.call(this, this.image_data, 300, 300, function(image_data) {
|
||||
this.io_master.input(io.id, image_data);
|
||||
io.io_master.input(io.id, image_data);
|
||||
})
|
||||
}
|
||||
},
|
||||
|
@ -1,19 +1,12 @@
|
||||
const webcam = {
|
||||
html: `
|
||||
<div class="webcam_box"></div>
|
||||
<button class="take_photo">
|
||||
<span class="camera_on">Click here to take a photo!</span>
|
||||
<span class="snapped">Snapped!</span>
|
||||
</button>
|
||||
`,
|
||||
init: function(opts) {
|
||||
var io = this;
|
||||
// this.target.find(".webcam_box").width(this.target.find(".webcam_box").width);
|
||||
let w = this.target.find(".webcam_box").width();
|
||||
let h = this.target.find(".webcam_box").height();
|
||||
if (this.io_master.config.live) {
|
||||
this.target.find(".take_photo").hide();
|
||||
}
|
||||
let RATIO = 4/3;
|
||||
let dim = Math.min(h, w / RATIO);
|
||||
Webcam.set({
|
||||
@ -24,48 +17,19 @@ const webcam = {
|
||||
dest_height: dim,
|
||||
})
|
||||
Webcam.attach(this.target.find(".webcam_box")[0]);
|
||||
window.setTimeout(function() {
|
||||
io.state = "CAMERA_ON";
|
||||
}, 1000);
|
||||
this.target.find(".webcam_box, .take_photo").click(function() {
|
||||
if (io.state != "CAMERA_ON" || config.live) {
|
||||
return;
|
||||
}
|
||||
Webcam.snap(function(image_data) {
|
||||
io.image_data = image_data;
|
||||
});
|
||||
|
||||
io.state = "SNAPPED";
|
||||
Webcam.freeze();
|
||||
io.target.find(".webcam_box video").hide();
|
||||
io.target.find(".camera_on").hide();
|
||||
io.target.find(".snapped").show();
|
||||
|
||||
})
|
||||
},
|
||||
submit: function() {
|
||||
var io = this;
|
||||
if (this.io_master.config.live) {
|
||||
if (this.state == "CAMERA_ON") {
|
||||
Webcam.snap(function(image_data) {
|
||||
this.io_master.input(io.id, image_data);
|
||||
});
|
||||
} else {
|
||||
window.setTimeout(function() {
|
||||
io.submit();
|
||||
}, 500);
|
||||
}
|
||||
} else if (this.state == "SNAPPED") {
|
||||
this.io_master.input(this.id, this.image_data);
|
||||
}
|
||||
Webcam.snap(function(image_data) {
|
||||
io.io_master.input(io.id, image_data);
|
||||
});
|
||||
// Webcam.freeze();
|
||||
this.state = "SNAPPED";
|
||||
},
|
||||
clear: function() {
|
||||
if (this.state == "SNAPPED") {
|
||||
this.state = "CAMERA_ON";
|
||||
this.target.find(".camera_on").show();
|
||||
this.target.find(".snapped").hide();
|
||||
Webcam.unfreeze();
|
||||
this.target.find(".webcam_box video").show();
|
||||
// Webcam.unfreeze();
|
||||
}
|
||||
},
|
||||
state: "NOT_STARTED",
|
||||
|
25
gradio/static/js/interfaces/output/key_values.js
Normal file
25
gradio/static/js/interfaces/output/key_values.js
Normal file
@ -0,0 +1,25 @@
|
||||
const key_values = {
|
||||
html: `
|
||||
<table class="key_values">
|
||||
<thead>
|
||||
<th>Property</th>
|
||||
<th>Value</th>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
`,
|
||||
init: function(opts) {},
|
||||
output: function(data) {
|
||||
let html = ""
|
||||
for (let row of data) {
|
||||
html += `<tr>
|
||||
<td>${row[0]}</td>
|
||||
<td>${row[1]}</td>
|
||||
</tr>`;
|
||||
}
|
||||
this.target.find("tbody").html(html);
|
||||
},
|
||||
clear: function() {
|
||||
this.target.find("tbody").empty();
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
$("#share").click(function() {
|
||||
$("#share").hide()
|
||||
$("#share_form").css('display', 'flex')
|
||||
})
|
||||
|
||||
$("#send_link").click(function(evt) {
|
||||
let name = $("#share_name").val()
|
||||
let email = $("#share_email").val()
|
||||
if (name && email) {
|
||||
$("#send_link").attr('disabled', true);
|
||||
$.ajax({
|
||||
"url" : "https://gradio.app/api/send-email/",
|
||||
"type": "POST",
|
||||
"crossDomain": true,
|
||||
"data": {
|
||||
"url": config["share_url"],
|
||||
"name": name,
|
||||
"email": email
|
||||
},
|
||||
"success": function() {
|
||||
$("#share_message").text("Shared successfully.");
|
||||
$("#share_more").text("Share more");
|
||||
},
|
||||
"error": function() {
|
||||
$("#share_message").text("Failed to share.");
|
||||
$("#share_more").text("Try again");
|
||||
},
|
||||
"complete": function() {
|
||||
$("#share_form").hide();
|
||||
$("#share_complete").show();
|
||||
$("#send_link").attr('disabled', false);
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
$("#share_more").click(function (evt) {
|
||||
$("#share_email").val("");
|
||||
$("#share_form").show();
|
||||
$("#share_complete").hide();
|
||||
})
|
@ -18,6 +18,7 @@
|
||||
<link rel="stylesheet" href="../static/css/interfaces/input/microphone.css">
|
||||
<link rel="stylesheet" href="../static/css/interfaces/output/image.css">
|
||||
<link rel="stylesheet" href="../static/css/interfaces/output/label.css">
|
||||
<link rel="stylesheet" href="../static/css/interfaces/output/key_values.css">
|
||||
<link rel="stylesheet" href="../static/css/interfaces/output/textbox.css">
|
||||
<link rel="stylesheet" href="../static/css/loading.css"/>
|
||||
<!-- TUI EDITOR -->
|
||||
@ -29,17 +30,9 @@
|
||||
<nav>
|
||||
<a href="https://gradio.app"><img src="../static/img/logo_inline.png" /></a>
|
||||
</nav>
|
||||
<div id="share_row">
|
||||
<button id="share" class="primary">Share this Interface</button>
|
||||
<div id="share_form">
|
||||
<input type="text" id="share_name" placeholder="sender name (you)"></input>
|
||||
<input type="text" id="share_email" placeholder="emails (comma-separated if multiple)"></input>
|
||||
<button class="primary" id="send_link">Send Link</button>
|
||||
</div>
|
||||
<div id="share_complete">
|
||||
<span id="share_message"></span>
|
||||
<button class="secondary" id="share_more"></button>
|
||||
</div>
|
||||
<div id="share" class="invisible">
|
||||
Live at <a id="share-link"></a>.
|
||||
<button id="share-copy">Copy Link</button>
|
||||
</div>
|
||||
<div id="interface_target"></div>
|
||||
<script src="../static/js/vendor/jquery.min.js"></script>
|
||||
@ -74,8 +67,8 @@
|
||||
<script src="../static/js/vendor/p5.dom.min.js"></script>
|
||||
<script src="../static/js/interfaces/output/image.js"></script>
|
||||
<script src="../static/js/interfaces/output/label.js"></script>
|
||||
<script src="../static/js/interfaces/output/key_values.js"></script>
|
||||
<script src="../static/js/interfaces/output/textbox.js"></script>
|
||||
<script src="../static/js/share.js"></script>
|
||||
<script src="../static/js/gradio.js"></script>
|
||||
<script>
|
||||
$.getJSON("static/config.json", function(config) {
|
||||
@ -89,7 +82,23 @@
|
||||
});
|
||||
});
|
||||
}, "#interface_target");
|
||||
if (config["share_url"]) {
|
||||
let share_url = config["share_url"];
|
||||
$("#share").removeClass("invisible");
|
||||
$("#share-link").text(share_url).attr("href", share_url);
|
||||
$("#share-copy").click(function() {
|
||||
copyToClipboard(share_url);
|
||||
})
|
||||
}
|
||||
});
|
||||
const copyToClipboard = str => {
|
||||
const el = document.createElement('textarea');
|
||||
el.value = str;
|
||||
document.body.appendChild(el);
|
||||
el.select();
|
||||
document.execCommand('copy');
|
||||
document.body.removeChild(el);
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 122 KiB |
34
size.sh
Normal file
34
size.sh
Normal file
@ -0,0 +1,34 @@
|
||||
#!/bin/bash
|
||||
#set -x
|
||||
|
||||
# Shows you the largest objects in your repo's pack file.
|
||||
# Written for osx.
|
||||
#
|
||||
# @see https://stubbisms.wordpress.com/2009/07/10/git-script-to-show-largest-pack-objects-and-trim-your-waist-line/
|
||||
# @author Antony Stubbs
|
||||
|
||||
# set the internal field separator to line break, so that we can iterate easily over the verify-pack output
|
||||
IFS=$'\n';
|
||||
|
||||
# list all objects including their size, sort by size, take top 10
|
||||
objects=`git verify-pack -v .git/objects/pack/pack-*.idx | grep -v chain | sort -k3nr | head`
|
||||
|
||||
echo "All sizes are in kB's. The pack column is the size of the object, compressed, inside the pack file."
|
||||
|
||||
output="size,pack,SHA,location"
|
||||
allObjects=`git rev-list --all --objects`
|
||||
for y in $objects
|
||||
do
|
||||
# extract the size in bytes
|
||||
size=$((`echo $y | cut -f 5 -d ' '`/1024))
|
||||
# extract the compressed size in bytes
|
||||
compressedSize=$((`echo $y | cut -f 6 -d ' '`/1024))
|
||||
# extract the SHA
|
||||
sha=`echo $y | cut -f 1 -d ' '`
|
||||
# find the objects location in the repository tree
|
||||
other=`echo "${allObjects}" | grep $sha`
|
||||
#lineBreak=`echo -e "\n"`
|
||||
output="${output}\n${size},${compressedSize},${other}"
|
||||
done
|
||||
|
||||
echo -e $output | column -t -s ', '
|
Binary file not shown.
Before Width: | Height: | Size: 72 KiB |
Loading…
Reference in New Issue
Block a user