目錄
直線擬合,算出離群點
嶺回歸擬合直線:
直線擬合,算出離群點
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()