如何计算两条曲线间的最小距离/最小像素数以确定桥的直径
计算两条曲线间最小距离以确定桥直径的方法
核心思路
通过分离目标轮廓、计算点对距离(或借助距离变换)得到两条曲线的最小像素距离,再按需转换为实际物理尺寸。
步骤1:分离桥的两条侧曲线
从Canny检测得到的轮廓中,筛选出对应桥两侧的目标曲线。可通过轮廓的位置、面积或外接矩形区分:
import cv2 import numpy as np # 假设已得到Canny边缘图canny_img和原始图像img contours, _ = cv2.findContours(canny_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) img_height, img_width = img.shape[:2] # 按左右位置筛选两条曲线(可根据实际场景调整逻辑) contour_left, contour_right = None, None for cnt in contours: x, _, _, _ = cv2.boundingRect(cnt) if x < img_width // 2: contour_left = cnt else: contour_right = cnt
步骤2:计算最小距离(两种实现方式)
方式1:遍历点对计算欧氏距离(适合点量少的情况)
先提取曲线点集,可通过多边形逼近降采样减少计算量,再遍历所有点对找最小距离:
# 提取轮廓点集 def get_contour_points(contour): return [(p[0][0], p[0][1]) for p in contour] # 多边形逼近降采样(可选,epsilon越小保留细节越多) epsilon_left = 0.001 * cv2.arcLength(contour_left, closed=True) approx_left = cv2.approxPolyDP(contour_left, epsilon_left, closed=True) pts_left = get_contour_points(approx_left) epsilon_right = 0.001 * cv2.arcLength(contour_right, closed=True) approx_right = cv2.approxPolyDP(contour_right, epsilon_right, closed=True) pts_right = get_contour_points(approx_right) # 计算最小距离 min_dist = float('inf') for p1 in pts_left: for p2 in pts_right: dist = np.sqrt((p1[0]-p2[0])**2 + (p1[1]-p2[1])**2) if dist < min_dist: min_dist = dist
方式2:距离变换法(高效,适合点量多的情况)
利用距离变换图直接获取另一条曲线上点的最小距离:
# 创建仅包含左侧曲线的掩码 mask_left = np.zeros_like(canny_img) cv2.drawContours(mask_left, [contour_left], -1, 255, thickness=cv2.FILLED) # 生成距离变换图(背景到左侧曲线的距离) dist_transform = cv2.distanceTransform(255 - mask_left, cv2.DIST_L2, 5) # 遍历右侧曲线的点,取最小距离 min_dist = float('inf') for p in contour_right: x, y = p[0][0], p[0][1] current_dist = dist_transform[y, x] if current_dist < min_dist: min_dist = current_dist
步骤3:转换为实际物理尺寸(可选)
若需要真实桥直径,需提前确定图像的像素比例尺(例如:已知图像中10cm的物体对应50像素,则比例尺为0.2cm/像素),计算:
scale = 0.2 # 示例:1像素对应0.2厘米 actual_diameter = min_dist * scale
内容的提问来源于stack exchange,提问作者user21094827
相关产品推荐
相关产品推荐

