I want to post a request to a Python-based API that has an image in its body. I have tried to send data with 5 methods:
- await http.post()
final api = Uri.parse("https://e8f628d7.ngrok.io/detections");
Map<String, dynamic> body = {'images': image};
final response = await http.post(
api,
body: body,
);
if (response.statusCode == 200) {
final responseJson = json.decode(response.body);
print(responseJson);
}
- Client().post()
Map<String, dynamic> body = {'images': image};
var client = new http.Client();
client.post("https://e8f628d7.ngrok.io/detections",body: body).then((response) {
print("Post " + response.statusCode.toString());
});
- dio
- MultipartRequest
final api = Uri.parse("https://e8f628d7.ngrok.io/detections");
var stream = new http.ByteStream(DelegatingStream.typed(image.openRead()));
var length = await image.length();
var request = new http.MultipartRequest("POST", api);
var multipartFileSign = new http.MultipartFile(
'profile_pic', stream, length,
filename: path.basename(image.path));
request.files.add(multipartFileSign);
// send
var response = await request.send();
print(response.statusCode);
response.stream.transform(utf8.decoder).listen((value) {
print(value);
});
- Link of [DELETED]First Answer to this question:
if (image == null) return;
String base64Image = base64Encode(image.readAsBytesSync());
http.post(api, body: {
'images': base64Image,
}).then((res) {
print(res.statusCode);
print(json.decode(res.body));
}).catchError((err) {
print(err);
});
}
I am able to send the image and am getting a 200 success response. But, I am not sure if the image is getting altered or any problem happens while sending the image as the response is empty whereas it should have some sort of response. This is my app.py from with which my server works:
import time
from absl import app, logging
import cv2
import numpy as np
import tensorflow as tf
from yolov3_tf2.models import (
YoloV3, YoloV3Tiny
)
from yolov3_tf2.dataset import transform_images, load_tfrecord_dataset
from yolov3_tf2.utils import draw_outputs
from flask import Flask, request, Response, jsonify, send_from_directory, abort
import os
# customize your API through the following parameters
classes_path = './data/labels/coco.names'
weights_path = './weights/yolov3.tf'
tiny = False # set to True if using a Yolov3 Tiny model
size = 416 # size images are resized to for model
output_path = './detections/' # path to output folder where images with detections are saved
num_classes = 80 # number of classes in model
# load in weights and classes
physical_devices = tf.config.experimental.list_physical_devices('GPU')
if len(physical_devices) > 0:
tf.config.experimental.set_memory_growth(physical_devices[0], True)
if tiny:
yolo = YoloV3Tiny(classes=num_classes)
else:
yolo = YoloV3(classes=num_classes)
yolo.load_weights(weights_path).expect_partial()
print('weights loaded')
class_names = [c.strip() for c in open(classes_path).readlines()]
print('classes loaded')
# Initialize Flask application
app = Flask(__name__)
# API that returns JSON with classes found in images
@app.route('/detections', methods=['POST'])
def get_detections():
raw_images = []
images = request.files.getlist("images")
image_names = []
for image in images:
image_name = image.filename
image_names.append(image_name)
image.save(os.path.join(os.getcwd(), image_name))
img_raw = tf.image.decode_image(
open(image_name, 'rb').read(), channels=3)
raw_images.append(img_raw)
num = 0
# create list for final response
response = []
for j in range(len(raw_images)):
# create list of responses for current image
responses = []
raw_img = raw_images[j]
num+=1
img = tf.expand_dims(raw_img, 0)
img = transform_images(img, size)
t1 = time.time()
boxes, scores, classes, nums = yolo(img)
t2 = time.time()
print('time: {}'.format(t2 - t1))
print('detections:')
for i in range(nums[0]):
print('\t{}, {}, {}'.format(class_names[int(classes[0][i])],
np.array(scores[0][i]),
np.array(boxes[0][i])))
responses.append({
"class": class_names[int(classes[0][i])],
"confidence": float("{0:.2f}".format(np.array(scores[0][i])*100))
})
response.append({
"image": image_names[j],
"detections": responses
})
img = cv2.cvtColor(raw_img.numpy(), cv2.COLOR_RGB2BGR)
img = draw_outputs(img, (boxes, scores, classes, nums), class_names)
cv2.imwrite(output_path + 'detection' + str(num) + '.jpg', img)
print('output saved to: {}'.format(output_path + 'detection' + str(num) + '.jpg'))
#remove temporary images
for name in image_names:
os.remove(name)
try:
return jsonify({"response":response}), 200
except FileNotFoundError:
abort(404)
# API that returns image with detections on it
@app.route('/image', methods= ['POST'])
def get_image():
image = request.files["images"]
image_name = image.filename
image.save(os.path.join(os.getcwd(), image_name))
img_raw = tf.image.decode_image(
open(image_name, 'rb').read(), channels=3)
img = tf.expand_dims(img_raw, 0)
img = transform_images(img, size)
t1 = time.time()
boxes, scores, classes, nums = yolo(img)
t2 = time.time()
print('time: {}'.format(t2 - t1))
print('detections:')
for i in range(nums[0]):
print('\t{}, {}, {}'.format(class_names[int(classes[0][i])],
np.array(scores[0][i]),
np.array(boxes[0][i])))
img = cv2.cvtColor(img_raw.numpy(), cv2.COLOR_RGB2BGR)
img = draw_outputs(img, (boxes, scores, classes, nums), class_names)
cv2.imwrite(output_path + 'detection.jpg', img)
print('output saved to: {}'.format(output_path + 'detection.jpg'))
# prepare image for response
_, img_encoded = cv2.imencode('.png', img)
response = img_encoded.tostring()
#remove temporary image
os.remove(image_name)
try:
return Response(response=response, status=200, mimetype='image/png')
except FileNotFoundError:
abort(404)
if __name__ == '__main__':
app.run(debug=True, host = '0.0.0.0', port=5000)
I try to send the same image directly through Postman and get the desired response but when I do it with the flutter app, I don't get it. Is there any possibility of the image getting altered or modified? And, is there any other method in which I can send the image to the API other than the above 3?