【问题标题】:Use Flutter to send a http Post-Request (containing an image) to a Flask API使用 Flutter 向 Flask API 发送 http Post-Request(包含图像)
【发布时间】:2021-01-19 14:13:50
【问题描述】:

我已经在 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 包可能值得研究。如果可以提供进一步的提示或代码,我将不胜感激。

【问题讨论】:

    标签: api flutter dart http-post dio


    【解决方案1】:

    您可能已经知道如何从图库/相机中选择图像(例如,使用 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));
    }
    }
    

    对于这些库中的每一个,您必须将它们作为依赖项添加到您的 Flutter 项目中的 pubspec.yaml 中:

    cupertino_icons: ^0.1.3
    http: ^0.12.2
    image_picker: ^0.6.7
    

    【讨论】:

      【解决方案2】:

      我用 Django 和 Flutter 做过类似的工作。我用image_picker选择图片,用dio上传图片。

      这是上传功能:

        _upLoadImage(File image) async {
          setState(() {
            loadingdone = false;
          });
          String path = image.path;
          var name = path.substring(path.lastIndexOf("/") + 1, path.length);
          var suffix = name.substring(name.lastIndexOf(".") + 1, name.length);
          FormData formData = FormData.fromMap({
              "img": await MultipartFile.fromFile(path,filename: name)
          });
          
      
          Dio dio = new Dio();
          var respone = await dio.post<String>("http://192.168.1.104:8000/uploadImg/", data: formData);
          if (respone.statusCode == 200) {
            Fluttertoast.showToast(
                msg: 'Done!',
                gravity: ToastGravity.BOTTOM,
                textColor: Colors.grey);
            setState(() {
                _label = jsonDecode(respone.data.toString())['label'];
                _score = jsonDecode(respone.data.toString())['score'];
                loadingdone = true;
            });
            
          }
        }
      

      选择图片后运行上传功能:

        Future getImage() async {
          var image = await ImagePicker.pickImage(source: ImageSource.gallery);
          _upLoadImage(image);
          setState(() {
            _image = image;
          });
        }
      

      【讨论】:

        猜你喜欢
        • 2011-02-25
        • 2023-01-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-10-19
        相关资源
        最近更新 更多