坐标转换完超限了。监理问你参数怎么来的,你说软件自动算的。人家再问精度验证做过没,当场就懵了。
不对,准确说,是心虚。
用最小二乘法自己算转换参数,精度验证自己做,就不怕超限了。
有一组已知点在源坐标系和目标坐标系下的坐标,要找变换关系,让转换后残差最小。说白了就是拟合,让所有点离拟合线最近。
上代码。
import numpy as npdeffit_transformation(src, dst): A = np.c_[src, np.ones(src.shape[0])] x_params, _, _, _ = np.linalg.lstsq(A, dst[:, 0], rcond=None) y_params, = _, _, _ = np.linalg.lstsq(A, dst[:, 1], rcond=None)return x_params, y_paramssrc = np.array([ [100.0, 200.0], [150.0, 250.0], [200.0, 300.0], [250.0, 350.0],])dst = np.array([ [500100.0, 3500200.0], [500150.0, 3500250.0], [500200.0, 3500300.0], [500250.0, 3500350.0],])x_p, y_p = fit_transformation(src, dst)print(f'X参数: {x_p}')print(f'Y参数: {y_p}')算出参数后,验证一下。
deftransform_point(point, x_params, y_params): x = x_params[0] * point[0] + x_params[1] * point[1] + x_params[2] y = y_params[0] * point[0] + y_params[1] * point[1] + y_params[2]return np.array([x, y])residuals = []for s, d inzip(src, dst): pred = transform_point(s, x_p, y_p) residual = np.linalg.norm(pred - d) residuals.append(residual)print(f'最大残差: {max(residuals):.4f}')print(f'平均残差: {np.mean(residuals):.4f}')print(f'RMS: {np.sqrt(np.mean(np.array(residuals)**2)):.4f}')验证好了,应用新数据。
new_points = np.array([ [120.0, 220.0], [180.0, 280.0],])for p in new_points: result = transform_point(p, x_p, y_p)print(f'点({p[0]}, {p[1]}) -> ({result[0]:.2f}, {result[1]:.2f})')最小二乘法算出来的参数,前提是控制点分布均匀、没有粗差。如果控制点里有明显错误的,得先剔除。不然一个坏点能把整个结果带偏。
精度要求高的项目,建议多做几组验证。留几个检查点不参与拟合,专门用来验证。RMS控制在限差以内,才算合格。
我上次做一个控制网平差,用这套方法自己算了一遍转换参数,RMS只有2.3毫米。监理看了直点头,说你这比软件算的靠谱。
将参数应用到新的观测数据上,评估剩余误差和超限风险。