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

基于面积筛选OpenCV边界框监控样品头位置变化的问题

问题描述

我希望通过对比运动指令下达前后的静态相机图像,使用OpenCV与边界框来监控旋转且移动的样品头的位置变化。由于存在位置变化及潜在光照变动,无法仅通过调整图像阈值来单独提取样品;而样品尺寸固定,因此计划通过面积筛选边界框数组,仅保留覆盖样品的边界框。但在尝试使用cv2.contourArea()函数计算轮廓面积数组时,持续报错:

OpenCV(4.7.0) :-1: error: (-5:Bad argument) in function 'contourArea' - contour is not a numerical tuple

附上相关代码寻求帮助:

import numpy as np
import matplotlib.pyplot as plt
import cv2

# read the image
img = cv2.imread("Test_IMG_Rev1\IMG_3_ROT100.jpg")
# Convert to Grayscale and RGB
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

# Apply Thresholding on the grayscale image
ret,thresh = cv2.threshold(img_gray,127,255,0)

# Plot Images
fig = plt.figure(figsize=(20,20))
ax = plt.subplot(1, 2, 1)
plt.imshow(img_rgb)
ax.set_title("Original Image")
ax = plt.subplot(1, 2, 2)
plt.imshow(thresh)
ax.set_title("Threshold Image")
#
plt.show()

# Get contours (Rotated)
result1 = img.copy()
contours1 = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours1 = contours1[0] if len(contours1) == 2 else contours1[1]
for cntr1 in contours1:
    rect = cv2.minAreaRect(cntr1)
    box = cv2.boxPoints(rect)
    box = np.int0(box)
    G = cv2.drawContours(result1,[box],0,(0,0,255),2)
#
plt.figure(figsize=(10,10))
img_result1 = cv2.cvtColor(result1, cv2.COLOR_BGR2RGB)
plt.imshow(img_result1)
解决方案

报错原因

你大概率是把拟合后的矩形框(box)传给了cv2.contourArea(),但这个函数要求的输入是原始轮廓(cntr1),不是拟合后的矩形点集;另外如果轮廓本身不是合法的数值数组,也会触发该错误。

修改后的代码

import numpy as np
import matplotlib.pyplot as plt
import cv2

# 读取图像
img = cv2.imread("Test_IMG_Rev1\IMG_3_ROT100.jpg")
# 转换为灰度图和RGB图
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

# 灰度图阈值处理
ret, thresh = cv2.threshold(img_gray, 127, 255, 0)

# 绘制图像
fig = plt.figure(figsize=(20,20))
ax = plt.subplot(1, 2, 1)
plt.imshow(img_rgb)
ax.set_title("原始图像")
ax = plt.subplot(1, 2, 2)
plt.imshow(thresh, cmap='gray')
ax.set_title("阈值处理后图像")
plt.show()

# 获取轮廓并基于面积筛选
result1 = img.copy()
contours1 = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours1 = contours1[0] if len(contours1) == 2 else contours1[1]

# 根据实际样品尺寸设置面积范围(单位:像素),替换成你的实际值
sample_min_area = 1000
sample_max_area = 5000

for cntr1 in contours1:
    # 计算原始轮廓的面积,传入正确的参数
    area = cv2.contourArea(cntr1)
    # 筛选符合样品面积范围的轮廓
    if sample_min_area < area < sample_max_area:
        rect = cv2.minAreaRect(cntr1)
        box = cv2.boxPoints(rect)
        box = np.int0(box)
        cv2.drawContours(result1, [box], 0, (0,0,255), 2)

plt.figure(figsize=(10,10))
img_result1 = cv2.cvtColor(result1, cv2.COLOR_BGR2RGB)
plt.imshow(img_result1)
plt.title("筛选后的样品边界框")
plt.show()

关键说明

  • cv2.contourArea()必须传入**cv2.findContours()返回的原始轮廓对象**,不能用拟合后的矩形点集
  • 提前测量样品对应的像素面积范围,设置合理的sample_min_area和sample_max_area,过滤掉背景噪声或其他无关轮廓
  • 确保图像读取正常:如果img为None,后续轮廓提取会得到无效数据,也可能触发类似错误,可添加assert img is not None, "图像读取失败"验证

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 20:05:14