Flask使用笔记

DIP Using Flask

目的

制作一个简单的图像处理软件,能够实现基本的图像处理操作。

DIP

真正核心的图像处理部分是调库的,python在这方面充分展现了第三方库的强大功能。

requirements如下

import numpy as np
import cv2
from PIL import Image,ImageEnhance,ImageDraw,ImageFont
from skimage import io,color,transform,img_as_float,img_as_ubyte,img_as_uint
from skimage.exposure import histogram,adjust_gamma,adjust_log,adjust_sigmoid,equalize_hist
import matplotlib.pyplot as plt

GUI

在这个项目中,我的主要工作就是GUI,所以可谈的就比较多了。作为我的第一个独立创作的flask应用,比较上心。

$ tree
├─.vscode
├─static
│  ├─css
│  ├─Image
│  └─js
├─templates
└─__pycache__

templates下是html的模板。对于flask来说,需要渲染的模板通过render_templates调用,这样可以极大的减少前端代码的重复率,提高开发效率。

对于这个项目来说,base.html下有3个扩展,index.htmlbasic.htmldip.html。这三个页面都继承自base.html

app.py如下:

from flask import Flask, render_template, url_for, request, flash, redirect
from flask_bootstrap import Bootstrap
from forms import *
import os
from werkzeug.utils import secure_filename
from ImageOP import ImageProcess
import numpy as np
import pyperclip

app = Flask(__name__)
basedir = os.path.abspath(os.path.dirname(__file__))
bootstrap = Bootstrap(app)
app.config["SECRET_KEY"] = "A-VERY-LONG-SECRET-KEY"
filename = ""
iop = ImageProcess()

@app.route("/", methods=["POST", "GET"])
def index():
    form = UpLoadFileForm()
    global filename
    print("in index")
    if form.validate_on_submit():
        f = form.photo.data
        filename = os.path.join('static/Image', secure_filename(f.filename))
        f.save(os.path.join(
            basedir, filename
        ))
        print(filename)
        try:
            iop.PhotoOpen(filename, change=True)
            flash("上传成功: " + filename, category="success")
        # return redirect(url_for('index'))
        except Exception as e:
            flash("文件打开失败", category="danger")
            flash(e, category="danger")
    if filename == "":
        flash("请打开图片", category="warning")
    if filename:
        iop.PhotoOpen(filename)
    print("index filename", filename)
    return render_template("index.html", upload_file_form=form, filename=filename + "?randomstr=" + str(np.random.rand()))

@app.route("/basic", methods=["POST", "GET"])
def basic():
    global filename
    if filename == "":
        return redirect(url_for("index"))
    rotate_form = RotateForm()
    if rotate_form.validate_on_submit():
        filename = iop.RotateOP(rotate_form.angle.data)
    if filename:
        iop.PhotoOpen(filename)
    return render_template("basic.html", filename=filename + "?randomstr=" + str(np.random.rand()), rotate_form=rotate_form)

@app.route("/dip", methods=["POST", "GET"])
def dip():
    global filename
    if filename == "":
        return redirect(url_for("index"))
    sharpen_form = SharpenForm()
    if sharpen_form.validate_on_submit():
        if sharpen_form.operation.data == 0:
            filename = iop.BSCenhance(sharp_factor=sharpen_form.factor.data, choice="sharp")
        elif sharpen_form.operation.data == 1:
            filename = iop.BSCenhance(bright_factor=sharpen_form.factor.data, choice="contrast")
        else:
            filename = iop.BSCenhance(contrast_factor=sharpen_form.factor.data, choice="bright")
    filter_form = FilterForm()
    if filter_form.validate_on_submit():
        # filter_form.filtername.data
        arr = ["gaussian", "emboss", "edge", "sharp", "rect"]
        filename = iop.filters(arr[filter_form.filtername.data])
    linear_form = LinearForm()
    if linear_form.validate_on_submit():
        filename = iop.Hist_linear(a=linear_form.slope.data, b=linear_form.bias.data)
    unlinear_form = UnLinearForm()
    if unlinear_form.validate_on_submit():
        if unlinear_form.function.data == 0:
            filename = iop.Hist_gamma(1.2)
        elif unlinear_form.function.data == 1:
            filename = iop.Hist_sigmoid()
        else:
            filename = iop.Hist_log()
    color_space_reverse_form = ColorSpaceReverseForm()
    if color_space_reverse_form.validate_on_submit():
        arr = ['RGB', 'HSV', 'RGB CIE', 'XYZ', 'YUV', 'YIQ', 'YPbPr', 'YCbCr']
        filename = iop.ColorSpaceChange(arr[color_space_reverse_form.toSpace.data])
    if filename:
        iop.PhotoOpen(filename)
    return render_template("dip.html", filename=filename + "?randomstr=" + str(np.random.rand()), 
                    sharpen_form=sharpen_form, filter_form=filter_form, 
                    linear_form=linear_form, unlinear_form=unlinear_form,
                    color_space_reverse_form=color_space_reverse_form)

