- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在开发一个应用程序,让用户可以拍照并将其发送到 Keras 模型进行预测。此模型已部署在 Google App Engine 服务中,其中包含一个 Python 脚本,该脚本使用 Flask 通过 POST 请求接收图像并调用模型进行预测。这是 Python 代码:
import numpy as np
import flask
import io
import logging
import tensorflow as tf
from keras.preprocessing.image import img_to_array
from keras.applications import imagenet_utils
from keras.models import load_model
from PIL import Image
# initialize our Flask application and the Keras model
app = flask.Flask(__name__)
app.config['PROPAGATE_EXCEPTIONS'] = True
model = None
def recortar(image):
# Function that centers and crop image. Please, asume that it works properly. Return is a numpy array.
return image
@app.route("/predict", methods=["POST"])
def predict():
model = load_model('modelo_1.h5')
graph = tf.get_default_graph()
data = {"success": False}
if flask.request.method == "POST":
if flask.request.files.get("image"):
# read the image in PIL format
image = flask.request.files["image"].read()
image = Image.open(io.BytesIO(image))
image = recortar(image)
app.logger.info('Tamaño: '+str(image.size))
image = img_to_array(image)
image = np.expand_dims(image, axis=0)
with graph.as_default():
preds = model.predict(image)
data['predictions'] = str(np.squeeze(preds).tolist())
data["success"] = True
return flask.jsonify(data)
else:
return "No se ha obtenido la imagen"
else:
return "El HTTP request no era POST"
# if this is the main thread of execution first load the model and
# then start the server
if __name__ == "__main__":
print(("* Loading Keras model and Flask starting server..."
"please wait until server has fully started"))
app.debug = True
app.run()
通过 curl 发送图像非常有效:正如预期的那样,我从服务器获得了包含预测的 JSON 响应。这是 CURL 命令和服务器响应:
>> curl -X POST -F image=@nevus.jpg 'https://example.com/predict'
{"predictions":"[0.7404708862304688, 0.25952914357185364]","success":true}
然后我尝试重复相同的过程,但通过 Android 应用程序,但我收到 500 错误作为响应。在检查 Stackdriver 错误报告的日志时,我看到以下堆栈跟踪:AttributeError:
'NoneType' object has no attribute 'size'
at predict (/home/vmagent/app/main.py:73)
at dispatch_request (/env/lib/python3.6/site-packages/flask/app.py:1799)
at full_dispatch_request (/env/lib/python3.6/site-packages/flask/app.py:1813)
at reraise (/env/lib/python3.6/site-packages/flask/_compat.py:35)
at handle_user_exception (/env/lib/python3.6/site-packages/flask/app.py:1718)
at full_dispatch_request (/env/lib/python3.6/site-packages/flask/app.py:1815)
at wsgi_app (/env/lib/python3.6/site-packages/flask/app.py:2292)
at reraise (/env/lib/python3.6/site-packages/flask/_compat.py:35)
at handle_exception (/env/lib/python3.6/site-packages/flask/app.py:1741)
at wsgi_app (/env/lib/python3.6/site-packages/flask/app.py:2295)
at __call__ (/env/lib/python3.6/site-packages/flask/app.py:2309)
at handle_request (/env/lib/python3.6/site-packages/gunicorn/workers/sync.py:176)
at handle (/env/lib/python3.6/site-packages/gunicorn/workers/sync.py:135)
这个错误是指图像对象,所以我假设,由于代码之前工作正常,错误一定是我通过 HTTP 请求发送图像的方式。回想一下,图像是在用户单击按钮时拍摄的,因为此按钮发送了拍摄照片的 Intent 。拍摄照片后,用户可以单击发送按钮,我在下面发布了其代码。请注意,orientedBitmap 对应于以位图格式拍摄的照片。
btn_enviarfoto.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d(TAG, "Botón \"enviar\" pulsado. Codificando imagen.");
ByteArrayOutputStream stream = new ByteArrayOutputStream();
orientedBitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
orientedBitmap.recycle();
uploadToServer(byteArray);
}
});
uploadToServer 只是调用 AsynchTask 类的执行方法,如下所示:
private void uploadToServer(byte[] data) {
Bitmap bitmapOrg = BitmapFactory.decodeByteArray(data, 0, data.length);
Log.d(TAG, "Imagen codificada. Enviando al servidor.");
ObtenerPrediccionTask task = new ObtenerPrediccionTask();
task.execute(bitmapOrg);
}
最后也是最重要的,这是 ObtenerPrediccionTask 类的代码:
public class ObtenerPrediccionTask extends AsyncTask<Bitmap, Void, String> {
@Override
protected String doInBackground(Bitmap... imagen) {
ByteArrayOutputStream bao = new ByteArrayOutputStream();
HttpURLConnection connection = null;
DataOutputStream outputStream = null;
String probabilidad_melanoma = "";
JsonReader jsonReader = null;
try {
for (int i = 0; i < imagen.length; i++) {
Bitmap imagen2 = imagen[i];
imagen2.compress(Bitmap.CompressFormat.JPEG, 90, bao);
byte[] ba = bao.toByteArray();
InputStream fileInputStream = new ByteArrayInputStream(ba);
URL url = new URL("https://example.com/predict"); // not the real URL
String lineEnd = "\r\n";
String twoHyphens = "--";
String boundary = "xxxxxxxx";
String str = twoHyphens + boundary + lineEnd;
connection = (HttpURLConnection) url.openConnection();
// Allow Inputs & Outputs
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setUseCaches(false);
// Enable POST method
connection.setRequestMethod("POST");
connection.setRequestProperty("Connection", "Keep-Alive");
connection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
outputStream = new DataOutputStream(connection.getOutputStream());
outputStream.writeBytes(twoHyphens + boundary + lineEnd);
outputStream.writeBytes("Content-Disposition: form-data; name=\"" +
"image" + "\";filename=\"" +
"foto.jpg" + "\"" + lineEnd);
outputStream.writeBytes(lineEnd);
int bytesAvailable = fileInputStream.available();
int bufferSize = Math.min(bytesAvailable, 1024);
byte[] buffer = new byte[bufferSize];
// Read file
int bytesRead = fileInputStream.read(buffer, 0, bufferSize);
while (bytesRead > 0) {
outputStream.write(buffer, 0, bufferSize);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, 1024);
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
}
outputStream.writeBytes(lineEnd);
outputStream.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
// Responses from the server (code and message)
int responseCode = connection.getResponseCode();
connection.getResponseMessage();
fileInputStream.close();
outputStream.flush();
outputStream.close();
if (responseCode == HttpURLConnection.HTTP_OK) {
InputStream responseStream = new
BufferedInputStream(connection.getInputStream());
BufferedReader responseStreamReader =
new BufferedReader(new InputStreamReader(responseStream));
String line = "";
StringBuilder stringBuilder = new StringBuilder();
while ((line = responseStreamReader.readLine()) != null) {
stringBuilder.append(line).append("\n");
}
responseStreamReader.close();
String response = stringBuilder.toString();
Log.d(TAG, "Imagen recibida por el servidor y pasada al modelo. Esta es la respuesta: " + response);
jsonReader = new JsonReader(new StringReader(response));
probabilidad_melanoma = readJson(jsonReader);
} else {
Log.d(TAG, Integer.toString(responseCode));
}
}
return probabilidad_melanoma;
} catch (MalformedURLException malformedURLException) {
Log.e(TAG, malformedURLException.toString());
return null;
} catch (IOException io) {
Log.e(TAG, io.toString());
return null;
} finally {
if (connection != null) {
connection.disconnect();
}
}
}
protected void onPostExecute(String probabilidad_melanoma) {
if (probabilidad_melanoma != null) {
Log.d(TAG, "Probabilidad melanoma: " + probabilidad_melanoma);
} else {
Log.w(TAG, "La respuesta ha sido nula");
}
}
}
readJson 函数也正常工作,所以不要被它打扰。
这最后一段代码是在 SO 中广泛搜索正确发送图像的方法的结果,但由于还没有任何效果,我已经没有想法了。我的代码有什么问题?
最佳答案
崩溃回溯表明在这一行 image
是 None
:
app.logger.info('Tamaño: '+str(image.size))
这意味着 recortar()
返回 None
,尽管您有评论:
# Function that centers and crop image. Please, asume that it works properly. Return is a numpy array.
所以您的错误一定是我通过 HTTP 请求发送图像的方式
假设可能是错误的。在花时间之前,我首先要添加检查以确保 recortar()
正常工作。
关于android - 在运行 Flask 服务的 GCP App Engine 服务上接收图像时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52077831/
我的应用程序从一个有 5 个选项卡的选项卡栏 Controller 开始。一开始,第一个出现了它的名字,但其他四个没有名字,直到我点击它们。然后根据用户使用的语言显示名称。如何在选项卡栏出现之前设置选
我有嵌套数组 json 对象(第 1 层、第 2 层和第 3 层)。我的问题是数据表没有出现。任何相关的 CDN 均已导入。该表仅显示部分。我引用了很多网站,但都没有解决我的问题。 之前我使用标准表来
我正在尝试设置要显示的 Parse PFLoginViewController。这是我的一个 View Controller 的类。 import UIKit import Parse import
我遇到了这个问题,我绘制的对象没有出现在 GUI 中。我知道它正在被处理,因为数据被推送到日志文件。但是,图形没有出现。 这是我的一些代码: public static void main(Strin
我有一个树状图,其中包含出现这样的词...... TreeMap occurrence = new TreeMap (); 字符串 = 单词 整数 = 出现次数。 我如何获得最大出现次数 - 整数,
因此,我提示用户输入变量。如果变量小于 0 且大于 10。如果用户输入 10,我想要求用户再次输入数字。我问时间的时候输入4,它说你输入错误。但在第二次尝试时效果很好。例如:如果我输入 25,它会打印
我已经用 css overflow 属性做了一个例子。在这个例子中我遇到了一个溢出滚动的问题。滚动条出现了,但没有工作意味着每当将光标移动到滚动条时,在这个滚动条不活动的时间。我对此一无所知,所以请帮
我现在正在做一个元素。当您单击一个元素时,会出现以下信息,我想知道如何在您单击下一个元素而不重新单击同一元素时使其消失....例如,我的元素中有披萨,我想单击肉披萨看到浇头然后点击奶酪披萨看到浇头和肉
我有一个路由器模块,它将主题与正则表达式进行比较,并将出现的事件与一致的键掩码链接起来。 (它是一个简单的 url 路由过滤,如 symfony http://symfony.com/doc/curr
这个问题在这里已经有了答案: 9年前关闭。 Possible Duplicate: mysql_fetch_array() expects parameter 1 to be resource, bo
我在底部有一个带有工具栏的 View ,我正在使用 NavigationLink 导航到该 View 。但是当 View 出现时,工具栏显示得有点太低了。大约半秒钟后,它突然跳到位。它只会在应用程序启
我试图在我的应用程序上为背景音乐添加一个 AVAudioPlayer,我正在主屏幕上启动播放器,尝试在应用程序打开时开始播放但出现意外行为... 它播放并立即不断创建新玩家并播放这些玩家,因此同时播放
这是获取一个数字,获取其阶乘并将其加倍,但是由于基本情况,如果您输入 0,它会给出 2 作为答案,因此为了绕过它,我使用了 if 语句,但收到错误输入“if”时解析错误。如果你们能提供帮助,我真的很感
暂停期间抛出异常 android.os.DeadObjectException 在 android.os.BinderProxy.transactNative( native 方法) 在 androi
我已经为猜词游戏编写了一些代码。它从用户输入中读取字符并在单词中搜索该字符;根据字符是否在单词中,程序返回并控制一些变量。 代码如下: import java.util.Random; import
我是自动化领域的新手。这是我的简单 TestNG 登录代码,当我以 TestNG 身份运行该代码时,它会出现 java.lang.NullPointerException,双击它会突出显示我导航到 U
我是c#程序员,我习惯了c#的封装语法和其他东西。但是现在,由于某些原因,我应该用java写一些东西,我现在正在练习java一天!我要创建一个为我自己创建一个虚拟项目,以便让自己更熟悉 Java 的
我正在使用 Intellij,我的源类是 main.com.coding,我的资源文件是 main.com.testing。我将 spring.xml 文件放入资源文件中。 我的测试类位于 test.
我想要我的tests folder separate到我的应用程序代码。我的项目结构是这样的 myproject/ myproject/ myproject.py moduleon
这个问题已经有答案了: What is a NullPointerException, and how do I fix it? (12 个回答) 已关闭 6 年前。 因此,我尝试比较 2 个值,一个
我是一名优秀的程序员,十分优秀!