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

如何用OpenCV提取图像中所有白色区域轮廓并绘制边界框?

提取图像中所有白色区域并绘制边界框问题

需求:提取图像中所有独立白色区域,为每个区域添加边界框,并获取框的面积等信息。目前通过阈值分割、Canny边缘检测得到了掩码,但仅能检测到主要轮廓,无法覆盖所有目标区域。

当前代码

img = cv2.imread("img.png")
 
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
_, thresh = cv2.threshold(img_gray, 128, 255, cv2.THRESH_BINARY)
img_blur = cv2.GaussianBlur(thresh, (5, 5), 2)
img_canny = cv2.Canny(img_blur, 0, 0)

cnts = cv2.findContours(img_canny, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
r1, r2 = sorted(cnts, key=cv2.contourArea)[-3:-1]
x, y, w, h = cv2.boundingRect(np.r_[r1, r2])
cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 2)
cv2.imshow("img", img)
cv2.waitKey(0) 

尝试过的代码(未达预期)

cnts = imutils.grab_contours(cnts)
(cnts, _) = contours.sort_contours(cnts)

for C in cnts:
    if cv2.contourArea(C) < 200:
        continue
    box = cv2.minAreaRect(C)
    box = cv2.boxPoints(box) if imutils.is_cv2() else cv2.boxPoints(box)
    box = perspective.order_points(box)
    orig = img.copy()
    cv2.drawContours(orig, [box.astype("int")], -1, (0, 255, 0), 1)
    cv2.imshow("img", orig)

相关图像

  • 原图
  • 预期效果(目标白色区域)
  • 当前仅检测单个轮廓的结果

解决方案

核心调整点

  1. 修正轮廓检索模式:用cv2.RETR_EXTERNAL替代cv2.RETR_TREE,只检测最外层轮廓,避免层级关系干扰独立区域检测。
  2. 优化预处理逻辑:采用图像反转+自适应阈值,更精准分割白色区域,适配光照不均场景。
  3. 修复遍历绘制逻辑:在同一个图像副本上批量绘制所有边界框,避免单次覆盖。

完整修正代码

import cv2
import numpy as np

# 读取图像并保留副本
img = cv2.imread("img.png")
result_img = img.copy()
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 预处理:反转图像(白色区域转为黑色,适配轮廓检测逻辑)+ 自适应阈值分割
inv_gray = cv2.bitwise_not(gray)
thresh = cv2.adaptiveThreshold(inv_gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2)

# 寻找最外层轮廓
cnts, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# 遍历轮廓,过滤噪声并绘制边界框
min_area_threshold = 200  # 可根据实际需求调整
for cnt in cnts:
    contour_area = cv2.contourArea(cnt)
    if contour_area < min_area_threshold:
        continue
    # 获取矩形边界框并绘制
    x, y, w, h = cv2.boundingRect(cnt)
    cv2.rectangle(result_img, (x, y), (x + w, y + h), (0, 255, 0), 2)
    # 输出面积信息
    print(f"区域轮廓面积:{round(contour_area, 2)},边界框面积:{w * h}")

# 显示结果
cv2.imshow("所有白色区域边界框", result_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

内容的提问来源于stack exchange,提问作者ksu1980

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 18:10:50