Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 多点椭球方程_Python_Algorithm_Scipy - Fatal编程技术网

Python 多点椭球方程

Python 多点椭球方程,python,algorithm,scipy,Python,Algorithm,Scipy,我有大量的像素颜色(96000种不同的颜色): 我想得到某种数学定义的概率区域,如: 我现在看到的主要障碍是——谷歌上的所有方法都主要是关于可视化和二维空间,但没有一种算法可以找到方程的系数,比如: a1x2+b1y2+c1y2+a2xy+b2xz+c2yz+a3x+b3y+c3z=0 对于我来说,用python实现它太难了( 无论如何,我只想确定某个像素是否或多或少位于我的底色中 我尝试使用scikit集群实现它,但由于只有一个集群,所以失败了 可能是一组数据。创建一个数组2563个元素

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

我想得到某种数学定义的概率区域,如:

我现在看到的主要障碍是——谷歌上的所有方法都主要是关于可视化和二维空间,但没有一种算法可以找到方程的系数,比如:

a1x2+b1y2+c1y2+a2xy+b2xz+c2yz+a3x+b3y+c3z=0

对于我来说,用python实现它太难了(

无论如何,我只想确定某个像素是否或多或少位于我的底色中

我尝试使用scikit集群实现它,但由于只有一个集群,所以失败了 可能是一组数据。创建一个数组2563个元素 表示每个像素颜色似乎是错误的

我想知道是否有一种简单的方法来确定这个点簇的边界? 或者,也许我只是想得太多了,有点像OpenCV
cv2.inRange()函数?

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

  • 查找平均点位置

    这将是你的椭球的中心

    p0 = sum (p[i]) / n      // average
    i = { 0,1,2,3,...,n-1 }  // of all points
    
    如果点密度不均匀,则使用边界框中心更安全。因此,找到
    xmin,ymin,zmin,xmax,ymax,zmax
    ,它们之间的中间就是你的中心

  • 找到到中心的最远点

    这将给你主半轴

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

    因此,向量
    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
    
    FinalRadius := 0
    for i := 0 to Amount:
        vecRadius := (3DPoints[i] - vecFoci1) + (3DPoints[i] - vecFoci2)
        FinalRadius := Max(FinalRadius, Length(vecRadius))
    
    因此,找到这样一个点:

    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
    
  • 椭球体

    现在你有了形成椭球体所需的所有参数

    (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 >
    
    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中可能会给您带来一些想法。

    有一种方法可以找到仅基于两个焦点的非完美对称椭球体。 也许这对获得大量分数有好处。 至少,它非常简单(基于某种随机搜索):


    查看3个变量。特征向量将给出椭圆的主轴。与您尝试做的事情类似的常见事情称为“主成分分析”。从三维数据生成3个正交向量(主成分)这总结了数据在各个方向上的变化。它们是一个椭圆的轴,看起来像上面的那个。@samgak,MattTimmermans,工作几乎完美无瑕。我只是没能在绘图上画出这些特征向量,但它们似乎是正确的:哦,我从来没想过可以很容易地绕一个椭球(和O(n))!但似乎我有一些离群数据,纯几何方法不会返回想要的结果。也许近似搜索会帮助我,但我不确定是否能够实现它。:)但你的第五段真的很精彩!我将使用从PCA获得的这些特征向量,然后围绕p0构建一个椭球。即使存在旋转,也不难检查椭球内是否存在其他像素。非常感谢!)我的数学真的很差…@Xobotun你可以稍微改变一下搜索公式,使之更符合你的需要。您没有指定椭球体的确切属性,所以我只展示了几何方法。例如,如果希望椭球体覆盖75%的点,可以将所有点转换为找到的椭球体的坐标系,然后重新缩放为立方体。然后缩小bbox,直到它只覆盖75%的点,重新缩放并重新计算a、b、c大小。。。您可以做任何事情(添加方程式、更改点积阈值角度等…)@Xobotun当你提到颜色时,这意味着你正在做一些基于概率的颜色量化,还有其他的方法,例如,请看:但由于我没有关于你的问题的背景信息,我可能是在错误的方向上假设…我想StackOverflow最好能更详细地问我的问题抽象术语多于具体术语。我提出这个问题的原因是为了提取看起来像我皮肤的像素:我们大学的科学顾问(简单地说是老师)让我们中的一些人完成了一项任务,通过过滤给定的图像来加速Viola-Jones人脸检测算法。当我告诉他过滤看起来像皮肤的区域的想法时,他说:“嗯,可能有用。”。现在我正试图发展这个想法,并测量检测人脸所需的时间。@Xobotun不是该领域的专家,但我的直觉告诉我HSV颜色空间比RGB更好。此外,在HSV中,您可以部分忽略V值,从而使您的问题成为2D而不是3D,请参阅以获取一些想法。
    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
    
    FinalRadius := 0
    for i := 0 to Amount:
        vecRadius := (3DPoints[i] - vecFoci1) + (3DPoints[i] - vecFoci2)
        FinalRadius := Max(FinalRadius, Length(vecRadius))