Django上传图片调用TensorFlow模型报expected str not JpegImageFile错误如何解决
问题原因
你代码中先用Image.open(pic)得到了PIL的图像对象(JpegImageFile/PngImageFile类型),但Keras的image.load_img()方法只接受文件路径字符串、字节流、os.PathLike类型对象,传入PIL对象自然触发类型错误。你原生Python环境能运行大概率是当时直接给load_img传的是本地图片的磁盘路径,和Django中拿到的上传文件场景逻辑不一致。
解决方案
方案1:直接复用已有的PIL图像(最简便)
你已经通过Image.open拿到了图像对象,完全不需要再调用image.load_img二次处理,直接对PIL对象做尺寸调整即可:
import numpy as np import os from PIL import Image from django.conf import settings from tensorflow.keras.models import load_model from tensorflow.keras.preprocessing import image # 模型加载放到全局,避免每次请求重复加载,大幅提升性能 detection = load_model(os.path.join(settings.BASE_DIR,'static/auto_chloro_model.h5')) def uploadImage(request): if request.method == 'POST': pic = request.FILES['image'] # 拿到PIL图像对象 img = Image.open(pic) # 统一处理通道,避免PNG透明通道导致后续报错 img = img.convert('RGB') # 直接对PIL对象resize,替代load_img的功能 img = img.resize((48,48)) # 后续逻辑不变 test_img = image.img_to_array(img) test_img = np.expand_dims(test_img, axis=0) result = detection.predict(test_img) a = result.argmax() print(a)
方案2:直接给load_img传上传文件对象,去掉多余的Image.open步骤
如果你要保留load_img的调用,就不要提前打开图片,直接把Django的上传文件对象传给load_img即可:
pic = request.FILES['image'] # 直接传上传文件对象,不要先用Image.open处理 test_img = image.load_img(pic, target_size=(48,48)) test_img = image.img_to_array(test_img) # 后续逻辑不变
注意事项
不要把模型加载逻辑放在视图函数内部,Django启动时就会全局加载一次,每次请求都重复加载模型会严重拖慢响应速度,还可能引发内存溢出问题。
内容的提问来源于stack exchange,提问作者Joyanta J. Mondal
相关产品推荐
相关产品推荐

