如何判断木棍二进制掩码是否笔直并计算弯曲曲率?
木棍二进制掩码的笔直判断与曲率计算方案
一、预处理:提取木棍中心骨架
直接取掩码中心点误差较大,优先采用**骨架提取(细化)**获取木棍的单像素中心轴线,这是后续分析的核心基础:
- 用OpenCV的
cv2.ximgproc.thinning()函数对二进制掩码做细化处理,确保输出为单像素宽度的骨架(需提前保证掩码是二值化状态:前景为白色,背景为黑色)。
二、判断木棍是否笔直
基于提取的骨架点集,通过最小二乘法拟合直线+点线距离统计判断笔直度:
- 提取骨架上所有非零像素的坐标,得到N×2格式的点集
points。 - 用最小二乘法拟合直线,得到直线方程参数。
- 计算每个骨架点到拟合直线的垂直距离,取所有距离的平均值
avg_dist。 - 设定阈值(可参考木棍平均宽度的1/10),若
avg_dist小于阈值则判定为笔直,否则为弯曲。
三、弯曲时的曲率计算方案
针对弯曲木棍,可通过两种方式量化弯曲程度:
方法1:局部曲率统计
- 对骨架点集做滑动窗口处理(比如取连续5个点),用三点法计算局部曲率:对于点
P_i-1, P_i, P_i+1,计算三点构成圆的半径r,局部曲率为1/r。 - 取所有局部曲率的平均值或最大值作为整体曲率值,数值越大表示弯曲程度越高。
方法2:全局圆弧拟合
- 对整个骨架点集拟合最优圆弧,得到圆弧半径
R,整体曲率即为1/R。可通过最小二乘法拟合圆弧参数,或用点集外接圆做近似计算。
示例代码片段(Python+OpenCV)
import cv2 import numpy as np from sklearn.linear_model import LinearRegression # 读取二值化掩码 mask = cv2.imread('stick_mask.png', 0) # 提取骨架 skeleton = cv2.ximgproc.thinning(mask) # 获取骨架点坐标 points = np.column_stack(np.where(skeleton > 0)) if len(points) > 2: # 最小二乘法拟合直线 X = points[:, 0].reshape(-1, 1) y = points[:, 1] model = LinearRegression().fit(X, y) y_pred = model.predict(X) # 计算点到直线的平均距离 distances = np.abs(y - y_pred) / np.sqrt(model.coef_[0]**2 + 1) avg_dist = np.mean(distances) # 设定判断阈值(示例值,可根据实际木棍尺寸调整) threshold = 2 if avg_dist < threshold: print("木棍是笔直的") else: print("木棍是弯曲的,正在计算曲率...") # 三点法计算平均曲率 curvature_list = [] for i in range(1, len(points)-1): p_prev = points[i-1] p_curr = points[i] p_next = points[i+1] # 计算三点外接圆半径 a = np.linalg.norm(p_curr - p_prev) b = np.linalg.norm(p_next - p_curr) c = np.linalg.norm(p_next - p_prev) s = (a + b + c) / 2 area = np.sqrt(s*(s-a)*(s-b)*(s-c)) if area < 1e-6: continue r = (a*b*c)/(4*area) curvature = 1/r if r !=0 else 0 curvature_list.append(curvature) avg_curvature = np.mean(curvature_list) print(f"平均曲率值:{avg_curvature:.6f}")
内容的提问来源于stack exchange,提问作者JITHU PRAKASH
相关产品推荐
相关产品推荐

