【后端过程记录】用flask搭建服务器作后端接收数据 将base64字符串码解码为可读取文件 载入训练好的模型进行预测

因为项目的原因了解到有一个python的flask框架,查了一下:
关于前端图片上传的canvas:
如下元素

<canvas id="canvas" width="5" height="5"></canvas>

可以用这样的方式获取一个 data-URL

var canvas = document.getElementById("canvas");
var dataURL = canvas.toDataURL();
console.log(dataURL);

// “data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNby
// blAAAADElEQVQImWNgoBMAAABpAAFEI8ARAAAAAElFTkSuQmCC”
设置jpegs图片的质量

var fullQuality = canvas.toDataURL("image/jpeg", 1.0);
// data:image/jpeg;base64,/9j/4AAQSkZJRgABAQ...9oADAMBAAIRAxEAPwD/AD/6AP/Z"
var mediumQuality = canvas.toDataURL("image/jpeg", 0.5);
var lowQuality = canvas.toDataURL("image/jpeg", 0.1);

getContext() 方法返回一个用于在画布上绘图的环境。

语法
Canvas.getContext(contextID)
参数
参数 contextID 指定了您想要在画布上绘制的类型。当前唯一的合法值是 “2d”,它指定了二维绘图,并且导致这个方法返回一个环境对象,该对象导出一个二维绘图 API。

提示:在未来,如果 < canvas> 标签扩展到支持 3D 绘图,getContext() 方法可能允许传递一个 “3d” 字符串参数。

返回值
一个 CanvasRenderingContext2D 对象,使用它可以绘制到 Canvas 元素中。
后端:
首先pip install Flask
然后新建文件:

from flask import Flask,make_response, jsonify

from multiprocessing import Process

# 配置全局app
app = Flask(__name__)
# 导入index中定义的所有函数
#from autotrade.server.index import *

def run_index():
    # 启动web服务器,使用多线程方式,接收所有http请求
    app.run(host='0.0.0.0', port=5000, threaded=True)

def make_new_response(data):
    res = make_response(jsonify({'code': 0, 'data': data}))
    res.headers['Access-Control-Allow-Origin'] = '*'
    res.headers['Access-Control-Allow-Method'] = '*'
    res.headers['Access-Control-Allow-Headers'] = '*'

    return res

@app.route('/')
def hello_world():
    return {'hello': 'world!'}

@app.route("/test")
def test():
    res = "{'no':'dddd'}"
    return make_new_response(res)


if __name__ == "__main__":
    app.run(debug=True)


在这里插入图片描述
打开浏览器:
在这里插入图片描述
在这里插入图片描述

向flask后端发请求接收图片:(点击按钮触发事件)
flask:

from flask import Flask,make_response, jsonify
from flask_cors import CORS
import socket
import threading
import json
import os
from io import BytesIO
from multiprocessing import Process
import io
from PIL import Image
# 配置全局app
app = Flask(__name__)
# 导入index中定义的所有函数
#from autotrade.server.index import *
def main():
    # 创建服务器套接字
    serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 获取本地主机名称
    host = socket.gethostname()
    # 设置一个端口
    port = 5000
    # 将套接字与本地主机和端口绑定
    serversocket.bind((host, port))
    # 设置监听最大连接数
    serversocket.listen(5)
    # 获取本地服务器的连接信息
    myaddr = serversocket.getsockname()
    print("服务器地址:%s" % str(myaddr))
    # 循环等待接受客户端信息
    while True:
        # 获取一个客户端连接
        clientsocket, addr = serversocket.accept()
        print("连接地址:%s" % str(addr))
        try:
            t = ServerThreading(clientsocket)  # 为每一个请求开启一个处理线程
            t.start()
            pass
        except Exception as identifier:
            print(identifier)
            pass
        pass
    serversocket.close()
    pass

def run_index():
    # 启动web服务器,使用多线程方式,接收所有http请求
    app.run(host='0.0.0.0', port=5000, threaded=True)


CORS(app, resources=r'/*', supports_credentials=True)



basedir = os.path.abspath(os.path.dirname(__file__))

