曲线轮廓像素长度测量求助:代码计算值与手动测量值不符
解决OpenCV轮廓长度计算与手动测量不符的问题
我看了你的代码,发现几个关键错误导致计算结果和手动测量差这么多,咱们一步步梳理:
核心错误点
轮廓索引完全错误
contours是一个包含所有检测到的轮廓的列表,每个单独的轮廓是(N, 1, 2)形状的数组(N是这个轮廓的点数量)。你代码里写的contours[i]是取第i个轮廓,而不是第一个轮廓的第i个点!这就导致你在计算不同轮廓之间的点距离,而不是同一个轮廓上相邻点的距离,结果自然完全不对。变量名不一致
你初始化了euclidean_dist=0,但循环里累加的是dist,这在Python里会直接抛出NameError,估计你是写代码时的笔误,实际运行时应该是统一了变量名,但这个小问题也容易让结果出错。未处理闭合轮廓的最后一段距离
当循环到轮廓的最后一个点时,i+1会超出范围,你用try-except跳过了,但闭合轮廓的最后一个点需要和第一个点计算距离,否则会少算一段长度。没必要手动计算——OpenCV有现成函数
OpenCV自带cv2.arcLength()函数,专门用来计算轮廓的弧长,它会自动处理闭合轮廓,比手动写循环靠谱多了。
修正后的代码
import cv2 import math # 读取图像,注意findContours需要二值图,所以先转灰度再二值化 image = cv2.imread('black_white_image.png') gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) _, binary_img = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY) # 检测轮廓 contours, hierarchy = cv2.findContours(binary_img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) # 手动计算修正版(用来验证) if contours: target_contour = contours[0] # 取第一个轮廓 total_length = 0.0 point_count = len(target_contour) for i in range(point_count): # 获取当前点和下一个点(最后一个点的下一个点是第一个点,保证闭合) x1, y1 = target_contour[i][0] x2, y2 = target_contour[(i+1) % point_count][0] total_length += math.hypot(x2 - x1, y2 - y1) print(f"手动修正后长度:{total_length:.2f} 像素") # 用OpenCV自带函数计算(推荐) if contours: arc_len = cv2.arcLength(contours[0], closed=True) print(f"OpenCV arcLength计算长度:{arc_len:.2f} 像素") # 绘制并保存轮廓 cv2.drawContours(image, contours, -1, (0,255,0), 3) cv2.imwrite('cnt_black_white_image.png', image)
额外注意事项
- 一定要确保输入
findContours的是二值图像(黑白图,只有0和255),如果直接传入彩色图,检测到的轮廓会混乱,结果肯定不对。 - 修正代码后得到的结果应该会和你在Inkscape测量的130像素接近。之前的289大概率是因为索引错误,把多个轮廓的点混在一起计算了。
内容的提问来源于stack exchange,提问作者Cks
相关产品推荐
相关产品推荐

