我一直在阅读一些将圆拟合到数据的方法(如this)。我想看看这些方法如何处理真实数据,并考虑使用 R 来实现这一点。我尝试在 rseek 搜索可以帮助解决此问题的软件包,但没有找到任何有用的东西。
那么,是否有软件包可以帮助轻松计算给定数据集的最佳拟合圆(类似于如何lm()
将线性模型拟合到数据集)?否则,如何在 R 中执行这样的任务?
我一直在阅读一些将圆拟合到数据的方法(如this)。我想看看这些方法如何处理真实数据,并考虑使用 R 来实现这一点。我尝试在 rseek 搜索可以帮助解决此问题的软件包,但没有找到任何有用的东西。
那么,是否有软件包可以帮助轻松计算给定数据集的最佳拟合圆(类似于如何lm()
将线性模型拟合到数据集)?否则,如何在 R 中执行这样的任务?
这是该论文中最小化 SS(a,b,r) 的函数的一个相当幼稚的实现:
fitSS <- function(xy,
a0=mean(xy[,1]),
b0=mean(xy[,2]),
r0 = mean(sqrt((xy[,1]-a0)^2 + (xy[,2]-b0)^2)),
...){
SS <- function(abr){
sum((abr[3] - sqrt((xy[,1]-abr[1])^2 + (xy[,2]-abr[2])^2))^2)
}
optim(c(a0,b0,r0), SS, ...)
}
我编写了几个支持函数来生成圆圈上的随机数据并绘制圆圈。因此:
> xy = sim_circles(10)
> f = fitSS(xy)
该fit$par
值是 xcenter、ycenter、radius 的向量。
> plot(xy,asp=1,xlim=c(-2,2),ylim=c(-2,2))
> lines(circlexy(f$par))
请注意,它不使用梯度,也不检查收敛的错误代码。您可以为其提供初始值,也可以猜测。
绘制和生成圆圈的代码如下:
circlexy <- function(xyr, n=180){
theta = seq(0,2*pi,len=n)
cbind(xyr[1] + xyr[3]*cos(theta),
xyr[2] + xyr[3]*sin(theta)
)
}
sim_circles <- function(n,x=0,y=0,r=1,sd=0.05){
theta = runif(n, 0, 2*pi)
r = r + rnorm(n, mean=0, sd=sd)
cbind(x + r*cos(theta),
y + r*sin(theta)
)
}
好吧,看这里:一个 R-blogger 专栏已经编写了一些代码来适应椭圆和圆形。他的代码(我不会在这里重新发布)基于 Radim Halíř 和 Jan Flusser 在 Matlab 中所做的工作。他的代码包括(注释)原始 Matlab 行以进行比较。
我看过很多关于这个主题的论文,只能说我没有资格确定哪些算法是最健壮的。有兴趣的可以看看这些论文:
http://www.emis.de/journals/BBMS/Bulletin/sup962/gander.pdf
http://ralph.cs.cf.ac.uk/papers/Geometry/fit.pdf
http://autotrace.sourceforge.net/WSCG98.pdf
后续编辑:我针对链接的 R 代码运行 Spacedman 的代码以拟合椭圆,使用圆圈上相同的“嘈杂”集 1e5 点作为输入。结果是:
testcircle<-create.test.ellipse(Rx=200,Ry=200,Rot=.56,Noise=5.5,leng=100000)
dim(testcircle)
[1] 100000 2
microbenchmark(fitSS(testcircle),fit.ellipse(testcircle))
Unit: milliseconds
expr min lq median uq max
fitSS(testcircle) 649.98245 704.05751 731.61282 787.84212 2053.7096
fit.ellipse(testcircle) 25.74518 33.87718 38.87143 95.23499 256.2475
neval
100
100
作为参考,两个拟合函数的输出为:
从SSfit
, 列表
ssfit
$par
[1] 249.9530 149.9927 200.0512
$value
[1] 185.8195
$counts
function gradient
134 NA
$convergence
[1] 0
$message
NULL
从fit.ellipse
,我们得到
ellfit
$coef
a b c d e
-7.121109e-01 -1.095501e-02 -7.019815e-01 3.563866e+02 2.136497e+02
f
-3.195427e+04
$center
x y
249.0769 150.2326
$major
[1] 201.7601
$minor
[1] 199.6424
$angle
[1] 0.412268
您可以看到椭圆方程的系数对于“偏离”圆的项接近于零;绘制这两个结果会产生几乎无法区分的曲线。