You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python OpenCV中while循环处理同图片每次输出结果不一致问题

问题原因分析

你的代码出现每次运行结果不一致的核心问题有两个:

  1. 全局计数器未重置
    counterBetween75、counterBetween105、counterBetween120等计数器是全局变量,而while(1)循环会持续对同一张图片重复处理。每次循环都会重新遍历轮廓并累加计数器,最终结果完全取决于你按ESC退出时的循环迭代次数,停留时间越长,累加次数越多,结果自然不同。

  2. 多条件判断的重叠风险
    你用了多个独立的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 15:36:20