Python OpenCV逐次显示单个轮廓如何避免保留之前绘制内容

问题描述
- 预期实现逐次单独显示单个检测轮廓的效果,判断问题出在for循环逻辑上
- 曾尝试使用
break语句,但不符合需求:break会在绘制完第一个轮廓后直接跳出整个循环,无法完成全量轮廓遍历 - 检测得到的contour为三维列表结构,单个轮廓数据格式示例:
[[[125 300]] [[124 301]] [[124 302]] [[124 303]] [[124 304]] [[125 304]] [[126 304]] [[127 304]] [[128 304]] [[129 304]] [[130 304]] [[131 304]] [[132 304]] [[133 304]] [[132 303]] [[131 302]] [[130 301]] [[129 301]] [[128 300]] [[127 300]] [[126 300]]]
- 疑问:该问题是否和Python队列有关?
原始问题代码
import cv2 import math from matplotlib import pyplot as plt def lines(): # reading image in BGR format img = cv2.imread("C://Users/ranz/Desktop/1.bmp") res = cv2.resize(img, (570,610), cv2.INTER_LINEAR) cnt_point = [] #grayscale gry = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #threshold for black pixel _, thresh = cv2.threshold(gry,0,255,cv2.THRESH_BINARY_INV) #find all contours cnt,_ = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE) #draw blank mask blank_mask = np.zeros((thresh.shape[0], thresh.shape[2], 3), np.uint8) for i in range(len(cnt)): cv2.drawContours(blank_mask, cnt[i], -1, (0, 255, 0), 1) print(cnt[i]) cv2.imshow('test',blank_mask) cv2.waitKey(0) cv2.destroyAllWindows() lines()
问题原因与修复方案
这个问题和Python队列没有关系,核心是4处代码错误:
- 空白mask在循环外只初始化一次,每次绘制轮廓是在原有mask上叠加,显示的是历史所有轮廓的累加结果,而非单个轮廓
- 创建mask时维度参数错误:二值化后的
thresh是单通道灰度图,不存在shape[2]属性,直接写会触发维度报错 - 缺少numpy导入,代码中
np.zeros无法正常执行 cv2.drawContours的第二个参数要求传入轮廓列表,直接传入单个轮廓cnt[i]会导致绘制异常;另外窗口销毁语句放在函数调用前,执行逻辑顺序错误
修正后可正常运行的代码:
import cv2 import numpy as np import math from matplotlib import pyplot as plt def lines(): # 读取BGR格式图像 img = cv2.imread("C://Users/ranz/Desktop/1.bmp") res = cv2.resize(img, (570,610), cv2.INTER_LINEAR) cnt_point = [] # 转灰度图 gry = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 反色二值化,提取黑色像素区域 _, thresh = cv2.threshold(gry,0,255,cv2.THRESH_BINARY_INV) # 查找所有轮廓 cnt,_ = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE) for i in range(len(cnt)): # 每次循环重新生成空白mask,避免轮廓叠加 blank_mask = np.zeros((thresh.shape[0], thresh.shape[1], 3), np.uint8) # 单个轮廓需要包装为列表传入drawContours接口 cv2.drawContours(blank_mask, [cnt[i]], -1, (0, 255, 0), 1) print(cnt[i]) cv2.imshow('test',blank_mask) # 按任意键切换显示下一个轮廓 cv2.waitKey(0) # 所有轮廓遍历完成后销毁窗口 cv2.destroyAllWindows() lines()
内容的提问来源于stack exchange,提问作者peter teoh
相关产品推荐
相关产品推荐

