You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 02:24:03