Flask上传图片调用CocoDataset类报NoneType无shape属性错误如何解决
问题原因
你遇到的AttributeError: 'NoneType' object has no attribute 'shape'错误,根源是cv2.imread()没有读到有效图片,返回了None:cv2.imread()只能读取本地磁盘上已存在的图片文件,你当前只把用户上传文件的原始文件名(字符串)传给了CocoDataset,并没有先把用户上传的文件保存到服务器本地,cv2.imread找不到对应路径的文件,自然返回空。
修复方案
方法1:先保存上传文件到本地,再传入路径调用(最简单,符合你现有代码逻辑)
修改Flask端的post方法逻辑,拿到上传文件后先保存到本地static/images目录,再把本地文件的完整路径传给CocoDataset,不需要修改CocoDataset类的代码:
def post(self): target = os.path.join(APP_ROOT, 'static/images/') print(target) if not os.path.isdir(target): os.mkdir(target) file = request.files['file'] # 构造上传文件的本地保存路径,可改用uuid生成文件名避免重名、规避中文路径问题 upload_save_path = os.path.join(target, file.filename) # 先把上传的文件保存到本地 file.save(upload_save_path) # 传入本地文件的完整路径 coco = CocoDataset(upload_save_path) image = coco.detection() output_filename = 'detection.jpg' output_save_path = os.path.join(target, output_filename) # 用绝对路径保存输出图片,避免相对路径寻址错误 image.save(output_save_path) return render_template('index.html', upload=True, filename=output_filename)
方法2:直接传递图片数组(无需额外保存上传文件,性能更高)
可以直接读取上传文件的字节流转为numpy数组,传给CocoDataset处理,省掉一次磁盘读写:
Flask端修改
import numpy as np # 省略其他已有代码 def post(self): target = os.path.join(APP_ROOT, 'static/images/') if not os.path.isdir(target): os.mkdir(target) file = request.files['file'] # 直接读文件流转为cv2可用的数组 file_bytes = file.read() img_np = np.frombuffer(file_bytes, np.uint8) img = cv2.imdecode(img_np, cv2.IMREAD_COLOR) # 直接传图片数组给CocoDataset coco = CocoDataset(img) image = coco.detection() output_filename = 'detection.jpg' output_save_path = os.path.join(target, output_filename) image.save(output_save_path) return render_template('index.html', upload=True, filename=output_filename)
CocoDataset类修改
class CocoDataset: def __init__(self, img): # 兼容直接传图片数组和传本地路径两种模式 if isinstance(img, str): self.img = cv2.imread(img) else: self.img = img def detection(self): net = cv2.dnn.readNetFromDarknet('yolov3-spp.cfg', 'yolov3-spp.weights') with open('coco.names', 'r') as f: classes = [line.strip() for line in f.readlines()] my_img = self.img print(my_img.shape) my_img = cv2.resize(my_img, (800, 800)) wt, ht, _ = my_img.shape # 剩下的检测逻辑保持不变 #__________________# im = Image.fromarray(my_img) return im
注意事项
- 如果上传的文件名包含中文,
cv2.imread会直接返回None,优先用方法2或者给上传文件重命名为无中文的文件名 - 所有文件路径建议用
os.path.join拼接绝对路径,不要用字符串硬拼接,避免不同操作系统的路径兼容问题 - 确保
static/images目录对程序运行用户有读写权限
内容的提问来源于stack exchange,提问作者Junaid
相关产品推荐
相关产品推荐

