• 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地址

    一个人没有梦想,和咸鱼有什么区别!
  • 相关阅读:
    RTSP视频流媒体智能分析平台EasyNVR中的H264及H265编码视频存储计算方法介绍
    RTSP协议视频平台EasyNVR内H265编码EasyWasmPlayer播放器如何优化起播时的快照功能?
    RTSP协议视频智能分析平台EasyNVR如何获取云端录像的视频快照截图?
    RTSP拉流协议视频智能分析平台EasyNVR在Chrome浏览器播放视频windows内存占用过高如何解决?
    jquery基础
    js链式编程
    js设计模式--单体模式
    js接口
    js的面向对象
    js函数
  • 原文地址:https://www.cnblogs.com/TABball/p/12726943.html
Copyright © 2020-2023  润新知