@app.route('/getPic',methods=['GET', 'POST'])
def findpic():
    img_url = basedir+'/data/tt/b/b_1.png'
    print(img_url)
    with open(img_url, 'rb') as f:
        a = f.read()
    '''对读取的图片进行处理'''
    img_stream = io.BytesIO(a)
    img = Image.open(img_stream)


    imgByteArr = io.BytesIO()
    img.save(imgByteArr,format='PNG')
    imgByteArr = imgByteArr.getvalue()
    print(imgByteArr)
    return  imgByteArr

if __name__ == "__main__":
    app.run(debug=True)

注意:Python在内存中读写数据,用到的模块是StringIO和BytesIO,当为StringIO时getvalue()方法用于获得写入后的str。StringIO操作的只能是str,如果要操作二进制数据,就需要使用BytesIO。可以用一个bytes初始化BytesIO,然后,像读文件一样读取:

>>> from io import BytesIO
>>> f = BytesIO(b'\xe4\xb8\xad\xe6\x96\x87')
>>> f.read()
b'\xe4\xb8\xad\xe6\x96\x87'

BytesIO实现了在内存中读写bytes。

vue代码:

   <button @click="getPic">获取图片</button>
    <img :src="picurl" alt="beachball" />
 data () {

    return {
      picurl: "",}
      },
 methods: {
    getPic() {
      var that = this;
      this.$axios.get('http://127.0.0.1:5000/getPic',{responseType: "arraybuffer",}).then(function (response) {
        that.picurl =
            "data:image/jpeg;base64," + that.arrayBufferToBase64(response.data);
      });
    },
    arrayBufferToBase64(buffer) {
      //第一步,将ArrayBuffer转为二进制字符串
      var binary = "";
      var bytes = new Uint8Array(buffer);
      var len = bytes.byteLength;
      for (var i = 0; i < len; i++) {
        binary += String.fromCharCode(bytes[i]);
      }
      //将二进制字符串转为base64字符串
      return window.btoa(binary);
    },
}

点击按钮后:
在这里插入图片描述
后端的显示:
在这里插入图片描述

图片传给后端

捣鼓了半天终于把图片传给后端了,不过暂时用的java测试。中途遇到无数次cannot read property xxx xxx is not defined,怀疑是自己哪些代码莫名出了问题,因为canvas是getelementbyid,所以如果写的是ref的话是获取不到的,然后注释掉了一堆代码,结果:

在这里插入图片描述
后端的响应:
在这里插入图片描述

flask获取图片数据:

flask获取参数方式:

request.form.get(“key”, type=str, default=None) 获取表单数据

request.args.get(“key”) 获取get请求参数

request.values.get(“key”) 获取所有参数

import base64
img1='E:/nsfw_tensorflow/corpus/weibocore_WBC_IMAGE_DATA_SOURCE_6521.jpg'

pimg=open(img1, 'rb').read()

print(pimg)

# base64图片加密
result = base64.b64encode(pimg)

print(result)

# 再把加密后的结果解码
temp = base64.b64decode(result)

print(temp)

现在出现一个问题,从前端发送图片之后后端接收到的data一直是str类型,不知道怎么取出来:

@app.route('/getpic', methods=['POST'])
def getpic():
    data = flask.request.get_data().decode('utf-8')
    data = json.loads(data)
    data_b64 = data["data"]
    print(type(data_b64))

在这里插入图片描述
修改:

def getpic():
    data = json.loads(flask.request.get_data("data"))
    data_64 = str.encode(data['data'])
    print(type(data_64))
    print(data_64)

得到类型为bytes.
前端去掉base64前面的前缀:

 var image = this.thisCancas.toDataURL("image/png").split('base64,')[1];

搞了好久试了好多方法终于把前端的图片base码解出来了!!!!!!激动
后端的代码:

def decode_base64(data):
    """Decode base64, padding being optional.

    :param data: Base64 data as an ASCII byte string
    :returns: The decoded byte string.

    """
    missing_padding = len(data) % 4
    if missing_padding != 0:
        data += b'='* (4 - missing_padding)
    # return base64.decodestring(data)
    return base64.b64decode(data)

