How do I create separate functions (within index function in the controller.py) so I can create two independent plots with two independent files that I load independently?
In other words, I would like the user take the following steps:
Upload the Training file
Click the 'Plot' button to plot
Now upload the Test file
Click the 'Plot' button to plot.
Both plots should appear on the same HTML template. Both files will use the same plotting function (or now). Ideally, I would like to use different functions.
Here's how the input HTML looks like:
The function to plot is the following:
def compute_mean_std(filename=None):
# data = np.loadtxt(os.path.join('uploads', filename))
df = pd.read_csv(os.path.join('uploads', filename))
sns.set_style('darkgrid')
fig, ax = plt.subplots(3, sharex=True)
ax[0].plot(df.index, df.x, color="red")
ax[1].plot(df.index, df.y, color="blue")
ax[2].plot(df.index, df.z, color="teal")
ax[0].legend(numpoints=1, loc=1)
ax[1].legend(loc=1)
ax[2].legend(loc=1)
# Check static folder:
if not os.path.isdir('static'):
os.mkdir('static')
else:
for plotfilename in glob.glob(os.path.join('static', '*.png')):
os.remove(plotfilename)
plotfile = os.path.join('static', str(time.time()) + '.png')
plt.savefig(plotfile)
return plotfile
While the controller has the following code:
from compute import compute_mean_std as compute_function
#app.route('/', methods=['GET', 'POST'])
def index():
form = Average(request.form)
filename = None # default
if request.method == 'POST':
# Save uploaded file on server if it exists and is valid
if request.files:
file = request.files[form.filename.name]
if file and allowed_file(file.filename):
# Make a valid version of filename for any file ystem
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'],
filename))
result = compute_function(filename)
else:
result = None
return render_template("view.html", form=form, result=result)
Right now both plot the same plots.
So How do we differentiate the two file uploads.? The option is we have to create two file input...
<input type="file" name="file_training">
<input type="file" name="file_test">
and in your view function you have to check which file is user uploaded
# Inside POST method
file_training = request.files.get('file_training')
file_test = request.files.get('file_test')
return jsonify({"file_training": file_training, "file_test": file_test})
HTML
In your ajax success keep track of which have the values.
Related
I am making an image segmentation app which segments image into 'k' colors
the code for flask app goes like this:
##not pasting standard starting code
app.config['template_path'] = r'C:\Users\Asus\Documents\deep learning\deep_learn\NOTEBOOKS\app\templates'
def image_return():
if request.method == 'POST':
if request.files:
print('address accessed')
file = request.files['img']
k = request.values['k']
print('DONE FILE')
if not file.filename == '':
print('FILENAME EXISTS')
name = secure_filename(file.filename)
print(name)
address = os.path.join(
app.config['template_path'], 'uploads/', name)
file.save(address)
print('DONEEEE')
img = reader(address)
red_image, path = main(img, name, k)
print('image red. and saved to path')
return red_image, path
else:
redirect(request.url)
return flash('something went wrong try again')
# app.route('/transformed', methods=['POST'])
def transform():
red_image, path = image_return()
return render_template('imagetrans.html', address=path)
### ALL THE PRINT STATEMENTS RAN SUCCESSFULLY AND SAVED THE CONVERTED IMAGE TO THE PATH
## THE APPROACH I AM USING IS TO NOT DISPLAY LIVE IMAGE BUT TO SAVE IS FIRSTLY AND THEN DISPLAY IT FROM A SAVED LOCATION
the HTML goes like this:
<body>
<center>
<img src={{address}} alt="display.error" />
</center>
</body>
the python code for generating images works well
def color_reduction(img, k):
# transform the image
print(type(img))
data = np.float32(img).reshape((-1, 3))
# determine the criteria
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 20, 0.001)
# implementing k - means
ret, label, center = cv2.kmeans(
data, k, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS)
center = np.uint8(center)
result = center[label.flatten()]
result = result.reshape(img.shape)
return result
template_path = r'C:\Users\Asus\Documents\deep learning\deep_learn\NOTEBOOKS\app\templates\transformed'
def main(img, filename, k=5, title=None):
red_image = color_reduction(img, k=int(k))
path = os.path.join(template_path, f'{filename}_{k}.jpg')
cv2.imwrite(path, red_image)
return red_image, path
the reduced_image is not read in img src even after passing correct variable address
I think I am going wrong at the HTML part!
Have you checked what the value for address is in the html, i.e. if you look at the page source what does the address value render as in your browser?
I think this is probably going wrong since it looks like you are passing an absolute filepath to the html whereas really you should pass a path that is relative to the flask app instance.
i.e. if your flask app is in a folder called my_site then to src you would just pass the path from my_site to the image, i.e. my_site\static\img\img.jpg rather than C:\Users\Documents\projects\my_site\static\img\img.jpg.
I am trying to display the image of python script output using below lines but instead of displaying in browser, code downloading the file instead of displaying
this is the function i have created in views.py:
def adc(request):
file = "C:\Users\TheBoss\Downloads\New_test.xlsx"
df = pd.read_excel(file, sheet_name='Graph')
plt.plot(df['Date'], df['Video Device - Not Responding'], label = 'Video Device - Not Responding')
#plt.plot(df['Date'], df['30th Apr'], 'b', label = '30-Apr')
plt.xticks(rotation=45)
plt.tick_params(axis='x', which='major', labelsize=6)
# naming the y axis
plt.ylabel('Condition Count')
# giving a title to my graph
plt.title('Condition')
# function to show the plot
plt.legend()
#plt.show()
plt.savefig('C:\\Users\\TheBoss\\Downloads\\test.png')
image_data = open("C:\\Users\\TheBoss\\Downloads\\test.png", "rb").read()
return HttpResponse(image_data, content_type="test/png")
Generally, this should be enough to display image inline.
def adc(request):
file = "C:\Users\TheBoss\Downloads\New_test.xlsx"
df = pd.read_excel(file, sheet_name='Graph')
plt.plot(df['Date'], df['Video Device - Not Responding'], label = 'Video Device - Not Responding')
plt.xticks(rotation=45)
plt.tick_params(axis='x', which='major', labelsize=6)
plt.ylabel('Condition Count')
plt.title('Condition')
plt.legend()
buffer = io.BytesIO()
plt.savefig(buffer, format='png')
return HttpResponse(buffer.getvalue(), content_type="test/png")
It should display as an image in most browsers and if you want to insert the image in HTML, you'd use a simple
<img src="{% url 'my_image' %}">
I know from experience that this works in Edge, Firefox and Opera. Sometimes browsers need additional convincing to display image inline and in those cases setting the header Content-Disposition to inline usually works.
I have an image retrieval program in python, I want to make a web-based program using flask. But, I don't understand how to get input images from flask. So I can process the input image in my image retrieval program then show the result in my flask page.
here my flask code:
import os
from flask import Flask, flash, request, redirect, url_for, send_from_directory, Request, render_template
from werkzeug.utils import secure_filename
UPLOAD_FOLDER = 'res/uploads'
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg'}
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['MAX_CONTENT_LENGTH'] = 10 * 1024 * 1024
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
#app.route('/', 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 redirect(url_for('uploaded_file',
filename=filename))
return render_template('home.html')
#app.route('/uploads/<filename>')
def uploaded_file(filename):
return send_from_directory(app.config['UPLOAD_FOLDER'],
filename)
app.run(host='0.0.0.0', port= 81)
and this is part of my image retrieval program, I need the input image from flask to fill 'inputImage.jpg' on my queryPath:
from PIL import Image
# Define path of testing data and indexing file
queryPath = root_path + 'inputImage.jpg'
index_file = root_path + 'mtcd.csv'
# define the bins for quantization
colorBins = 64
R_Bins = 4
G_Bins = 4
B_Bins = 4
edgeBins = 18
query = cv2.imread(queryPath)
# Color Quantization
colorQuant = combineColorQuantization(query, B_Bins, G_Bins, R_Bins)
# Edge Quantization
edgeQuant = edgeQuantization(query, edgeBins)
# Texton Search
features = textonSearch(colorQuant, colorBins, edgeQuant, edgeBins)
# GLCM
glcm, en = GLCM(query)
features.extend(glcm[0])
features.extend(glcm[1])
features.extend(glcm[2])
features.extend(en)
# perform the search
searcher = Searcher(index_file)
results = searcher.search(features)
# display the query
fig = figure(figsize=(5,5))
title('Query Image')
imshow(array(Image.open(queryPath)))
axis('off')
# loop over the results
fig = figure(num=None, figsize=(20,5))
title('Result Image')
result = []
i = 1
for (score, resultID) in results:
# load the result image and display it
a = fig.add_subplot(2, 6, i)
image = imread(root_path + 'batik/'+resultID)
i += 1
imshow(image)
axis('off')
print(result)
You can def the image processing code as a seperate function like this
def process_file(path)
# Define path of testing data and indexing file
queryPath = path
index_file = root_path + 'mtcd.csv'
# define the bins for quantization
colorBins = 64
R_Bins = 4
G_Bins = 4
B_Bins = 4
edgeBins = 18
query = cv2.imread(queryPath)
# Color Quantization
colorQuant = combineColorQuantization(query, B_Bins, G_Bins, R_Bins)
# Edge Quantization
edgeQuant = edgeQuantization(query, edgeBins)
# Texton Search
features = textonSearch(colorQuant, colorBins, edgeQuant, edgeBins)
# GLCM
glcm, en = GLCM(query)
features.extend(glcm[0])
features.extend(glcm[1])
features.extend(glcm[2])
features.extend(en)
# perform the search
searcher = Searcher(index_file)
results = searcher.search(features)
# display the query
fig = figure(figsize=(5,5))
title('Query Image')
imshow(array(Image.open(queryPath)))
axis('off')
# loop over the results
fig = figure(num=None, figsize=(20,5))
title('Result Image')
result = []
i = 1
for (score, resultID) in results:
# load the result image and display it
a = fig.add_subplot(2, 6, i)
image = imread(root_path + 'batik/'+resultID)
i += 1
imshow(image)
axis('off')
print(result)
call the process_file() method from flask route code block
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))
process_file(os.path.join(app.config['UPLOAD_FOLDER'], filename))
return redirect(url_for('uploaded_file',
filename=filename))
return render_template('home.html')
This is related to another question I posted, but is more specific (and hopefully gets more specific answers).
I am trying to display png images on an IPython notebook, and update the display as the png files are updated.
One possible solution is below. Unfortunately, my implementation does not update the file, and creates a new HTML block at the end of the old one. What I want instead, is to replace the old HTML block with the new one -i.e. replace the content only.
As example code, I have two notebooks. One notebook generates pngs and saves them in a figures directory.
import os
import glob
import time
import matplotlib.pyplot as plt
import numpy as np
for ix in range(20):
N = 50
x = np.random.rand(N)
y = np.random.rand(N)
colors = np.random.rand(N)
area = np.pi * (15 * np.random.rand(N))**2 # 0 to 15 point radiuses
fig = plt.figure(figsize=(8,8))
plt.scatter(x, y, s=area, c=colors, alpha=0.5)
fig.savefig(os.path.join("figures", "fig1.png"), bbox_inches="tight")
plt.close(fig)
time.sleep(3)
A second notebook shows the pngs It is supposed top show a single png which updates. Instead it stacks the same png on itself, every time the png is updated.
import os
import time
from IPython.html.widgets import interact, interactive, fixed
from IPython.html import widgets
from IPython.display import clear_output, display, HTML
def get_latest_file_ts(directory="figures", file_name="fig1.png", strip_directory=True):
"""
Continuously check for modifications to the file file_name in directory. If file has been
modified after touched_on, return the Unix timestamp of the modification time.
:param directory: string / the directory where the file is
:param file_name: string / the file name
:param strip_directory: boolean / if True, strip the directory part of the file name
:return:
"""
if strip_directory:
fname = os.path.join(directory, file_name)
else:
fname = file_name
try:
return os.stat(fname).st_mtime
except:
print "FileNotFoundException: Could not find file %s" % fname
return None
def check_if_modified_file(directory="figures", file_name="fig1.png",
touched_on=1420070400, sleep_time=1, strip_directory=True):
"""
Continuously check for modifications to the file file_name in directory. If file has been
modified after touched_on, return the Unix timestamp of the modification time.
:param directory: string / the directory where the file is
:param file_name: string / the file name
:param touched_on: float / the Unix timestamp on which the file was last modified
:param sleep_time: float / wait time between interactions
:param strip_directory: boolean / if True, strip the directory part of the file name
:return:
"""
if strip_directory:
fname = os.path.join(directory, file_name)
else:
fname = file_name
while True:
try:
latest_touch = os.stat(fname).st_mtime
if latest_touch == touched_on:
time.sleep(sleep_time)
else:
return latest_touch
except:
print "FileNotFoundException: Could not find %s" % fname
return None
def show_figs(directory="figures", file_name="fig1.png"):
s = """<figure>\n\t<img src="%s" alt="The figure" width="304" height="228">\n</figure>""" % os.path.join(directory, file_name)
display(HTML(s))
timestamp = get_latest_file_ts(directory="figures", file_name="fig1.png", strip_directory=True)
show_figs(directory="figures", file_name="fig1.png")
cnt = 1
while True and cnt < 4:
timestamp = check_if_modified_file(directory="figures", file_name="fig1.png", touched_on=timestamp, sleep_time=1, strip_directory=True)
display(HTML(""))
show_figs(directory="figures", file_name="fig1.png")
time.sleep(1)
cnt += 1
(as you can see I have added upper limits on the executions of both the generator and consumer loops)
Any help on how to make widgets update HTML content would be awesome.
The problem that you only see the first image is very likely related to caching of the browser. To overcome this issue a simple solution is to add a varying query string to the image src as shown e.g. here.
Thus your show_figs method could look like:
import time
def show_figs(directory="figures", file_name="fig1.png"):
s = """<figure>\n\t<img src="{0}?{1}" alt="The figure" width="304" height="228">\n</figure>""".format(os.path.join(directory, file_name),time.time())
display(HTML(s))
In combination with the clear_output function you should be able to get your updated image.
I'm learning how to use the Django framework for a work project that will allow users to load files in various formats (at the moment I am only dealing with CSV files), graph that data using Pandas, and display that data back to the user via a Django template. I haven't had any problems creating the graph in iPython, but have been struggling with getting it to an HTML Django template.
I've followed the following example from matplotlib:
# graph input file
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
from matplotlib.figure import Figure
from matplotlib.dates import DateFormatter
def graph(request):
fig = Figure()
ax = fig.add_subplot(111)
x = []
y = []
now = datetime.datetime.now()
delta = datetime.timedelta(days=1)
for i in range(10):
x.append(now)
now += delta
y.append(random.randint(0, 1000))
ax.plot_date(x, y, '-')
ax.xaxis.set_major_formatter(DateFormatter('%Y-%m-%d'))
fig.autofmt_xdate()
canvas = FigureCanvas(fig)
response = HttpResponse( content_type = 'image/png')
canvas.print_png(response)
return response
The above example works great and I can see it in a template, but that's just a graph with hard-coded values.
I've attempted to use Pandas because of its seemingly simplistic syntax and my attempts in Django are as follows:
# graph input file
import pandas as pd
from pandas import DataFrame
def graph(request):
data_df = pd.read_csv("C:/Users/vut46744/Desktop/graphite_project/sampleCSV.csv")
data_df = pd.DataFrame(dataArray)
data_df.plot()
response = HttpResponse( content_type = 'image/png')
return response
In Django calling the .plot() displays the graph fine, but displays a blank page to the HTML template. I've also tried using Numpy's genfromtxt() and loadtxt(), but to no avail. Also, my Google searches have not been fruitful either.
Any help or suggestion would be great. If you know of a better alternative to Pandas then I am willing to try other options.
Haven't tried this yet, but I would attack it something like:
def graph(request):
fig = Figure()
ax = fig.add_subplot(111)
data_df = pd.read_csv("C:/Users/vut46744/Desktop/graphite_project/sampleCSV.csv")
data_df = pd.DataFrame(data_df)
data_df.plot(ax=ax)
canvas = FigureCanvas(fig)
response = HttpResponse(content_type='image/png')
canvas.print_png(response)
return response