- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
给定:
我在 csv 文件中有一组 3D 点。
X, Y, Z
x0, y0, z0
x1, y1, z1
...
xn, yn, zn
问题陈述:目标是根据最小二乘误差拟合平面。获取点与平面之间的误差距离。我可以自由选择Python或C++。我更喜欢 c++,但 python 也不错。
平面方程为:
Ax + By + Cz + D = 0 -- Equation 1
选项 1:C++ 方式
我在网上找到了这个链接,描述了一种解决平面拟合的c++方法 http://www.janssenprecisionengineering.com/downloads/Fit-plane-through-data-points.pdf但这里他们没有使用方程 1,而是使用方程 2
Z = A'x + B'y + C' -- Equation 2
where, A' = -A/C
B' = -B/C
C' = -D/C
一旦我知道了 A' B' C',我就可以根据方程 3 计算每个点到平面的距离(引用 -> Math Insight ):
Error = abs(A * x + B * y - z + C) / sqrt(pow(A, 2) + pow(B, 2) + 1); -- Equation 3
我开始用C++实现它
std::ofstream abc;
abc.open("Logs\\abc.csv");
cv::Mat Plane;
double Xi = 0;
double Yi = 0;
double Zi = 0;
double X2i = 0;
double Y2i = 0;
double XiYi = 0;
double XiZi = 0;
double YiZi = 0;
for (int o = 0; o < GL.PointX.size(); ++o) {
std::cout << "POINT X : " << GL.PointX[o] << std::endl;
std::cout << "POINT Y : " << GL.PointY[o] << std::endl;
std::cout << "POINT Z : " << GL.PointZ[o] << std::endl;
Xi = Xi + GL.PointX[o];
Yi = Yi + GL.PointY[o];
Zi = Zi + GL.PointZ[o];
X2i = X2i + (GL.PointX[o] * GL.PointX[o]);
Y2i = Y2i + (GL.PointY[o] * GL.PointY[o]);
XiYi = XiYi + (GL.PointX[o] * GL.PointY[o]);
XiZi = XiZi + (GL.PointX[o] * GL.PointZ[o]);
YiZi = YiZi + (GL.PointY[o] * GL.PointZ[o]);
}
cv::Mat PlaneA_Mat = (cv::Mat_<double>(3, 3) << X2i, XiYi, Xi, XiYi, Y2i, Yi, Xi, Yi, 1);
cv::Mat PlaneB_Mat(3, 1, CV_64FC1);
double R = 0, R2 = 0, FR2=0;
int Observation = 70;
PlaneB_Mat.at<double>(0, 0) = XiZi;
PlaneB_Mat.at<double>(1, 0) = YiZi;
PlaneB_Mat.at<double>(2, 0) = Zi;
Plane = PlaneA_Mat.inv() * PlaneB_Mat;
double A = Plane.at<double>(0, 0); //-A/C
double B = Plane.at<double>(1, 0); //-B/C
double C = Plane.at<double>(2, 0); //-D/C
abc << A << "," << B << "," << "-1" << "," << C;
abc <<"\n";
double Dsum = 0;
for (int o = 0; o < GL.PointX.size(); ++o) {
double Error = abs(A * GL.PointX[o] + B * GL.PointY[o] - GL.PointZ[o] + C) / sqrt(pow(A, 2) + pow(B, 2) + 1);
std::cout << "Error : " << Error << std::endl;
Error_projection << Error ;
Error_projection << "\n";
Dsum = Dsum + Error;
GL.D.push_back(Error);
}
R = (Observation * XiYi - Xi * Yi) / sqrt((Observation * X2i - Xi * Xi) * (Observation * Y2i - Yi * Yi));
R2 = pow(R, 2);
FR2 = pow(Zi - Dsum, 2) / pow(Zi - (1 / Observation)*Zi, 2);
std::cout << "PlaneA_Mat : " << PlaneA_Mat << std::endl;
std::cout << "PlaneB_Mat: " << PlaneB_Mat << std::endl;
std::cout << "FINAL PLANE: " << Plane << std::endl;
std::cout << "R: " << R << std::endl;
std::cout << " Correlation coefficient (R^2) : " << R2 << std::endl;
std::cout << " Final Correlation coefficient (FR^2) : " << FR2 << std::endl;
我得到的结果是:
A : 12.36346708893272
B : 0.07867292340114898
C : -3.714791111490779
并且还得到了每个点相对于平面的误差。 错误值非常大。
*选项 2:Python 方式*
然后我开始在网络上查找一些代码并发现了这个 --> 3D Plane Fit代码。我根据自己的需要进行了修改,效果非常好。
import numpy as np
import scipy.optimize
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import pandas
fig = plt.figure()
ax = fig.gca(projection='3d')
def fitPlaneLTSQ(XYZ):
(rows, cols) = XYZ.shape
print(rows, cols)
G = np.ones((rows, 3))
print(XYZ)
print(XYZ[0])
G[:, 0] = XYZ[0] # X
G[:, 1] = XYZ[1] # Y
print(G)
Z = XYZ[2]
(a, b, c), resid, rank, s = np.linalg.lstsq(G, Z)
print("a : ", a )
print("b : ", b )
print("c : ", c)
print("Residual : ", resid)
print("Rank : ", rank)
print("Singular Value", s)
normal = (a, b, -1) # I Don't Know WHY ?
print("normal : ", normal)
'''
normala = abs(pow(a,2)+pow(b,2)+pow(-1,2))
np.sqrt(normala)
abb=normal/normala
print("Normala : ",normala)
print("Normala : ", abb)
'''
nn = np.linalg.norm(normal) # I Don't Know WHY ?
print("nn : ", nn)
normal = normal/nn # I Don't Know WHY ?
print("Normal : ", normal)
return (c, normal)
#Import Data from CSV
result = pandas.read_csv("C:/Users/Logs/points_L.csv", header=None) # , names=['X', 'Y','Z']
#result =result.head(5)
print(result)
normal1 = pandas.read_csv("C:/Users/Logs/pose_left.csv", header=None) # , names=['X', 'Y','Z']
print(normal1)
abc = pandas.read_csv("C:/Users/Logs/abc.csv", header=None) # , names=['X', 'Y','Z']
print(abc)
#standard normal distribution / Bell.
#np.random.seed(seed=1)
data = result
#print(data)
print("NEW : ")
print(data)
c, normal = fitPlaneLTSQ(data)
print(c, normal)
# plot fitted plane
maxx = np.max(data[0])
maxy = np.max(data[1])
minx = np.min(data[0])
miny = np.min(data[1])
print(maxx,maxy, minx, miny)
point = np.array([0.0, 0.0, c]) # I Don't Know WHY ?
print("Point : ", point)
d = -point.dot(normal) # I Don't Know WHY ?
print("D : ", d)
# plot original points
ax.scatter(data[0], data[1], data[2])
ax.quiver(data[0], data[1], data[2], normal1[0], normal1[1], normal1[2], length=0.2)
# compute needed points for plane plotting
xx, yy = np.meshgrid([minx, maxx], [miny, maxy])
print(xx)
print(yy)
print("minx : ", minx)
print("maxx : ", maxx)
print("miny : ", miny)
print("maxy : ", maxy)
print("xx : ", xx)
print("yy : ", yy)
z = (-normal[0]*xx - normal[1]*yy - d)*1. / normal[2] # I Don't Know WHY ?
unit1 = np.sqrt(pow(normal[0], 2) + pow(normal[1],2) + pow(normal[2],2))
print("Unit 1 : ", unit1)
Error = abs(normal[0]*data[0] + normal[1]*data[1] + normal[2]*data[2] + d)/unit1
print("Error", Error)
Error_F = pandas.DataFrame(Error)
print("Print : ", Error_F)
Error_F.to_csv("C:/Users/Logs/Py_Error.csv")
print("Z : ", z)
# plot plane
ax.plot_surface(xx, yy, z, alpha=0.2)
ax.set_xlim(-1, 1)
ax.set_ylim(-1,1)
ax.set_zlim(1,2)
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')
plt.show()
如果您能回答以下问题,将会非常有帮助:
# I Dont Know WHY ?
您能否提供他们使用它背后的数学推理。请小心地解释它,就像你向菜鸟解释一样。 为什么我的最终相关系数 R^2 提供奇怪的结果?
Thank You Very Much !
最佳答案
嗯,这不是一个答案,但对于评论来说太长了。 “点与平面之间的距离”的另一种解释是,对于点 p
n.p + d
其中平面有方程
n.p + d = 0
我们假设
|n| = l
因此,如果我们有 N 个点 p[] 的集合,我们会寻找实数 d 和单位 vector n 来最小化
S = Sum{ i | (n.P[i] + d)*(n.P[i] + d) }
一些代数派生出以下计算方法:
a/通过计算 Pbar(均值点)和 Q(P[] 的“协方差”)
Pbar = Sum{ i | P[i]}/N
Q = Sum{ i | (P[i]-Pbar)*(P[i]-Pbar)' } / N
b/计算 n 和对应于最小特征值的 Q 特征向量。
c/计算
d = -n'*Pbar
关于python - 3D 平面拟合方法(C++ 与 Python),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59881691/
我正在处理一组标记为 160 个组的 173k 点。我想通过合并最接近的(到 9 或 10 个组)来减少组/集群的数量。我搜索过 sklearn 或类似的库,但没有成功。 我猜它只是通过 knn 聚类
我有一个扁平数字列表,这些数字逻辑上以 3 为一组,其中每个三元组是 (number, __ignored, flag[0 or 1]),例如: [7,56,1, 8,0,0, 2,0,0, 6,1,
我正在使用 pipenv 来管理我的包。我想编写一个 python 脚本来调用另一个使用不同虚拟环境(VE)的 python 脚本。 如何运行使用 VE1 的 python 脚本 1 并调用另一个 p
假设我有一个文件 script.py 位于 path = "foo/bar/script.py"。我正在寻找一种在 Python 中通过函数 execute_script() 从我的主要 Python
这听起来像是谜语或笑话,但实际上我还没有找到这个问题的答案。 问题到底是什么? 我想运行 2 个脚本。在第一个脚本中,我调用另一个脚本,但我希望它们继续并行,而不是在两个单独的线程中。主要是我不希望第
我有一个带有 python 2.5.5 的软件。我想发送一个命令,该命令将在 python 2.7.5 中启动一个脚本,然后继续执行该脚本。 我试过用 #!python2.7.5 和http://re
我在 python 命令行(使用 python 2.7)中,并尝试运行 Python 脚本。我的操作系统是 Windows 7。我已将我的目录设置为包含我所有脚本的文件夹,使用: os.chdir("
剧透:部分解决(见最后)。 以下是使用 Python 嵌入的代码示例: #include int main(int argc, char** argv) { Py_SetPythonHome
假设我有以下列表,对应于及时的股票价格: prices = [1, 3, 7, 10, 9, 8, 5, 3, 6, 8, 12, 9, 6, 10, 13, 8, 4, 11] 我想确定以下总体上最
所以我试图在选择某个单选按钮时更改此框架的背景。 我的框架位于一个类中,并且单选按钮的功能位于该类之外。 (这样我就可以在所有其他框架上调用它们。) 问题是每当我选择单选按钮时都会出现以下错误: co
我正在尝试将字符串与 python 中的正则表达式进行比较,如下所示, #!/usr/bin/env python3 import re str1 = "Expecting property name
考虑以下原型(prototype) Boost.Python 模块,该模块从单独的 C++ 头文件中引入类“D”。 /* file: a/b.cpp */ BOOST_PYTHON_MODULE(c)
如何编写一个程序来“识别函数调用的行号?” python 检查模块提供了定位行号的选项,但是, def di(): return inspect.currentframe().f_back.f_l
我已经使用 macports 安装了 Python 2.7,并且由于我的 $PATH 变量,这就是我输入 $ python 时得到的变量。然而,virtualenv 默认使用 Python 2.6,除
我只想问如何加快 python 上的 re.search 速度。 我有一个很长的字符串行,长度为 176861(即带有一些符号的字母数字字符),我使用此函数测试了该行以进行研究: def getExe
list1= [u'%app%%General%%Council%', u'%people%', u'%people%%Regional%%Council%%Mandate%', u'%ppp%%Ge
这个问题在这里已经有了答案: Is it Pythonic to use list comprehensions for just side effects? (7 个答案) 关闭 4 个月前。 告
我想用 Python 将两个列表组合成一个列表,方法如下: a = [1,1,1,2,2,2,3,3,3,3] b= ["Sun", "is", "bright", "June","and" ,"Ju
我正在运行带有最新 Boost 发行版 (1.55.0) 的 Mac OS X 10.8.4 (Darwin 12.4.0)。我正在按照说明 here构建包含在我的发行版中的教程 Boost-Pyth
学习 Python,我正在尝试制作一个没有任何第 3 方库的网络抓取工具,这样过程对我来说并没有简化,而且我知道我在做什么。我浏览了一些在线资源,但所有这些都让我对某些事情感到困惑。 html 看起来
我是一名优秀的程序员,十分优秀!