我已经编写了一段代码,它接受输入的HSL颜色值,并将其归类为8种预定义颜色之一。由于我所测量的对象的颜色不是完全“平滑”的(精确的H、S和L值随像素而异,但每个值都有一个有限的范围,取决于颜色),所以在将产生的HSL值识别为特定颜色之前,我希望聚合对象上几个像素的H、S和L。
举个例子,如果物体实际上是黑色的,那么它的任何像素的H应该在24-33之间,而黄色的H范围是33 - 37。将几个被测的H集合在一起,而不是依赖于单一的度量,将倾向于产生一个接近于与正确颜色相对应的任何范围的中间的结果,这就降低了需要解释模糊的33种情况的可能性。
我一直在使用类似于中位数的聚合算法(如下所示的精确算法),但我遇到了这样做不太好的情况。特别是,紫色对象的H范围包括231 - 240和0- 10 (240是最大H值,因此它环绕)。所有其他颜色的可能的H,S,和L的是单一的,连续的范围,对此中值方法(或我修改的版本)工作良好,但在紫色H的情况下并不理想,因为它产生的结果实际上更接近其范围的边缘,因此输入的HSL值更有可能被误认为另一种颜色(红色的H范围是9-14)。
对于这个任务,是否有比中位数更好的聚合算法,它会产生更接近颜色的H、S和L范围中间的结果,甚至在紫色H的情况下也是如此?
算法:
private hslColor aggregateEachAttribute(hslColor[] hslData)
{
List<double> hAttributes = new List<double>();
List<double> sAttributes = new List<double>();
List<double> lAttributes = new List<double>();
for (int i = 0; i < hslData.Length; i++)
{
hAttributes.Add(hslData[i].H);
}
for (int i = 0; i < hslData.Length; i++)
{
sAttributes.Add(hslData[i].S);
}
for (int i = 0; i < hslData.Length; i++)
{
lAttributes.Add(hslData[i].L);
}
hAttributes.Sort();
sAttributes.Sort();
lAttributes.Sort();
while (hAttributes.Distinct().Count() >= 3)
{
hAttributes.RemoveAll(h => h == hAttributes[0]);
hAttributes.RemoveAll(h => h == hAttributes[hAttributes.Count() - 1]);
}
while (sAttributes.Distinct().Count() >= 3)
{
sAttributes.RemoveAll(s => s == sAttributes[0]);
sAttributes.RemoveAll(s => s == sAttributes[sAttributes.Count() - 1]);
}
while (lAttributes.Distinct().Count() >= 3)
{
lAttributes.RemoveAll(l => l == lAttributes[0]);
lAttributes.RemoveAll(l => l == lAttributes[lAttributes.Count() - 1]);
}
return new hslColor(hAttributes[0], sAttributes[0], lAttributes[0]);
}发布于 2017-09-18 04:38:42
如果你只是需要担心,如果你的点是 240-X对于一些相当小的X,你可以通过将X加到你的数据模块240中,计算一个中位数,然后从结果mod 240中减去X。
更广泛地说,你可以通过找到一个最小距离之和的值来寻找一个中值或medoid,其中d(x,y) =min(x-y,x-y,x-240+x-y,x-240+y-x)。我认为你可以在O(n)之后用一些非常复杂的代码来计算O(n log n),在这个代码中,你可以计算与每个候选人中间或中间相关联的距离之和,根据它们是顺时针方向还是逆时针方向从当前点开始,并在从一个候选点或中间点移动到下一个点时,逐步更新距离之和。
https://stackoverflow.com/questions/46270465
复制相似问题