import numpy as np
import matplotlib.pyplot as plt
import operator as op
class Ransac:
weight = 0
bias = 0
#最小二乘法拟合
def least_square(self, samples):
X = np.zeros([samples.shape[0], 2], dtype=float)
X[:, 0] = samples[:, 0]
X[:, 1] = 1
Y = samples[:, 1]
A = np.dot(X.T, X)
B = np.linalg.pinv(A)
C = np.dot(B, X.T)
Theta = np.dot(C, Y)
A = np.linalg.pinv(np.dot(X.T, X))
B = np.dot(A, X.T)
Theta = np.dot(B, Y)
weight = Theta[0]
bias = Theta[1]
return weight, bias
#判断是否有重复样本
def isRepeat(self, src, dst):
for i in range(len(src)):
if op.eq(list(src[i]), list(dst)):
return True
return False
#随机采样
def random_sample(self, samples, point_ratio):
num = len(samples)
inliners_num = int(num * point_ratio)
inliners = []
outliners = []
cur_num = 0;
while cur_num != inliners_num:
index = np.random.randint(0, num)
sample_cur = samples[index]
if not self.isRepeat(inliners, sample_cur):
cur_num += 1
inliners.append(list(sample_cur))
for i in range(num):
if not self.isRepeat(inliners, samples[i]):
outliners.append(list(samples[i]))
return np.array(inliners), np.array(outliners)
def fun_plot(self, samples, w, b):
data_x = np.linspace(0, 50, 50)
data_y = [w * x + b for x in data_x]
plt.ion()
plt.plot(samples[:, 0], samples[:,1], 'bo')
plt.plot(data_x, data_y, 'r')
plt.show()
plt.pause(0.05)
plt.clf()
def ransac(self, samples, point_ratio = 0.05, epoch = 50, reject_dis = 5, inliners_ratio = 0.4):
# samples 输入样本
# point_ratio 随机选择样本的比例
# epoch 迭代次数
# reject_dis 小于此阈值将outliners加入inliners
# inliners_ratio 有效inliners最低比例
max_inlinear_num = 0;
for i in range(epoch):
inliners, outliners = self.random_sample(samples, point_ratio)
w, b = self.least_square(inliners)
#self.fun_plot(samples, w, b)
for j in range(len(outliners)):
distance = np.abs(w * outliners[j,0] + b - outliners[j,1]) / np.sqrt(np.power(w,2) + 1)
if distance <= reject_dis:
inliners = np.vstack((inliners, outliners[j]))
w, b = self.least_square(inliners)
self.fun_plot(inliners, w, b)
if len(inliners) >= len(samples) * inliners_ratio:
if len(inliners) > max_inlinear_num:
self.weight = w
self.bias = b
max_inlinear_num = len(inliners)
plt.ioff()
plt.close()