#上面这个函数用来解码base64字符串
@app.route('/getpic', methods=['POST'])
def getpic():
    data = json.loads(flask.request.get_data("data"))
    data_64 = str.encode(data['data'])
    print(type(data_64))

    #print(data_64)
    print('------------------------')
    print(str(data_64, 'utf8')) #用这个方法去掉base64码前面b'xxx'的b
    imgdata = decode_base64(data_64)
    file = open('1.jpg', 'wb')
    file.write(imgdata)
    file.close()

其中注意前端发送的数据也经过了处理,使得去掉了img/jpeg前缀

现在载入模型进行拍照预测:
附上关键的代码:

import torch
from torchvision import transforms
def run_index():
    # 启动web服务器,使用多线程方式,接收所有http请求
    app.run(host='0.0.0.0', port=5000, threaded=True)
def decode_base64(data):
    """Decode base64, padding being optional.

    :param data: Base64 data as an ASCII byte string
    :returns: The decoded byte string.

    """
    missing_padding = len(data) % 4
    if missing_padding != 0:
        data += b'='* (4 - missing_padding)
    # return base64.decodestring(data)
    return base64.b64decode(data)
transform=transforms.Compose([
            transforms.Resize(224),
            transforms.CenterCrop(224),
            transforms.ToTensor(),
            transforms.Normalize(mean=[0.485,0.456,0.406],
                                 std=[0.229,0.224,0.225])
                            ])
 CORS(app, resources=r'/*', supports_credentials=True)
@app.route('/getpic', methods=['POST'])
def getpic():
    data = json.loads(flask.request.get_data("data"))
    data_64 = str.encode(data['data'])
    print(type(data_64))

    #print(data_64)
    print('------------------------')
    print(str(data_64, 'utf8'))
    imgdata = decode_base64(data_64)
    file = open('1.jpg', 'wb')
    file.write(imgdata)
    file.close()
    image = Image.open(r"1.jpg").convert('RGB')
    image = transform(image).unsqueeze(0)
    modelme = torch.load('modefresnet.pkl')
    modelme.eval()
    outputs = modelme(image)
    _, predict = torch.max(outputs.data, 1)
    for j in range(image.size()[0]):
        print('predicted: {}'.format(class_names[predict[j]]))

    return class_names[predict[j]]
if __name__ == "__main__":
    app.run(debug=True)

在这里插入图片描述
试了好多次,几乎都与预测结果相符。
哈哈哈哈哈花了两天弄这个,之前关于图片解码编码一直没弄出来,现在成功了还是挺开心的。

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是使用Flask框架建立后端系统,编写API接口,接收前端传递过来的手写数字图片的像素数据,调用训练好的模型进行预测,并将预测结果返回给前端的代实现: ```python from flask import Flask, request, jsonify import numpy as np import torch import torchvision.transforms as transforms app = Flask(__name__) # 加载训练好的模型 model = torch.load('model.pth') # 定义图像预处理函数 def preprocess(image): transform = transforms.Compose([ transforms.Resize(28), transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,)) ]) return transform(image).unsqueeze(0) # 定义API接口 @app.route('/predict', methods=['POST']) def predict(): # 从前端接收手写数字图片数据 image_data = request.files['image'].read() image = Image.open(io.BytesIO(image_data)) # 进行图像预处理 preprocessed_image = preprocess(image) # 调用训练好的模型进行预测 with torch.no_grad(): output = model(preprocessed_image) _, predicted = torch.max(output.data, 1) # 将预测结果返回给前端 return jsonify({'result': predicted.item()}) if __name__ == '__main__': app.run() ``` 在上述代中,我们首先加载训练好的模型,并定义了一个图像预处理函数,用于将前端传递过来的手写数字图片进行预处理。然后,我们定义了一个API接口,使用POST方法接收前端传递过来的手写数字图片数据,进行预处理并调用训练好的模型进行预测,最后将预测结果返回给前端。在主函数中,我们使用Flask框架的run()方法来启动后端服务器。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值