OpenCV目标检测后图像裁剪报错(-215),坐标使用疑问求助
问题原因与解决方案
核心问题
你遇到的(-215:Assertion failed) size.width>0 && size.height>0错误,根源是对OpenCV dnn输出的bbox格式理解错误,导致裁剪出的图像尺寸为0。
OpenCV的dnn_DetectionModel.detect()方法返回的bbox数组,每个元素格式是[x, y, width, height]:
x/y:目标框左上角坐标width/height:目标框的宽度和高度
而你直接把box[2]、box[3]当成了右下角的x2、y2,这会触发两种错误:
- 部分bbox的
height值小于y(比如你输出里的[45 722 188 472],y=722,你直接用y2=472),此时y1 > y2,Python切片image[y1:y2]会得到空数组,触发尺寸断言错误。 - 当
y + height超过图像高度时,裁剪范围超出图像边界,同样会导致无效图像。
修正后的代码
import cv2 import numpy as np image = cv2.imread('venv/img.jpg') # 先检查图像是否加载成功 if image is None: print("无法加载图像,请检查路径") exit() classNames = [] classFile = 'coco.names' with open(classFile,'rt') as f: # 修复原代码的换行符错误 classNames = f.read().rstrip('\n').split('\n') configPath = 'ssd_mobilenet_v3_large_coco_2020_01_14.pbtxt' weightsPath = 'frozen_inference_graph.pb' net = cv2.dnn_DetectionModel(weightsPath, configPath) net.setInputSize(320, 320) net.setInputScale(1.0 / 127.5) net.setInputMean((127.5, 127.5, 127.5)) net.setInputSwapRB(True) classIds, confs, bbox = net.detect(image, confThreshold=0.5) print(classIds, bbox) if len(classIds) != 0: img_h, img_w = image.shape[:2] for classId, confidence, box in zip(classIds.flatten(), confs.flatten(), bbox): cv2.rectangle(image, box, color=(0, 255, 0), thickness=2) # 正确解析bbox格式 x1, y1, w, h = box # 计算右下角坐标并限制在图像范围内 x2 = min(x1 + w, img_w) y2 = min(y1 + h, img_h) # 确保起始坐标不小于0 x1 = max(x1, 0) y1 = max(y1, 0) # 仅当裁剪范围有效时执行操作 if x2 > x1 and y2 > y1: crop_person = image[y1:y2, x1:x2] cv2.imshow(f'crop_{classId}', crop_person) cv2.waitKey(0) cv2.destroyWindow(f'crop_{classId}') image = cv2.resize(image,(480,640)) cv2.imshow('img',image) cv2.waitKey(0) cv2.destroyAllWindows()
关键修正点
- 修正bbox解析逻辑:将
x2 = box[2]改为x2 = x1 + w,y2 = box[3]改为y2 = y1 + h,还原正确的坐标计算方式。 - 添加边界检查:确保裁剪坐标不超出图像宽高范围,同时保证
x2 > x1和y2 > y1,避免生成空图像。 - 修复类别读取错误:原代码中
rstrip('n')和split('n')应为rstrip('\n')和split('\n'),否则无法正确读取coco类别名称。 - 优化窗口管理:每次显示裁剪图像后关闭对应窗口,避免窗口堆积。
内容的提问来源于stack exchange,提问作者zerro
相关产品推荐
相关产品推荐

