Мне удалось объединить два кода с помощью FastAPI в Python. Теперь задача заключается в отправке изображения в формате Base64 через JSON для интерпретации. Однако я столкнулся с проблемами, поскольку C# возвращается System.Net.WebException: 'The remote server returned an error: (500) Internal Server Error'
.
Есть идеи?
Вот мои коды:
Питон
import tensorflow as tf
from fastapi import FastAPI
import json
import base64
from PIL import Image
import io
#from flask import request
from fastapi import Request
app = FastAPI()
# Load the saved model
cnn = tf.keras.models.load_model('modelo_cnn.h5')
# Test functions to verify the connection
# @app.get('/prueba0/')
# def prueba0():
# return "Hello, I'm connecting..."
# Test function to sum two numbers
@app.get('/prueba1/{a}/{b}')
def prueba1(a: int, b: int):
return a + b
# Test function to display a message
@app.get('/prueba2/{text}')
def prueba2(text: str):
return "Hello, your message was... " + text
#########################################################################################
# Overlap identification function
@app.post('/traslape/')
def traslape(request: Request):
global cnn
# Get data from the request body
body = request.body()
# Decode JSON data
data = json.loads(body)
# # # Open the JSON file (image)
# with open(image) as f:
# img = json.load(f)
# # Decode the image
# image = base64.b64decode(img["image"])
# # Open the image from bytes using Pillow
# image = Image.open(io.BytesIO(image))
# # Concatenate images horizontally
# #imagen_completa = tf.concat([imagen_i, imagen_d], axis=1)
# # Apply gamma correction to the image
# gamma = tf.convert_to_tensor(0.6)
# gamma_corrected = tf.pow(imagen / 255.0, gamma) * 255.0 # imagen_completa
# image_bw = tf.cast(gamma_corrected, tf.uint8)
# # Convert the image to grayscale
# grayscale_image = tf.image.rgb_to_grayscale(image_bw)
# # Define new dimensions
# new_height = 360
# new_width = 500
# # Resize the image
# imagen_completa_resize = tf.image.resize(grayscale_image, [new_height, new_width])
# # Perform classification using the loaded model
# result = cnn.predict(imagen_completa_resize)
# if result[0][0] > result[0][1]:
# result = False # No mask
# else:
# result = True # With mask
return True
using System;
using System.IO;
using System.Net;
using System.Text;
namespace comunica_api
{
class Program
{
static void Main(string[] args)
{
// Path to the image in your local file system
string imagePath = @"C:\Users\VirtualImages[00]20240418_124751_028.jpg";
try
{
// Read the bytes of the image from the file
byte[] imageBytes = File.ReadAllBytes(imagePath);
// Convert the bytes to a Base64 formatted string
string base64String = Convert.ToBase64String(imageBytes);
// URL of the API
string url = "http://localhost:8000/traslape/";
// Data to send
string json = "{\"image\": \"" + base64String + "\"}";
// Create the HTTP request
var request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST"; // Use the POST method
request.ContentType = "application/json"; // Set content type as JSON
request.ContentLength = json.Length;
// Convert JSON string to bytes
byte[] jsonBytes = Encoding.UTF8.GetBytes(json);
// Print the request content before sending it
Console.WriteLine("Request:");
Console.WriteLine("URL: " + url);
Console.WriteLine("Method: " + request.Method);
Console.WriteLine("Headers:");
foreach (var header in request.Headers)
{
Console.WriteLine(header.ToString());
}
Console.WriteLine("Body:");
Console.WriteLine(json);
// Write bytes into the request body using StreamWriter
using (Stream requestStream = request.GetRequestStream())
using (StreamWriter writer = new StreamWriter(requestStream))
{
// Write JSON string into the request body
writer.Write(json);
}
// Send the request and get the response
// HERE IS THE ERROR
using (var response = (HttpWebResponse)request.GetResponse())
//
{
// Read the response from the server
using (var streamReader = new StreamReader(response.GetResponseStream()))
{
// Read the response as a string and display it in the console
string responseText = streamReader.ReadToEnd();
Console.WriteLine("API Response:");
Console.WriteLine(responseText);
}
}
}
catch (FileNotFoundException)
{
Console.WriteLine("The specified image could not be found.");
}
catch (WebException ex)
{
// Handle any communication error with the API
Console.WriteLine("API Communication Error:");
Console.WriteLine(ex.Message);
}
// Wait for the user to press Enter before exiting the program
Console.ReadLine();
}
}
}
найдите UploadFile для FastAPI
Проблема в том, как вы читаете request
body
на стороне сервера. Метод request.body()
возвращает сопрограмму , поэтому ее следует await
использовать, а это означает, что конечная точка также должна быть определена с помощью async def
— см. этот ответ для получения более подробной информации о конечных точках def
и async def
и о том, как FastAPI их обрабатывает. . Пример:
@app.post('/traslape/')
async def traslape(request: Request):
body = await request.body()
data = json.loads(body)
return "whatever"
Обратите внимание: поскольку вы конвертируете тело в JSON, вы можете сделать это напрямую, используя вместо этого следующее:
data = await request.json()
Самостоятельное получение тела и последующее преобразование его в JSON полезно, если вы хотите использовать другие (возможно, более быстрые) кодировщики JSON, например orjson
, как показано в этом ответе , а также этом ответе и ️ 🔁 этот ответ (вы также можете найти это полезным, когда дело доходит до возврата данных JSON в FastAPI).
Если вы хотите, чтобы конечная точка была определена с помощью def
, но при этом иметь возможность получать необработанное тело запроса POST
, решения можно найти в следующем ответе:
Используя FastAPI для синхронизации, как я могу получить необработанное тело запроса POST?
Похожие сообщения, демонстрирующие, как загружать/работать с изображениями base64 в FastAPI, можно найти здесь , а также здесь и здесь . Обратите внимание, что вам не обязательно отправлять изображение в виде строки base64, закодированной как application/json
или application/x-www-form-urlencoded
в теле запроса; вместо этого вы можете загрузить его в кодировке multipart/form-data
, как показано в этом ответе, и соответствующие ссылки включены в этот ответ.
Это работает для меня, большое спасибо :)
В качестве примечания: не следует передавать изображения через base64. Этот формат имеет накладные расходы размером 4/3. Для небольших двоичных файлов это нормально, но изображения обычно слишком велики, чтобы их можно было игнорировать.