目录
直线拟合,算出离群点
岭回归拟合直线:
直线拟合,算出离群点
import cv2
import numpy as np# 输入的点
points = np.array([[51, 149],[122, 374],[225, 376],[340, 382],[463, 391],[535, 298],[596, 400],[689, 406],[821, 407]
], dtype=np.float32)# 使用 RANSAC 算法拟合直线,并返回内点和离群点
def fit_line_ransac(points, max_iters=1000, threshold=10):"""使用 RANSAC 算法拟合直线,并判断离群点:param points: 输入的点集,形状为 (N, 2):param max_iters: 最大迭代次数:param threshold: 内点阈值:return: 拟合直线的斜率和截距 (k, b), 内点索引, 离群点索引"""best_k, best_b = 0, 0best_inliers = []max_inliers = 0for _ in range(max_iters):# 随机选择两个点sample_indices = np.random.choice(len(points), 2, replace=False)sample = points[sample_indices]x1, y1 = sample[0]x2, y2 = sample[1]# 计算直线的斜率和截距if x1 == x2: # 垂直线k = float('inf')b = x1else:k = (y2 - y1) / (x2 - x1)b = y1 - k * x1# 计算所有点到直线的距离distances = np.abs(k * points[:, 0] - points[:, 1] + b) / np.sqrt(k**2 + 1)# 统计内点inliers = np.where(distances < threshold)[0]# 更新最佳模型if len(inliers) > max_inliers:max_inliers = len(inliers)best_k, best_b = k, bbest_inliers = inliers# 离群点 = 所有点 - 内点outliers = np.setdiff1d(np.arange(len(points)), best_inliers)return (best_k, best_b), best_inliers, outliers# 使用 OpenCV 绘制点、拟合直线和内点/离群点
def draw_points_and_line(image, points, inliers, outliers, k, b, color_line=(255, 0, 0), color_inliers=(0, 255, 0), color_outliers=(0, 0, 255)):"""使用 OpenCV 绘制点、拟合直线和内点/离群点:param image: 背景图像:param points: 输入的点集:param inliers: 内点索引:param outliers: 离群点索引:param k: 直线斜率:param b: 直线截距:param color_line: 直线颜色 (BGR):param color_inliers: 内点颜色 (BGR):param color_outliers: 离群点颜色 (BGR)"""# 绘制内点for i in inliers:x, y = points[i]cv2.circle(image, (int(x), int(y)), 5, color_inliers, -1)# 绘制离群点for i in outliers:x, y = points[i]cv2.circle(image, (int(x), int(y)), 5, color_outliers, -1)# 绘制拟合直线x_min, x_max = int(np.min(points[:, 0])), int(np.max(points[:, 0]))y_min = int(k * x_min + b)y_max = int(k * x_max + b)cv2.line(image, (x_min, y_min), (x_max, y_max), color_line, 2)# 创建背景图像
image_width = 1000 # 图像宽度
image_height = 600 # 图像高度
background = np.zeros((image_height, image_width, 3), dtype=np.uint8) # 黑色背景# 使用 RANSAC 算法拟合直线,并判断离群点
(k, b), inliers, outliers = fit_line_ransac(points)
print(f"RANSAC 拟合直线: y = {k:.2f}x + {b:.2f}")
print(f"内点索引: {inliers}")
print(f"离群点索引: {outliers}")# 绘制点、拟合直线和内点/离群点
draw_points_and_line(background, points, inliers, outliers, k, b)# 显示图像
cv2.imshow("RANSAC Line Fitting with OpenCV", background)
cv2.waitKey(0)
cv2.destroyAllWindows()# 保存图像
cv2.imwrite("ransac_line_fitting_opencv.jpg", background)
岭回归拟合直线:
import cv2
import numpy as np
from sklearn.linear_model import Ridge# 生成带噪声的点
np.random.seed(42)
num_points = 100
x = np.linspace(0, 10, num_points)
y = 2 * x + 1 + np.random.normal(0, 1, num_points) # y = 2x + 1 + 噪声# 将 x 转换为二维数组(因为 sklearn 需要二维输入)
X = x.reshape(-1, 1)# 使用岭回归拟合直线
ridge = Ridge(alpha=1.0) # alpha 是正则化强度
ridge.fit(X, y)# 获取拟合的斜率和截距
slope = ridge.coef_[0]
intercept = ridge.intercept_# 打印拟合结果
print(f"拟合直线方程: y = {slope:.2f}x + {intercept:.2f}")# 计算拟合直线的两个端点
x_min, x_max = 0, 10
y_min = slope * x_min + intercept
y_max = slope * x_max + intercept# 将点缩放到图像尺寸
scale = 40 # 缩放因子
image_width = 640
image_height = 480# 创建一个空白图像用于可视化
image = np.zeros((image_height, image_width, 3), dtype=np.uint8)# 绘制点
for xi, yi in zip(x, y):cv2.circle(image, (int(xi * scale), int(yi * scale)), 3, (0, 255, 0), -1)# 绘制拟合的直线
pt1 = (int(x_min * scale), int(y_min * scale))
pt2 = (int(x_max * scale), int(y_max * scale))
cv2.line(image, pt1, pt2, (0, 0, 255), 2)# 显示图像
cv2.imshow("Ridge Regression Line Fit", image)
cv2.waitKey(0)
cv2.destroyAllWindows()