PyTorch版Scaled YOLO v4使用pycocotools遇numpy版本冲突问题
环境配置
- Python 3.9
- numpy 1.21.0
- CUDA 10.2
报错信息
你遇到两个互斥的pycocotools报错:
- 第一个:ERROR: pycocotools unable to run: 'numpy.float64' object cannot be interpreted as an integer,触发位置为
cocoEval = COCOeval(cocoGt, cocoDt, 'bbox')执行时 - 第二个:ERROR: pycocotools unable to run: numpy.ndarray size changed, may indicate binary incompatibility. Expected 88 from C header, got 80 from PyObject,触发位置为
from pycocotools.coco import COCO导入时
两个报错的常规解决方案完全互斥:降级numpy到1.16.5可解决第一个报错,但会触发第二个;升级numpy到1.21.0可解决第二个报错,但会触发第一个。
相关代码
业务逻辑代码
# 保存JSON if save_json and len(jdict): f = 'detections_val2017_%s_results.json' % \ (weights.split(os.sep)[-1].replace('.pt', '') if isinstance(weights, str) else '') # 文件名 print('\nCOCO mAP with pycocotools... saving %s...' % f) with open(f, 'w') as file: json.dump(jdict, file) try: # 出现第二个报错时代码在此处终止 from pycocotools.coco import COCO from pycocotools.cocoeval import COCOeval imgIds = [int(Path(x).stem) for x in dataloader.dataset.img_files] cocoGt = COCO(glob.glob('../coco/annotations/instances_val*.json')[0]) # 初始化COCO真值API cocoDt = cocoGt.loadRes(f) # 初始化COCO预测结果API # 出现第一个报错时代码在此处终止 cocoEval = COCOeval(cocoGt, cocoDt, 'bbox') cocoEval.params.imgIds = imgIds # 待评估的图像ID cocoEval.evaluate() cocoEval.accumulate() cocoEval.summarize() map, map50 = cocoEval.stats[:2] # 更新结果(mAP@0.5:0.95, mAP@0.5) except Exception as e: print('ERROR: pycocotools unable to run: %s' % e)
变量类型说明
- cocoGt:
<pycocotools.coco.COCO object at 0x000002351F4CE6A0>,类型为pycocotools.coco.COCO - cocoDt:
<pycocotools.coco.COCO object at 0x000002351F4E58E0>,类型为pycocotools.coco.COCO
尝试将cocoGt、cocoDt转为int类型报错:int() argument must be a string, a bytes-like object or a number, not 'COCO',该操作是错误的,cocoGt和cocoDt本身就要求为COCO对象,无需做类型转换。
COCOeval类__init__参考定义
def __init__(self, cocoGt=None, cocoDt=None, iouType='segm'): ''' 使用真值和预测结果的coco API初始化CocoEval :param cocoGt: 包含真值标注的coco对象 :param cocoDt: 包含检测结果的coco对象 :return: None ''' if not iouType: print('iouType not specified. use default iouType segm') self.cocoGt = cocoGt # 真值COCO API self.cocoDt = cocoDt # 检测结果COCO API self.params = {} # 评估参数 self.evalImgs = defaultdict(list) # 单图单类别评估结果 包含[KxAxI]个元素 self.eval = {} # 汇总评估结果 self._gts = defaultdict(list) # 评估用真值 self._dts = defaultdict(list) # 评估用检测结果 self.params = Params(iouType=iouType) # 参数 self._paramsEval = {} # 评估用参数 self.stats = [] # 结果汇总 self.ious = {} # 所有真值和检测结果的iou if not cocoGt is None: self.params.imgIds = sorted(cocoGt.getImgIds()) self.params.catIds = sorted(cocoGt.getCatIds())
可行解决方案
方案1:替换兼容新版numpy的pycocotools版本(优先推荐)
问题根源是官方原生pycocotools长期未更新,不兼容numpy 1.20+版本,可直接替换为社区维护的兼容版本,无需修改任何业务代码:
- 卸载原有pycocotools:
pip uninstall -y pycocotools - 按系统安装对应兼容版本:
- Windows系统:执行
pip install pycocotools-windows - Linux/macOS系统:执行
pip install pycocotools>=2.0.6,也可通过conda安装conda install -c conda-forge pycocotools
- Windows系统:执行
该版本已修复numpy浮点型转整数的报错,且是基于新版numpy编译,不会触发二进制不兼容报错。
方案2:手动修改pycocotools源码适配(适合不想换安装包的场景)
仅需要修改本地cocoeval.py文件中的一处代码即可:
- 找到本地pycocotools安装路径下的
cocoeval.py文件,通常在Python安装目录的Lib/site-packages/pycocotools/路径下 - 定位到iouThrs定义的代码行,原代码为:
iouThrs = np.linspace(.5, 0.95, np.round((0.95 - .5) / .05) + 1, endpoint=True) - 将
np.round的返回值用int()包裹,修改后为:iouThrs = np.linspace(.5, 0.95, int(np.round((0.95 - .5) / .05)) + 1, endpoint=True) - 检查文件中其他所有将numpy浮点值直接传入要求整数参数的位置,全部用
int()包裹即可。
修改后既保留numpy 1.21.0版本解决二进制不兼容问题,也修复了float64不能转为整数的报错。
内容的提问来源于stack exchange,提问作者water MINERAL
相关产品推荐
相关产品推荐

