python 使用散點擬合角度
阿新 • • 發佈:2021-01-08
與一般的擬合直線不同,擬合角度的目的是獲得直線與水平軸的夾角,即下圖中的a:
常用的最小二乘法無法用於上圖左邊的情況,更進一步的直線擬合方法同樣不適用:
https://blog.csdn.net/liyuanbhu/article/details/50866802
所以採用一種較簡單的混合法來計算:
import numpy as np
import math
def linear_regression(x, y):
"""
擬合直線
x, y: list()
return: b, k y = a0 + k*x
"""
N = len(x)
sumx = sum(x)
sumy = sum(y)
sumx2 = sum(x**2)
sumxy = sum(x*y)
A = np.mat([[N, sumx], [sumx, sumx2]])
b = np.array([sumy, sumxy])
return np.linalg.solve(A, b)
def angle_regression(x, y):
"""
擬合角.
x-y計算一次, y-x計算一次, 求哪個誤差小,如果x-y誤差小,直接返回angle, 如果y-x誤差小, 計算沿45°對稱的角
return: 弧度
"""
# 垂直的情況
if x.min() == x.max():
return math.pi / 2.
# x-y
b1, k1 = linear_regression(x, y)
# y-x
b2, k2 = linear_regression(y, x)
# 計算誤差
err1 = 0
err2 = 0
for i in np.arange(x.shape[0]):
err1 += abs(k1*x[i] - y[i] + b1) / math.sqrt(k1**2 + 1)
err2 += abs(k2*y[i] - x[i] + b2) / math.sqrt(k2**2 + 1)
if err1 <= err2:
return (math.atan(k1) + 2*math.pi) % (2*math.pi)
else:
# 計算沿45°對稱的角
return (math.pi/2. - math.atan(k2) + 2*math.pi) % (2*math.pi)
if __name__ == "__main__":
x = np.array([1, 1, 2, 1, 1])
y = np.array([1, 2, 3, 4, 5])
print(angle_regression(x, y))