运行OpenCV图像遮罩代码时cv2.isContourConvex报错如何解决
错误原因
这个报错是两个核心问题共同导致的:
- OpenCV版本接口不匹配:OpenCV 3.x版本中
cv2.findContours返回3个值,顺序为(处理后图像, 轮廓列表, 层级结构),但你使用的OpenCV 4.x版本仅返回2个值,顺序为(轮廓列表, 层级结构)。你代码中写的_, contours = cv2.findContours(...)错误地把层级结构赋值给了contours变量,传入cv2.isContourConvex的参数根本不是轮廓数据,完全不符合函数要求的CV_32F或CV_32S深度格式,直接触发断言失败。 - 缺少轮廓有效性校验:即使接口适配正确,如果边缘检测后没有得到有效轮廓、或者轮廓点数小于3,调用
cv2.isContourConvex也会触发同类报错。
修复方案
按照以下步骤修改代码即可:
- 修正
cv2.findContours的返回值接收逻辑 - 新增轮廓有效性过滤,跳过点数不足、面积为0的无效轮廓
- 新增空轮廓判断,避免取最大轮廓时索引越界
- 补充图片读取校验、优化文件名分割逻辑避免异常
修改后的完整代码如下:
import cv2 import numpy as np filepath = 'blackmeasles (1).jpg' BLUR = 21 CANNY_THRESH_1 = 10 CANNY_THRESH_2 = 200 MASK_DILATE_ITER = 10 MASK_ERODE_ITER = 10 MASK_COLOR = (0.0,0.0,0.0) # In BGR format img = cv2.imread(filepath) # 新增图片读取成功校验 if img is None: raise ValueError(f"无法读取路径为{filepath}的图片") gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) edges = cv2.Canny(gray, CANNY_THRESH_1, CANNY_THRESH_2) edges = cv2.dilate(edges, None) edges = cv2.erode(edges, None) contour_info = [] # 修正返回值接收顺序,适配OpenCV4.x contours, _ = cv2.findContours(edges, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE) for c in contours: # 过滤点数小于3、面积为0的无效轮廓 if len(c) < 3 or cv2.contourArea(c) <= 0: continue contour_info.append((c, cv2.isContourConvex(c), cv2.contourArea(c),)) if not contour_info: raise ValueError("未检测到有效轮廓,请调小Canny低阈值参数后重试") contour_info = sorted(contour_info, key=lambda c: c[2], reverse=True) max_contour = contour_info[0] mask = np.zeros(edges.shape) cv2.fillConvexPoly(mask, max_contour[0], (255)) mask = cv2.dilate(mask, None, iterations=MASK_DILATE_ITER) mask = cv2.erode(mask, None, iterations=MASK_ERODE_ITER) mask = cv2.GaussianBlur(mask, (BLUR, BLUR), 0) mask_stack = np.dstack([mask]*3) mask_stack = mask_stack.astype('float32') / 255.0 img = img.astype('float32') / 255.0 masked = (mask_stack * img) + ((1-mask_stack) * MASK_COLOR) masked = (masked * 255).astype('uint8') # 优化文件名分割逻辑,避免文件名含多个点时出错 fileName = filepath.rsplit('.', 1)[0] fileExtension = filepath.rsplit('.', 1)[1] filepath = f"{fileName}-masked.{fileExtension}" print(filepath) cv2.imwrite(filepath, masked)
内容的提问来源于stack exchange,提问作者PadmaPriya
相关产品推荐
相关产品推荐

