api - 使用 Flutter 向 Flask API 发送 http Post-Request(包含图像)
问题描述
我已经在 CIFAR10 数据集(占位符,稍后将替换为不同的模型)上训练了一个 CNN,并将该模型集成到烧瓶 API 中。API 托管在 Heroku 上,我现在想使用 Flutter / Dart 在我的手机上拍照,将它们发送到 Flask API,在它们上运行我训练过的模型并返回预测。
使用 python,我可以轻松地向我的 API 发出 post 请求并返回预测。这是我的简单python代码:
import requests
import json
img = open('some-picture.jpg', 'rb')
files = {'image': img}
response = requests.post("url_to_api", files=files)
print(response.text)
我很久没有使用 Flutter / Dart 了,我认为发出 htpp 请求的过程比在 python 中要复杂一些。有人可以给我一些指示或代码,让我可以用相机拍照,将其上传到我的 API,并将响应存储在变量中吗?这是烧瓶 API 的(简化的)python 代码:
from flask import Flask, request
import os
import numpy as np
from PIL import Image
from tensorflow import keras
app = Flask(__name__)
app.config["DEBUG"] = True
model = keras.models.load_model('cifar10_cnn.h5')
labels = ["Airplane", "Automobile", "Bird", "Cat", "Deer", "Dog", "Frog", "Horse", "Ship", "Truck"]
@app.route('/', methods=["POST"])
def predict():
# stuff not relevant to question, left out for conciseness #
file = request.files['image']
image = Image.open(file).resize((32, 32))
image = np.array(image)
image = image / 255
image = image.reshape(-1, 32, 32, 3)
predictions = model.predict([image])
index = np.argmax(predictions)
results = {'Prediction:': labels[index]}
return results
if __name__ == '__main__':
app.run()
到目前为止,我知道 Multipart 文件似乎是要走的路,而且 Dio 包可能值得研究。如果可以提供进一步的提示或代码,我将不胜感激。
解决方案
您可能已经知道如何从图库/相机中选择图像(例如使用image_picker
库)。File image;
您可以使用该选择器的结果填充类字段。这可能很简单:
import 'dart:io';
import 'package:image_picker/image_picker.dart';
class _MyHomePageState extends State<MyHomePage> {
File image;
final picker = ImagePicker();
pickImageFromGallery(ImageSource source) async {
final image = await picker.getImage(source: source);
setState(() {
this.image = File(image.path);
});
}
}
(更改ImageSource source
以匹配您的愿望:相机或画廊)
然后您可以将该文件上传到您的 api。使用http
库:
import 'package:http/http.dart' as http;
import 'package:http_parser/http_parser.dart';
class _MyHomePageState extends State<MyHomePage> {
doUpload(){
var request = http.MultipartRequest(
'POST',
Uri.parse("url_to_api"),
);
Map<String, String> headers = {"Content-type": "multipart/form-data"};
request.files.add(
http.MultipartFile(
'image',
image.readAsBytes().asStream(),
image.lengthSync(),
filename: "filename",
contentType: MediaType('image', 'jpeg'),
),
);
request.headers.addAll(headers);
print("request: " + request.toString());
request.send().then((value) => print(value.statusCode));
}
}
对于这些库中的每一个,您都必须将它们作为依赖项添加到pubspec.yaml
您的 Flutter 项目中:
cupertino_icons: ^0.1.3
http: ^0.12.2
image_picker: ^0.6.7
推荐阅读
- sqlite - 如何从 SQLite Query 中的某个时间戳中选择多个系列
- sql - PostgreSQL 性能:查询达到 52 周高点的股票(加入最大值行)
- android - FileProvider.getUriForFile 不会将图像保存到图库并且无法访问文件 OnActivityResult
- database - 列索引未反映在具有“IN”语句的谓词的解释计划中
- python - 如何在odoo中将树视图拆分为两列
- c# - Oxyplot - 编辑 LineSeries 中的左键单击标签
- performance - 使用 SIMD 会加载主 CPU 寄存器吗?
- python - 用opencv和python清理图像背景后如何正确提取字母?
- r - 要替换的项目数不是替换长度的倍数 + 同一图中的多个图错误
- acumatica - 通用查询作为主要列表/入口点