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
相关产品推荐
相关产品推荐