@app.route("/share", methods=["POST", "GET"])
def share():
    global filename
    url = "127.0.0.1:5000/" + filename
    pyperclip.copy(url)
    flash("图片已经黏贴到剪切板", category="success")
    return "filename: " + url

@app.route("/equalization", methods=["POST", "GET"])
def equalization():
    global filename
    filename = iop.Hist_equalize()
    return redirect(url_for("dip"))

@app.route("/smooth", methods=["POST", "GET"])
def smooth():
    global filename
    filename = iop.filters("rect")
    return "smooth over py"

@app.route("/histogram", methods=['POST', 'GET'])
def histogram():
    print("in histogram")
    hist = iop.Hist()
    return hist + "?randomstr=" + str(np.random.rand())

@app.route("/FFTDCT", methods=["POST", "GET"])
def FFTDCT():
    print("in fft dct", request.form.get("operation"))
    ret = iop.FftDct(request.form.get("operation"))
    print(ret)
    return ret + "?randomstr=" + str(np.random.rand())

@app.route("/org", methods=["GET"])
def org():
    global filename
    print(filename)
    filename = iop.orgFile
    print(filename)
    iop.PhotoOpen(filename, change=True)
    return redirect(url_for("index"))

@app.route("/undo", methods=["GET", "POST"])
def undo():
    global filename
    print(iop.temp)
    if iop.temp <= 1:
        print("here")
        filename = iop.orgFile
        iop.PhotoOpen(iop.orgFile)
        flash("已是最原始操作!", category="warning")
    else:
        iop.temp -= 1
        filename = iop.base_dir + 'temp'+str(iop.temp)+'.'+iop.format
        print("in undo")
        print(filename)
        iop.PhotoOpen(filename)
    return "undo over py"

@app.route("/redo", methods=["GET", "POST"])
def redo():
    try:
        global filename
        iop.temp += 1
        iop.PhotoOpen(iop.base_dir + 'temp'+str(iop.temp)+'.'+iop.format)
        filename = iop.base_dir + 'temp'+str(iop.temp)+'.'+iop.format
    except:
        iop.temp -= 1
        flash("已经是最新操作!", category="warning")
    return "redo over py"

@app.route("/rotate1")
def rotate1():
    global filename
    filename = iop.RotateOP(90)
    return redirect(url_for("basic"))

@app.route("/rotate2")
def rotate2():
    global filename
    filename = iop.RotateOP(-90)
    return redirect(url_for("basic"))

if __name__ == "__main__":
    app.run(debug=True, host="0.0.0.0", port="5000")

flask

在flask中,有一个常用的语句@app.route(),这个方法可以将重定向的网页调用下面的函数,这样就为html间的通信提供了有力的工具。
在javascript中,可以使用$ajax(settings)来对python进行访问。

$ajax({
	url: "127.0.0.1:5000/",
	type: "POST",
	data: {data: none},
	dataType: html,
	success: function(data, status) {
		console.log(status);
	}
});

在python中,使用flask提供的url_for

@app.route("/about")
def about():
    return url_for("index")

总结

学习flask,让我了解了不少前端知识,我也第一次明白什么是框架,为什么要用框架。

之前曾用纯粹的javascript作为控制,尝试过一个“别踩白块”的实验,后来自己写了一个简单的俄罗斯方块。虽说使用同一种语言既控制前端又控制逻辑,应该是比较方便的,但是我在写方块的旋转和移动的时候,明显觉得对javascript的不适,感觉它不像python、PHP那样,想如果能用其他面向对象的Language来写更复杂的算法就好了。

事实上,python用户如此庞大,必然有与js交流的方法。

  • flask是python的前端框架,引入flask极大简化了applications of python的开发周期。我曾经很不理解为什么要用框架,直接写不是更灵活么?大二的时候,曾经参与tjy基金会网站的项目,只学过一点MySQL的我就去搞数据库了,负责前端开发的java学长在做完前端之后还来帮SQL实战不来的我们,我就很佩服,那是第一次体会到用框架的方便和高效。
  • flask能够模板化Bootstrap3,相比以前暴力撸html,Bootstrap提供了更加美观、强大、功能完善和安全的界面,而且不会牺牲灵活性。
  • flask对数据库也是很友好的。这学期有一个课程项目,要求用Unity3D制作一个甲烷气体浓度检测仪的使用教程,其中用来临时存储气体浓度数据都是放在.txt里,包括所有以前的课程项目,都是用临时的文本存储,现在想想感觉自己弱爆了……
  • 所有的逻辑都在python内部进行啦!机器学习的模型在flask里面被调用就完了,很省事嘛!

项目源代码

Github地址

posted @ 2020-04-18 17:23  TABball  阅读(140)  评论(0编辑  收藏  举报