我有大量的像素颜色(96,000 种不同的颜色):
我想获得某种数学定义的概率区域,例如 this question :
我现在看到的主要障碍——谷歌上的所有方法主要是关于可视化和二维空间,但没有找到方程系数的算法,如:
a1x2 + b1y2 + c1y2 + a2xy + b2xz + c2yz + a3x + b3y + c3z = 0
而且 this paper 对我来说太难了,无法在 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
您可以使用任何您想要的阈值(应基于椭球大小)。
所以我们知道最后一个半轴应该垂直于两者
(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
现在您拥有了形成椭球体所需的所有参数。向量
(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 中仍可能会给您带来一些想法。