Python OpenCV中while循环处理同图片每次输出结果不一致问题
问题原因分析
你的代码出现每次运行结果不一致的核心问题有两个:
全局计数器未重置
counterBetween75、counterBetween105、counterBetween120等计数器是全局变量,而while(1)循环会持续对同一张图片重复处理。每次循环都会重新遍历轮廓并累加计数器,最终结果完全取决于你按ESC退出时的循环迭代次数,停留时间越长,累加次数越多,结果自然不同。多条件判断的重叠风险
你用了多个独立的if判断区间,当轮廓距离刚好处于区间边界(比如等于90)时,可能会被多个条件同时命中,导致同一个轮廓被重复统计,进一步加剧结果的不确定性。
另外,代码末尾的numOfObj=len(contours)仅获取最后一张图片的轮廓数量,并非所有图片的统计总和,逻辑也存在错误。
解决办法及修正代码
核心修正点
- 将计数器移到
while循环内部,每次处理图片时重置为0,确保每次统计都是当前HSV参数下的最新结果。 - 用
elif替代独立if,避免同一轮廓被多次统计。 - 增加全局统计变量,在退出单张图片处理时累加结果,最终输出所有图片的总和。
修正后的完整代码
import cv2 import glob import numpy as np import math path = glob.glob('photos/*.jpg') # 仅保留HSV参数为全局变量 filterPhoto = 16 remClutter = 175 # trackbar回调函数,更新HSV参数 def callback(x): global filterPhoto, remClutter filterPhoto = cv2.getTrackbarPos('Filter','Clutter controller') remClutter = cv2.getTrackbarPos('Clutter','Clutter controller') # 创建窗口和trackbar cv2.namedWindow('Clutter controller', 2) cv2.resizeWindow("Clutter controller", 670, 10) cv2.createTrackbar('Filter','Clutter controller', 16, 50, callback) cv2.createTrackbar('Clutter','Clutter controller', 175, 255, callback) # 全局统计所有图片的结果 total_below75 = 0 total_75_90 = 0 total_90_110 = 0 total_above110 = 0 if len(path) > 0: for file in path: print(f"正在处理图片: {file}") while True: # 每次循环重置当前图片的计数器 counterBetween75 = 0 counterBetween105 = 0 counterBetween120 = 0 basicCounter = 0 img = cv2.imread(file) hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) hsremClutter = np.array([filterPhoto, 0, remClutter], np.uint8) hsv_high = np.array([180, 255, 255], np.uint8) mask = cv2.inRange(hsv, hsremClutter, hsv_high) res = cv2.bitwise_and(img, img, mask=mask) contours, hierarchy = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) cv2.drawContours(img, contours, -1, (0,0,0), 1) for c in contours: rect = cv2.boundingRect(c) x,y,w,h = rect distancePoints = math.dist([x + w, y + h], [x, y]) distancePoints = round(distancePoints, 3) # 用elif避免重复统计 if 75 < distancePoints < 90: counterBetween75 += 1 cv2.rectangle(img, (x,y-4),(x+w,y+h), (255,155,0),1) cv2.putText(img, str(distancePoints), (x, y-9), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (0, 255, 0), 1) elif 90 <= distancePoints < 110: counterBetween105 += 1 cv2.rectangle(img, (x,y-4),(x+w,y+h), (255,155,0),1) cv2.putText(img, str(distancePoints), (x, y-9), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (0, 255, 0), 1) elif distancePoints >= 110: counterBetween120 += 1 cv2.rectangle(img, (x,y-4),(x+w,y+h), (255,155,0),1) cv2.putText(img, str(distancePoints), (x, y-9), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (0, 255, 0), 1) elif 0 < distancePoints <=75: basicCounter += 1 cv2.imshow('original', img) k = cv2.waitKey(1) & 0xFF if k == 27: # 退出当前图片处理,将结果累加至全局统计 total_below75 += basicCounter total_75_90 += counterBetween75 total_90_110 += counterBetween105 total_above110 += counterBetween120 break cv2.destroyAllWindows() # 输出最终统计结果 print("\n===== 所有图片统计结果 =====") print(f"小于75微米: {total_below75}") print(f"75-90微米之间: {total_75_90}") print(f"90-110微米之间: {total_90_110}") print(f"大于110微米: {total_above110}")
内容的提问来源于stack exchange,提问作者Liron Krouchinin
相关产品推荐
相关产品推荐

