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

OpenCV contourArea报错:contour非numpy数组/标量,求排查

问题排查与修复:OpenCV contourArea函数报错

核心错误原因

error: OpenCV(4.7.0) :-1: error: (-5:Bad argument) in function 'contourArea'

  • contour is not a numpy array, neither a scalar
  • Expected Ptrcv::UMat for argument 'contour'

报错本质是传入cv2.contourArea的不是合法的轮廓对象,问题出在对find_contours返回值的错误接收。

具体问题点

  • find_contours函数返回轮廓列表和层级数组两个值,但在main函数中错误地将返回值整体赋值给了contours,导致contours变成了一个包含两个元素的元组(轮廓列表+层级数组),而非单纯的轮廓列表。
  • 后续调用find_ruler_contour时,函数会遍历这个元组,当遍历到层级数组时,将其传入cv2.contourArea,不符合函数要求的输入格式,触发报错。
  • 额外问题:ruler_length_mm = 1812790数值明显异常(1800多米),属于输入错误,需根据实际尺子长度修正。

修复后的代码

import cv2
import numpy as np

def load_image(image_path):
    image = cv2.imread(image_path)
    return image

def preprocess_image(image, blur_radius=5):
    gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    blurred_image = cv2.GaussianBlur(gray_image, (blur_radius, blur_radius), 0)
    _, thresholded_image = cv2.threshold(blurred_image, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
    return thresholded_image

def find_contours(thresholded_image):
    contours, hierarchy = cv2.findContours(thresholded_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    return list(contours), hierarchy

def calculate_floral_area(contours):
    total_area = 0
    for contour in contours:
        area = cv2.contourArea(contour)
        total_area += area
    return total_area

def find_ruler_contour(contours, min_ruler_area, max_ruler_area):
    for contour in contours:
        area = cv2.contourArea(contour)
        if min_ruler_area <= area <= max_ruler_area:
            return contour
    return None

def calculate_conversion_factor(ruler_contour, ruler_length_mm):
    ruler_area_pixels = cv2.contourArea(ruler_contour)
    # 注意:此逻辑仅适用于正方形尺子,长方形需改用外接矩形计算
    ruler_length_pixels = np.sqrt(ruler_area_pixels)
    conversion_factor = ruler_length_mm / ruler_length_pixels
    return conversion_factor ** 2

def main(image_path, ruler_length_mm, min_ruler_area, max_ruler_area):
    image = load_image(image_path)
    thresholded_image = preprocess_image(image)
    # 修复:正确接收轮廓列表,忽略层级数组
    contours, _ = find_contours(thresholded_image)
    
    ruler_contour = find_ruler_contour(contours, min_ruler_area, max_ruler_area)
    if ruler_contour is None:
        print("Ruler not found")
        return

    conversion_factor = calculate_conversion_factor(ruler_contour, ruler_length_mm)
    contours = [c for c in contours if not np.array_equal(c, ruler_contour)]

    floral_area_pixels = calculate_floral_area(contours)
    floral_area_mm2 = floral_area_pixels * conversion_factor

    print(f"Floral area: {floral_area_mm2} square millimeters")

if __name__ == "__main__":
    image_path = "/Users/yusufyildirim/Desktop/IMG_7020.jpg"
    # 修正为合理的尺子长度,示例为180mm,需根据实际调整
    ruler_length_mm = 180
    min_ruler_area = 160000
    max_ruler_area = 200000
    main(image_path, ruler_length_mm, min_ruler_area, max_ruler_area)

额外优化建议

如果使用的是长方形尺子,建议替换calculate_conversion_factor函数的逻辑,用外接矩形计算更准确:

def calculate_conversion_factor(ruler_contour, ruler_length_mm):
    # 获取尺子外接矩形的宽和高
    x, y, w, h = cv2.boundingRect(ruler_contour)
    # 取长边对应实际尺子长度
    ruler_length_pixels = max(w, h)
    conversion_factor = ruler_length_mm / ruler_length_pixels
    return conversion_factor ** 2

内容的提问来源于stack exchange,提问作者Yusuf Yıldırım

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 01:32:56