椭圆方程包含多个点

时间:2017-03-01 19:53:10

标签: python algorithm scipy

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

enter image description here

我希望获得某种数学定义的概率区域,例如this question

enter image description here

我现在看到的主要障碍 - Google上的所有方法主要是关于可视化和二维空间,但是没有找到方程系数的算法,如:

a 1 x 2 + b 1 y 2 + c 1 < / sub> y 2 + a 2 xy + b 2 xz + c 2 yz + a 3 x + b 3 y + c 3 z = 0

this paper对我来说太难以在python中实现它。 :(

无论如何,我只想确定一些像素是否或多或少存在于我的辩护中。

我尝试使用scikit群集,但由于只有一个,我失败了 可能是一组数据。并创建一个256 3 元素的数组 代表每个像素颜色似乎是错误的方式。

我想知道是否有一种简单的方法来确定这个点群的边界? 或者,也许我只是在思考它,而且还有像OpenCV这样的东西 cv2.inRange()函数?

2 个答案:

答案 0 :(得分:1)

这可以通过优化和拟合椭球多项式来解决。但是,我会从更快的几何方法开始:

  1. 找到平均点位置

    这将是椭圆体的中心

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

    如果您的点密度不均匀,则使用边界框中心更安全。所以找xmin,ymin,zmin,xmax,ymax,zmax,他们之间的中间是你的中心。

  2. 找到最远点的中心

    将为您提供主轴半轴

    pa = p[j];
    |p[j]-p0| >= |p[i]-p0|   // max
    i = { 0,1,2,3,...,n-1 }  // of all points
    
  3. 找到第二个半轴

    因此向量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产品的结果可能不会精确为零,因此最好对此类测试进行测试:

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

    您可以使用任何您想要的阈值(应该基于椭圆体大小)。

  4. 找到最后一个半轴

    所以我们知道最后一个半轴应该垂直于两个

    (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
    
  5. <强>椭球

    现在您拥有形成椭球所需的所有参数。载体

    (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 >
    
  6. 整个过程只是O(n),结果可以作为优化和拟合的起点,以加快它们的速度而不会降低精度。如果您想进一步提高准确度,请参阅:

    子链接显示了适合的例子......

    您还可以看一下:

    这与你的任务基本类似,但只在2D中仍然可以带给你一些想法。

答案 1 :(得分:1)

有一种方法可以仅基于两个焦点来查找非完美的对称椭球。 可能对大量积分有好处。 至少,这非常简单(基于某种随机搜索):

3DPoints - Array of some Amount of points
vecCenter - average of 3DPoints
AngleCosine - cos of angle between two vectors

RandomOrder(3DPoints)

vecFocus := (0, 0, 0)
for i := 0 to Amount:
    vecRadius := 3DPoints[i] - vecCenter

    // Change vecRadius direction to parallel if it's not
    if AngleCosine(vecFocus, vecRadius) < 0 then
        vecRadius *= -1
    vecFocus += (vecRadius - vecFocus) / Amount

通过向后第二次传递数组可以改善结果 然后将焦点放在vecCenter +/- vecFocus处。 然后可以通过一些系数提出到病灶的距离,或者通过第二遍计算病灶的距离,如下所示:

FinalRadius := 0
for i := 0 to Amount:
    vecRadius := (3DPoints[i] - vecFoci1) + (3DPoints[i] - vecFoci2)
    FinalRadius := Max(FinalRadius, Length(vecRadius))