scipy 包含多个点的椭球方程

rkue9o1l  于 2022-11-09  发布在  其他
关注(0)|答案(2)|浏览(128)

我有大量的像素颜色(96千种不同的颜色):

我想得到一个数学上定义的概率区域,比如this question

我现在看到的主要障碍--谷歌上的所有方法主要是关于可视化和二维空间的,但没有一种算法可以找到方程的系数,比如:
a1x2 + b1y2 + c1y2 + a2xy + b2xz + c2yz + a3x + b3y + c3z = 0
而且this paper对我来说太难了,不能用python实现。
无论如何,我只是想确定一些像素是或多或少位于我的音域。
我试着用scikit聚类来做它,但是我失败了,因为我只有一组数据,而且创建一个2563个元素的数组来代表每个像素的颜色似乎是一个错误的方法。
我想知道是否有一个简单的方法来确定这个点簇的边界?或者,也许我只是想多了,有像OpenCV cv2.inRange()函数这样的东西?

ewm0tg9j

ewm0tg9j1#

这可以通过优化和拟合椭圆多项式来解决。2然而,我会从更快的几何方法开始:
1.查找平均点位置
那就是椭圆体的中心

p0 = sum (p[i]) / n      // average
i = { 0,1,2,3,...,n-1 }  // of all points

如果你的点密度不是均匀的,那么使用包围盒中心会更安全。所以找到xmin,ymin,zmin,xmax,ymax,zmax,它们之间的中间就是你的中心。
1.寻找到中心的最远点
这会给予你主半轴

pa = p[j];
|p[j]-p0| >= |p[i]-p0|   // max
i = { 0,1,2,3,...,n-1 }  // of all points

1.寻找第二个半轴
所以矢量pa-p0垂直于其他半轴所在的平面。所以找到p0与该平面距离最远的点:

pb = p[j];  
|p[j]-p0| >= |p[i]-p0|   // max
dot(pa-p0,p[j]-p0) == 0  // but inly if inside plane
i = { 0,1,2,3,...,n-1 }  // from all points

注意点积的结果可能不是精确的零,所以最好对如下内容进行测试:

|dot(pa-p0,p[j]-p0)| <= 1e-3

可以使用所需的任何阈值(应基于椭球体大小)。
1.查找最后一个半轴
所以我们知道最后一个半轴应该垂直于

(pa-p0) AND (pb-p0)

所以找到这样的点:

pc = p[j];  
|p[j]-p0| >= |p[i]-p0|   // max
dot(pa-p0,p[j]-p0) == 0  // but inly if inside plane
dot(pb-p0,p[j]-p0) == 0  // and perpendicular also to b semi-axis
i = { 0,1,2,3,...,n-1 }  // from all points

1.椭圆体
现在您已经拥有了形成椭圆体所需的所有参数。vectors

(pa-p0),(pb-p0),(pc-p0)

是椭圆体的基本向量(可以使用叉积使它们垂直)。它们的大小给出半径。p0是中心。也可以使用以下参数方程:

a=pa-p0;
b=pb-p0;
c=pc-p0;
p(u,v) = p0 + a*cos(u)*cos(v)
            + b*cos(u)*sin(v)
            + c*sin(u);
u = < -0.5*PI , +0.5*PI >
v = < 0.0 , 2.0*PI >

这整个过程只是O(n),结果可以用作优化和拟合的起点,以加快它们的速度,而不损失精度。如果您想进一步提高精度,请参阅:

下面的子链接为您展示了拟合的示例...
你也可以看看这个:

这与您的任务基本相似,但仅在2D中,可能会给您带来一些想法。

oxf4rvwz

oxf4rvwz2#

这是一个快速简单的随机搜索方法的非严格解决方案 。最好的一面-不需要繁重的线性代数库*。似乎它在网格碰撞检测中工作得很好。
假设椭圆体中心与云中心匹配,然后使用某种镜像平均值来搜索主轴。
完整的工作代码稍微大一点,放在git上,主轴搜索的思路是:

np.random.shuffle(pts)

pts_len = len(pts)
pt_average =  np.sum(pts, axis = 0) / pts_len

vec_major = pt_average * 0
minor_max, major_max = 0, 0

# may be improved with overlapped pass,

for pt_cur in pts:
    vec_cur = pt_cur - pt_average
    proj_len, rej_len = proj_length(vec_cur, vec_major)

    if proj_len < 0:
        vec_cur = -vec_cur
    vec_major += (vec_cur - vec_major) / pts_len

    major_max = max(major_max, abs(proj_len))
    minor_max = max(minor_max, rej_len)

在某些方面,它甚至可以得到进一步的改进/优化。

以及完整的experiment code(带图)

  • 即随机调整代码行,直到它们正常工作

**实际上是找出此解决方案原因

相关问题