在Google Cloud Functions中运行Roboflow推理时的问题
问题:Roboflow模型推理时触发TypeError错误
我打算通过移动端抓拍图片,将图片发送到运行在Google Cloud Functions上的Python脚本,调用自己训练好的Roboflow目标检测模型做推理。以下是部署在Cloud Functions上的推理脚本:
from flask import Flask, request from roboflow import Roboflow app = Flask(__name__) # 配置Roboflow密钥、模型端点和版本 ROBOFLOW_API_KEY = "XXX" ROBOFLOW_MODEL_ENDPOINT = "XXX" ROBOFLOW_VERSION = "X" # 初始化Roboflow客户端 rf = Roboflow(api_key=ROBOFLOW_API_KEY) project = rf.workspace().project(ROBOFLOW_MODEL_ENDPOINT) model = project.version(ROBOFLOW_VERSION).model @app.route("/upload", methods=["POST"]) def upload(request): # 接收移动端传来的图片文件 image_file = request.files["image"] image_data = image_file.read() image_filename = image_file.filename # 将图片数据转为base64编码字符串 base64_img_data = base64.b64encode(image_file.read()) # 调用Roboflow API做推理 prediction = model.predict(base64_img_data, confidence=40, overlap=30) results = prediction.json() # 返回推理结果 return results if __name__ == "__main__": app.run()
用以下代码发送本地图片测试时,Roboflow的classification.py抛出兼容性错误:
# 用multipart/form-data格式发送图片到Cloud Function response = requests.post(cloud_function_url, files={"image": ("image.jpg", image_data, "image/jpeg")})
错误日志:
Traceback (most recent call last): File "/layers/google.python.pip/pip/lib/python3.9/site-packages/flask/app.py", line 2190, in wsgi_app response = self.full_dispatch_request() File "/layers/google.python.pip/pip/lib/python3.9/site-packages/flask/app.py", line 1486, in full_dispatch_request rv = self.handle_user_exception(e) File "/layers/google.python.pip/pip/lib/python3.9/site-packages/flask/app.py", line 1484, in full_dispatch_request rv = self.dispatch_request() File "/layers/google.python.pip/pip/lib/python3.9/site-packages/flask/app.py", line 1469, in dispatch_request return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) File "/layers/google.python.pip/pip/lib/python3.9/site-packages/functions_framework/__init__.py", line 99, in view_func return function(request._get_current_object()) File "/workspace/main.py", line 38, in upload prediction = model.predict(base64_img_data) File "/layers/google.python.pip/pip/lib/python3.9/site-packages/roboflow/models/classification.py", line 54, in predict self.__exception_check(image_path_check=image_path) File "/layers/google.python.pip/pip/lib/python3.9/site-packages/roboflow/models/classification.py", line 126, in __exception_check raise Exception("Image does not exist at " + image_path_check + "!") TypeError: can only concatenate str (not "bytes") to str
错误原因分析
- Base64数据类型错误:
base64.b64encode()返回的是bytes类型,但Roboflow的model.predict()方法把传入的bytes当成了文件路径字符串,尝试拼接错误提示时触发类型不兼容报错。 - 重复读取文件导致空数据:
image_file.read()被调用了两次,第一次读取后文件指针移到末尾,第二次读取会得到空bytes,即便类型正确也无法正常推理。 - Cloud Functions冗余代码:Cloud Functions本身由functions_framework托管,不需要手动创建Flask app和路由装饰器,原代码的Flask配置属于冗余内容。
修复方案
修改Cloud Functions脚本,解决上述三个问题:
import base64 from roboflow import Roboflow # 配置Roboflow密钥、模型端点和版本 ROBOFLOW_API_KEY = "XXX" ROBOFLOW_MODEL_ENDPOINT = "XXX" ROBOFLOW_VERSION = "X" # 初始化Roboflow客户端(全局初始化,避免每次请求重复创建) rf = Roboflow(api_key=ROBOFLOW_API_KEY) project = rf.workspace().project(ROBOFLOW_MODEL_ENDPOINT) model = project.version(ROBOFLOW_VERSION).model def upload(request): # 接收图片文件 image_file = request.files["image"] # 只读取一次图片数据 image_data = image_file.read() # 将bytes类型的base64编码转为字符串 base64_img_data = base64.b64encode(image_data).decode("utf-8") # 调用推理接口,传入字符串格式的base64数据 prediction = model.predict(base64_img_data, confidence=40, overlap=30) return prediction.json()
验证说明
用原来的测试代码重新发送请求,此时脚本会正确处理图片数据,调用Roboflow模型完成推理并返回结果。
内容的提问来源于stack exchange,提问作者Kédar
相关产品推荐
相关产品推荐

