目录
直线拟合,算出离群点
岭回归拟合直线:

直线拟合,算出离群点
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, 0
    best_inliers = []
    max_inliers = 0
    for _ 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 = x1
        else:
            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, b
            best_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()

















